问题
I've created a simple static library libvec.a
with AR tool from simple addv.o
and multo.o
. The object file addv.o
contains 1 function symbol (addvec
) and multo.o
contains 1 function (multvec
). I have also written a simple program to test it (driver.c
which adds 2 vectors and uses addvec
function from the library; also it has included vector.h
that defines the function prototypes). And then I compiled it with
gcc -static driver.o ./libvec.a
and everything went okay. But at first I tried to compile it with
gcc -static ./libvec.a driver.o
and I got an error:
undefined reference to 'addvec'
I'm wondering why I got an error when I specified the library first? Should the ordering matter?
回答1:
Always link object files before libraries, period. At least until you know enough about what's going on not to need to ask the question in the first place.
The trouble is that the linker scans the library, and it is looking for main()
. It doesn't find it, so it doesn't pull anything out of the library. Then it scans driver.o
, finds what is looking for, but not the things that were in libvec.a
(which it has forgotten about as they weren't relevant). So, the functions from libvec.a
are unsatisfied references — and the linking fails.
Note that 'object files before libraries' works when linking with static libraries or shared libraries.
回答2:
Now this perfectly makes sense from Computer Systems: A Programmer's Perspective book.
During the symbol resolution phase, the linker scans the relocatable object files and archives left to right in the same sequential order that they appear on the compiler driver’s command line. (The driver automatically translates any .c files on the command line into .o files.) During this scan, the linker maintains a set E of relocatable object files that will be merged to form the executable, a set U of unresolved symbols (i.e., symbols referred to, but not yet defined), and a set D of symbols that have been defined in previous input files. Initially, E, U , and D are empty.
For each input file f on the command line, the linker determines if f is an object file or an archive. If f is an object file, the linker adds f to E, updates U and D to reflect the symbol definitions and references in f , and proceeds to the next input file.
If f is an archive, the linker attempts to match the unresolved symbols in U against the symbols defined by the members of the archive. If some archive member, m, defines a symbol that resolves a reference in U , then m is added to E, and the linker updates U and D to reflect the symbol definitions and references in m. This process iterates over the member object files in the archive until a fixed point is reached where U and D no longer change. At this point, any member object files not contained in E are simply discarded and the linker proceeds to the next input file.
If U is nonempty when the linker finishes scanning the input files on the command line, it prints an error and terminates. Otherwise, it merges and relocates the object files in E to build the output executable file.
Unfortunately, this algorithm can result in some baffling link-time errors because the ordering of libraries and object files on the command line is significant. If the library that defines a symbol appears on the command line before the object file that references that symbol, then the reference will not be resolved and linking will fail.
来源:https://stackoverflow.com/questions/28786873/ordering-of-object-files-and-libraries-in-static-linking