C: undefined reference... to library used successfully elsewhere - c

I am trying to compile a C++ project (openFrameworks + CodeBlocks), using an external C library. I get "undefined reference" error, although I succesfully compile and use the library elsewhere.
The code consists of sources main.cpp, testApp.cpp and header files, including one for my library "myprocessing". When I make , the code is compiled and dies at linking with error
obj/i686Release/./src/testApp.o: In function `testApp::update()':
testApp.cpp:(.text+0x261): undefined reference to `gauss_5(datarect_t)'
collect2: ld returned 1 exit status
make: *** [bin/faceGrabber] Error 1
where gauss_5 is my library function, and it is called in testApp.cpp (header with declarations is included there).
Below I paste the make commands used to compile the code, generated by CodeBlocks (I strip it for clarity)
# compiling object for: ./src/testApp.cpp
g++ -c -g [some -I...] -DOF_USING_GTK -DOF_USING_MPG123 -Wall
-fexceptions -I. -Ilib/ -MMD -MP -MFobj/i686Debug/./src/testApp.d
-MTobj/i686Debug/./src/testApp.d -oobj/i686Debug/./src/testApp.o
-c ./src/testApp.cpp
# compiling object for: ./src/main.cpp
g++ -c -g -pthread [some -I...] -DOF_USING_GTK -DOF_USING_MPG123
-Wall -fexceptions -I. -Ilib/ -MMD -MP -MFobj/i686Debug/./src/main.d
-MTobj/i686Debug/./src/main.d -oobj/i686Debug/./src/main.o
-c ./src/main.cpp
# linking bin/faceGrabber_debug . ./src ./lib
g++ -o bin/faceGrabber_debug obj/i686Debug/./src/testApp.o
obj/i686Debug/./src/main.o -Wl,-rpath=./libs -Llib/ -lz
-lmyprocessing [some libs...]
Note that my library is referenced (-lmyprocessing) in the last, linking step. So, all the headers and libraries are found by the compiler, but somehow they are not compiled-in.
I tried both .a static and .so dynamic files for myprocessing, unsuccessfully. As I mentioned, I use the same library in other project (outside openFrameworks and CodeBlocks) and it works.

You say that the library is written in C. However, the fact that the linker is able to print out the type of the argument to gauss_5() suggests that it's working with the mangled, C++ name of the function.
I suspect you might be missing extern "C" { ... } guards around your C header.

Related

C Link External Library in Makefile

I am having issues linking a library (termbox) when compiling. I get the error:
make: *** No rule to make target `termbox.h', needed by `test.o'. Stop.
Makefile:
edit: test.o
gcc -Wall -o edit test.o
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src
Include:
#include "termbox/src/termbox.h"
I have also tried using the compiled library but ran into similar issues. Do I have to use some sort of combination of specifying the header file and the location of the compiled library?
The directory of my termbox folder is in the same directory as test.c.
Thanks!
You have managed to compile and include the header file for the library, but you did not yet tell the compiler where the code (definitions) are - i.e. you did not tell it to link in the library yet.
You will need to do that next, this is done in a similar way to telling the linker what files to link, but with some extra syntax. It appears to be a static library (.a suffix) so you can link like this:
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -Itermbox/src -Lsrc -ltermbox
Where -L... specifies where libraries can be found and -l... specifies the library name to link to minus the lib prefix and the .a or .so suffix. Also note that order is important, so leave the library linkage at the end.
More on library linking order here
UPDATE
Sorry I added the linking to the wrong line! - here is the updated answer:
# The linker stage
edit: test.o
gcc -Wall -o edit test.o -Lsrc -ltermbox
# Compile stage
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src

No undefined references when compiling shared library

