C语言 将头文件与生成文件链接:未定义的引用错误



我有一个包含以下文件的项目,都在同一个文件夹中

client.c
server.c
reliable_udp.h
reliable_udp.c
conf.h

在其他库中,client.c还包括reliable_udp.h(#include "reliable_udp.h"(,以便使用packet_sendprint_conf(在reliable_udp.c中实现(的功能。

我是Makefile的新手,我正在尝试写一个:

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

如果我尝试运行make,我会得到以下输出:

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

显然,我无法正确编写Makefile.我应该如何解决它?为什么我会收到此错误?

为什么我会收到此错误?

因为链接配方不包含"reliable_udp.0"对象,并且因为生成文件中的任何内容都不会将"reliable_udp.c"编译为"reliable_udp.o">

发布的 makefile 包含几个问题,如问题的评论中所述。

下面是一个建议的简单生成文件,应执行所需的功能。

注意:将<tab>替换为制表符

注意:在以下生成文件中,调用命令可以是:

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

现在提议的制作文件

#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

一个快速的解决方法是修改生成文件,如下所示:

all: $(OBJ)
        ${CC} ${CLFAGS} reliable_udp.o client.o -o client
        ${CC} ${CLFAGS} reliable_udp.o server.o -o server

不过这并不漂亮,在"现实世界"中,更好的选择可能是为"reliable_udp"创建一个共享库,或者至少重构一点 Makefile。

错误的原因是"reliable_udp"未编译到最终的二进制文件中,因为它没有在 makefile 中的任何位置显式指定。

最新更新