PDA

View Full Version : Static Linking Ordering Issues



SneakyPeterson
11th June 2010, 09:45
Hello Everyone,

I've been surfing through the web and the forums in order to find an answer to this question, but have unable to find a working solution to my problem. I have found a number of people with the same problem, but it seems like every time I try something that works for them, I don't have any luck. Anyway, I just thought I'd post that I'd done some due diligence before asking for help on what seems to be a common problem.

For reference:
I am using QT 4.6 on Linux. The static libraries I create have the .a extension.

Anyways, here's the issue:
I am working on a project that requires about 10 different statically linked libraries, and it seems that this number is going to increase in the near future. As some of you may know, when attempting to link static libraries, the order in which you compile the libraries is somewhat of an issue. When a library is compiled, the dependencies it has are generated, and so if the dependencies for a static library have been defined before the library is compiled, those dependencies will be left unresolved, leaving a compiler warning similar to:

libcode.a(code.o): In function `code::dependentOnOtherLibrary()':
code.cpp:306: undefined reference to `fromotherlibrary::foo()'

So far I have only found one solution to the problem that works for me: changing the order that libraries are compiled manually so that the libraries that depend on other files are compiled first and their dependencies resolved by latter libraries. This solution seems rather cumbersome, and with me being a lazy programmer, I want to have this work done for me by QT :p Anyways, here's the stuff I've tried so far that I haven't been able to get working. That's not to say that they aren't the right solutions, just that I can't get any of them working and thus am kind of lost as to what the correct next step to take is:

1. Adding a CONFIG += create_prl to all libraries that are included and a CONFIG += link_prl to the application that includes the library. It seems that the create_prl flag should generate the dependencies that a library generates and the definitions it resolves. I thought when using these generated .prl files in my application that the errors would go away, but sadly these additions seemed to have no effect. Is this a dynamic linking thing only? (I don't have a hell of a lot of experience with dynamic linking)
2. Adding the libraries that I'm using to the PRE_TARGETDEPS or POST_TARGETDEPS macros defined by qmake to both the library files that depend on other libraries and the application that uses the libraries. It seems that these dependency variables should state to the linker what symbols the libraries they contain define either before or after compilation, depending on which one you use. Anyways, I couldn't get this to work :/
3. Playing around the the LDFLAGS in qmake. I know that it's possible (incredibly inefficient but possible) to send -( and -) flags to the ld linker surrounding the libraries that you compile. When doing so, the linker will continuously recompile the libraries until all unresolved symbols have been resolved. Even though this means I'm probably going to be unnecessarily recompiling libraries, it also means that I don't have to manually reconfigure my project file every time the architecture of my project changes. Besides, I can always use the extra compiling time to grab some coffee :p The problem that i'm running into is I don't believe the -( and -) flags are defined by qt, and even if they were i'm unsure how i'd get them to surround the libraries during compilation without adding the libraries themselves to the ldflags variable, which seems to be a no-no anyway.

Phew. If you've managed to read all of that, congratulations and thank you! I apologize for the length, but I wanted to make sure that I described the problem and what I've tried in detail. I suppose what I'm asking from you now is if you see a solution above that I've tried unsuccessfully that I should be able to successfully implement in order to solve my problem, or whether there is something else that I can do that I have overlooked.

Cheers,
sneakypeterson

SixDegrees
11th June 2010, 11:51
The order of compilation makes no difference. What matters is the order of the libraries during linkage. Libraries with unresolved symbols should occur before the libraries containing the resolution on most systems. On a very few systems, link order doesn't matter, but these are rare, and this ability can cause other problems.

The simplest thing to do is put your libraries in the proper order to begin with. You created them, after all, and should know what symbols they contain, so this normally isn't difficult. For external libraries, you may have to move libraries containing their resolution later in the list, but once the order is established, you're done.

It is possible to automate this process with scripts that examine compiler output and search for symbols in libraries using tools like nm, but it generally isn't worth the trouble.

Another solution, since you're creating your own libraries, is to pack all their constituent object files into a single library archive. This can be done at compilation time, or after the fact using ar to disassemble and reassemble your archive files.

In general, a large and growing number of dependencies indicates some sort of design flaw. You should probably be creating a single library in the first place.