为何执行Make时未调用clean却自动删除目标文件?
Make自动删除目标文件的原因及解决办法
我执行make命令时既没调用clean目标,也没要求删除目标文件,但日志显示系统自动执行了rm bin/main.o bin/graph.o bin/basic.o bin/colors.o bin/grid.o删除目标文件,这是怎么回事?
附上我的Makefile:
.PHONY: all clean CC = gcc CFLAGS = -g -m32 -std=c17 BIN = bin ALG_SRCS = $(wildcard alg/*.c) COMMON_SRCS = $(wildcard *.c) ALG_OBJS = $(patsubst alg/%.c, $(BIN)/%.o, $(ALG_SRCS)) COMMON_OBJS = $(patsubst %.c, $(BIN)/%.o, $(COMMON_SRCS)) ALG_EXES = $(patsubst alg/%.c, $(BIN)/%, $(ALG_SRCS)) all: $(ALG_EXES) $(BIN)/%: $(BIN)/%.o $(COMMON_OBJS) | $(BIN) $(CC) $(CFLAGS) -o $@ $^ -lncursesw $(BIN)/%.o: %.c | $(BIN) $(CC) $(CFLAGS) -c $< -o $@ $(BIN)/%.o: alg/%.c | $(BIN) $(CC) $(CFLAGS) -c $< -o $@ $(BIN): mkdir -p $(BIN) clean: rm -rf $(BIN)
执行日志:
$ make mkdir -p bin gcc -g -m32 -std=c17 -c alg/basic.c -o bin/basic.o gcc -g -m32 -std=c17 -c graph.c -o bin/graph.o gcc -g -m32 -std=c17 -c grid.c -o bin/grid.o gcc -g -m32 -std=c17 -c main.c -o bin/main.o gcc -g -m32 -std=c17 -o bin/basic bin/basic.o bin/graph.o bin/grid.o bin/main.o -lncursesw gcc -g -m32 -std=c17 -c alg/colors.c -o bin/colors.o gcc -g -m32 -std=c17 -o bin/colors bin/colors.o bin/graph.o bin/grid.o bin/main.o -lncursesw rm bin/main.o bin/graph.o bin/basic.o bin/colors.o bin/grid.o
原因分析
这是Make的默认中间文件自动清理机制导致的。
Make会自动识别并删除「中间文件」——也就是那些不是Makefile中明确声明的最终目标、仅用于生成最终目标的临时文件。在这个Makefile里:
- 最终目标是
$(ALG_EXES)(即bin/basic、bin/colors这类可执行文件) bin/main.o、bin/graph.o等.o文件只是生成可执行文件的依赖,既没有被显式列为all目标的一部分,也没有单独作为顶层目标存在
因此Make判定这些.o文件是中间产物,在完成所有最终目标的构建后,自动执行删除操作清理冗余文件。
解决办法
如果需要保留这些.o文件,可以用以下几种方式修改Makefile:
- 将
.o文件加入最终目标
修改all目标,把所有.o文件也列为需要构建的目标:
all: $(ALG_EXES) $(COMMON_OBJS) $(ALG_OBJS)
这样Make会把这些.o文件当作需要保留的最终产物,不会自动删除。
- 用
.PRECIOUS保护文件
添加.PRECIOUS目标,指定需要保留的.o文件:
.PRECIOUS: $(COMMON_OBJS) $(ALG_OBJS)
.PRECIOUS是Make的特殊目标,标记在此的文件不会被自动删除,即使它们是中间文件。
- 如果不需要保留,无需修改
如果需求只是生成可执行文件,这个自动清理行为是正常的——毕竟最终产物已经生成,.o文件只是编译过程的临时产物。
内容的提问来源于stack exchange,提问作者traveh
相关产品推荐
相关产品推荐

