When one starts using libraries, an problem that happens often is a linking error. Compilation went through but the linker complains that it cannot find something. A useful tool in this respect is nm
and I will describe below how one can employ it. I will do it with my gcc
example
Compiling and Linking: Simple Example with gcc
/2008/03/compilelink
but please not that nm
on Windows (for example under Cygwin) is able to work with object files and libraries from MS VS. Hence the text could be used in this case as well (just change .o
to .obj
and .a
to .lib
).
I assume that you have already done points 1) to 3) and now we are at the point 4) Linking application with the library. Instead of issuing a correct command to link with the library, let us try to make a binary just from main.o
.
$ g++ -o main main.o
main.o:main.cpp:(.text+0x1e): undefined reference to `testlib(int)'
collect2: ld returned 1 exit status
Now we have a typical linking error and I hope that it is understandable. In main.cpp
there is a call of testlib
but there is no definition of such a function. We know where this function resides but let us imagine for a moment that we are not sure in that.
nm
shows what symbols are defined in the object file
$ nm main.o
00000000 b .bss
00000000 d .data
00000000 d .eh_frame
00000000 t .text
U __Z7testlibi
U ___gxx_personality_v0
U ___main
00000000 T _main
Please note that we do not see testlib
but rather __Z7testlibi
. This happens because of name mangling in C++ (this does not happen in C or Fortran where the difference could be just in underscore). We can force nm
to show names before name mangling
$ nm -C main.o
00000000 b .bss
00000000 d .data
00000000 d .eh_frame
00000000 t .text
U testlib(int)
U __gxx_personality_v0
U __main
00000000 T main
Then we see the name as written in the code. What is more important here is however the symbol U
before the function name. It says that this function is not defined in the object file and the linker should take it either from other object file or from the library.
Usually the list of name is long and one can use grep
to find the lines that are of interest, for example
$ nm main.o | grep testlib
U __Z7testlibi
This confirms the message from the linker. "undefined reference to `testlib(int)"
means exactly this, that in the object file there is a symbol with U as shown by nm
. Now we suspect that this symbol is defined in libtestlib.a
and want to check it with nm
.
$ nm ../lib/libtestlib.a | grep testlib
testlib.o:
0000003e t __GLOBAL__D__Z7testlibi
0000005a t __GLOBAL__I__Z7testlibi
00000076 T __Z7testlibi
nm
confirms that the function is there, as we see T
before the function name.
This is basically what should be done when you see the linking error. The goal is to undertand what library has symbols required by the linker and nm
can help you to find the answer.
If you have many libraries to check for a given symbol, you may find useful my script findlib:
#!/bin/bash
#to find a library that contains a given symbol
#Use:
#findlib sym libs
sym="$1"
shift
for name do
echo $name
nm $name | grep sym
done
More information:
$ man nm
$ info nm
RSS