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

时间:2008-09-16 11:57:47

标签: dependencies 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)不是目标,因此当$(BOMS)规则更新签名时make不会注意到。

我尝试创建一个.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来自哪里?

2 个答案:

答案 0 :(得分:1)

Make能够检测实际的文件更改非常糟糕,而不仅仅是更新的时间戳。

对我来说,问题的根源是bom-checkout总是修改bom的时间戳,导致重新生成依赖关系。我可能会尝试解决这个问题 - 尝试检查bom而不会弄乱时间戳。结帐工具周围的包装脚本可能会起作用;首先将bom签出到临时文件,将其与已检出的版本进行比较,并仅在新版本不同时替换它。

如果您没有严格限制使用make,那么还有其他工具可以更好地检测实际文件更改(例如,SCons)。

答案 1 :(得分:0)

我不是制作专家,但我会尝试让$(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),我会玩那个并看看。