In the case of the GNU linker ld
,
invoked by GCC, what you have observed is explained by the following points.
An object file in the linkage sequence is added to the linkage unconditionally,
whether it contains symbols that the program needs or not.
A static library is an archive of object files together with a "table of contents"
that the linker can inspect.
By default, an object file within a static library in the linkage sequence is not added
to the linkage unconditionally. The linker searches a static library only to
find definitions of symbols that it has observed to be referenced,
but not defined, by object files already added to the linkage. An object file is extracted
from the library and added to the linkage only if it provides definitions of such symbols. It is added only if the linker
already needs some of the definitions that it provides.
For the avoidance of confusion, we'll change the output message:
"some_func in library\n"
to:
"some_func in somelib.o"
Then a demonstration of these points that explains what you've seen:
Case 1
Link troublingsource.o
itself and somelib.o
from a static library.
Linkage sequence: main.o
, troublingsource.o
, libsomelib.a
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o main.o main.c
ar rcs libsomelib.a somelib.o
gcc -o test main.o troublingsource.o -L. -lsomelib
./test
Troubling func
Here:
main.o
was added unconditionally to the linkage.
- Symbol
main
was found defined in main.o
- Symbol
some_func
was found referenced but not defined in main.o
troublingsource.o
was added unconditionally to the linkage
- Symbol
some_func
, previously referenced but not defined, was found defined in troublingsource.o
.
- No unresolved references remained.
libsomelib.a
was not even searched.
Case 2
Link someblib.o
itself and troublingsource.o
from a static library.
Linkage sequence: main.o
, somelib.o
, libtroublingsource.a
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o main.o main.c
ar rcs libtroublingsource.a troublingsource.o
gcc -o test main.o somelib.o -L. -ltroublingsource
./test
some_func in somelib.o
Here:
main.o
was added unconditionally to the linkage.
- Symbol
main
was found defined in main.o
- Symbol
some_func
was found referenced but not defined in main.o
someblib.o
was added unconditionally to the linkage
- Symbol
some_func
, previously referenced but not defined, was found defined in somelib.o
.
- No unresolved references remained.
libtroublingsource.a
was not even searched.
Case 3
Link someblib.o
and troublingsource.o
from separate static libraries.
Linkage sequence: main.o
, libsomelib.a
, libtroublingsource.a
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o main.o main.c
ar rcs libsomelib.a somelib.o
ar rcs libtroublingsource.a troublingsource.o
gcc -o test main.o -L. -lsomelib -ltroublingsource
./test
some_func in somelib.o
Here:
main.o
was added unconditionally to the linkage.
- Symbol
main
was found defined in main.o
- Symbol
some_func
was found referenced but not defined in main.o
libsomeblib.a
was searched for an object file providing a definition of some_func
- A definition of
some_func
was found in member somelib.o
of libsomelib.a
somelib.o
was extracted from libsomelib.a
and added to the linkage.
- No unresolved references remained.
libtroublingsource.a
was not even searched.
Case 4
Link someblib.o
itself and troublingsource.o
itself.
Linkage sequence: main.o
, somelib.o
, troublingsource.o
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o main.o main.c
gcc -o test main.o somelib.o troublingsource.o
troublingsource.o: In function `some_func':
troublingsource.c:(.text+0x0): multiple definition of `some_func'
somelib.o:somelib.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Here:
main.o
was added unconditionally to the linkage.
- Symbol
main
was found defined in main.o
- Symbol
some_func
was found referenced but not defined in main.o
someblib.o
was added unconditionally to the linkage
- Symbol
some_func
, previously referenced but not defined, was found defined in somelib.o
troublingsource.o
was added unconditionally to the linkage
- Symbol
some_func
, allready defined in somelib.o
, was found defined again in troublingbsource.o
. Error.
Case 5
Link someblib.o
from a static library.
Linkage sequence: libsomelib.a
main.o
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o main.o main.c
ar rcs libsomelib.a somelib.o
gcc -o test -L. -lsomelib main.o
main.o: In function `main':
main.c:(.text+0xa): undefined reference to `some_func'
collect2: error: ld returned 1 exit status
Here:
libsomelib.a
was encountered before any object files were added to the
linkage. At that point no symbols were referenced but undefined, so libsomelib.a
was not even searched,
main.o
was added unconditionally to the linkage.
- Symbol
main
was found defined in main.o
- Symbol
some_func
was found referenced but not defined in main.o
- There were no further object files or libraries to link.
some_func
was finally an undefined reference. Error.