I have some questions about gcc link order. GCC man says linker search symbols from left to right without repeatly search by default. Here is my test:
main.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("HELLO WROLD\n");
return 0;
}
printf.c
#include <stdio.h>
#include <stdlib.h>
int printf(const char *fmt, ...)
{
write(1, "AAA\n", 4);
}
[root@lenovo testcode]# gcc -c -fno-builtin-printf *.c
[root@lenovo testcode]# gcc -o test main.o printf.o
[root@lenovo testcode]# ./test
AAA
[root@lenovo testcode]# gcc -o test printf.o main.o
[root@lenovo testcode]# ./test
AAA
[root@lenovo testcode]# ar rcs libprintf.a printf.o
[root@lenovo testcode]# gcc -o test libprintf.a main.o
[root@lenovo testcode]# ./test
HELLO WROLD
[root@lenovo testcode]# gcc -o test main.o libprintf.a
[root@lenovo testcode]# ./test
AAA
[root@lenovo testcode]# gcc -shared -o libprintf.so printf.o
[root@lenovo testcode]# gcc -o test libprintf.so main.o
[root@lenovo testcode]# export LD_LIBRARY_PATH=.
[root@lenovo testcode]# ./test
AAA
[root@lenovo testcode]# gcc -o test main.o libprintf.so
[root@lenovo testcode]# ./test
AAA
From the result, we can see the order of .o and .o, .o and .so make no difference, only order of .o and .a has the effect. But that is inconsistant with gcc man page. So why?
gcc does indeed process the object files from left to right. When you have
gcc -o test libprintf.a main.o
The first object file gcc sees is libprintf.a
. There are no unresolved symbols for the output object at this point, so nothing from libprintf.a
is used/needed. Next, main.o
is processed, the linker makes a note of the fact that printf
is unresolved, and then proceeds to process the implicit libraries where it is able to resolve the printf
symbol that was unresolved in main.o
.
Likewise, when you have:
gcc -o test main.o libprintf.a
The first object file to be processed is main.o
, where the unresolved symbol printf
is noted, the next to be processed is libprintf.a
from which the linker is able to resolve printf
. When libc
is eventually processed, printf
is already resolved so the instance of printf
in libc
is not used.
When linking with .o files:
gcc -o test main.o printf.o
The libc
library is again treated as if it was specified at the end of the command line, so the printf
symbol is resolved from the first (left-to-right) object file that defines it.
For both of the libprintf.so
cases, the libc
library is again treated as if it was specified at the end of the command line. What is different from the static library case is that the left-to-right ordering of the *.so
libraries determines the run-time dynamic symbol search order. Since this order has libprintf.so
before the implicit libc.so
, the version of printf
in libprintf.so
is used.
gcc -o test libprintf.so main.o
gcc -o test main.o libprintf.so
As an additional experiment, you could try:
gcc -o test main.o -lc libprintf.so
This should show the version of printf
being used from libc.so
instead of libprintf.so
because -lc
comes before libprintf.so
in left-to-right order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With