Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc linking with static libraries

Tags:

c

gcc

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

like image 910
Steven A Avatar asked Sep 28 '16 18:09

Steven A


2 Answers

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.

like image 116
taskinoor Avatar answered Oct 19 '22 06:10

taskinoor


I've noticed that on some operating systems, common libraries are available without explicit linking. In particular, I've often taken a working C project originally developed on my Mac, and the project would not compile on Linux until I explicitly linked against the libraries I used (like libm).

Of course, this is typically for dynamic rather than static linking...

like image 2
Daniel Standage Avatar answered Oct 19 '22 05:10

Daniel Standage