Im wondering why Im getting no undefined references when compiling as a shared library using -shared as an option for gcc. Consider the following case:
#include <confuse.h>
int
main(int argc, char **argv)
{
cfg_opt_t opts[1];
cfg_t *cfg = cfg_init(opts, CFGF_NOCASE);
return 0;
}
libconfuse is needed here in order to run the program properly. If im compiling it as a "normal" application without specifying that libconfuse is needed (-lconfuse) im getting the following (from my perspective regular) error:
$ gcc -Wall -Wno-unused-variable test.c -o test
/tmp/ccTVz6an.o: In function `main':
test.c:(.text+0x20): undefined reference to `cfg_init'
collect2: error: ld returned 1 exit status
If im compiling the same code as a shared library im not getting any error message regarding the library:
$ gcc -Wall -Wno-unused-variable test.c -o test.so -shared
$ echo $?
0
Can someone please bring light into darkness?
You are compiling a (shared) library, not a program, and libraries are expected not to be complete, so undefined references do not prevent the shared library from building.
Yes, it may sound a bit surprising, particularly if you come from a OS (Windows?) where the shared libraries are always fully linked, but that's how ELF works.
If you want to ensure that all your references are are resolved when building a shared library you can use the linker option --no-undefined:
gcc -Wall -Wno-unused-variable test.c -o test.so -shared -Wl,--no-undefined
Note that libraries used to resolve references when linking a shared library will be added to the header of that library, as NEEDED entries, and then linked automatically when using that library. See objdump -p for details.
With shared libraries (not static ones), you could link a library libA.so into your other library libB.so.
So you could compile your shared library as:
gcc -Wall -Wno-unused-variable -fPIC test.c \
-o libmytest.so -shared -lconfuse
Later you would link that library to some main.c with
gcc -Wall main.c -lmytest -L. -o myprog
or you could load it at runtime, using dlopen(3) on ./libmytest.so (read the man page about why ./ is significant to dlopen)
Simple explanations are in the Program Library HowTo. But Drepper's paper: How to Write Shared Libraries is the best reference.
And it is permitted for a shared library (or even a static one) to have undefined references, since quite often the user of that library would explicitly link the lower level libraries needed by it.

C: Undefined reference to floor

I am using Eclipse on Ubuntu to write/compile/run C code.
I am trying to build my project.
Following is the output in the Eclipse console.
22:18:31 **** Build of configuration Debug for project Project1 ****
make all
Building file: ../project1.c
Invoking: GCC C Compiler
gcc -I/lib/i386-linux-gnu -O0 -g3 -Wall -c -fmessage-length=0 -pthread -lm -MMD -MP -MF"project1.d" -MT"project1.d" -o "project1.o" "../project1.c"
../project1.c: In function ‘main’:
../project1.c:146:6: warning: unused variable ‘this_thread_id’ [-Wunused-variable]
../project1.c: In function ‘_pre_init’:
../project1.c:126:1: warning: control reaches end of non-void function [-Wreturn-type]
Finished building: ../project1.c
Building file: ../scheduler.c
Invoking: GCC C Compiler
gcc -I/lib/i386-linux-gnu -O0 -g3 -Wall -c -fmessage-length=0 -pthread -lm -MMD -MP -MF"scheduler.d" -MT"scheduler.d" -o "scheduler.o" "../scheduler.c"
Finished building: ../scheduler.c
Building target: Project1
Invoking: GCC C Linker
gcc -L/lib/i386-linux-gnu -lm -pthread -o "Project1" ./project1.o ./scheduler.o
./project1.o: In function `advance_global_time':
/home/akshay/Cworkspace/Project1/Debug/../project1.c:50: undefined reference to `floor'
collect2: ld returned 1 exit status
make: *** [Project1] Error 1
Can anyone please help me figure out what the problem is and how to solve it?
You need to link libraries after the object files.
You have:
gcc -L/lib/i386-linux-gnu -lm -pthread -o "Project1" ./project1.o ./scheduler.o
You need:
gcc -L/lib/i386-linux-gnu -pthread -o "Project1" ./project1.o ./scheduler.o -lm
There seems to have been a change in the way the linkers work — at some time, it was possible to specify shared libraries (such as the maths library) before the object files, and all would work. However, nowadays, if the shared library doesn't satisfy any symbols when it is scanned, it is omitted from the link process. Ensuring that the object files are listed before the libraries fixes this.
See also Undefined reference to 'pthread_create'; same problem, same solution. And I doubt if that is the only such question in SO.
You need to link against the mathematical library, i.e., add -lm at the end of the link line. No idea how to do that in Eclipse, sorry.
Note, the linking flags in your output look out of order. Perhaps you attempted to add the -lm via the Linker Flags in Eclipse. This causes issues in Eclipse. I suggest you try...
Right click on your project -> properties -> C/C++ Build -> Settings
-> GCC Linker -> Libraies -> add "m" -> Apply -> build
OR, at the very list, make sure that the -L and -l parameters come after your .o files in the Linking process.
I just got hit by this today and it eluded me for a while.

