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
Related
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.
i stumbled upon a Makefile that look weird i couldn't understand it
here is the that Makefile
AS=as -32 -Iinclude
LD=ld -m elf_i386
CC=gcc -m32 -fno-pie -fno-stack-protector
CPP=gcc -E -nostdinc -Iinclude
CFLAGS=-W -nostdlib -Wno-long-long -I include -fomit-frame-pointer
.s.o:
${AS} -a $< -o $*.o >$*.map
all: boot setup
boot: boot.o
${LD} --oformat binary -N -e start -Ttext 0x0000 -o boot $<
setup: setup.o
${LD} --oformat binary -N -e start -Ttext 0x0000 -o setup $<
clean:
rm -f boot setup *.o *.map
the part that i didn't understand is this
.s.o:
${AS} -a $< -o $*.o >$*.map
what is the significance of .s.o in this case
and what this $*.o >$*.map trying to do.
.s.o: is a suffix rule that exists for compatibility with old versions of make. It is the same as the pattern rule %.o : %.s . $* is an automatic make variable containing the base of the source file name (in this case the filename without the extension .o).
The command generated for processing boot.s to boot.o would be:
as -32 -Iinclude -a boot.s -o boot.o >boot.map
GNU Assembler(AS) option -a generates a listing file to standard output. Standard output is being redirected by the *nix shell (via >) to a file name ending in .map. The end result in this example is that boot.s will be assembled to an object file called boot.o and standard output will be written to the file boot.map
Note: I personally would have redirected standard output to a file name with the extension .lst rather than the .map extension.
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 ?
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
I have created a (very simple) makefile:
DEBUG = -DDEBUG
main: main.c add.c
gcc $(DEBUG) main.c add.c -o main -lm
What I want (and don't understand how to do), is to create the makefile so that if the user prints make debug, the code will compile with the debug option, but when printing only make, the debug will be left out. What is the best way to do this?
You probably are looking for something like
main: main.c add.c
gcc $(DEBUG) main.c add.c -o main -lm
debug: DEBUG = -DDEBUG
debug: main
This may be late, ...
The basic idea is to build all objects in the subdirectory, say ./build.
We create a release file in ./build when we compile with make and create a debug file when make debug. So if there is a release file when make debug, remove everything in ./build and then build.
all: $(BD)/release $(bin1) $(bin2)
debug: CFLAGS += -g -DDEBUG=1
debug: CXXFLAGS += -g -DDEBUG=1
debug: $(BD)/debug $(bin1) $(bin2)
$(BD)/%.o: %.c Makefile # changes in Makefile will cause a rebuild
#mkdir -p $(BD)
$(CC) $(CFLAGS) -c -o $# $<
$(BD)/%.o: %.cpp Makefile
#mkdir -p $(BD)
$(CXX) $(CXXFLAGS) -c -o $# $<
$(BD)/release:
#if [ -e $(BD)/debug ]; then rm -rf $(BD); fi
#mkdir -p $(BD)
#touch $(BD)/release
$(BD)/debug:
#if [ -e $(BD)/release ]; then rm -rf $(BD); fi
#mkdir -p $(BD)
#touch $(BD)/debug
I came up with this solution, that depends on bash variable substitution.
Makefile:
main: main.c add.c
${CC} `echo $${DEBUG+-DDEBUG}` main.c add.c -o main -lm
When environment variable DEBUG is defined to anything (even blank), this makefile will substitute the -DDEBUG useful to the compiler. So invocation looks like:
DEBUG=1 make main