Reputation: 2578
Recently I discoved that Linux linker does not fail due to undefined symbols from static libraries, however does fail due to the same undefined symbols if I link directly with te object files. Here is a simple example:
Source code:
$ cat main.c
int main() { return 0; }
$ cat src.c
int outerUnusedFunc() {
return innerUndefinedFunc();
}
int innerUndefinedFunc();
Creating *.o and *.a from it, comparing using "nm":
$ gcc -c -o main.o main.c
$ gcc -c -o src.o src.c
$ ar r src.a src.o
ar: creating src.a
$ nm src.o
U innerUndefinedFunc
0000000000000000 T outerUnusedFunc
$ nm src.a
src.o:
U innerUndefinedFunc
0000000000000000 T outerUnusedFunc
(Here we clearly see that both *.o and *.a contain the equal symbols list)
And now...
$ ld -o exe main.o src.o
src.o: In function `outerUnusedFunc':
src.c:(.text+0xa): undefined reference to `innerUndefinedFunc'
$ echo $?
1
$ ld -o exe main.o src.a
$ echo $?
0
What is the reason for GCC to treat it differenty?
Upvotes: 1
Views: 1048
Reputation: 61610
If you read the static-libraries
tag wiki
it will explain why no object files from src.a
are linked into your program, and therefore
why it doesn't matter what undefined symbols are referenced in them.
The difference between an object file foo.o
and a static library libfoo.a
, as linker inputs, is
that an object file is always linked into your program, unconditionally, whereas the same object file
in a static library library, libfoo.a(foo.o)
, is extracted from libfoo.a
and linked into
the program only if the linker needs it to carry on the linkage, as explained by the tag wiki.
Naturally, the linker will give errors only for undefined references in object files that are linked into the program.
The behaviour you are observing is behaviour of the linker, whether or not you invoke it via a GCC front-end.
Giving the linker foo.o
tells it: I want this in the program. Giving the linker
libfoo.a
tells it: Here are some object files that you might or might not need.
Upvotes: 3
Reputation: 1301
In the second case — with static library — command line with says "build exe from main.o and add all required things from src.a".
ld
just ignores the library because no external symbols required for main.o
(outerUnusedFunc
is not referenced from main.o
).
But in the first case command line says "build exe from main.o and src.o".
ld
should place src.o
content into output file.
Hence, it obligate to analyze src.o
module, add outerUnusedFunc
into output file and resolve all symbols for outerUnusedFunc
despite it is unused.
You can enable garbage collection for code sections
gcc --function-sections -Wl,--gc-sections -o exe main.c src.c
In this case outerUnusedFunc
(as well as all other functions) will be placed
in separate section. ld
will see that this section unused (no symbols referenced). It will remove all the section from output file so that innerUndefinedFunc
would not be referenced and the symbol should not be resolved — the same result as for library case.
On the other hand, you can manually reference outerUnusedFunc
as "undefined" so that ld
should find it in library and add to output file.
ld -o exe main.o -u outerUnusedFunc src.a
in this case the same error (undefined reference to innerUndefinedFunc) will be produced.
Upvotes: 2