Undefined reference while linking static C library - c

In my latest project I am encountering a strange issue regarding an undefined reference to a method of a shared library. I searched on SO but all I could find was either C++ related (extern "C") or not really helping.
The library in question is my fork of libosm which uses protobuf to generate de-/serialization code for OpenStreetMap data in its binary format (.osm.pbf). The function in question is osmpbf__blob__unpack but that is just the first I end up using so I suspect its a general problem.
I inspected the resulting libosm.a with nm and the method is there and exported but for some reason it is not found while linking. Below are my current flags. I tried changing the order and even including all libraries twice (as suggested in another thread) but I always end up with the undefined reference.
CFLAGS = -v -std=c99 -O3 -Wall -Wextra -pedantic
LIBFLAGS = -losmpbf -lprotobuf-c -lz -lpthread
At the moment I am quite lost on what the error could be, but I think it might be a minor general error. It has been a while since I used C..
Any help would be appreciated.
Cheers,
Florian
Edit: Here is my complete Makefile. I just made up the name for the variable LIBFLAGS since I use my own little rule but it seems like I should use LDLIBS and the builtin rules for this simple case.
CC = gcc
CFLAGS = -v -std=c99 -O3 -Wall -Wextra -pedantic
LIBFLAGS = -losmpbf -lprotobuf-c -lz -lpthread
all: main.x
main.x: main.c
$(CC) $(CFLAGS) $(LIBFLAGS) main.c -o main.x
clean:
rm -rf *.o main.x

The problem is the linker (gcc), like most linkers, processes the parameters from left to right. so the link sees the libraries, but there is no unresolved references to be handled, so nothing happens.
The fix is to place the libraries last on the line rather than just after the CFLAGS.

Related

undefined reference to pthread

I want to compile a program which is using threads. I use the #include <pthread.h> library, however when I compile it using my make file I get the following errors:
file.c:(.text+0x378): undefined referece to `pthread_create`
file.c:(.text+0x3ad): undefined referece to `pthread_join`
The program run fine with the normal gcc compilator using -lpthread flag
The source of the make file that I am using:
CC=gcc
COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c
LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -lpthread
CFLAGS = -Wall -O -I$(dir $(LIBLAB))
TEMPFILES = core core.* *.o temp.* *.out typescript*
all:
#echo "Please compile directly the intended programs by name"
clean:
rm -f ${TEMPFILES}
I have set the -lpthread flag in the make file but is not working, what changes should I make in the make file?
Your replacement for LINK.c is wrong. You can't add libraries to this because it means they appear on the link line first.
If you'd shown us the output of make, in addition to the makefile, probably we would have seen it more quickly. Libraries like -lpthread must come at the end of the link line, after any objects that might have needed to use the library.
As I mentioned in comments, you should remove the LINK.c setting and add:
CFLAGS = -pthread
and that should be good enough. If you do need to add libraries, you should use LDLIBS like this:
LDLIBS = -lpthread
not replace the LINK.c variable.

Passing $(sysconfdir) to Source Code from Autoconf/Automake

I'm quite frustrated. I'm trying to pass the name of the system configuration directory to a source file as a symbol. Some research on this very site gave me to understand that I should add the line
AM_CPPFLAGS = -DSYSCONFIR='$(sysconfdir)'
to my Makefile.am. I did so, and the define does show up in the invocation of gcc; in fact, here it is:
gcc -DHAVE_CONFIG_H -I. -I../../src -I.. -DSYSCONFIR='/usr/etc' -g -O2 -MT perm.o -MD -MP -MF .deps/perm.Tpo -c -o perm.o ../../src/perm.c
The trouble is, gcc barfs anyway, telling me that SYSCONFDIR is undeclared.
I've got to be doing something wrong, but for the love of St. Gulik, I don't know what it is. My autoconf is 2.68, my automake is 1.11.3, my gcc is 4.6.3, and I'm trying to do this under Ubuntu 12.04.
A clean compile, a clean compile! My kingdom for a clean compile!
What you show looks like typo.
You are setting and passing SYSCONFIR which is not the same as SYSCONFDIR.

Does gcc -nostdlib prevent explicit appending of standardlibs?

If I call the GCC Linker with the option -nostdlib does this override any manual/explicit appendecis of standardlibs?
GCC is 4.8.1 from MinGW.
Example:
gcc -nostdlib [MyObjectsAndLibraries] -lmsvcrt -o Outfile
Since libmsvcrt is a standard library, will it be added to the link process or will it be ignored? I can't find any reliable data on this., this is why I would also appreciate some kind of source to this.
In this context, "standard libraries" means the libraries that gcc would implicitely link by default. Libraries explicitely mentioned on the command line will always be linked. In fact, gcc documentation at http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Link-Options.html#Link-Options even points out that unless you really know what you're doing you should add explicitely -lgcc when using -nostdlib, as the compiler may rely on some builtins defined in it:
In other words, when you specify -nostdlib or -nodefaultlibs you should usually specify -lgcc as well. This ensures that you have no unresolved references to internal GCC library subroutines.
Since I found this on Google,
#Virgile's answer is enough, but you may run into linker errors when you link with the style of command you gave. There is two steps to program building: compile and link. You can use GCC to do one or the other or both at the same time.
It is important to note the order of which you specify things. In your build, it may be problematic because your exe never gets linked with msvcrt or gcc. Including two libraries which have potentially the same symbols is also very bad.
Here is canonical build and link statements
gcc -g0 -O2 -Wall -nostdlib -c *.c
gcc -g0 -O2 -Wall -nostdlib -o a.exe *.o -lmsvcrt -lgcc
gcc -g0 -O2 -Wall -nostdlib -o a.exe *.c -lmsvcrt -lgcc
Here is a good reference
https://stackoverflow.com/a/18389266/2262111

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.

Resources