Switched from shared library to dll, now getting an error that it can't find pow()

Here is the error:
symbol lookup error: ./src/libprog3.so: undefined symbol: pow
Everything else in the library works fine, even functions that use math.h, but when I call the function that needs pow(), it crashes. It worked perfectly fine when it was a shared library. I am using gcc and a makefile to compile. The only change I made to the makefile was adding -ldl for the library. I still have -lm in it. I changed the driver program to support the change to the dll instead of the shared library, but the function causing the error hasn't changed.
Is there more to the makefile that I need to change?
Here is the makefile:
testlib: src/driver.o src/prog3.o
gcc -fPIC -Wall -c src/prog3.c -o src/prog3.o
gcc -Wall -shared -o src/libprog3.so src/prog3.o
gcc -Wall -o $# src/driver.c -ldl -lm -Lsrc -lprog3
You need to be doing:
gcc -Wall -shared -o src/libprog3.so src/prog3.o -lm
That is, shared libraries must be built with their dependencies. If you omit the -lm, you're telling the linker that unresolved symbols in libprog3.so are intended to be resolved by symbols in the main program or libraries it has already caused to be loaded. I see you did put -lm on the link command line for the main program, but my guess is that the main program did not actually use any symbols from libm.so and thus it did not get added to the DT_NEEDED table for the main program and therefore is not already loaded.
In any case, making dependencies explicit like this is almost always best.

Why am I getting a gcc "undefined reference" error trying to create shared objects?

Why am I getting an "undefined reference" error using gcc?
I am trying to create a shared object (.so) that exports one function, "external()". I then try to link against the .so but get "undefined reference 'external'". What am I doing wrong here?
File: external.c
int external() {
return 5;
}
File: program.c
int external();
int main(char** argv, int* argc) {
return external();
}
Commands:
$ gcc -fPIC -c external.c
$ gcc -shared -o libexternal.so external.o
$ gcc -L. -lexternal -o program program.c
/tmp/cc3MmhAE.o: In function `main':
program.c:(.text+0x7): undefined reference to `external'
collect2: ld returned 1 exit status
I can even run nm and see that the .so is defining 'external':
Command:
$ nm libexternal.so | grep external
0000040c T external
What am I missing here?
Recent versions of gcc/ld default to linking with --as-needed.
This means if you write -lexternal before the C file the library will automatically get excluded (the order matters when testing if things are "needed" like this)
You can fix this with either of:
gcc -L. -o program program.c -lexternal
gcc -L. -Wl,--no-as-needed -lexternal -o program program.c
The latter of which passes --no-as-needed to the linker, which would cause the library to still be linked, even if you didn't call external() from it.
Note: -Wl,--no-as-needed isn't applied globally to everything that's linked, it's only applied to things that follow it in the command line order. So -lexternal -Wl,--no-as-needed also wouldn't work. This does mean that you can mix and match behaviours though, for example gcc -L. -Wl,--no-as-needed -lexternal -Wl,--as-needed -o program program.c -lmightneed would always link against external, but only link against mightneed if one or both of program.c/libexternal.so caused it to be needed.

Resources