如何使用一个Makefile有效地构建组件的不同版本

时间:2020-03-05 18:55:43  来源:igfitidea点击:

我希望自己不要陷入困境。我已经实现了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)。