22

I am currently using GCC to compile and I need to use <math.h>. The problem is that it won't recognize the library.

I have also tried -lm and nothing.

The function I tried to use was ceil() and I get the following error:

: undefined reference to `ceil'
collect2: ld returned 1 exit status

I am using the latest Ubuntu and math.h is there. I tried to use -lm on a different computer, and it worked perfectly.

How can I solve this problem?

I did include <math.h>. Also, the command I used was:

gcc -lm -o fb file.c
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
drum
  • 5,416
  • 7
  • 57
  • 91

3 Answers3

32

Take this code and put it in a file ceil.c:

#include <math.h>
#include <stdio.h>
int main(void)
{
    printf("%f\n", ceil(1.2));
    return 0;
}

Compile it with:

$ gcc -o ceil ceil.c
$ gcc -o ceil ceil.c -lm

One of those two should work. If neither works, show the complete error message for each compilation. Note that -lm appears after the name of the source file (or the object file if you compile the source to object before linking).

Notes:

  1. A modern compiler might well optimize the code to pass 2.0 directly to printf() without calling ceil() at all at runtime, so there'd be no need for the maths library at all.

  2. Rule of Thumb: list object files and source files on the command line before the libraries. This answer shows that in use: the -lm comes after the source file ceil.c. If you're building with make etc, then you typically use ceil.o on the command line (along with other object files); normally, you should list all the object files before any of the libraries.

There are occasionally exceptions to the rule of thumb, but they are rare and would be documented for the particular cases where the exception is expected/required. In the absence of explicit documentation to the contrary, apply the rule of thumb.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • @Johnathan Leffler is there a way to do this without tpying -lm every single time during compiling? – Brandon Feb 11 '16 at 20:01
  • @Brandon: Migrate to Mac? The functions from `` are in the main system library, so you don't need to specify `-lm` (though there is a `libm.dylib` to give you a library to link against if you specify `-lm` on the command line). Otherwise, make sure you're using a makefile and you have `LDLIBS` (or `LDLIBES`) set to `-lm` if you use it enough to warrant it — or write per-program rules that include/exclude the library as required by each program. So, in other words, "No, there isn't a way to avoid specifying it". You could ask the GLibC team why they've not gone to a single library. – Jonathan Leffler Feb 11 '16 at 22:42
  • Note that if you optimize the code, it is possible for the compiler to evaluate `ceil(1.2)` at compile time and avoid the need to call the function at runtime, in which case you might not need the `-lm` library at all. But that would be an obscure edge-case for the simple program in my example — in general, the compiler would not be able to make that optimization and then you'd need to link with the maths library unless the functions are already in the main system library. – Jonathan Leffler Nov 29 '16 at 00:22
  • Thanks! I had missed putting the flag after the file. – Flipbed Jun 08 '17 at 08:23
12

I just wanted to mention that Peter van der Linden's book Expert C Programming has a good treatment on this subject in chapter 5 Thinking of Linking.

Archives (static libraries) are acted upon differently than are shared objects (dynamic libraries). With dynamic libraries, all the library symbols go into the virtual address space of the output file, and all the symbols are available to all the other files in the link. In contrast, static linking only looks through the archive for the undefined symbols presently known to the loader at the time the archive is processed.

If you specify the math library (which is usually a static one) before your object files, then the linker won't add any symbols.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daniel Näslund
  • 2,300
  • 3
  • 22
  • 27
8

Try compiling like that:

gcc -Wall -g file.c -lm -o file

I had the same problem and it was solved using this command. Also if you installed your Ubuntu the same day you had the problem it might be an update problem.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user4371544
  • 81
  • 1
  • 1