代码之家  ›  专栏  ›  技术社区  ›  Chris Nelson

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

  •  2
  • Chris Nelson  · 技术社区  · 17 年前

    我希望我没有把自己画成一个角落。我已经得到了实现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签出发生在一个.假目标中(因此它总是被签出),并跟踪“.sig”文件中最后一个签出的内容(如果签名文件丢失或内容与新文件的签名不同,则bom已更改),a依赖关系的生成依赖于签名)。在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规则,并用touch管理签出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 回复  |  直到 17 年前
        1
  •  1
  •   JesperE    17 年前

    make很难检测到实际的文件更改,而不是仅仅更新时间戳。

    在我看来,问题的根源在于bom签出总是修改bom的时间戳,从而导致依赖项重新生成。我可能会试着解决这个问题——试着签出bom而不弄乱时间戳。围绕checkout工具的包装脚本可以做到这一点:首先将bom签出到一个临时文件中,将其与已签出的版本进行比较,并仅在新版本不同时替换它。

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

        2
  •  0
  •   mbyrne215    17 年前

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