【发布时间】:2012-11-19 19:45:42
【问题描述】:
我有一个关于在 Makefile 中编译和链接的问题(也许一般来说)。
我有一个 server.c 文件,它由具有main() 函数的主程序组成。 server.c 包括 rio.c。我有一个名为rio 的模块,它由rio.c 和rio.h 组成。它没有main() 功能。
我有两个问题,如何实际编写 Makefile,以及这样做的最佳实践。
Q1:如何编写 Makefile
我有以下 Makefile:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
all: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o sysstatd
server.o: server.c
$(CC) $(CFLAGS) -c server.c
rio.o: rio.c rio.h
$(CC) $(CFLAGS) -c rio.c
clean:
rm -f *~ *.o sysstatd
我遇到了链接问题。它说我对 C 中使用的所有函数都有多个定义。我不确定这怎么可能,因为 server.c 是用 -c 标志编译的,所以实际上没有任何链接。它应该知道有些函数存在但实际上并没有链接它们,直到all 规则将两个目标文件编译在一起并生成一个包含所有链接的目标文件。
这里有什么问题?
Q2:最佳实践
由于我有一个模块和另一个包含主程序的文件,我应该将主程序server.c 编译为一个单独的模块,然后在all 中一起编译,还是编译 server.c 并添加rio.o 模块在那里?请注意,这仍然会产生与上面相同的链接问题,所以我很确定我的问题出在其他地方。
【问题讨论】:
-
你在使用任何外部库吗?
-
是的。但它在我自己的函数上调用错误,说 server.c 首先定义了它们。 server.c 和 rio.h 都导入:stdio.h、stdlib.h、unistd.h 和 errno.h
-
当您说“server.c 包含 rio.c”时,您的意思是在文件
server.c中,您有类似#include "rio.c"的行吗?如果是这样,那是错误的方法,也是错误的可能来源;你应该包括rio.h。 -
不仅如此,您还必须在 make 文件中显式链接文件。我很确定您会在
-o sysstatd <L>之后执行此操作,其中<L>是要链接的库。例如,如果您要链接libsomelib.a,前提是它在您的$PATH中,您可以将<L>替换为-lsomelib。 -
@JohnBode 是的,这就是问题所在。这就说得通了。我的 server.o 已经具有 rio.c 功能,因为它包含 rio.c,导致链接错误。如果您将其添加为答案,我会接受。
标签: c compilation linker makefile