How to properly link msgpack into a shared library - c

I'm trying to compile a few .c files that used msgpack-c functions into a shared library. I have the following Makefile:
MSGPACK_CS = msgpack.c
CFLAGS = -std=c99
MSGPACK_OBJECTS = $(subst .c,.o,$(MSGPACK_CS))
MSGPACK_LIBS = msgpack.so
all: $(MSGPACK_OBJECTS) $(MSGPACK_LIBS)
%.o: %.c
$(CC) -c -shared -fPIC $(CFLAGS) $<
$(MSGPACK_LIBS): $(MSGPACK_OBJECTS)
ld -Lmsgpack/.libs -share -o $# $(MSGPACK_OBJECTS) -lmsgpack
I can compile a program that uses msgpack without problem, but this gives me the following error:
msgpack.o: In function `msgpack_pack_int64':
/usr/local/include/msgpack/pack_template.h:373: undefined reference to `__stack_chk_fail_local'
ld: msgpack.so: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: Bad value
Apparently the linkage process isn't going well, but I don't know what is wrong. What can I do?

Try linking with the gcc driver instead of calling ld directly. ld doesn't know about the gcc support libs that are needed for the C runtime:
gcc -Lmsgpack/.libs -shared -o $# $(MSGPACK_OBJECTS) -lmsgpack
If this still doesnt't work, you might need to add -fno-stack-protector to your CFLAGS to supress runtime stack checking.

Related

Undefined reference when using ta-lib/ta_lib.h file and Makefile

I want to use the ta_lib functions in my C code and am trying to import the ta_lib functions. The header file gets imported correctly but i cannot get the linker to find the actual library.
I want to do the compiling process with MAKE and gcc.
Firstly I import the header
#include <ta-lib/ta_libc.h>
And then when i need to use a function
TA_ADOSC(0, CSV_LENGTH - 1, temp_high, temp_low, temp_close, temp_volume, 3, 10, &beginIdx, &endIdx, tmp_adosc);
The program compiles fine using my makefile
# create CC variable
CC = gcc
# create CFLAGS variable
CFLAGS = -L/usr/local/lib -Wall -g
LDLIBS = -lta_lib -I/usr/local/include -lm
output: main.o
$(CC) $(CFLAGS) -o output main.o
main.o: main.c
$(CC) $(LDLIBS) -c main.c
# target: dependencies
# action
clean:
rm -f \*.o output
Once I try to run make i get the following
gcc -L/usr/local/lib -Wall -g -o output main.o
/usr/bin/ld: main.o: in function `calculate_indicators': main.c:(.text+0x226): undefined reference to `TA_ADOSC'
collect2: error: ld returned 1 exit status
make: \*\*\* \[Makefile:10: output\] Error 1
From my understanding I need to fix the linking to the shared library.
The library is installed:
ldconfig -p | grep libta_lib.so
Returns the following
libta_lib.so.0 (libc6,x86-64) => /usr/local/lib/libta_lib.so.0
libta_lib.so.0 (libc6,x86-64) => /lib/libta_lib.so.0
libta_lib.so (libc6,x86-64) => /usr/local/lib/libta_lib.so
libta_lib.so (libc6,x86-64) => /lib/libta_lib.so
Since i am fairly new to C and using external libraries I can't find what seems to be the problem
You are adding the libraries to the compile line. They need to be added to the link line. And preprocessor options like -I are used by the compiler, and "where to find libraries" options like -L are used by the linker.
Also, libraries always must come at the end of the link line, after all the object files. And, the -L "where to search" option should come before the -l "what library to find" option.
Write your rules like this:
CFLAGS = -I/usr/local/include -Wall -g
LDFLAGS = -L/usr/local/lib
LDLIBS = -lta_lib -lm
output: main.o
$(CC) $(CFLAGS) $(LDFLAGS) -o output main.o $(LDLIBS)
main.o: main.c
$(CC) $(CFLAGS) -c main.c
However, it's better to just let make do the work for you; it knows how to correctly compile things (as long as you set the standard variables). You don't need to include a rule to build main.o at all.

