Makfile, undefined reference to `main' - makefile

I'm writing my first Makefile for a AVR-project and ran into some problems. It says "undefined reference to `main'" the first time that I execute "make" but spits out all object files and a main.map file. The next time I execute "make" it completes the compilation and also spits out the main.elf and main.hex files.
As I mentioned, I'm new to this but something tells me that it's a linking problem. I have searched for similar posts but haven't found any solution so any help is appreciated.
I have a project folder where the Makefile is and in the project folder a src folder and a header folder exists where the .c files and .h are located.
Here follows the Makefile:
SOURCE_FILES=$(wildcard src/*)
OBJECT_FILES=$(patsubst %.c,%.o,$(SOURCE_FILES))
INCLUDE_PATH=headers/
MCU=atmega328p
CFLAGS=-g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues
hex : elf
avr-size main.elf
avr-objcopy -R .eeprom -O ihex main.elf main.hex
elf : object
avr-gcc $(CFLAGS) -o main.elf -Wl,-Map,main.map $(wildcard *.o)
object : $(SOURCE_FILES)
avr-gcc $(CFLAGS) -Os -c $(SOURCE_FILES) -I$(INCLUDE_PATH)
load: main.hex
avrdude -c arduino -p m328p -P /dev/ttyACM0 -D -U flash:w:main.hex
clean:
rm *.o *.hex *.map *.elf
EDIT:
The output after the first make:
avr-gcc -g -mmcu=atmega328p -Wall -Wstrict-prototypes -Os -mcall-prologues -o main.elf -Wl,-Map,main.map
/usr/lib/gcc/avr/4.8.2/../../../avr/lib/avr5/crtm328p.o: In function `__bad_interrupt':
../../../../crt1/gcrt1.S:195: undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [elf] Error 1
The output after the second make:
avr-gcc -g -mmcu=atmega328p -Wall -Wstrict-prototypes -Os -mcall-prologues -o main.elf -Wl,-Map,main.map Car.o main.o TinyTimber.o
avr-size main.elf
text data bss dec hex filename
7046 8 855 7909 1ee5 main.elf
avr-objcopy -R .eeprom -O ihex main.elf main.hex

Related

How do I link a archive file with C code?

I'm trying to link a static library archive file (libx/libx.a) with a C code. The library requires 2 flags (-lx -lpthread). After linking the static library my ultimate goal is to create a shared library. I have the following Make file,
rsa-engine: rsa/rsa.c rsa/bignum.c rsa/aes.c rsa/x509parse.c rsa/pem.c
gcc -fPIC -o rsa/rsa.o -c rsa/rsa.c
gcc -fPIC -o rsa/bignum.o -c rsa/bignum.c
gcc -fPIC -o rsa/aes.o -c rsa/aes.c
gcc -fPIC -o rsa/x509parse.o -c rsa/x509parse.c
gcc -fPIC -o rsa/pem.o -c rsa/pem.c
gcc -fPIC rsa-engine.c libx/libx.a -L.libx/ -lx -lpthread -o rsa-engine.o
gcc -shared -o librsa_engine.so -lcrypto rsa-engine.o rsa/rsa.o rsa/bignum.o rsa/aes.o rsa/x509parse.o rsa/pem.o
clean:
rm -f *.o rsa/*.o *.so rsa-engine
After using the make command it produces the following output,
/usr/bin/ld: cannot find -lx
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'rsa-engine' failed
make: *** [rsa-engine] Error 1
I found similar questions here. But that did not help. Seems like I can't make the link work. Any help with what I'm doing wrong?
I would like to achieve the same result generated by the following command,
CC := gcc
CFLAGS := -Wall -g -MD -O2 -I ../
LDFLAGS := -lx -lpthread
tests_files := hello
all: $(tests_files)
hello: hello.o ../libx/libx.a
$(CC) $(CFLAGS) -static $(<) -L../libx/ $(LDFLAGS) -o $(#)
It seems that your libx.a is located in libx, yet -L references .libx directory. Anyway, since you reference libx/libx.a directly, you may skip both -L.libx/ -lx and it should link just fine.

script-file Not found by linker

when running a makefile, which includes a usage of
a script-file, I receive an error saying the linker doesn't find the script file.
When running the make file the output is as follows:
arm-none-eabi-gcc -g -Wall -Werror -c -o main.o main.c
arm-none-eabi-gcc -g -Wall -Werror -c -o misc.o misc.c
arm-none-eabi-gcc main.o misc.o misc.h -g -Wall -Werror -Wl,-Map=HOST.map -T=msp432p401r.lds -o HOST
/usr/lib/gcc/arm-none-eabi/9.2.1/../../../arm-none-eabi/bin/ld: cannot open linker script file =msp432p401r.lds: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:11: HOST] Error 1
The makefile content is:
#---- Variables (machine depending) --------
TARGET = HOST
CC = arm-none-eabi-gcc #gcc
CFLAGS = -g -Wall -Werror # compiler flags
LDFLAGS = -Wl,-Map=$(TARGET).map -T=msp432p401r.lds # linker flag
SOURCE = main.c misc.c misc.h
OBJS = $(SOURCE:.c=.o) # replace all c with o
#---- Targets -----------
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(CFLAGS) $(LDFLAGS) -o $#
I have searched a lot for a solution for this issue, and tried various fixes, with no success.
The script file is located at the same location as the source files.
What can be the reason for not finding the file?
Thanks

arm-eabi-none undefined reference to memset error for LPC2148

Whenever I try to use any array parameters I'm getting the memset() error. Also, I cant use sprintf() statement even after including standard libraries, what are the parameters should I include in the makefile to link or fix this memset() and sprintf() reference error.
memset() error full code with lpc214x linker file
My target board is LPC2148(arm7-TDMA based)
here is the Makefile
ARMGNU ?= arm-none-eabi
COPS = -Wall -nostdlib -nostartfiles -ffreestanding
all : main.hex main.bin main.elf
clean :
rm -f *.o
rm -f *.bin
rm -f *.hex
rm -f *.elf
crt0.o : crt0.S
$(ARMGNU)-gcc -c crt0.S
main.o : main.c
$(ARMGNU)-gcc $(COPS) -c main.c -o main.o
main.elf : lpc2148.ld crt0.o main.o
$(ARMGNU)-ld crt0.o main.o -T lpc2148.ld -o main.elf
main.bin : main.elf
$(ARMGNU)-objcopy main.elf -O binary main.bin
main.hex : main.elf
$(ARMGNU)-objcopy main.elf -O ihex main.hex
The issue is that you are using arm-none-eabi-ld during linking operation which is unable to link to standard libgcc for the target processor.
Please modify the Makefile and use arm-none-eabi-gcc to link your various object files.
As, you are using a custom startup file you also need to pass -nostartfiles option to linker.
The modified Makefile is below:
all : main.hex main.bin main.elf
clean :
rm -f *.o
rm -f *.bin
rm -f *.hex
rm -f *.elf
crt0.o : crt0.S
$(ARMGNU)-gcc -c crt0.S
main.o : main.c
$(ARMGNU)-gcc $(COPS) -c main.c -o main.o
main.elf : lpc2148.ld crt0.o main.o
$(ARMGNU)-gcc crt0.o main.o -T lpc2148.ld -o main.elf -nostartfiles
main.bin : main.elf
$(ARMGNU)-objcopy main.elf -O binary main.bin
main.hex : main.elf
$(ARMGNU)-objcopy main.elf -O ihex main.hex

Makefile linking: undefined reference to _exit

I have been trying to create a neatly-organized makefile project template utilizing the ARM mbed library. I have already solved a few of the problems (see this post) related to header file paths. However, now I am having problems with the linker. My goal is to have sources and headers in src, object files in obj, and the final binaries in either debug or release.
Here is the error I am getting...
make
arm-none-eabi-g++ -DTARGET_M4 -DMBED_BUILD_TIMESTAMP=1453683815.81 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_FF_ARDUINO -DTARGET_STM32F446RE -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4 -std=c++98 -fno-rtti -I lib/ -I lib/mbed/ -I lib/mbed/TARGET_NUCLEO_F446RE/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/ -I lib/mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/ -I lib/mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE/ -o obj/main.o src/main.cc
/usr/lib/gcc/arm-none-eabi/6.1.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
make: *** [makefile:54: obj/main.o] Error 1
This is my makefile. I have denoted where the problem(s) might be, but I am not sure.
#Project parameters
PROJECT = Nucleo_blink
OBJECTS = obj/main.o
DEST = debug
VPATH = src lib $DEST
TARGET = NUCLEO_F446RE
#Compilation options
DEBUG = 1
#Tools
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CXX = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
include $(TARGET).mk
CFLAGS = $(INCLUDE_PATHS) $(CC_SYMBOLS) $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -O0
else
CFLAGS += -DNDEBUG -Os
endif
#MY PROBLEM MAY BE HERE
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
#`-u _printf_float -u _scanf_float` after -specs for floating point I/O
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
LIBRARIES = -lmbed
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex
clean:
rm -f debug/* obj/* asm/* $(DEPS)
obj/%.o: %.c
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=c99 $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.cc
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.cpp
$(CXX) $(CC_FLAGS) $(CC_SYMBOLS) -std=c++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
obj/%.o: %.asm
$(CC) $(CPU) -c -x assembler-with-cpp -o asm/$# $<
#OR HERE
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $(DEST)/$# $^ $(LIBRARIES) $(LD_SYS_LIBS) $(LIBRARIES) $(LD_SYS_LIBS)
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $#
$(PROJECT).hex: $(PROJECT).elf
#$(OBJCOPY) -O ihex $< $#
$(PROJECT).lst: $(PROJECT).elf
#$(OBJDUMP) -Sdh $< > $#
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
Before you ask, I have already tried changing --specs=nano.specs to --specs=nosys.specs. It does nothing. The strange part is that the linker settings above work fine for the automatically generated mbed makefile.
Here is the working makefile. It compiles without errors...
# This file was automagically generated by mbed.org. For more information,
# see http://mbed.org/handbook/Exporting-to-GCC-ARM-Embedded
GCC_BIN =
PROJECT = Nucleo_blink
OBJECTS = ./source/main.o
SYS_OBJECTS = #Long list of object files
INCLUDE_PATHS = -I. -I./source -I./mbed -I./mbed/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4 -I./mbed/TARGET_NUCLEO_F446RE/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F446RE -I./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARY_PATHS = -L./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM
LIBRARIES = -lmbed
LINKER_SCRIPT = ./mbed/TARGET_NUCLEO_F446RE/TOOLCHAIN_GCC_ARM/STM32F446XE.ld
###############################################################################
AS = $(GCC_BIN)arm-none-eabi-as
CC = $(GCC_BIN)arm-none-eabi-gcc
CPP = $(GCC_BIN)arm-none-eabi-g++
LD = $(GCC_BIN)arm-none-eabi-gcc
OBJCOPY = $(GCC_BIN)arm-none-eabi-objcopy
OBJDUMP = $(GCC_BIN)arm-none-eabi-objdump
SIZE = $(GCC_BIN)arm-none-eabi-size
ifeq ($(HARDFP),1)
FLOAT_ABI = hard
else
FLOAT_ABI = softfp
endif
CPU = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=$(FLOAT_ABI)
CC_FLAGS = $(CPU) -c -g -fno-common -fmessage-length=0 -Wall -Wextra -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
CC_SYMBOLS = -DTARGET_M4 -DTARGET_FF_ARDUINO -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -DTARGET_RTOS_M4_M7 -DTARGET_FF_MORPHO -DTARGET_LIKE_MBED -DTARGET_CORTEX_M -D__FPU_PRESENT=1 -DTARGET_LIKE_CORTEX_M4 -DTARGET_NUCLEO_F446RE -D__MBED__=1 -DTARGET_STM -DMBED_BUILD_TIMESTAMP=1468213384.59 -DTARGET_STM32F446RE -DTARGET_STM32F4 -D__CORTEX_M4 -DARM_MATH_CM4
#My makefile above copies these two lines
LD_FLAGS = $(CPU) -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float -Wl,--wrap,main -Wl,-Map=$(PROJECT).map,--cref
LD_SYS_LIBS = -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
ifeq ($(DEBUG), 1)
CC_FLAGS += -DDEBUG -O0
else
CC_FLAGS += -DNDEBUG -Os
endif
.PHONY: all clean lst size
all: $(PROJECT).bin $(PROJECT).hex size
clean:
rm -f $(PROJECT).bin $(PROJECT).elf $(PROJECT).hex $(PROJECT).map $(PROJECT).lst $(OBJECTS) $(DEPS)
.asm.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.s.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.S.o:
$(CC) $(CPU) -c -x assembler-with-cpp -o $# $<
.c.o:
$(CC) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu99 $(INCLUDE_PATHS) -o $# $<
.cpp.o:
$(CPP) $(CC_FLAGS) $(CC_SYMBOLS) -std=gnu++98 -fno-rtti $(INCLUDE_PATHS) -o $# $<
$(PROJECT).elf: $(OBJECTS) $(SYS_OBJECTS)
$(LD) $(LD_FLAGS) -T$(LINKER_SCRIPT) $(LIBRARY_PATHS) -o $# $^ -Wl,--start-group $(LIBRARIES) $(LD_SYS_LIBS) -Wl,--end-group
$(PROJECT).bin: $(PROJECT).elf
$(OBJCOPY) -O binary $< $#
$(PROJECT).hex: $(PROJECT).elf
#$(OBJCOPY) -O ihex $< $#
$(PROJECT).lst: $(PROJECT).elf
#$(OBJDUMP) -Sdh $< > $#
lst: $(PROJECT).lst
size: $(PROJECT).elf
$(SIZE) $(PROJECT).elf
DEPS = $(OBJECTS:.o=.d) $(SYS_OBJECTS:.o=.d)
-include $(DEPS)
I think my problem is some sort of path error...
- The _exit symbol may be defined, but inaccessible by main.o
- There may be some major error in the makefile I'm missing
- Something totally different?
Feel free to comment any suggested changes to this question.
EDIT: All I had to do to fix the error was change CFLAGS to CCFLAGS. The answer I marked as the solution explained what was happening, and a potential way to fix it. Although I didn't need to use the suggested solution, the explanation of why it wasn't working is useful, and the information provided by both answers is useful.
Adding --specs=nosys.specs to your linker options may also solve this issue.
You can see exactly what this does by looking at the nosys.specs file which will be somewhere in your compiler directory.
See also: exit.c:(.text+0x18): undefined reference to `_exit' when using arm-none-eabi-gcc
_exit is a system call, as well as some other functions you probably will need later. When you compile a binary for (for example) Linux, these calls are serviced by the operating system. In bare-metal embedded project you need to define these functions by yourself. The common way is to create a file called syscalls.c or something like that and put all needed system calls there. Take a look at example of such file, rapidly found by google: https://github.com/bjornfor/stm32-test/blob/master/STM32L1xx_StdPeriph_Lib_V1.1.1/syscalls.c
As a bonus, if you properly implement _read and _write to work with UART, you will get a serial console capable to do formatted IO via printf and scanf .
The _exit symbol may be defined, but inaccessible by main.o - There may be some major error in the makefile I'm missing - Something totally different?
This happens when a call to a standard library method indirectly has a dependency on exit(). Often from automatically generated exception unwind code that's supposed to abort your process on exit, which obviously has different semantics in a bare metal application. The division-by-zero floating point exception is one such example. -fno-exceptions does not help with this.
You can of course supply a do-nothing exit() handler but your code would be smaller if the exception unwind code didn't get inserted in the first place.
I discovered by examining the generated assembler that you can replace the exception handlers with do-nothing versions like this in a compilation unit:
extern "C" void __wrap___aeabi_unwind_cpp_pr0() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr1() {}
extern "C" void __wrap___aeabi_unwind_cpp_pr2() {}
and then link those in as replacements at link time with these additional linker arguments.
-Wl,-wrap,__aeabi_unwind_cpp_pr0,
-Wl,-wrap,__aeabi_unwind_cpp_pr1
-Wl,-wrap,__aeabi_unwind_cpp_pr2
Another benefit is that your code should shrink as a result. You may even want to insert your own implementations that reset the MCU.
For me it took both -fno-exceptions and --specs=nosys.specs in compiler flags.
It seems like you use stdlib. System cal exit(int) calls in-system function _exit(int).
For me decision was applying -nostdlib option because I wasn't going to use stdlib.
Thanks, UserHuman, https://stackoverflow.com/a/51657692/8313090

Gcc /usr/bin/ld compiler error

I got this error when I do make
gcc -o tests/simple_test tests/simple_test.o -L. libtraceback.a -Wall -Werror -gdwarf-2 -O0 -m32 -fno-stack-protector -fno-omit-frame-pointer -Itraceback/ -mpreferred-stack-boundary=2 -static
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_eh.a when searching for -lgcc_eh
/usr/bin/ld: cannot find -lgcc_eh
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
I read one post and tried
sudo ln -s /usr/lib/x86_64-linux-gnu /usr/lib64
But it doesn't help, is there any reason for this?
Im running on a surface pro 2 using vmware running 64bits ubuntu 13.10.
If you do not have any parcticular reason to build a 32bit application on a 64bit machine just do not use the option -m32.
In case you are following this tutorial then fixed make file code is below working on Ubuntu 20
# $# = target file
# $< = first dependency
# $^ = all dependencies
# First rule is the one executed when no parameters are fed to the Makefile
all: run
kernel.bin: kernel-entry.o kernel.o
ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary --entry main
kernel-entry.o: kernel-entry.asm
nasm $< -f elf -o $#
kernel.o: kernel.c
gcc -m32 -ffreestanding -c $< -o $# -fno-pie
mbr.bin: mbr.asm
nasm $< -f bin -o $#
os-image.bin: mbr.bin kernel.bin
cat $^ > $#
run: os-image.bin
qemu-system-i386 -fda $<
clean:
$(RM) *.bin *.o *.dis
To run make file
make run
to clean all output files
make clean

Resources