GNU Makefile重复生成已有目标问题求助
问题根源
你的Makefile存在两个关键问题,导致每次执行make都会重新构建目标:
1. 错误使用$?自动变量
$?代表所有比目标文件更新的依赖文件。当foo.o已经存在且foo.cpp没有被修改时,$?是空值,此时编译命令会变成:
g++ -std=c++14 -Wall -Wextra -pedantic -O0 -c
这个命令缺少源文件参数,会触发编译错误,Make会判定目标构建失败,因此每次运行make都会重新尝试构建。
即使依赖文件有更新,$?在多依赖场景下也容易出问题,对于单依赖的目标文件规则,更适合用$<(代表第一个依赖文件),它总能准确获取到对应的源文件。
2. 未明确指定输出目标文件
虽然-c参数会让g++默认生成与源文件同名的.o文件,但如果编译命令中没有明确用-o $@指定输出为目标文件($@代表当前规则的目标),一旦出现路径或参数异常,可能导致生成的文件并非预期的目标文件,Make会因为找不到正确的目标文件而重复构建。
修正后的Makefile
# Compiler: g++ for C++ source files CC = g++ # Compiler flags: CFLAGS = -std=c++14 -Wall -Wextra -pedantic -O0 -c foo.o: foo.cpp $(CC) $(CFLAGS) -o $@ $< bar.o: bar.cpp $(CC) $(CFLAGS) -o $@ $< foobar: foo.o bar.o $(CC) -o $@ $^
关键修正点说明
- 用
$<替代$?:确保编译命令始终能获取到对应的源文件,避免空参数错误。 - 添加
-o $@:明确指定输出为当前规则的目标文件,保证生成的文件与Make跟踪的目标一致。 - 最终链接规则用
$^替代$?:$^代表所有依赖文件(这里是foo.o bar.o),而$?只会包含比foobar更新的依赖,用$^更可靠。
这样修改后,Make会正常根据文件时间戳判断是否需要重新构建,只有当源文件比目标文件新时,才会执行编译或链接操作。
内容的提问来源于stack exchange,提问作者user20278411
相关产品推荐
相关产品推荐

