Makefile compiling and linking problems - c

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.

Related

AVR GCC - Use static library - undefined reference errors

I'm currently trying to read values from a temperature sensor (Dallas ds18b20) with an AVR atmega328p. In order to read values, I need to import an external library (using this one). I have used the Makefile in the external repository to create a static library (libds18b20.a in lib directory). I also added the header files to my own source. I have the following Makefile:
PORT_ID=/dev/ttyACM0
MCU=atmega328p
F_CPU=1200000
CC=avr-gcc
PROGRAMMER_ID=stk500v1
OBJCOPY=avr-objcopy
CFLAGS=-std=c99 -Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I.
TARGET=main
SRCS=main.c
BAUD_RATE=19200
PATH_DS18B20=./lib
all:
${CC} -L ${PATH_DS18B20} ${CFLAGS} -o ${TARGET}.bin ${SRCS}
${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.bin ${TARGET}.hex
flash:
avrdude -v -P ${PORT_ID} -b ${BAUD_RATE} -c ${PROGRAMMER_ID} -p ${MCU} -U flash:w:${TARGET}.hex
clean:
rm -f *.bin *.hex
However, when I try to run this Makefile I got the following errors (output partially omitted):
/main.c:(.text.startup+0x2e): undefined reference to `ds18b20convert'
/main.c:60: undefined reference to `ds18b20read'
These functions are defined in the headers files. I'm expecting that the static library is not properly linked. What am I doing wrong here?
I managed to get this working by omitting the -L flag and put the path directly behind the ${SRCS}-variable including the name of the static library:
PORT_ID=/dev/ttyACM0
MCU=atmega328p
F_CPU=1200000
CC=avr-gcc
PROGRAMMER_ID=stk500v1
OBJCOPY=avr-objcopy
CFLAGS=-std=c99 -Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I.
TARGET=main
SRCS=main.c
BAUD_RATE=19200
PATH_DS18B20=./lib/libds18b20.a
all:
${CC} ${CFLAGS} -o ${TARGET}.bin ${SRCS} ${PATH_DS18B20}
${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.bin ${TARGET}.hex
flash:
avrdude -v -P ${PORT_ID} -b ${BAUD_RATE} -c ${PROGRAMMER_ID} -p ${MCU} -U flash:w:${TARGET}.hex
clean:
rm -f *.bin *.hex

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).

Linking multiple C libraries to C create executable [duplicate]

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 ?

Makefile undefined reference to library

I know this is a very common question, but no matter where I looked I couldn't find a solution that worked.
I am writing an OS, and am also writing my own version of the c standard library, purely as a general interest type thing. I have my c standard library, which currently consists only of an incomplete string.h, in the sb_libc folder in the kernel's main directory. I can't use make to actually make the kernel if it includes my string.h header. I keep getting "undefined reference to strcpy". In order to test if I could include anything, I wrote two additional files, io.c and io_asm.s, and put their *.o files into the kernel's main directory. I can link those with the kernel just fine. Clearly, my library search paths are wrong in my make file. I'll post it below. If anyone can give me an idea on what I'm doing wrong, that would be great.
OBJECTS = loader.o io.o io_asm.o kmain.o ./sb_libc/string.o
CC = gcc
CFLAGS = -e kmain -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror -c -I./sb_libc/ -L./sb_libc/
LDFLAGS = -T link.ld -melf_i386 -I./sb_libc/ -L./sb_libc/
AS = nasm
ASFLAGS = -f elf
all: kernel.elf
kernel.elf: $(OBJECTS)
ld $(LDFLAGS) $(OBJECTS) -o kernel.elf
os.iso: kernel.elf
cp kernel.elf iso/boot/kernel.elf
genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -A os -input-charset utf8 -quiet -boot-info-table -o os.iso iso
run: os.iso
bochs -f bochsrc.txt -q
%.o: %.c
$(CC) $(CFLAGS) $< -o $#
%.o: %.s
$(AS) $(ASFLAGS) $< -o $#
clean:
rm -rf *.o kernel.elf os.iso

How to link files in different folders produced by calling multiple make files?

I have the following make file
all: XmlNode.o y.tab.o y.tab.o lex.yy.o
gcc -g -o prog y.tab.o lex.yy.o XmlAttributeNode.o XmlNode.o -ll -ly -lm
XmlNode.o:
cd XmlNode; make
y.tab.o: y.tab.c
gcc -g -c y.tab.c
lex.yy.o: lex.yy.c
gcc -g -c lex.yy.c
y.tab.c: LexYacc/prog1.y
bison -y -dv LexYacc/prog1.y
lex.yy.c: LexYacc/prog1.l
lex -l LexYacc/prog1.l
clean:
rm -f y.tab.* lex.yy.* *.o prog
XmlAttributeNode.o and XmlNode.o are made in the XmlNode folder, thus I get the error
gcc: XmlAttributeNode.o: No such file or directory
gcc: XmlNode.o: No such file or directory
I looked at the following questions 1, 2, and 3, but I can't seem to find how I can get a list of all the .o files produced by XmlNode.o so 1) I don't have to type them by hand and 2) the proper path is included so gcc can find the .o files. So something like this:
XmlNode.o:
cd XmlNode; XmlNodeList = .o files from this make; XmlPath = `pwd`;
and then:
all: XmlNode.o y.tab.o y.tab.o lex.yy.o
gcc -g -o prog y.tab.o lex.yy.o XmlPath/XmlNodeList -ll -ly -lm
Any help would be appreciated.
Assuming the info in the comments, this will at least work.
all: XmlNode.o y.tab.o y.tab.o lex.yy.o
gcc -g -o prog y.tab.o lex.yy.o XmlNode/XmlAttributeNode.o XmlNode/XmlNode.o -ll -ly -lm
XmlNode/XmlAttributeNode.o XmlNode/XmlNode.o:
cd XmlNode; make
y.tab.o: y.tab.c
gcc -g -c y.tab.c
lex.yy.o: lex.yy.c
gcc -g -c lex.yy.c
y.tab.c: LexYacc/prog1.y
bison -y -dv LexYacc/prog1.y
lex.yy.c: LexYacc/prog1.l
lex -l LexYacc/prog1.l
clean:
rm -f y.tab.* lex.yy.* *.o prog; cd XmlNode; make clean

Resources