Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC libm not working

Tags:

c

linux

I have a c program that calls sin, cos, and acos. When I compile I get the following errors:

/tmp/ccDfW98S.o: In function `zip_search':
main.c:(.text+0xf30): undefined reference to `sin'
main.c:(.text+0xf45): undefined reference to `sin'
main.c:(.text+0xf66): undefined reference to `cos'
main.c:(.text+0xf7b): undefined reference to `cos'
main.c:(.text+0xf9c): undefined reference to `cos'
main.c:(.text+0xfc6): undefined reference to `acos'
collect2: ld returned 1 exit status

I know this is common when you don't use the -lm gcc flag. I AM using this flag. I'm calling GCC like this:

gcc -o zipcode-server -lm main.c

When I compile on one of my computers this works fine. The only difference that I can think of is that this isn't working on x86_64 and the computer it does work on is i686. Both are Ubuntu. The file libm.a is present on the computer it isn't working on and I don't get any errors saying it can't be found. What could be causing this?

like image 799
Stewart Avatar asked Apr 07 '12 23:04

Stewart


People also ask

How do I add LIBM?

Link your program with the `libm. a' library, e.g. by specifying `-lm' on the link command line.

What is LIBM?

LIBM is the standard C library of basic mathematical functions, such as sin(x), cos(x), exp(x), etc. To include the LIBM functions, just add -lm on your link command line. The Intel compiler includes an optimized math library that contains optimized implementations of LIBM functions.

Where is libm a?

So, libm is actually located at /usr/lib/x86_64-linux-gnu/libm. a .

Where is the c library in linux?

The library file is copied to a standard directory so that client programs, without fuss, can access the library. A typical location for the library, whether static or dynamic, is /usr/lib or /usr/local/lib ; other locations are possible.


1 Answers

You should put -lm after main.c

In general, if you have multiple libraries, they should be written in order of their usage. For example, if library A uses library B, you should have -lA -lB.

In your case, the object file that is the result of compilation of main.c uses library m and therefore -lm should come after it.


For the curious, this is mostly for efficiency reasons. With this scheme, the linker can resolve currently unknown symbols with every new library seen in the argument list, and picking up new unknown symbols from that library on the way. This means that the linker can visit the libraries one by one, and therefore match the unknown symbols against a small number of symbols provided by each library.

On the contrast, the linker could load in symbols from all libraries at once, and then start matching unknown symbols. In that case however, the linker needs to deal with a much greater number of symbols, increasing both the memory footprint and the execution time of the linker.

Since the libraries could always be declared to the linker in the proper order of their dependencies1, there is no reason for the linker to choose the inefficient way.

1Libraries normally have a one-way relationship, in the sense that one uses the other. Circular dependencies between libraries is rare, if at all existing, but it could still be used with this model by repeating certain libraries to be reinspected.

like image 138
Shahbaz Avatar answered Oct 24 '22 18:10

Shahbaz