Reputation: 5025
I have a project with the following files, all in the same folder
client.c
server.c
reliable_udp.h
reliable_udp.c
conf.h
Among the other libraries, client.c
includes also reliable_udp.h
( #include "reliable_udp.h"
) in order to use the functions packet_send
and print_conf
(that are implemented in reliable_udp.c
).
I'm new to Makefile
s, and I'm trying to write one:
CC = gcc
CFLAGS = -Wall -Wextra -Wpedantic -O3
SRC = client.c server.c
OBJ = $(SRC:.c=.o)
all: $(OBJ)
${CC} ${CLFAGS} client.o -o client
${CC} ${CLFAGS} server.o -o server
client.o: reliable_udp.h
clean:
rm -f *.o core
cleanall:
rm -f *.o core client server
If I try to run make
, I get the following output:
gcc -Wall -Wextra -Wpedantic -O3 -c -o client.o client.c
gcc client.o -o client
client.o: In function `main':
client.c:(.text.startup+0x84): undefined reference to `packet_send'
client.c:(.text.startup+0x8b): undefined reference to `print_conf'
collect2: error: ld returned 1 exit status
Makefile:7: recipe for target 'all' failed
make: *** [all] Error 1
Obviously I'm failing writing correctly the Makefile
. How should I fix it? Why am I getting this error?
Upvotes: 3
Views: 3478
Reputation: 16540
Why am I getting this error?
Because the link recipes do not include the 'reliable_udp.0' object and because nothing in the makefile will compile 'reliable_udp.c into 'reliable_udp.o`
the posted makefile contains several problems, as expressed in the comments to the question.
The following is a proposed, simple makefile that should perform the desired functionality.
Note: replace <tab>
with a tab character
Note: in the following makefile, the invocation command can be:
make -- to generate both 'client' and 'server'
as it will use the first target, which is 'all'
make all -- to generate both 'client' and 'server'
make client -- to only generate the 'client' executable
make server -- to only generate the 'server' executable
make clean -- to delete the object files
make cleanall -- to delete the object files and the executables
and now the proposed makefile
#use ':=' rather than '=' so macros only evaluated once
#assure the desired utilities are used
CC := /usr/bin/gcc
RM := /usr/bin/rm -f
CFLAGS := -Wall -Wextra -Wpedantic -std=GNU11 -O3
#generate a list of all the source files
SRC := client.c server.c reliable_udp.c
#generate a list of all the object file names
OBJ := $(SRC:.c=.o)
#let make know that the target 'all' will not produce a file of the same name
#notice the 'all' target dependencies are the final executables
.PHONY: all
all: client server
#this will perform all the compiles
#while expecting the user supplied header files to be in the local directory
%.o:%.c
<tab>$(CC) -c $(CFLAGS) $^ -o $@ -I.
#link the 'client' executable
client: client.o reliable_udp.o
<tab>${CC} $^ -o $@
#link the 'server' executable
server: server.o reliable_udp.o
<tab>${CC} $^ -o $@
#let make know that this target will not produce a file of the same name
.PHONY: clean
clean:
<tab>$(RM) $(OBJ) core
#let make know that this target will not produce a file of the same name
.PHONY: cleanall
cleanall:
<tab>$(RM) $(OBJ) core client server
Upvotes: 4
Reputation: 26
A quick fix would be to modify the Makefile as follows:
all: $(OBJ)
${CC} ${CLFAGS} reliable_udp.o client.o -o client
${CC} ${CLFAGS} reliable_udp.o server.o -o server
It's not pretty though, in "real world" a better option might be to make a shared library for "reliable_udp", or at least refactor Makefile a little bit.
The reason of the error is that "reliable_udp" is not compiled in to the final binaries, since it's not explicitly specified anywhere in the makefile.
Upvotes: 1