gcc - how to create an so from a source file and other o files?

I am working on a c project. https://github.com/eantoranz/gitmod It's broken up into separate c/h files. In my current Makefile, I take each one of the c files and compile them into their own .o file, then when I want to create the final program, I ask to compile a c file that has a main and provide all the other .o files. So far, so good (let me know if this approach is not correct).
As a next step, I want to separate the main part of the program from all the other pieces of the code and would like to pack all of the previous o files into a single so file (that had been compiled as just another .o file so far).
So, old approach was like this:
gitmod.o: src/gitmod.c include/gitmod.h lock.o root_tree.o thread.o object.o cache.o
$(CC) -c -o $# $< $(CFLAGS)
gitmod: src/main.c gitmod.o
$(CC) $< *.o -o $# $(CFLAGS)
These would be the last 2 steps of this process using the so replacing gitmod.o for libgitmod.so, after creating all the previous .o files:
libgitmod.so: src/gitmod.c include/gitmod.h lock.o root_tree.o thread.o object.o cache.o
$(CC) $< *.o -shared -o $# $(CFLAGS)
gitmod: src/main.c libgitmod.so
$(CC) $< -llibgitmod.so -o $# $(CFLAGS)
libgitmod.so would be the shared library that I would like to actually contain all the other sections of code (I really hope that is possible).
When make is going through libgitmod.so, I am getting this:
gcc src/gitmod.c *.o -shared -o libgitmod.so -Iinclude `pkg-config fuse3 libgit2 glib-2.0 --cflags --libs` -DGITMOD_DEBUG -Wall -g
/usr/bin/ld: object.o: warning: relocation against `stderr##GLIBC_2.2.5' in read-only section `.text'
/usr/bin/ld: /tmp/ccir4Ou9.o: relocation R_X86_64_PC32 against symbol `stderr##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:32: libgitmod.so] Error 1
What am I doing wrong?
-fPIC, which means Position Indepent Code, flags is required to create shared object.
You can add the flag in the compile flag, then you can create a shared object.

Using debugger in MakeFile

I've written an entire program and its makefile, the only trouble is I have to idea how to implement the debugger. I've been looking at similar questions online but to no avail.
Here's my makefile:
# the variable CC is the compiler to use.
CC=gcc
# the variable CFLAGS is compiler options.
CFLAGS=-c -Wall
assign4: main1.o ObjectManager.o
$(CC) main1.o ObjectManager.o -o assign4
main1.o: main1.c ObjectManager.h
$(CC) $(CFLAGS) main1.c
ObjectManager.o: ObjectManager.c ObjectManager.h
$(CC) $(CFLAGS) ObjectManager.c
clean:
rm -rf *o assign4
I've tried to adjust the CFLAGS: to -g Wall, but all it says is:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [ObjectManager.o] Error 1
Any suggestions to fix this?
Look at this rule:
ObjectManager.o: ...
$(CC) $(CFLAGS) ObjectManager.c
If CFLAGS is -c -Wall, that -c means that gcc will compile the source file, but not attempt to link it. This is exactly what was intended, to produce an object file and not an executable. One consequence of this is that the source dile (ObjectManager.c) need not contain a main function-- the compiler trusts you to provide one at link time.
But if CFLAGS is -g -Wall, the -g does not imply -c. So gcc will attempt to create an executable, and abort if main is not present.
Solution:
CFLAGS := -Wall -g # the -g can be added with a conditional if you like
ObjectManager.o: ...
$(CC) $(CFLAGS) -c ObjectManager.c

"undefined reference to function" error on a function in the library

I am trying to work with id3 tags with C, so I downloaded mplib and installed it.
I am trying to call this function inside mplib.h where __P is a Macro
extern id3_tag_list* mp_get_tag_list_from_file __P((const char* path));
by writing in
example.c:
int main() {
char* pa = "R U MINE";
id3_tag_list* list = mp_get_tag_list_from_file(pa);
id3_tag *newTag = list->tag;
printf("tag %d\n", newTag->version);
return 0;
}
but when I link, I get an error:
example.o: In function `main':
example.c:(.text+0x27): undefined reference to `mp_get_tag_list_from_file'
collect2: error: ld returned 1 exit status
make: *** [example] Error 1
My makefile looks like this
OBJECTS = example.o
target=example
misc=Makefile
cflags=-Wall -g -O0 -Werror -pedantic -std=c99
all: $(target)
$(target) : $(OBJECTS) $(misc)
gcc $(cflags) -o $(target) $(OBJECTS)
clean:
rm -f $(OBJECTS) $(target)
I am having trouble compiling this. I believe the problem is that I am having issues with linking it to the actual mplib.c file where that function is actually defined, but I am not sure how to do it exactly. I got the library from http://mplib.sourceforge.net/ and I installed it by using 'make' and 'make install'. Am I supposed to manually move the mplib.c file somewhere?
If you build mplib 1.0.3, it creates a library libmp.a. Therefore, you need to specify -lmp on the linker command line, and perhaps -L /where/you/installed/it/lib to specify the directory where the library was installed.
The linker command line should probably look like:
LDFLAGS = -L/usr/local/lib
LDLIBS = -lmp
gcc $(cflags) -o $(target) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
Actually, it would be better if it looked like:
$(CC) $(CFLAGS) -o $# $(OBJECTS) $(LDFLAGS) $(LDLIBS)
The upper-case macro CFLAGS is used for flags to the C compiler. $# means 'the name of the current target'. LDFLAGS are flags for the linker, such as where to find libraries, and LDLIBS contains the specification of libraries. An option such as -lmp means 'look for libmp.so or libmp.a in each of the directories on the list of places searched for libraries' (to a sufficiently close approximation). The -L option prefixes the following directory to the list of places searched for libraries.

How to compile this lib for usage?

I'm new to C programming, and I'm trying to compile this Simple training example with GCC on Ubuntu 12.10.
Looks like fann.h should not be included (as stated on the file itself), so I included fixedfann.h instead.
First attempt (without include, just to see what the compiler will ask for):
$ gcc main.c -o output
/tmp/cckKyM92.o: In function `main':
main.c:(.text+0x62): undefined reference to `fann_create_standard'
main.c:(.text+0x7a): undefined reference to `fann_set_activation_function_hidden'
main.c:(.text+0x8e): undefined reference to `fann_set_activation_function_output'
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
main.c:(.text+0xce): undefined reference to `fann_save'
main.c:(.text+0xda): undefined reference to `fann_destroy'
collect2: ld returned 1 exit status
fann_create_standard is on fann.h and fann.c. As fann.h is included by fixedfann.h, and fann.h should not be included directly, I believe I have to compile fann.c and fixedfann.c, and link then (tell me if I'm doing any mistake, I'm still not familiar with this "linking" stuff).
So I did:
$ gcc fann/fixedfann.c -o fann/fixedfann.o
fann/fixedfann.c:22:20: fatal error: config.h: No such file or directory
compilation terminated.
and then I did:
$ gcc fann/fixedfann.c -o fann/fixedfann.o -include fann/include/config.h
fann/fixedfann.c:22:20: fatal error: config.h: No such file or directory
compilation terminated.
Now, why it's not finding the config.h file here?
--update
Thanks #JonathanLeffler, I could make some steps here. But now I'm stuck at:
$ gcc fann/fixedfann.c -o fann/fixedfann.o -I./fann/include/ -lm
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status
and, with grep, I could not find any reference to main on the fann folder... Also no function _start, and I don't know who is linking this crt1.o... Any idea what's wrong here?
--update2
Ok, I got the .o files using Harmeet's Makefile, now I'm trying to link everything.
I created the main.o with gcc -c main.c, and I tried:
gcc -o output main.o fann/fixedfann.o -lm
(-lm for the libmath, that is needed) and I got:
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
This fann_train_on_file is on fann_train_data.c, so I tried:
gcc -o output main.o fann/fixedfann.o fann/fann_train_data.o -lm
but I got lots of multiple definition of... errors... :/
Looks like fann_train_data.o is already included/linked, but if so, why it's not finding fann_train_on_file?
--update3
I'm still really stuck here... Any idea of which (if any) of this two lines should work?:
gcc -o output main.o hello.o fann/fixedfann.o fann/fann_train_data.o -lm
or
gcc -o output main.o hello.o fann/fixedfann.o -lm
--update for Harmeet
The output was:
$ make
gcc -L./fann -lfann main.o -o main
main.o: In function `main':
main.c:(.text+0x62): undefined reference to `fann_create_standard'
main.c:(.text+0x7a): undefined reference to `fann_set_activation_function_hidden'
main.c:(.text+0x8e): undefined reference to `fann_set_activation_function_output'
main.c:(.text+0xba): undefined reference to `fann_train_on_file'
main.c:(.text+0xce): undefined reference to `fann_save'
main.c:(.text+0xda): undefined reference to `fann_destroy'
collect2: ld returned 1 exit status
make: *** [main] Error 1
You can use ar to make a static library and work with that.
Create a Makefile under your hello-fann-3/fann/ folder with the following contents -
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -c -Iinclude
all: libfann.a
libfann.a: $(OBJECTS)
ar rcs $# $^
%.o: %.c
gcc $(CFLAGS) $^
Then use the make command in hello-fann-3/fann/ to build the static library. The above Makefile will generate libfann.a that you can link to your program.
Create a Makefile under your hello-fann-3/ folder with the following contents -
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -c -I./fann/include
LFLAGS = -L./fann -lfann
main: $(OBJECTS)
gcc $(LFLAGS) $^ -o $#
%.o: %.c
gcc $(CFLAGS) $^
Then use the make command in hello-fann-3/ to build the main program.
In your main.c, you must include fan.h like -
#include "fann.h"
If you do not understand the Makefile, you can read about it here -
http://www.gnu.org/software/make/manual/html_node/index.html
You just need to link the fann library.
If you compile manually do this
gcc main.c -lfann -lm -o main
then simply run it like
./main
If you are on Ubuntu and you faced the following error
./main: error while loading shared libraries: libfann.so.2: cannot open shared object file: No such file or directory
Then run
sudo ldconfig
If you are using NetBeans, then simply Right click on your project -> Properties -> Build -> Linker,
then in the Libraries section click on the browse button [...] then in the new window click on Add Library...
Then add fann library (for example my fann library path is: /usr/local/lib/libfann.a) and click Ok
A fellow helped me, and we came to this line that compiled everything, and make the executable:
$ gcc fann/fann.c fann/fann_io.c fann/fann_train.c fann/fann_train_data.c fann/fann_error.c fann/fann_cascade.c main.c -Ifann/include -lm
And this is the answer.
That said, this is exactly what fixedfann.c is doing (include all this .c files). But if I try:
$ gcc fann/fixedfann.c main.c -Ifann/include -lm
..I get:
undefined reference to `fann_train_on_file'
This fann_train_on_file is on fann_train_data.c, which is included by fixedfann.c, so why it is undefined? I don't know... :/
--update
I realized that:
$ gcc fann/fixedfann.c main.c -Ifann/include -lm
will work if I comment the headers on fixedfann.c:
//#include "config.h"
//#include "fixedfann.h"
#include "fann.c"
#include "fann_io.c"
#include "fann_train.c"
#include "fann_train_data.c"
#include "fann_error.c"
#include "fann_cascade.c"

Resources