Makefile undefined reference to library - c

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

Related

I want to compile my code to 32 bit systems and have the following make file, how do I make it right?

So, I got this Makefile from a git repository and it compiles the source code that came with this correctly. The project is for an Operating System from scratch. This Makefile is for a 64-bit OS tutorial. I'm currently learning about 32-bit operating systems and I don't want to jump into the long mode for now. My project compiles correctly with this makefile but it never loads the kernel into memory. I think I should change the CCFLAGS = -ggdb -c -ffreestanding -target x86_64-none-elf to some other flags. How do I go about this. I already tried install i386-elf-gcc using brew but it's giving me a lot of errors. Any help would be appreciated. Thanks :)
CC = clang
GDB = gdb
LD = ld.lld
ASM = nasm
INC = -Iinc/
SRC = $(shell find . -type f -name "*.c")
ASM_SRC = $(shell find . -type f -name "*.asm")
# CRITICAL: assembly must be linked first
OBJ = ${ASM_SRC:.asm=.o} ${SRC:.c=.o}
CCFLAGS = -ggdb -c -ffreestanding -target x86_64-none-elf
LDFLAGS = -Ttext 0x8200
LDFLAGS_BIN = ${LDFLAGS} --oformat binary
LDFLAGS_ELF = ${LDFLAGS} --oformat binary --entry main
ASFLAGS = -f elf64
all: kernel kernel.elf
kernel: ${OBJ}
#${LD} -o $# ${LDFLAGS_BIN} $^
kernel.elf: ${OBJ}
#${LD} -o $# ${LDFLAGS_ELF} $^
%.o: %.c
#${CC} ${CCFLAGS} ${INC} -o $# $^
%.o: %.asm
#${ASM} $< ${ASFLAGS} -o $#
clean:
#rm -f kernel kernel.elf *.o **/*.o

How to include .h with makefile in linux?

I am writing software for ARM microcontrollers in C using linux and I'm not using an IDE. The reason for this is to learn how really low level stuff works. Now I want to include a .h file that has a corresponding .c file, in my main.c program the "usual way" by writing #include "timer.h". This of course requires me to somehow change the Makefile and or linkerscript!?
How can I do this?
Right now the file timer.h is included, but directly in the Makefile like this:
LD=arm-none-eabi-gcc
OBJCOPY=arm-none-eabi-objcopy
CFLAGS=-mcpu=cortex-m3 -mthumb -g -std=c99 -Wall
LDFLAGS=-mcpu=cortex-m3 -mthumb -g -lgcc -lc -lcs3 -lcs3unhosted -lefm32gg -Llib
ASFLAGS=-mcpu=cortex-m3 -mthumb -g
LINKERSCRIPT=lib/efm32gg.ld
polling.bin : polling.elf
${OBJCOPY} -O binary $< $#
polling.elf : polling.o timer.o dac.o gpio.o interrupt_handlers.o
${LD} -T ${LINKERSCRIPT} $^ -o $# ${LDFLAGS}
%.o : %.c
${CC} ${CFLAGS} -c $< -o $#
.PHONY : pretty
pretty :
-indent *.c *.h
.PHONY : upload
upload :
-eACommander.sh -r --address 0x00000000 -f "polling.bin" -r
.PHONY : clean
clean :
-rm -rf *.o *.elf *.bin *.hex

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.

Adapt Makefile for cross-compilation

I have a makefile that works fine when I compile using /usr/bin/gcc to compile it. However I'm trying to compile it using a crosstool-ng compiler. I've changed CC to the cross-compilers location, and added a prefix to the directory that holds the compiler, but I get an error compiling.
The Makefile is here (sorry, it's long):
CFLAGS ?= -Wall -O0 -ggdb3
PREFIX = /home/me/crosstool-ng-1.18.0/x-tools/i586-system-linux-gnu/
CC = /home/me/crosstool-ng-1.18.0/x-tools/i586-system-linux-gnu/bin/i586-system-linux-gnu-gcc
ALL_CFLAGS = $(CFLAGS) -D_GNU_SOURCE
.phony: all
all: food libfood.so.1.0.0 foo_query
.phony: tools
tool tools: libfood_print foo_print
.phony: install
install: libfood.so.1.0.0
cp libfood.so.1.0.0 $(PREFIX)/lib
cd $(PREFIX)/lib ; \
ln -sf libfood.so.1.0.0 libfood.so.1 ; \
ln -sf libfood.so.1 libfood.so
cp libfood.h $(PREFIX)/include
cp foo_data.h $(PREFIX)/include
cp food $(PREFIX)/bin
cp foo_query $(PREFIX)/bin
%.o: %.c
$(CC) $(ALL_CFLAGS) -c $<
food: food.o foo.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lm -lpthread
libfood.so.1.0.0: libfood.o
$(CC) -shared -Wl,-soname,libfood.so.1 -o libfood.so.1.0.0 libfood.o
libfood_print: libfood_print.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lfood
foo_print: foo_print.o foo.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lm -lpthread
foo_query: foo_query.o
$(CC) $(ALL_CFLAGS) -o $# $^ -lfood
food.o: food.c foo.h foo_data.h
foo.o: foo.c foo.h foo_data.h
foo_print.o: foo_print.c foo_data.h
foo_query.o: foo_query.c foo_data.h
libfood.o: libfood.c libfood.h
$(CC) $(ALL_CFLAGS) -fPIC -c $<
foo_print.o: foo_print.c foo.h
.phony:clean
clean:
rm -rf *.o *~ food libfood.so.1.0.0 foo_print libfood_print foo_query
The error message I'm getting says cannot find -lfood
collect2: ld returned 1 exit status
If anyone could suggest a fix for this I'd be very grateful.
EDIT: My Solution:
I should probably have been clearer but this Makefile was being used to build a package that was included in buildroot. I tried the suggestion by Jonatan, but unfortunately I still got the same error. My workaround was to run buildroot using make -k, and then build again using make.
An easy way to solve this would be:
ALL_CFLAGS += -L$(PREFIX)/lib
If you really want to install your lib in the toolchain, you should look for the usr/lib directory, usually the path is TOOLCHAIN_DIR/TOOLCHAIN_PREFIX/sysroot/usr/lib
Check other binaries in the $(PREFIX)/lib directory, you will notice that they were compile to run in you host, and not in your target.
The files the compiler need to check dependencies, link, and execute in your target, are installed in the sysroot directory.

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