我想保留以前编译的代码的日志,以便在设置编译选项时保持一致。我设计了以下方案,但它有一种奇怪的行为,我不太完全理解。这是一个重现错误的简化版本:
生成文件:
.DEFAULT_GOAL = final
MKFILES = Makefile Makefile.checks
include Makefile.checks
.PHONY: final
final: info.txt results.txt
@cat $^
results.txt: $(MKFILES) | .PRELIM
@echo 'First file with opt=$(opt)' > $@
info.txt: info.src $(MKFILES) | .PRELIM
@cat $< > $@
@echo 'Internal record of opt=$(opt)' >> $@
.PHONY: .FORCE
.FORCE:
.PHONY: .PRELIM
.PRELIM: Makefile.log
.PHONY: clean
clean:
rm -rf *.txt *.log
Makefile.checks:
# SETUPS & CHECKS
opt ?= 0
BUILDSTAT := 0
ifneq ($(MAKECMDGOALS),clean)
ifneq ("$(wildcard Makefile.log)","")
include Makefile.log
ifneq ($(opt),$(oldopt))
$(warning Previously compiled opt = $(oldopt))
$(warning Currently requested opt = $(opt))
BUILDSTAT := 1
endif
endif
endif
# RESOLUTION SECTION
ifneq ($(BUILDSTAT),0)
info.txt: .FORCE
Makefile.log: .FORCE
$(warning The build is not consistent, a clean make is recomended. )
ifneq ($(MAKECMDGOALS),anyway)
$(warning To force compilation, run 'make anyway opt=X' )
$(error Aborting compilation)
endif
endif
.PHONY: anyway
anyway: $(.DEFAULT_GOAL)
Makefile.log:
@echo 'Creating new Makefile.log'
@echo '########################################' > Makefile.log
@echo 'oldopt := $(opt)' >> Makefile.log
@echo 'BUILDSTAT := $(BUILDSTAT)' >> Makefile.log
@echo '########################################' >> Makefile.log
Makefile创建日志并检查以前的选项:make
后跟make opt=1
通过发出警告并停止按预期行事。但是,当我make anyway opt=1
时,makefile似乎在实际编译之前多次解析Makefile.checks
:
Makefile.checks:12: Previously compiled opt = 0
Makefile.checks:13: Currently requested opt = 1
Makefile.checks:26: The build is not consistent, a clean make is recomended.
Creating new Makefile.log
Makefile.checks:26: The build is not consistent, a clean make is recomended.
Creating new Makefile.log
(...repeated many times...)
Makefile.checks:26: The build is not consistent, a clean make is recomended.
Creating new Makefile.log
This is a personal log
Internal record of opt=1
First file with opt=0
我怀疑这可能与修改Makefile.log之后Makefile重新解析自身的方式有关,该Makefile.log本身包含在导致整个目标列表重新编译的MKFILES中。我尝试使用-d
选项,但它对我帮助不大。这个设计最终变得非常复杂,但我不知道如何简化它,而且我不太了解makefile如何解释我自己发生的事情。
我真的很感谢这个错误的解释。哪个依赖项导致循环以及为什么它最终离开它并继续完成编译?您认为有更好的方法来记录编译选项吗?
编辑:我将在这里添加进一步要求的信息/解释。我修改了一些代码来简化它。
我尝试做的是存储上一次构建中使用的编译选项,以便在重新编译代码的一部分时不混合选项(或者至少要警告这是我和# 39;做的事)。我实现此方法的方法是Makefile.checks
:选项是从Makefile.log
写入/加载的,BUILDSTAT
是一种布尔值来检查是否存在差异并跟踪它在后续构建中。
Makefile.checks
首先设置默认值,然后检查日志是否存在并加载&#34; old&#34;分离变量中的选项,然后比较两者以检查差异。如果找到任何一个,它会在此处发出警告,然后再次检查并停止(当您有多个选项时,这种分离更有意义),除非明确要求使用目标anyway
忽略它们。在最后一种情况下,日志和文件info.txt(这是存储选项的另一种方式)需要使用最后的构建信息(特别是BUILDSTAT=1
)进行更新,以保留构建可能具有的记录a&#34;混合编译&#34;)。
编辑 - &#34;解决方案&#34;:显然,如果不是&#34;强迫&#34;重新编译日志,我使日志本身成为虚假目标(在if内),它可以防止这种行为。我仍然没有发现这种方法有任何缺点,但它确实感觉有点&#34;脏&#34;。