Linking multiple C libraries to C create executable [duplicate] - c

This question already has answers here:
Undefined Reference to `pthread_init' When Using -lpthread Flag:
(1 answer)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Why does order in which input libraries are specified matter?
(3 answers)
Closed 5 years ago.
I am trying create a C executable which depends on multiple C static libraries.
I have two libraries :
../libs/libsulibs.a and ../ppm_client/libppm_client.a. libppm_client.a calls some functions of libsulibs.a
Here are my Makefiles
../libs/Makefile
LIBS=-lpthread
CC=gcc
CFLAGS=-Wall -g
INCLUDES=-I .
OBJ=WheelTimer.o threadApi.o LinkedListApi.o
TARGET=libsulibs.a
${TARGET}:$(OBJ)
ar rs ${TARGET} $(OBJ)
%.o:%.c
${CC} ${CFLAGS} -c ${INCLUDES} $<
clean:
rm *.o
rm ${TARGET}
I successfully create libsulibs.a through this makefile
../ppm_client/Makefile
CC=gcc
CFLAGS=-Wall -g
INCLUDES=-I . -I ../libs -I ../ppm
OBJ=ppm_pkt_enums.o ppm_client.o ppm_client_sock.o
TARGET=libppm_client.a
${TARGET}:$(OBJ)
ar rs ${TARGET} ${OBJ}
ppm_pkt_enums.o:ppm_pkt_enums.c
gcc -g -c ${INCLUDES} ppm_pkt_enums.c -o ppm_pkt_enums.o
ppm_client.o:ppm_client.c
gcc -g -c ${INCLUDES} ppm_client.c -o ppm_client.o
ppm_client_sock.o:ppm_client_sock.c
gcc -g -c ${INCLUDES} ppm_client_sock.c -o ppm_client_sock.o
clean:
rm *.o
rm ${TARGET}
This makefile too successfully create the libppm_client.a.
Now, in current dir, I have main Makefile to create executable
CC=gcc
CFLAGS=-g -Wall
STANDARD_LIBS=-lpthread
PPM_OBJ=ppm.o ppm_main.o
LIBS_OBJ=libs/LinkedListApi.o libs/threadApi.o libs/WheelTimer.o
PPM_LIBS=../libs/libsulibs.a
PPM_CLIENT_LIBS=../ppm_client/libppm_client.a
INCLUDES=-I . -I ../libs -I ../ppm_client
TARGET:exe ${PPM_LIBS} ${PPM_CLIENT_LIBS}
ppm.o:ppm.c
gcc -g -c ${INCLUDES} ppm.c -o ppm.o
ppm_main.o:ppm_main.c
gcc -g -c ${INCLUDES} ppm_main.c -o ppm_main.o
${PPM_LIBS}:
(cd ../libs; make)
${PPM_CLIENT_LIBS}:
(cd ../ppm_client; make)
exe:${PPM_LIBS} ${PPM_OBJ} ${STANDARD_LIBS} ${PPM_CLIENT_LIBS}
${CC} ${CFLAGS} ${PPM_OBJ} -o exe -L ../libs -lsulibs -L ../ppm_client -lppm_client ${STANDARD_LIBS}
clean:
rm *.o
(cd ../libs; make clean)
(cd ../ppm_client; make clean)
rm exe
But when I run make, it ends up with the error : undefined reference to pthread_init . pthread_init is a function defined in libsulibs.a and is dependent on standard pthread library.
vm#vm:~/Documents/PeriodicPacketManager/ppm$ make
(cd ../libs; make)
make[1]: Entering directory `/home/vm/Documents/PeriodicPacketManager/libs'
gcc -Wall -g -c -I . WheelTimer.c
gcc -Wall -g -c -I . threadApi.c
gcc -Wall -g -c -I . LinkedListApi.c
ar rs libsulibs.a WheelTimer.o threadApi.o LinkedListApi.o
ar: creating libsulibs.a
make[1]: Leaving directory `/home/vm/Documents/PeriodicPacketManager/libs'
gcc -g -c -I . -I ../libs -I ../ppm_client ppm.c -o ppm.o
gcc -g -c -I . -I ../libs -I ../ppm_client ppm_main.c -o ppm_main.o
(cd ../ppm_client; make)
make[1]: Entering directory `/home/vm/Documents/PeriodicPacketManager/ppm_client'
gcc -g -c -I . -I ../libs -I ../ppm ppm_pkt_enums.c -o ppm_pkt_enums.o
gcc -g -c -I . -I ../libs -I ../ppm ppm_client.c -o ppm_client.o
gcc -g -c -I . -I ../libs -I ../ppm ppm_client_sock.c -o ppm_client_sock.o
ar rs libppm_client.a ppm_pkt_enums.o ppm_client.o ppm_client_sock.o
ar: creating libppm_client.a
make[1]: Leaving directory `/home/vm/Documents/PeriodicPacketManager/ppm_client'
gcc -g -Wall ppm.o ppm_main.o -o exe -L ../libs -lsulibs -L ../ppm_client -lppm_client -lpthread
../ppm_client/libppm_client.a(ppm_client_sock.o): In function `ppm_client_init_socket':
/home/vm/Documents/PeriodicPacketManager/ppm_client/ppm_client_sock.c:138: undefined reference to `pthread_init'
collect2: error: ld returned 1 exit status
make: *** [exe] Error 1
Kindly help what am I missing here.

Woa !!
#Antti Haapalam
Changing the order of libraries worked.
In Main Makefile, i changed the order from :
${CC} ${CFLAGS} ${PPM_OBJ} -o exe -L ../libs -lsulibs -L ../ppm_client -lppm_client ${STANDARD_LIBS}
To:
${CC} ${CFLAGS} ${PPM_OBJ} -o exe -L ../ppm_client -lppm_client -L ../libs -lsulibs ${STANDARD_LIBS}
Can anyone comment the reasoning ?

Related

Getting undefined reference error from makefile

I am working on a project that uses some code written by someone else inside a folder called CommandParser. My project is called TCP_IP and inside it there is the CommandParser folder.
This is my makefile.
TARGET = $(BIN_DIR)/sim_tcp_ip
LIBS = -lpthread -L ./CommandParser -lcli
OBJS = $(OBJ_DIR)/prueba.o \
$(OBJ_DIR)/ListaEnlazada.o \
$(OBJ_DIR)/Grafico.o \
$(OBJ_DIR)/Net.o \
$(OBJ_DIR)/Topologias.o
BIN_DIR = ./bin
OBJ_DIR = ./obj
INC_DIR = ./inc
SRC_DIR = ./src
CFLAGS = -Wall -I$(INC_DIR)
$(TARGET): $(OBJS) CommandParser/libcli.a
mkdir -p $(BIN_DIR)
gcc $(CFLAGS) $(OBJS) -o $(TARGET) $(LIBS)
$(OBJ_DIR)/%.o : %.c
mkdir -p $(OBJ_DIR)
gcc -c -MD $(CFLAGS) $< -o $#
CommandParser/libcli.a:
(cd CommandParser; make)
-include $(OBJ_DIR)/*.d
.PHONY: clean
clean:
rm -rf $(OBJ_DIR) $(BIN_DIR)
(cd CommandParser; make clean)
all:
make
(cd CommandParser; make)
CommandParser has its own makefile.
CC=gcc
CFLAGS=-g -Wall
INCLUDES=-I .
CLILIB=libcli.a
TARGET:exe ${CLILIB}
OBJ=cmd_hier.o parser.o serialize.o string_util.o clistd.o clicbext.o gluethread/glthread.o ut/utinfra/ut_parser.o
exe:testapp.o ${CLILIB}
#echo "Building final executable"
# ${CC} ${CFLAGS} ${INCLUDES} testapp.o -o exe -L . -lcli -lpthread -lrt
cmd_hier.o:cmd_hier.c
#echo "Building cmd_hier.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} cmd_hier.c -o cmd_hier.o
parser.o:parser.c
#echo "Building parser.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} parser.c -o parser.o
gluethread/glthread.o:gluethread/glthread.c
#echo "Building gluethread/glthread.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} gluethread/glthread.c -o gluethread/glthread.o
serialize.o:serialize.c
#echo "Building serialize.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} serialize.c -o serialize.o
string_util.o:string_util.c
#echo "Building string_util.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} string_util.c -o string_util.o
clistd.o:clistd.c
#echo "Building clistd.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} clistd.c -o clistd.o
clicbext.o:clicbext.c
#echo "Building clicbext.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} clicbext.c -o clicbext.o
testapp.o:testapp.c
#echo "Building testapp.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} testapp.c -o testapp.o
ut/utinfra/ut_parser.o:ut/utinfra/ut_parser.c
#echo "Building ut/utinfra/ut_parser.o"
# ${CC} ${CFLAGS} -c ${INCLUDES} ut/utinfra/ut_parser.c -o ut/utinfra/ut_parser.o
${CLILIB}: ${OBJ}
#echo "Building Library ${CLILIB}"
ar rs ${CLILIB} ${OBJ}
clean:
rm -f exe
rm -f *.o
rm -f gluethread/*.o
rm -f ut/utinfra/*.o
rm -f ${CLILIB}
rm -f CMD_HIST_RECORD_FILE.txt
install:
cp ${CLILIB} /usr/local/lib/
cp libcli.h /usr/include/
cp cmdtlv.h /usr/include/
uninstall:
rm -f /usr/local/lib/${CLILIB}
rm -f /usr/include/libcli.h
rm -f /usr/include/cmdtlv.h
When do make inside CommandParser, I don't get any error. However, something seems to be wrong with my makefile because if I do make in my TCP_IP folder, I get some undefined reference errors.
/usr/bin/ld: ./CommandParser/libcli.a(ut_parser.o): en la función ut_parser_init': /home/darinel/Documentos/Cursos/C++/TCP_IP/CommandParser/ut/utinfra/ut_parser.c:52: referencia a mq_open' sin definir
/usr/bin/ld: ./CommandParser/libcli.a(ut_parser.o): en la función run_test_case': /home/darinel/Documentos/Cursos/C++/TCP_IP/CommandParser/ut/utinfra/ut_parser.c:261: referencia a mq_timedreceive' sin definir
/usr/bin/ld: ./CommandParser/libcli.a(ut_parser.o): en la función cli_out': /home/darinel/Documentos/Cursos/C++/TCP_IP/CommandParser/ut/utinfra/ut_parser.c:517: referencia a mq_send' sin definir
collect2: error: ld returned 1 exit status
make: [makefile:16: bin/sim_tcp_ip] Error 1
The message shows that these errors come from the CommandParser code, and not from my code, even though it previously worked fine in the CommandParser folder.
It appears that the CommandParser library is looking for another library, that contains functions like mq_open, mq_send, and mq_timedreceive. If you look up these functions you'll see that they're provided by the realtime library, librt. So, you need to add the -lrt option to your link line.
Also, please pay close attention to the order of libraries on the link line. You should always order them highest-level to lowest-level. You have:
LIBS = -lpthread -L ./CommandParser -lcli
but -lpthread is a lower-level library so it should come after -lcli. Also, the modern way of building executables using threads is to use the -pthread option on BOTH the compile line AND the link line, so you should use:
LIBS = -pthread -L ./CommandParser -lcli -lrt
CFLAGS = -pthread -Wall -I$(INC_DIR)

Makefile compiling and linking problems

So I've been trying to search for a solution that Im having with my make file currently. I get the error:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
So I have 5 files in my src folder: find.c, rebalance.c, remove.c, lib.c, and insert.c. In my src/bin folder I just have main.c and in another folder 'include' outside of src I have bst.h. This is what my makefile looks like:
all: static bin shared
mkdir -p build/bin
mkdir -p build/lib
mkdir -p build/objects
mv *.o build/objects
mv *.a build/lib
mv main build/bin
mv libbst.so build/lib
static:
gcc src/lib.c -c -I include
gcc src/find.c -c -I include
gcc src/insert.c -c -I include
gcc src/rebalance.c -c -I include
gcc src/remove.c -c -I include
ar rcs libbst.a find.o insert.o lib.o rebalance.o remove.o
shared:
gcc -c -o lib.o src/lib.c
gcc -c -o find.o src/find.c
gcc -c -o insert.o src/insert.c
gcc -c -o rebalance.o src/rebalance.c
gcc -c -o remove.o src/remove.c
gcc -shared -o libbst.so find.o insert.o lib.o rebalance.o remove.o
bin:
gcc src/lib.c -c -I include
gcc lib.o -o lib -lbst -L.
gcc src/bin/main.c -c -I include
gcc main.o -o main -lbst -L.
clean:
rm -rf *.so *.a *.o main build
install:
Im assuming that I'm just not using the right commands to link everything together. This always fails in the 'bin' section of the Makefile. I would really appreciate any help or advice on what I can do here, im kind of stumped right now.

how do I link a c file to two executables

I have a file called wrapsock.c that has several wrapper functions for the socket.h header file. I have two executables, FTP_client and FTP_server who both need to use the wrapsock.c file. I am having trouble with my makefile to link the wrapsock.c file to both of these programs
Here is my makefile below:
all: ./bin/FTP_client ./bin/FTP_server
bin/FTP_client: main_client.o wrapsock.o
gcc -o bin/FTP_client main_client.o wrapsock.o -lpthread -g
mv main_client.o ./bin
mv wrapsock.o ./bin
bin/FTP_server: main_server.o wrapsock.o
gcc -o bin/FTP_server main_server.o wrapsock.o -lpthread -g
mv main_server.o ./bin
mv wrapsock.o ./bin
main_client.o: src/main_client.c
gcc -c src/main_client.c -g
wrapsock.o: src/wrapsock.c src/wrapsock.h
gcc -c src/wrapsock.c -g
main_server.o: src/main_server.c
gcc -c src/main_server.c -g
clean:
rm ./bin/*.o
rm ./bin/FTP_client
rm ./bin/FTP_server
This is the error I am receiving:
gcc -c src/main_client.c -g
gcc -c src/wrapsock.c -g
gcc -o bin/FTP_client main_client.o wrapsock.o -lpthread -g
mv main_client.o ./bin
mv wrapsock.o ./bin
gcc -o bin/FTP_server main_server.o wrapsock.o -lpthread -g
gcc: error: wrapsock.o: No such file or directory
make: *** [makefile:9: bin/FTP_server] Error 1
mv wrapsock.o ./bin
gcc -o bin/FTP_server main_server.o wrapsock.o -lpthread -g
gcc: error: wrapsock.o: No such file or directory
To move the object is not a good way, create the objects directly into the directory bin as you do for the executable :
all: ./bin/FTP_client ./bin/FTP_server
bin/FTP_client: bin/main_client.o bin/wrapsock.o
gcc -o bin/FTP_client bin/main_client.o bin/wrapsock.o -lpthread -g
bin/FTP_server: bin/main_server.o bin/wrapsock.o
gcc -o bin/FTP_server bin/main_server.o bin/wrapsock.o -lpthread -g
bin/main_client.o: src/main_client.c
gcc -c src/main_client.c -g -o bin/main_client.o
bin/wrapsock.o: src/wrapsock.c src/wrapsock.h
gcc -c src/wrapsock.c -g -o bin/wrapsock.o
bin/main_server.o: src/main_server.c
gcc -c src/main_server.c -g -o bin/main_server.o
clean:
rm ./bin/*.o
rm ./bin/FTP_client
rm ./bin/FTP_server
Not sure why are you moving the binary objects to bin/, but after you've built your client target wrapsock.o is no longer in project root and resides in bin/ instead, so when server target gets its turn, gcc can no longer find it. I would just ditch the moves or if there is a reason for performing them, do so in a separate target that is done only after both binaries have been built (i.e. lists them as prerequisites).

Unable to link against BFD [duplicate]

This question already has answers here:
Trying to include a library, but keep getting 'undefined reference to' messages
(3 answers)
Closed 8 years ago.
I am trying to include this file in my project: http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html
But it requires linking against BFD. I have both binutils and binutils-devel installed. I have tried linking with -lbfd as well as directly to /usr/lib64/libbfd.so and /usr/lib64/libbfd.a (which both do exist). I also tried searching pkg-config to see if there was a different flag I should be using, but there is no reference to BFD or binutils in pkg-config.
No matter what I've tried I get the following errors:
undefined reference to 'bfd_init'
undefined reference to 'bfd_openr'
undefined reference to 'bfd_check_format'
undefined reference to 'bfd_checkformat_matches'
undefined reference to 'bfd_close'
undefined reference to 'bfd_map_over_sections'
First I am compiling my logger and the backtrace-symbols.c file I linked to above (as the logger is where I intend to use this for printing traces). Then I am linking those two object files together into a combined object file:
CC = clang
CFLAGS = -g -Wall -c
SOURCE = simplog.c
OBJ = simplog.o, simplog-temp.o, backtrace-symbols.o
all:
$(CC) $(CFLAGS) $(SOURCE); mv simplog.o simplog-temp.o; \
$(CC) -ansi $(CFLAGS) backtrace-symbols.c; \
ld -r simplog-temp.o backtrace-symbols.o -o simplog.o
clean:
rm -f $(OBJ)
Then I am linking this object file into my main project:
CC= clang++
PROG= ./bin/chiplus8
OBJS= ./src/main.o ./src/Chip8.o ./src/EmuCPU.o ./src/SimpleLogger/simplog.o
LIBS=
CXXFLAGS= -g -Wall -std=c++11 $(shell pkg-config --cflags ${LIBS})
LDFLAGS= $(shell pkg-config --static --libs ${LIBS})
all: logger $(PROG)
$(PROG): $(OBJS)
mkdir -p ./bin/
$(CC) -g -rdynamic -o $(PROG) $(LDFLAGS) -lbfd -liberty $(OBJS)
rm -f $(OBJS)
logger:
cd ./src/SimpleLogger; make clean all
clean:
rm -f $(PROG) $(OBJS)
I'm really not sure what I need to do to get this to link properly anymore. Is there something I'm missing?
Change:
$(PROG): $(OBJS)
mkdir -p ./bin/
$(CC) -g -rdynamic -o $(PROG) $(LDFLAGS) -lbfd -liberty $(OBJS)
rm -f $(OBJS)
To this:
$(PROG): $(OBJS)
mkdir -p ./bin/
$(CC) -g -rdynamic -o $(PROG) $(LDFLAGS) $(OBJS) -lbfd -liberty
rm -f $(OBJS)
Object files have to be placed before libraries with the compilation command. See this question.

Is it possible to compile svdlibc on a mac (64 bit)?

I'm trying to compile svdlibc on a 64 bit mac. Running the make file returns the error message:
main.c:1: error: CPU you selected does not support x86-64 instruction set
main.c:1: error: CPU you selected does not support x86-64 instruction set
make: *** [main.o] Error 1
Which doesn't make much sense.
The make file is:
# Linux or Windows:
CC = gcc -Wall -O4 -march=i486
# CC = icc -w1 -O3 -march=i486
# Macintosh:
ifeq ($(HOSTTYPE),powerpc)
CC = cc -pipe -O3 -Wall -fno-common -arch ppc
endif
LIBS=-lm
OBJ=svdlib.o svdutil.o las2.o
svd: Makefile main.o libsvd.a
${CC} ${CFLAGS} -o svd main.o libsvd.a ${LIBS}
mv -f $# ${HOSTTYPE}/$#
ln -s ${HOSTTYPE}/$# $#
main.o: Makefile main.c svdlib.h
${CC} ${CFLAGS} -c main.c
libsvd.a: ${HOSTTYPE} ${OBJ}
rm -f $# ${HOSTTYPE}/$#
ar cr $# ${OBJ}
ranlib $#
mv -f $# ${HOSTTYPE}/$#
ln -s ${HOSTTYPE}/$# $#
svdlib.o: Makefile svdlib.h svdlib.c
${CC} ${CFLAGS} -c svdlib.c
svdutil.o: Makefile svdutil.c svdutil.h
${CC} ${CFLAGS} -c svdutil.c
las2.o: Makefile las2.c svdlib.h svdutil.h
${CC} ${CFLAGS} -c las2.c
clean:
rm *.o
$(HOSTTYPE):
if test ! -d $(HOSTTYPE); \
then mkdir $(HOSTTYPE); fi
Editing the make file to alter the -march flag lets the compilation proceed but apparently the linking fails with:
ld: lto: could not merge in main.o because Invalid ALLOCA record for
architecture x86_64
Has anyone done this? Or is there a different svd library that I should use instead? (For large sparse matrices?)
EDIT: porneL seems to have found the problem. Changing the top line in the makefile to:
CC = gcc -Wall -O3 -march=x86-64
compilation work. Haven't tested the results yet, but looks very promising.
-O4 causes this for some reason. Use -O3 instead.
You could try with port ( http://www.macports.org/ ) it seems it s availablee :
svdlibc #1.34 (math, science)
SVDLIBC is a C library to perform singular value decomposition
Basically you ll install macports then , sudo port install svdlibc.

Resources