(使用GNU make)
我有一个Makefile
与默认目标负责"编译"代码。我希望run_test
目标执行测试,但如果需要,将重新编译。
我想在任何编译步骤运行之前清除日志文件,但是只有在编译步骤运行时才清除,所以如果只是测试运行则不清除。我定义了一个reset_log
目标来清除日志。我想要的行为是:
-
make all
当所有更新时-没有运行,日志未清除 -
make all
当不是时-日志被清除,然后运行适当的编译规则 -
make run_test
当全部更新时-没有编译,日志未清除,测试运行 -
make run_test
当不是时-日志被清除,然后运行适当的编译规则,然后运行测试
如何使reset_log
目标(或等效命令)仅在必须进行编译时运行,但在任何依赖关系配方运行之前运行?下面是简化的Makefile
:
LOG_FILE = file.log
all: compile
compile: final.out
reset_log:
-rm -f $(LOG_FILE)
final.out: final.in reset_log 1.out 2.out
cp -v final.in final.out | tee -a $(LOG_FILE)
1.out: 1.in
cp -v 1.in 1.out | tee -a $(LOG_FILE)
2.out: 2.in
cp -v 2.in 2.out | tee -a $(LOG_FILE)
run_test: compile
@echo "======= Run Test Here ======="
clean:
-rm *.out $(LOG_FILE)
.PHONY: local_target reset_log run_test clean
注意:这个例子不工作 (reset_log
和final.out
目标每次都重新运行,因为reset_log
是final.out
的依赖项,本身没有依赖项),但演示了我想要运行reset_log
的地方。
一种可能的解决方案是在依赖关系食谱运行之前为过期的目标运行食谱。
更新2016-10-18
基于user657267的解决方案(以及我在评论中建议的小改进),这里是上述示例的重新编码,即我需要的最终解决方案:
LOG = file.log
all: compile
compile: $(LOG)
$(LOG): final.out
mv $@.tmp $@ || ( echo "WARNING: $< not found. Creating dummy $@ to allow make to run" > $@ )
final.out: 1.out 2.out
%.out: %.in
cp -v $< $@ | tee -a $(LOG).tmp
run_test: compile
@echo "======= Run Test Here ======="
clean:
-rm *.out $(LOG)
.PHONY: run_test clean compile
使用第二个临时日志文件
log := file.log
out := final.out 1.out 2.out
.PHONY: run_test clean
$(log): $(out)
mv $@.tmp $@
run_test: $(log)
@echo "======= Run Test Here ======="
clean:
$(RM) $(out) $(log)
%.out: %.in
cp -v $< $@ | tee -a $(log).tmp