I always thought that libraries had to be listed after any object files that depended on them, but given this simple program:
#include
#
I confirm the unexpected link-order behaviour that you observe with gcc 5.1 and also that I have the traditional behaviour with gcc 4.9.2. I would infer that this novelty comes in with gcc 5.x, and that your toolchain is gcc 5.x. Possibly it is a distro-specific anomaly of the toolchain build. My toolchain is as per ubuntu 14.04.
The novel behaviour only affects dynamic libraries. I can see what is causing it
if I link in verbose mode (-v
) with gcc 4.9.2 and also with gcc 5.1, placing -lm
before it is needed,
and examine the differences in the verbose output.
From gcc 4.9.2 I have (with artifical line-wrapping):
/usr/lib/gcc/x86_64-linux-gnu/4.9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/4.9/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccsHNLNB.res
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker
/lib64/ld-linux-x86-64.so.2 -z relro -o mathtest
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.9
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../lib -L/lib/x86_64-linux-gnu
-L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../.. -lm mathtest.o -lgcc --as-needed
-lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crtn.o
And from gcc 5.1 I have:
/usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=/tmp/cc5hI8vd.res
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc
-plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --sysroot=/ --build-id
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu -dynamic-linker
/lib64/ld-linux-x86-64.so.2 -z relro -o mathtest
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/5
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib -L/lib/x86_64-linux-gnu
-L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib
-L/usr/lib/gcc/x86_64-linux-gnu/5/../../.. -lm mathtest.o -lgcc --as-needed
-lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crtn.o
The relevant difference is that the gcc 4.9.2 linkage passes the option --as-needed
in 4 places whereas the gcc 5.1 linkage passes it in only 3. gcc 4.9.2 passes --as-needed
for the first time at the the 5th quoted "line":
--eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker
gcc 5.1 does not pass it there. Thereafter, both linkages pass this option at the same 3 places, starting as the 13th "line":
-L/usr/lib/gcc/x86_64-linux-gnu/4.9/../../.. -lm mathtest.o -lgcc --as-needed
This means that for gcc 4.9.2, the library option -lm
on "line" 13 falls within the
scope of the first --as-needed
. For gcc 5.1 it does not. The effect of this option
is to inform the linker that the dynamic library libm
(or any dynamic library that
is encountered in the option's scope) shall be linked only if it is encountered
at a point in the linkage at which it can satisfy some unresolved symbols. In the
absence of this option, at a given point in the linkage, a dynamic library is by
default deemed to be needed for the linkage regardless of whether there are yet any
unresolved symbols that it can satisfy. See the documentation of --as-needed
Thus the gcc 4.9.2 linkage will not link libm
, although it appears on the
commandline, because at the point where it appears - before mathtest.o
- --as-needed
is
in force and there are as yet no unresolved references that libm
satisfies. The gcc 5.1
linkage will link libm
because it appears on the commandline at a point where --as-needed
is not in force.