我已经创建了一个makefile来编译和链接我的程序,但是,我不明白为什么会出现这个错误。这与SDL有关吗?
GCC = gcc
CFLAGS = -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g
SDL = -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer
all: ./game
game: global.o display.o player.o entities.o controls.o sound.o menu.o
$(GCC) $(CFLAGS) global.o display.o player.o entities.o controls.o sound.o menu.o -o game
global.o: global.c
$(GCC) $(CFLAGS) $(SDL) global.c
display.o: display.c
$(GCC) $(CFLAGS) $(SDL) display.c
player.o: player.c
$(GCC) $(CFLAGS) $(SDL) player.c
entities.o: entities.c
$(GCC) $(CFLAGS) $(SDL) entities.c
controls.o: controls.c
$(GCC) $(CFLAGS) $(SDL) controls.c
sound.o: sound.c
$(GCC) $(CFLAGS) $(SDL) sound.c
menu.o: menu.c
$(GCC) $(CFLAGS) $(SDL) menu.c
clean:
rm *o game
您的链接命令扩展为:
gcc -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g global.o display.o player.o entities.o controls.o sound.o menu.o -o game
如您所见,其中包含-c
标志。-c
标志告诉gcc不要进行链接。所以它实际上没有任何作用。(.o
文件只能用于链接,而您已经禁用了链接,这就是为什么您会收到该消息)
您不希望在编译和链接时使用相同的标志。对于编译,您可能需要-c -std=c99 -Wall -Wextra -pedantic -O3 -Wfloat-equal -g
,而对于链接,您需要-lm -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer -g
。
发布的makefile中有几个小疏忽。
其中:
- 库名称仅在链接步骤中使用,而不是在编译步骤中使用
- 建议使用通配符make运算符来获取源文件的列表。然后使用pattern替换操作符来获取对象文件的列表:
例如:
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
- 当目标(all,clean)不会生成相同名称的文件时,请在make文件的早期插入
.PHONY:
语句:
类似于:
.PHONY : all clean
发布的make文件没有处理相关头文件的功能,有几种方法可以处理。这遵循OP的引导,不处理头文件,因此更改头文件不会重新编译/重新链接受影响的源文件。
此行:
rm *o game
不会删除name.o文件,因为它缺少"."在根名称和'o'扩展名之间。此外,"-f"标志应与"rm"命令一起使用。
建议:
rm -f *.o game
- 这句话:
all: ./game
可能会产生问题
建议:
all: game
- 一旦创建了对象文件列表(如上所述),则可以减少编译规则:
通过使用make运算符:
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ -I.
编译器和链接器的CCD_ 9参数允许使用调试器。如果调试器是
gdb
,那么更好的参数是-ggdb
几乎总是,不需要对宏定义进行多次评估,因此与其在宏定义中使用
=
,不如使用:=
如果您希望
game
是可执行的,那么在"链接"规则中插入一个chmod
命令作为最后一行
建议阅读makefile
中可以使用的特殊运算符,以帮助您理解以下建议的makefile
通常最好用宏替换对shell识别命令的调用。
CC := /user/bin/gcc
RM := /usr/bin/rm
CFLAGS := -c -std=c99 -Wall -Wextra -pedantic -O3 -Wfloat-equal -ggdb
LFLAGS := -std=c99 -O3 -ggdb
SDL := -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer
SRC := $(wildcard *.c)
OBJS := $(SRC:.c=.o)
.PHONY : all clean
all: game
game: $(OBJS)
$(CC) $(LFLAGS) $(OBJS) -o $@ $(SDL) -lm
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ -I.
clean:
$(RM) -f *.o game
不要将-lm
或SDL库放入CFLAGS
中,库操作数将转到命令行的末尾。相反,使用一个额外的变量LDLIBS
并像这样修改game
规则:
game: global.o display.o player.o entities.o controls.o sound.o menu.o
$(GCC) $(CFLAGS) -o $@ global.o display.o player.o entities.o controls.o sound.o menu.o $(LDLIBS)
-lm
操作数(它不是一个选项)和SDL的操作数仅在链接时应用,因此它不应是CFLAGS
的一部分,并且在没有链接的情况下编译时(即提供-c
时)不应指定。