avr-gcc undefined reference to function in linked object file - c

I have some code for handling all uart related functions and operations in a .h/.c pair that I usually include in my project. I have a makefile that compiles all of my .c files into .o files then links them all to one executable. For some reason, one of my projects using this pair compiles fine but the other gives this error:
obj/fiveax.o: In function `fiveax_init':
fiveax.c:(.text+0x10): undefined reference to `uart_init'
collect2: error: ld returned 1 exit status
when trying to link to the exectutable after compiling all the .o files. I have included my makefile below, it is the same for both projects with the only difference being the appname.
Makefile
########################################################################
####################### Makefile Template ##############################
########################################################################
# Compiler settings - Can be customized.
CC = avr-gcc
CXXFLAGS = -mmcu=atmega2560 -D BUILD=1
LDFLAGS = -Iinclude -Ilibs/FreeRTOS/include -Llibs/FreeRTOS -lfreertos
DEV = /dev/ttyUSB0
AVRCONF = -C/etc/avrdude.conf
AVRLOAD = $(AVRCONF) -v -patmega2560 -carduino -P$(DEV) -b57600 -D -Uflash:w:bin/$(APPNAME).hex:i
# Makefile settings - Can be customized.
APPNAME = FiveAx
EXT = .c
SRCDIR = src
OBJDIR = obj
INCDIR = include
DEPDIR = dep
############## Do not change anything from here downwards! #############
SRC = $(wildcard $(SRCDIR)/*$(EXT))
OBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)/%.o)
DEP = $(OBJ:$(OBJDIR)/%.o=$(DEPDIR)/%.d)
# UNIX-based OS variables & settings
RM = rm
DELOBJ = $(OBJ)
# Windows OS variables & settings
DEL = del
EXE = .exe
WDELOBJ = $(SRC:$(SRCDIR)/%$(EXT)=$(OBJDIR)\\%.o)
########################################################################
####################### Targets beginning here #########################
########################################################################
all: bin $(APPNAME)
# Builds the app
$(APPNAME): $(OBJ)
$(CC) $(CXXFLAGS) -o bin/$#.elf $^ $(LDFLAGS)
avr-objcopy -j .text -j .data -O ihex bin/$(APPNAME).elf bin/$(APPNAME).hex
bin:
mkdir -p $#
# Creates the dependecy rules
$(DEPDIR)/%.d: $(SRCDIR)/%$(EXT)
#$(CPP) $(CFLAGS) $< -MM -MT $(#:$(DEPDIR)/%.d=$(OBJDIR)/%.o) >$# $(LDFLAGS)
# Includes all .h files
-include $(DEP)
# Building rule for .o files and its .c/.cpp in combination with all .h
$(OBJDIR)/%.o: $(SRCDIR)/%$(EXT)
$(CC) $(CXXFLAGS) -o $# -c $< $(LDFLAGS)
load: bin $(APPNAME)
avrdude $(AVRLOAD)
################### Cleaning rules for Unix-based OS ###################
# Cleans complete project
.PHONY: clean
clean:
$(RM) -r $(DELOBJ) $(DEP) bin
# Cleans only all files with the extension .d
.PHONY: cleandep
cleandep:
$(RM) $(DEP)
edit: I have included the header file for uart.h in the source file.
edit: I was asked for the output of the makefile
avr-gcc -mmcu=atmega2560 -D BUILD=1 -Iinclude -Ilibs/FreeRTOS/include -o obj/uart.o -c src/uart.c -Llibs/FreeRTOS -lfreertos
avr-gcc -mmcu=atmega2560 -D BUILD=1 -Iinclude -Ilibs/FreeRTOS/include -o obj/servo.o -c src/servo.c -Llibs/FreeRTOS -lfreertos
avr-gcc -mmcu=atmega2560 -D BUILD=1 -Iinclude -Ilibs/FreeRTOS/include -o obj/main.o -c src/main.c -Llibs/FreeRTOS -lfreertos
avr-gcc -mmcu=atmega2560 -D BUILD=1 -Iinclude -Ilibs/FreeRTOS/include -o obj/fiveax.o -c src/fiveax.c -Llibs/FreeRTOS -lfreertos
avr-gcc -mmcu=atmega2560 -D BUILD=1 -Iinclude -Ilibs/FreeRTOS/include -o bin/FiveAx.elf obj/uart.o obj/servo.o obj/main.o obj/fiveax.o
obj/fiveax.o: In function `fiveax_init':
fiveax.c:(.text+0x10): undefined reference to `uart_init'
collect2: error: ld returned 1 exit status
make: *** [Makefile:41: FiveAx] Error 1

It's impossible to read the information requested because it's not formatted as a code block so all the lines run together. Please use the live preview feature of the SO question editor to check that the content you're adding is readable, to save the sanity of the people trying to help you.
The link line appears to be this:
avr-gcc -mmcu=atmega2560 -D BUILD=1 -Iinclude -Ilibs/FreeRTOS/include -o bin/FiveAx.elf obj/uart.o obj/servo.o obj/main.o obj/fiveax.o
Here we can see that the library -lfreertos is not present, and also that all the object files come at the end after the flags. I don't see how this could have happened given the makefile you show above:
CXXFLAGS = -mmcu=atmega2560 -D BUILD=1
LDFLAGS = -Iinclude -Ilibs/FreeRTOS/include -Llibs/FreeRTOS -lfreertos
$(CC) $(CXXFLAGS) -o bin/$#.elf $^ $(LDFLAGS)
so it seems that the make output here doesn't match the makefile you've shown us. Are you sure you're using that makefile?

Related

Trying to compile the Paho MQTT C example on Raspberry Pi

I am trying to run the Paho MQTT example in C on my raspberry pi: https://www.eclipse.org/paho/clients/c/
I tried just downloading the pre-built binaries and linking to lpaho-mqtt3c
I put that library here: /home/pi/mqtt_C_testing/Eclipse-Paho-MQTT-C-1.3.1-Linux/lib
And I added: LD_LIBRARY_PATH=/home/pi/mqtt_C_testing/Eclipse-Paho-MQTT-C-1.3.1-Linux/lib/
My makefile looks like this:
IDIR = /home/pi/mqtt_C_testing/Eclipse-Paho-MQTT-C-1.3.1-Linux/include
LDIR = /home/pi/mqtt_C_testing/Eclipse-Paho-MQTT-C-1.3.1-Linux/lib
CC = gcc
LD = gcc
CFLAGS = -Wall
LIBS = -lpaho-mqtt3c
PROG_NAME = main
# directories in project
BIN = bin
SRC = src
OBJ = obj
INCLUDE = include
INCLUDES = -I./$(INCLUDE)
all : $(PROG_NAME)
$(PROG_NAME) : $(BIN)/$$#
$(BIN)/% : $(OBJ)/%.o
$(CC) $(CFLAGS) $^ -o $# $(LIBS)
$(BIN)/main : $(addprefix $(OBJ)/, \
main.o)
$(OBJ)/main.o : $(addprefix $(INCLUDE)/, \
MQTTProperties.h MQTTReasonCodes.h MQTTSubscribeOpts.h MQTTClient.h \
MQTTClientPersistence.h MQTTAsync.h)
$(OBJ)/%.o : $(SRC)/%.c
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -f $(OBJ)/*.o
When I try to build though, gcc cannot find the library:
gcc -Wall obj/main.o -o bin/main -lpaho-mqtt3c
/usr/bin/ld: cannot find -lpaho-mqtt3c
collect2: error: ld returned 1 exit status
make: *** [makefile:26: bin/main] Error 1
My directory structure is like this:
pi#raspberrypi:~/mqtt_C_testing $ ls
bin Eclipse-Paho-MQTT-C-1.3.1-Linux include makefile obj src
And I have main.c (the mqtt example file) in src and I put all the MQTT header files in include.
The library files for mqtt are here: /home/pi/mqtt_C_testing/Eclipse-Paho-MQTT-C-1.3.1-Linux/lib
I'm really not sure if I'm the right track at all here, so any help is appreciated. Thanks!
To get this to compile I did the following:
1) I built the lib by cloning the repo at github.com/eclipse/paho.mqtt.c and ran make then make install. This puts the .so files in /usr/local/lib
2) I put all the .h files in the main folder of my project directory: /home/pi/mqtt_C_testing/
3) I called the paho mqtt synchronous example main.c and have that also in the main directory.
4) I can then simply use: gcc -Wall -o test main.c -lpaho-mqtt3c to build and create an executable called "test"
5) I had success writing a makefile also that is run just with make. I'm a noob to all this, but I found this website (http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/) really helped with creating the makefile. I have not really had success putting the .h files in their own include directory yet though.
CC = gcc
CFLAGS=-I.
DEPS = MQTTAsync.h MQTTClientPersistence.h MQTTProperties.h MQTTClient.h MQTTReasonCodes.h MQTTSub$
OBJ = main.o
LIBS= -lpaho-mqtt3c
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
mainmake: main.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)

mongoc_init undefined reference

I am trying to use the mongo C driver in a Trivia server program I am making to use it to track login information scores etc.
It took me a decent amount of time to figure out how to compile the stuff in a makefile but I was able to include mongoc.h so things like mongoc_client work fine. As soon as I try to actually use a function though, such as mongoc_init I get
> undefined reference to `mongoc_init'
I feel like things should be linked though since the mongoc.h include all other header files and it looks like it is linking properly. Here is my makefile - I'm not sure what to do or even what information to provide to solve this issue.
client:
make -f makefile.client
server:
make -f makefile.server
clean:
rm -f *~ *.o tserve core tclient core *.tar *.zip *.gzip *.bzip *.gz
^ Makefile
C = gcc
CFLAGS = -g -Wall
LDFLAGS = -lpthread
INFO = -L/usr/local/lib -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0 -lmongoc-1.0 -lbson-1.0
all: tserve
csapp.o: csapp.c csapp.h
$(CC) $(CFLAGS) -c csapp.c
tserve.o: tserve.c readq.h csapp.h
$(CC) $(CFLAGS) -c tserve.c $(INFO)
readq.o: readq.c readq.h csapp.h
$(CC) $(CFLAGS) -c readq.c
tserve: tserve.o readq.o csapp.o
^ makefile.server
C = gcc
CFLAGS = -g -Wall
LDFLAGS = -lpthread
all: tclient
csapp.o: csapp.c csapp.h
$(CC) $(CFLAGS) -c csapp.c
tclient.o: tclient.c csapp.h
$(CC) $(CFLAGS) -c tclient.c
tclient: tclient.o csapp.o
^ makefile.client
If it is worth noting - the system is question had the driver installed using the following code
system("wget https://github.com/mongodb/mongo-c-driver/releases/download/1.0.2/mongo-c-driver-1.0.2.tar.gz");
system("tar -xzf mongo-c-driver-1.0.2.tar.gz");
system("rm mongo-c-driver-1.0.2.tar.gz");
if (chdir("mongo-c-driver-1.0.2"))
perror("error:");
system("./configure --prefix=/usr --libdir=/usr/lib64");
system("make");
system("sudo make install");
the code is also at https://www.github.com/decix/TriviaServer
the following file is expected to be named Makefile.mak
# note: with very minor changes this should work for most C projects
# irregardless of the OS being used
SHELL := /bin/sh
.PHONY: all clean
#
# macro for all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
CC := /usr/bin/gcc
MAKE := /usr/bin/make
name := tserve
CFLAGS := -c -g -std=c11 -Wall -Wextra -pedantic-errors
#CPPFLAGS += =MD
# when #(DEBUG) is used in the compile/link steps,
# them max info for the gdb debugger is generated
DEBUG := -ggdb3
LDFLAGS := -L/lib -L/usr/lib -L/usr/local/lib
LIBS := -lpthread -lmongoc-1.0 -lbson-1.0
INC := -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0
name := tserve
all: $(name)
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ)
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
#
#create dependancy files
# -- inference rule
#
%.d: %.c Makefile.mak
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I. $(INC)
# ========= END $< TO $# =========
#
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
You only use the INFO variable, which contains -lmongoc-1.0 -lbson-1.0 (which is what you need), to build tserve.o. In this build step, the linker is not involved, so the -l options are not evaluated and don't do anything. Instead, you need to specify them when you build tserve.
You could solve this by supplying a recipe for tserve that does this, such as
tserve: tserve.o readq.o csapp.o
$(CC) $(LDFLAGS) $(INFO) -o $# $+
...but it would be better, in my opinion, to split INFO and put the parts into the variables that the predefined rules use for the relevant purposes. Then your whole Makefile could be replaced with
# C compiler
CC = gcc
# C compiler flags
CFLAGS = -g -Wall
# C preprocessor flags
CPPFLAGS = -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0 -pthread
# Linker flags
LDFLAGS = -L/usr/local/lib -pthread
# Libraries
LDLIBS = -lmongoc-1.0 -lbson-1.0
all: tserve
csapp.o: csapp.c csapp.h
tserve.o: tserve.c readq.h csapp.h
readq.o: readq.c readq.h csapp.h
tserve: tserve.o readq.o csapp.o
The .o files will then be built through implicit rules that generate them from corresponding .c files and use CPPFLAGS and CFLAGS, saving you the trouble of specifying the recipes explicitly -- the rules only exist to track dependencies -- and the linking step uses an implicit rule that uses LDFLAGS and LDLIBS. Note that I supplied -pthread in both CPPFLAGS and LDFLAGS because it is relevant for both the preprocessor and the linker.
For further information, see the bit about implicit rules in the GNU make manual, and speaking of dependency tracking, you may find this article about automating it enlightening.

makefile for creating (.so) file from existing files

I have 4 files: 1.c, 1.h, 2.c, 2.h.
I need a makefile, which will create a dynamic library (.so) from those 4 files.
I have tried to write a makefile like this:
library.so : 1.c 1.h 2.c 2.h
but it did not work. It would be great, if someone helps me, thanks.
Something like
CC=gcc
CFLAGS= -Wall -g -O -fPIC
RM= rm -f
.PHONY: all clean
all: library.so
clean:
$(RM) *.o *.so
library.so: 1.o 2.o
$(LINK.c) -shared $^ -o $#
1.o: 1.c 1.h 2.h
2.o: 2.c 1.h 2.h
But this is untested! I am assuming Linux with GNU make, and a directory containing only the source code of your library (with the above Makefile), which might be bad practice -you might want a test case- (you could have a special Makefile rule for %.pic.o depending on %.c, etc...)
Hints: use make -p to understand the builtin rules. Then make --trace or (with remake) remake -x to understand a bit more what make is doing.
Read also Drepper's paper: How to Write Shared Libraries, documentation of GNU make, Program Library HowTo, this answer, ...
The simplest way is:
CXXFLAGS += -fPIC
CXXFLAGS += -O3
x.so: 1.o 2.o
$(LINK.cc) -shared $^ $(LOADLIBS) $(LDLIBS) -o $#
Slightly more advanced:
CC = gcc
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
OBJECTS = $(SOURCES:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
CC = gcc # C compiler
CFLAGS = -fPIC -Wall -Wextra -g # C flags
LDFLAGS = -shared # linking flags
RM = rm -f # rm command
TARGET_LIB = sh_main.so # target lib
SRCS = add.c sub.c main.c # source file
DEPS = header.h # header file
OBJS = $(SRCS:.c=.o) # object file
.PHONY: all
all: ${TARGET_LIB}
$(TARGET_LIB): $(OBJS)
$(CC) ${LDFLAGS} -o $# $^ # -o $# says, put the output of the compilation in the file named on the left side of the :
$(SRCS:.c=.d):%.d:%.c
$(CC) $(CFLAGS) -MM $< >$# # the $< is the first item in the dependencies list, and the CFLAGS macro is defined as above
include $(SRCS:.c=.d)
.PHONY: clean
clean:
-${RM} ${TARGET_LIB} ${OBJS} $(SRCS:.c=.d)
After the shared library created successfully. We need to install it.
Become the root user.
Copy the shared library into standard directory "/usr/lib".
Run ldcofig command.
Recompile your .c file with shared library.
root#Admin:~/C/SharedLibrary# gcc -c main.c
root#Admin:~/C/SharedLibrary# gcc -o main main.o sh_main.so
root#Admin:~/C/SharedLibrary# ldd main
Note: In my case.
main.c: main C file
sh_main.so: shared library.
I'm no gnu make expert, this seems reasonable to me
CFLAGS+=-fPIC
%.so: ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
library.so: 1.o 2.o # default target first
# changes to `1.h` imply `1.o` needs to be rebuilt
1.o: 1.h
2.o: 2.h

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.

error with makefile (executables)

Hi after a previous problem with not having makedepend installed (now solved), I now have the following error when trying to run my makefile:
$ make
makedepend -- -- -I /usr/include/linux -I include
cp executables
cp: missing destination file operand after `executables'
Try `cp --help' for more information.
make: *** [executables] Error 1
and here is my makefile:
CMDLINE_SRC=$(wildcard commandLine/*.c)
CMDLINE_OBJS = $(CMDLINE_SRC:.c=.o)
EXECUTABLES = $(CMDLINE_SRC:.c=)
LIB_SRC=$(wildcard c/*.c)
LIB_OBJ = $(LIB_SRC:.c=.o)
LIB_OUT = lib/libclinrisk.a
INCLUDES = -I include
# compiler
CC = gcc
CCFLAGS =
LDFLAGS =
# library paths
LIBS = -Llib -lclinrisk -lm
.SUFFIXES: .c
default: dep executables
executables: $(EXECUTABLES)
cp $(EXECUTABLES) executables
$(EXECUTABLES): $(LIB_OUT)
.c:
$(CC) $(INCLUDES) $(LDFLAGS) $< -o $# $(LIBS)
.c.o:
$(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $#
$(LIB_OUT): $(LIB_OBJ)
ar rcs $(LIB_OUT) $(LIB_OBJ)
depend: dep
dep:
makedepend -- $(CFLAGS) -- -I /usr/include/linux $(INCLUDES) $(LIB_SRC)
clean:
rm -f $(LIB_OBJ) $(LIB_OUT) Makefile.bak
rm -f $(CMDLINE_OBJ) $(CMDLINE_PROGS)
rm -f executables/*
what is the problem here? I am new to makefiles! will try figure this out in the meantime.
The problem looks like it's to do with:
cp $(EXECUTABLES) executables
however I'm unaware of a correct pathway to executables...
Thanks.
Nothing in your Makefile code sets the EXECUTABLES variable, so it substitutes to an empty string, which calls cp with just a single argument, thus generating the error.

Resources