Steven A Steven A - 2 months ago 19
C Question

gcc linking with static libraries

I am reading a book titled "An Introduction to GCC" and would like some clarification. The book indicates that the code below will cause an error but when I compile, it builds and runs perfectly:

#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;
}


I quote from the book "Trying to create an executable from this source file alone causes the compiler to give an error at the link stage:"

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


The solution that the book gives is that you are supposed to include the path to the math library ‘libm.a’ as follows:

$ gcc -Wall calc.c /usr/lib/libm.a -o calc


It would be very inconvenient to have to specify the paths to built in libraries that we use in our programs. I can understand the reason for adding the path to my own custom libraries, but libm.a is built into gcc. And although the book is quite old (published in 2004), what has changed with more modern versions of gcc, so that we do not need to include the path to libm.a?

* UPDATE *

I noticed that the answer given by taskinoor demonstrates updated code that requires that I use the -lm flag if the value passed to sqrt() is not known at compile time.

I learned C/C++ using VS but my goal now is to learn and use gcc. I have Visual Studio 2013 and the VS compiler/linker does not seem so picky. For example, I am able to compile just about any simple program without having to specify mysterious compiler flags.

I am learning on gcc version 5.4 that comes with KUBUNTU 16.04.1

Answer

sqrt (2.0);

Modern GCC is well capable to determine that you are trying to find square root of a constant and thus it is able to calculate that in compile time. Your object code does not contain an actual call to sqrt.

If you use a variable which is input via scanf at run then it won't link without libm.

int main() {
    double x;

    scanf("%lf", &x);
    printf("%lf\n", sqrt(x));

    return 0;
}

Without libm gcc 4.8.4 on Ubuntu 14.04 this results:

/tmp/ccVO2fRY.o: In function `main':
sqrt.c:(.text+0x2c): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

But if I put a constant instead of x like your example then it links fine without libm.

P.S: I don't know the exact version since when GCC is able to do this. Hopefully someone else can point to that.