我有一个关于在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 in所有并在那里添加rio.o模块?请注意,这仍然会产生我上面相同的链接问题所以我很确定我的问题出在其他地方。
答案 0 :(得分:14)
你应该稍微修改一下结构:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
all: sysstatd
sysstatd: $(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
不同之处在于,虚假规则all
取决于sysstatd
是最新的,sysstatd
是最新的,因为它是目标文件的最新版本。
现在只是相当冗长,明确地编写编译动作。使用:
就足够了CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
all: sysstatd
sysstatd: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o sysstatd
server.o: server.c
rio.o: rio.c rio.h
clean:
rm -f *~ *.o sysstatd
你也可以辩论:server.c
不使用rio.h
吗?如果是,则应列出依赖项。如果没有,为什么rio.h
存在? make
会假设server.o
取决于server.c
,因此您无需指定(但不会对标题进行假设)。您还可以使用宏来防止重复程序名称:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd
all: $(PROG)
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $@
server.o: rio.h
rio.o: rio.h
clean:
rm -f *~ *.o $(PROG) core a.out
如果您需要其他库,则可以使用:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd
LOCALLIBDIR = /usr/local/lib
LDFLAGS = -L$(LOCALLIBDIR)
LDLIBS = -lone -ltwo
all: $(PROG)
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) $(LDLIBS)
server.o: rio.h
rio.o: rio.h
clean:
rm -f *~ *.o $(PROG) core a.out