You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:15:38