为何Makefile中的归档目标表现得如同.PHONY目标?
问题
我有一个简单的Makefile,用于从单个目标文件foo.o构建归档文件libfoo.a,内容如下:
CC=gcc CFLAGS=-g -Wall AR=ar libfoo.a: libfoo.a(foo.o) foo.o: foo.c
首次执行make时,会正常编译C文件并创建包含该目标文件的归档:
$ make gcc -g -Wall -c -o foo.o foo.c ar rv libfoo.a foo.o ar: creating libfoo.a a - foo.o
但立即再次执行make(未修改foo.o)时,它仍会尝试用ar r(替换插入foo.o)更新归档:
$ make ar rv libfoo.a foo.o r - foo.o
为何Make会执行此不必要的操作?(若其他目标依赖libfoo.a,该目标也会被重新构建等)
根据make -d的输出,它似乎在检查不存在的libfoo.a(foo.o)文件,因此决定重新运行ar r。这是预期行为吗?还是我的Makefile存在疏漏?
解答
问题根源
你使用的libfoo.a(foo.o)是GNU Make的归档成员目标语法,但Make无法直接识别归档内部的成员状态——它会把libfoo.a(foo.o)当作一个独立的、实际不存在的文件,每次检查都会判定这个"文件"处于过期状态,因此会反复触发ar命令执行。
修正后的Makefile写法
要让Make正确判断归档是否需要更新,应该直接将foo.o作为libfoo.a的依赖,并显式定义构建规则:
CC=gcc CFLAGS=-g -Wall AR=ar ARFLAGS=rv libfoo.a: foo.o $(AR) $(ARFLAGS) $@ $^ foo.o: foo.c
修改后,Make会对比libfoo.a和foo.o的修改时间:只有当foo.o比libfoo.a新,或者libfoo.a本身不存在时,才会重新运行ar命令生成归档。
多成员归档的处理
如果你的归档需要包含多个目标文件,只需将所有.o文件列在libfoo.a的依赖列表中即可,比如:
libfoo.a: foo.o bar.o baz.o $(AR) $(ARFLAGS) $@ $^
Make会自动对比所有依赖目标文件与归档的时间戳,避免无意义的重复构建。
内容的提问来源于stack exchange,提问作者j-hui
相关产品推荐
相关产品推荐

