Search code examples
cgccld

Why does the math library only need to be linked when used outside of main?


Using gcc test.c, the first code sample compiles, while the second does not. Why?

They both work with explicit linking of the math library (i.e. gcc test.c -lm.

First Sample:

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

int main () {
   printf("%lf\n", sqrt(4.0) );
   return 0;
}

Second Sample:

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

double sqrt2(double a) { return sqrt(a); }

int main() {
  printf("%lf\n", sqrt(4.0));
  printf("%lf\n", sqrt2(4.0));
  return 0;
}

Linker error with second sample:

/tmp/ccuYdso7.o: In function `sqrt2':
test.c:(.text+0x13): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

gcc -v:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-mul
Thread model: posix
gcc version 8.1.0 (GCC)

There is no linker error for uses of sqrt in the main function. Is there any particular reason that this is the case?

I also checked with clang, but neither compiled (linker errors) without the -lm.


Solution

  • gcc is a particularly clever compiler.

    It will optimise out sqrt(4.0) as a compile time evaluable constant expression. It can do that since the definition of sqrt is defined by the standard and its return value is solely a function of its input. (Note futher that under IEEE754, sqrt must return the closest double to the final result. This further supports the optimisation hypothesis.)

    In the second case, the presence of function (which could be used by other translation units) defeats this optimisation.