Placement of -l options matters in GCC

I ran into an interesting puzzle with GCC this afternoon when trying to compile the code below.

#include <math.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    long double x = 2;
    long double y = 1024;

    long double result = powl(x, y);
    printf("%LF ^ %LF : %LF\n", x, y, result);
    return 0;
}

The first command that I used to compile the code failed:

jeyoung@LENNY:~/Temp$ cc -lm -o powltest powltest.c
/usr/bin/ld: /tmp/ccfqvvbz.o: in function `main':
powltest.c:(.text+0x2e): undefined reference to `powl'
collect2: error: ld returned 1 exit status
jeyoung@LENNY:~/Temp$

After about one hour of trying to resolve this error, I was resigned to reading the documentation. This is what I found from the section Options for Linking.

-l library

Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)

The -l option is passed directly to the linker by GCC. Refer to your linker documentation for exact details. The general description below applies to the GNU linker.

The linker searches a standard list of directories for the library. The directories searched include several standard system directories plus any that you specify with -L.

Static libraries are archives of object files, and have file names like liblibrary.a. Some targets also support shared libraries, which typically have names like liblibrary.so. If both static and shared libraries are found, the linker gives preference to linking with the shared library unless the -static option is used.

It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.

After changing the position of -lm, the code was compiled successfully.

jeyoung@LENNY:~/Temp$ cc -o powltest powltest.c -lm
jeyoung@LENNY:~/Temp$ ./powltest
2.000000 ^ 1024.000000 : 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216.000000
jeyoung@LENNY:~/Temp$

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.