1

Using the example from this great answer about the link order in gcc, I tried the following:

echo 'extern int b; int a = b;' > b.cpp
g++ -c b.cpp -o b.o
ar cr libb.a b.o

echo 'int b;' > d.cpp
g++ -c d.cpp -o d.o
ar cr libd.a d.o

echo 'extern int a; int main() { return a; }' > a.cpp

g++ a.cpp -o a1 d.o b.o # Works
g++ a.cpp -o a2 libd.a libb.a # Fails

If the .a file is simply an archive file containing one or several .o files, how come linking with the lib*.a files (in the wrong order, as stated in the original answer) fails, but using the .o files directly (in the same order) works?

Community
  • 1
  • 1
Masseman
  • 359
  • 3
  • 13
  • 4
    Llibraries are ignored if they don't resolve a symbol, left to right. A .o file is not ignored. – Hans Passant Apr 06 '16 at 10:52
  • @HansPassant: What is the rationale behind this? In the end, only the parts that are needs are kept in the final binary anyway, right? Is there a way to make the behavior with libraries the same as with object files, other than extracting the files from the archive and linking with them directly? – Masseman Apr 06 '16 at 11:46
  • That's pretty subjective. In general it is the eternal battle between tool builders and programmers. Tool builders like to make their tools run fast and not use a lot of memory. They usually win. The linker I use doesn't do this, it makes two passes through the .lib files. But it has an 1-800 support phone number. – Hans Passant Apr 06 '16 at 12:12
  • What do you mean by "make the behavior ... the same"? Every part of an object file gets linked into the final executable. Doing that with a library pretty much defeats the purpose of having a library. Imagine going to your local library and asking for a copy of "War and Peace" and having to go home with every book in the library. – Pete Becker Apr 06 '16 at 12:29
  • I was under the impression that the linker only kept used parts when building the final binary, but with a couple of further test, I see how every `.o` that I list does in fact get added. My impression was then likely based on the fact that unused _libraries_ were ignored by the linker. Am I right that the gcc linker actually ignores unused `.o` files in the library, and not simply the whole library? – Masseman Apr 06 '16 at 12:52

1 Answers1

2

As far as the linker is concerned, the difference between a static library and an object file in the linkage sequence is:-

  • An object file is to be linked, just because it is an object file, whether or not it provides definitions of any symbols that the executable needs. If you don't want an object file to be linked, don't mention it to the linker.

  • A static library is an archive of object files that are to be extracted from the library and linked if required, where an object file in a library is required if and only if it provides a definition of at least one hitherto undefined symbol that the linker has observed in an object file or library appearing earlier in the linkage sequence.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • That makes perfect sense. So while a library may be just an archive of object files (as it is often described), by using one for linking, we are implicitly telling the linker that we want it to pick only useful object files from it. – Masseman Apr 06 '16 at 13:36
  • @Masseman Quite so. Though an object file that is linked, even from a library, might define symbols that are *not* needed as well as symbols that are. You can eliminate such redundancy, if code size is at a premium, by a [combination of compiler options and linker options](http://stackoverflow.com/q/6687630/1362568) – Mike Kinghan Apr 06 '16 at 13:44