Search code examples
cgcclinkerubuntu-14.04suse

Order of libraries passed to linker


At one point in time in my life the order of libraries that one passed to the gcc mattered. You pass gcc the list of libraries from the most to least dependant. For example consider the following source code:

testlib.c

include <math.h>

double proxy_sqrt(double x)
{
    return sqrt(x);
}

testlib.h

double proxy_sqrt(double);

use-testlib.c

#include "testlib.h"

int main(int argc, char* argv[])
{
    proxy_sqrt(36);
    return 0;
}

Then to compile and link:

gcc -c -o testlib.o testlib.c
ar rvs testlib.a testlib.o
gcc -o use-testlib use-testlib.c testlib.a -lm

Note that the last step the most to least dependent ordering is used.

But this (invalid?) order works on SLES12

gcc -o use-testlib use-testlib.c -lm testlib.a 

but fails on Ubuntu 14.04....

gcc -o use-testlib use-testlib.c -lm testlib.a
testlib.a(testlib.o): In function `proxy_sqrt':
testlib.c:(.text+0x1b): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

Anyone know why?

Verbose output from the 2 compilers is shown at the links below:

sles12

http://pastebin.com/sKe8B7V9

ubuntu14.04

http://pastebin.com/vf8fTaE2


Solution

  • Look at the differences in the linker (collect2) commands and the --as-needed and --no-as-needed options:

    SLES 12

    /usr/lib64/gcc/x86_64-suse-linux/4.8/collect2 --build-id --eh-frame-hdr \
        -m elf_x86_64 -dynamic-linker … /tmp/ccgoQd94.o -lm testlib.a -lgcc \
        --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s \
        --no-as-needed /usr/lib64/gcc/x86_64-suse-linux/4.8/crtend.o \
        /usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../lib64/crtn.o
    

    Ubuntu 14

    /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr \
        -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker … \
        /tmp/cciheQTH.o -lm testlib.a -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.8/crtend.o \
        /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
    

    The use of --as-needed at the start of the options for Ubuntu 14 changes the behaviour of things compared to SLES 12. Reputedly, it is to make things easier. I remain to be convinced — it just seems to give new ways for code to break when moved.