Search code examples
gcclinker-errorsbuilt-in

GCC builtin functions - 2003 vs 2019 behaviour


At page 14 of the book "Introduction to GCC" by Brian Gough, the author wants to show a linker error due to not supplying gcc with the libm library, where the code for the function sqrt resides:

$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function ‘main’:
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference to ‘sqrt’

The file calc.c (where the functionsqrt is invoked) is this:

#include <math.h>
#include <stdio.h>
int main (void)
{
    double x = sqrt (2.0);
    printf ("The square root of 2.0 is %f\n", x);
    return 0;
}

This book is from 2003. On my current Ubuntu Linux 18, I can't reproduce the link error: it links and works, printing the correct result:

$ ./calc
1.414214

I found with ldd calc that the libm.so shared library is not invoked at runtime. Nor of course is the static library libm.a involved here. So how does gcc deal with the function sqrt? I found that in this case it uses the sqrt GCC built-in function. Its code gets inserted in the calc.o object file at compile time. So no "undefined reference" error.

First question: this the whole story or am I missing something?

Second question: why did this behavior regarding the built-in functions of GCC change so much between 2003 (when the book was written) and now? (Practically invalidating the whole example, it seems to me)

Third question: why does the author make his examples (e.g.$ gcc -Wall calc.c -lm -o cal) implying that the static library libc.a will be used, when in reality in Linux that syntax invokes the dynamic library libm.so? Is this specific to Linux and not to GNU GCC? What am I mising?


Solution

  • I think this is due to optimization of a constant value. Modern GCC can compute exact value of sqrt (2.0). If you force it not to use the built-ins with -fno-builtin, it will still fail to link. Also, if you change the code a little bit so that the argument to sqrt() is not literal, it will fail to link:

    #include <math.h>
    #include <stdio.h>
    
    double t = 2.0;
    
    int main (void)
    {
        double x = sqrt (t);
        printf ("The square root of 2.0 is %f\n", x);
        return 0;
    }
    

    This produces link error:

    > gcc -o test test.c              
    /usr/bin/ld: /tmp/ccLjHnQx.o: in function `main':
    test.c:(.text+0x11): undefined reference to `sqrt'
    collect2: error: ld returned 1 exit status
    

    Regarding your 3rd question, -lm does not imply static library, AFAIK.