如何使用一个Makefile有效地构建组件的不同版本
我希望自己不要陷入困境。我已经实现了Makefile,这似乎是大多数方式,但我无法最后工作。我希望这里有人可以建议一种技术来做我想做的事情。
我将在源存储库中的版本控制文件中拥有所谓的"物料清单",并且构建类似以下内容的文件:
make VER=x
我希望我的Makefile使用$(VER)作为标记从存储库中检索BOM,生成要包含在Makefile中的依赖文件,重新扫描包括该依赖的文件,然后构建产品。
更一般而言,我的Makefile可能有多个目标-A,B,C等。并且我可以为每个目标建立不同的版本,所以我可以这样做:
make A VER=x make B VER=y make C VER=z
依赖性文件包含有关所有三个目标的信息。
但是,创建依赖文件有点昂贵,所以如果我这样做:
make A VER=x ...make source (not BOM) changes... make A VER=x
我真的希望Makefile不要重新生成依赖项。为了使事情变得尽可能复杂,我可以这样做:
make A VER=x .. change version x of A's BOM and check it in make A VER=x
所以我需要重新生成对第二个构建的依赖。
检出弄乱了用于重新生成依赖项的时间戳,因此我认为我需要一种使依赖项文件不依赖于BOM而是依赖于BOM更改的指示的方法。
我要做的是使BOM检出发生在.PHONY目标中(因此它总是被检出),并在" .sig"文件中跟踪上次检出的内容(如果签名文件丢失或者内容与新文件的签名不同,然后更改BOM),并且依赖项的生成取决于签名)。在我的Makefile的顶部,我进行了一些设置:
BOMS = $(addsuffix .bom,$(MAKECMDGOALS) SIGS = $(subst .bom,.sig,$(BOMS)) DEP = include.d -include $(DEP)
看来我总是需要做:
.PHONY: $(BOMS) $(BOMS): ...checkout TAG=$(VER) $@
但是,如上所述,如果我这样做,然后继续:
$(DEP) : $(BOMS) ... recreate dependency
然后,每次调用make时,依赖项都会更新。所以我尝试:
$(DEP) : $(SIGS) ... recreate dependency
和
$(BOMS): ...checkout TAG=$(VER) $@ ...if $(subst .bom,.sig,$@) doesn't exist ... create signature file ...else ... if new signature is different from file contents ... update signature file ... endif ...endif
但是,签名更改时,依赖项生成不会被触发。我认为是因为$(SIGS)不是目标,所以make不会注意到$(BOMS)规则何时更新签名。
我尝试创建一个.sig:.bom规则,并通过触摸管理已签出BOM的时间戳,但这没有用。
有人建议:
$(DEP) : $(SIGS) ... recreate dependency $(BOMS) : $(SIGS) ...checkout TAG=$(VER) $@ $(SIGS) : ...if $(subst .bom,.sig,$(BOMS)) doesn't exist ... create it ...else ... if new signature is different from file contents ... update signature file ... endif ...endif
但是,当从BOM表创建SIG时,BOM表如何依赖于SIG?正如我所读到的那样,"从BOM创建SIG,如果SIG比BOM更新,则检出BOM"。我如何引导该过程?第一个BOM是从哪里来的?
解决方案
回答
我不是专家,但是我会尝试让$(BOMS)依赖于$(SIGS),并使$(SIGS)目标执行我们当前在$(BOMS)目标下拥有的if / else规则。
$(DEP) : $(SIGS) ... recreate dependency $(BOMS) : $(SIGS) ...checkout TAG=$(VER) $@ $(SIGS) : ...if $(subst .bom,.sig,$(BOMS)) doesn't exist ... create it ...else ... if new signature is different from file contents ... update signature file ... endif ...endif
编辑:我们是对的,当然,我们不能让$(BOM)依赖于$(SIGS)。但是,为了重新创建$(DEP),我们需要将$(SIG)作为目标。也许有一个既取决于$(BOM)也取决于$(SIG)的中间目标。
$(DEP) : $(SIGS) ... recreate dependency $(NEWTARGET) : $(BOMS) $(SIGS) $(BOMS) : ...checkout TAG=$(VER) $@ $(SIGS) : ...if $(subst .bom,.sig,$(BOMS)) doesn't exist ... create it ...else ... if new signature is different from file contents ... update signature file ... endif ...endif
$(SIGS)可能还需要依赖$(BOMS),我会试着看看。
回答
与仅更新时间戳相比,Make很难检测到实际文件更改。
在我看来,问题的根源是bom-checkout始终会修改bom的时间戳,从而导致重新生成依赖项。我可能会尝试解决此问题-尝试在不弄乱时间戳的情况下签出Bom。结帐工具周围的包装器脚本可能会解决问题。首先将Bom检出到一个临时文件,将其与已检出的版本进行比较,然后仅在新版本不同时才将其替换。
如果我们不严格限制使用make,那么还有其他工具可以更好地检测实际文件更改(例如SCons)。