生成多个目标的配方

时间:2017-05-22 12:50:42

标签: makefile gnu-make

在我们的makefile中,我们有一个配方将所有对象和库文件链接在一起以生成可执行文件(.elf文件)。作为副作用,此步骤还会生成映射文件和Intel .hex文件:

$(ELF_FILE) : <list of dependencies here>
    <linker command line>

到目前为止,由于我们从未实际拥有$(MAP_FILE)$(HEX_FILE)目标,当另一个目标依赖于其中一个$(ELF_FILE)的副产品时,我们只是将其声明为依赖$(ELF_FILE),即使该目标的配方根本不想访问$(ELF_FILE)本身。例如:

# Target that needs map-file, which is a side product of the $(ELF_FILE) target.
$(TARGET_THAT_NEEDS_MAP_FILE) : $(ELF_FILE)
    <build-recipe>

# Target that needs hex-file, which is also a side product of the $(ELF_FILE) target.
$(TARGET_THAT_NEEDS_HEX_FILE) : $(ELF_FILE)
    <build-recipe>

我们最近发现一个配方可以用于多个目标,如下所示:

$(MAP_FILE) $(HEX_FILE) $(ELF_FILE) : <list of dependencies here>
    <linker command line>

通过这些新发现的知识,我们认为我们可以摆脱上述“黑客”并直接说明每个目标的直接依赖关系:

$(TARGET_THAT_NEEDS_MAP_FILE) : $(MAP_FILE)
    <build-recipe>

$(TARGET_THAT_NEEDS_HEX_FILE) : $(HEX_FILE)
    <build-recipe>

实施了这些变化后,我们现在观察到一种奇怪的效果,使我们怀疑我们误解了make的多目标单配方功能,或者我们没有正确使用它。奇怪的结果是生成.elf,.map和.hex文件的配方现在看起来运行两次。这似乎没有造成任何直接问题,但它似乎表明这里有些东西可疑。所以我的问题是,我们的新方法是否可行,或者我们应该坚持上述的黑客攻击?

编辑:我们以多线程方式运行make(即使用-j)。

1 个答案:

答案 0 :(得分:1)

当make尝试更新目标时(无论是$(MAP_FILE)$(HEX_FILE)还是$(ELF_FILE),它可能不知道其配方还会更新另一个目标,因此它也开始为那个配方,即使它是相同的。

当然,只有在使用-j选项时才会发生这种情况。 (你有没有可能尝试没有?)

举例说明:

$(TARGET): $(ELF_FILE) $(MAP_FILE)
   <update target>

此处制作将尝试更新$(ELF_FILE)$(MAP_FILE),然后两次点击食谱。 (如果依赖项位于不同的目标上,这也应该适用,只要目标通过make的一次执行更新,并且它们之间没有瓶颈。

我对此并不完全确定,但可能能够知道这是同一个食谱。

==

answer可能对您有用。 具体来说:

  

但是,如果输出文件和输入文件共享一个公共库,   你可以编写这样的模式规则:

%.foo %.bar %.baz : %.boz ; $(BUILDIT)
     

奇怪的是,对于具有多个目标的隐式规则,GNU make假定   单个调用配方将构建所有目标,它将完全按照您的意愿运行。

     

MadScientist

它指的是制作手册的那部分:

  

模式规则可能有多个目标。与普通规则不同,这个   不具有相同先决条件的许多不同规则   食谱。如果模式规则有多个目标,make就知道了   规则的配方负责制定所有目标。食谱   只执行一次以制作所有目标。搜索时   模式规则匹配目标,规则的目标模式其他   比匹配需要规则的目标的是偶然的:   只关心给文件的配方和先决条件   目前有问题。但是,当运行此文件的配方时,   其他目标被标记为已自行更新。