在单个makefile中构建来自相同源代码的多个配置

时间:2011-11-14 16:17:49

标签: makefile gnu-make

我有一小组C的源代码文件。我正在尝试拼凑一个Makefile,它们可以从同一组源代码中构建几个不同的输出。每个输出都使用特定于目标的变量进行自定义。

(现实世界的例子是在几个不同的电路板版本上运行的固件,但它是使用相同的源代码构建的,并使用条件编译进行自定义。)

这是一个示例Makefile,说明了我遇到的问题:

CINPUTFILES = Testfile.c

all: v12target v13target

# the same source code is built several different ways depending on a
# list of preset configurations
v12target: lots_of_common_variables = hello
v12target: more_variables = v12_specific
v12target: Rev12Output.mycommontargets

v13target: lots_of_common_variables = hello
v13target: more_variables = v13_specific
v13target: Rev13Output.mycommontargets

# (more vXXtarget targets omitted)

# TODO:  why is @echo required?
%.mycommontargets: %.hex %.elf
    @echo

# TODO: why are these output files deleted?
%.elf: $(CINPUTFILES)
    cp $< $@

%.hex: %.elf
    cp $< $@

# TODO: correct way of adding the dummy mycommontargets to PHONY?
.PHONY : all clean

这个想法是all目标构建了几个不同的目标 - 每个硬件版本都有一个目标。因为除了配置变量列表之外,每个构建过程都是相同的,所以它会调用许多设置变量的vXXtarget目标,然后调用一个公共目标:%.mycommontargets。然后,该目标设置生成实际输出文件。

注意TODO标记......

  1. %.mycommontargets:出于某种原因,如果我删除@echo,我会收到错误消息:

    make: *** No rule to make target `Rev12Output.mycommontargets', needed by `v12target'.  Stop.
    

    为什么会发生这种情况,我需要做些什么才能摆脱它?

  2. 如果我保留@echo,则构建成功完成。但是然后决定继续并删除输出!

    $ make
    cp Testfile.c Rev12Output.elf
    cp Rev12Output.elf Rev12Output.hex
    
    cp Testfile.c Rev13Output.elf
    cp Rev13Output.elf Rev13Output.hex
    
    rm Rev12Output.hex Rev12Output.elf Rev13Output.hex Rev13Output.elf
    

    为什么make会这样做?决定什么时候会这样做,什么时候不呢?我从来没有意识到make甚至有能力删除这样的文件;它与增量构建的整个想法背道而驰,我认为这应该是有帮助的。我宁愿保留所有中间和输出文件...

  3. mycommontargets模式添加到.PHONY
  4. 的正确方法是什么?

    我想我可以保留@echo,然后将每个目标添加到.PRECIOUS。但即使我没有很多make的经验,我也有强烈的感觉,如果我必须使用像@echo之类的黑客并且使用更加模糊的特殊目标,例如{{{ 1}}。只是感觉不对。

    (对于1个问题似乎在空间中提出3个问题的道歉,但我感觉他们有很强的相关性......)

1 个答案:

答案 0 :(得分:1)

  1. 问题在于每个非虚假目标都需要一个规则才能实现。但是,你不能使模式规则的目标虚假。在你的情况下,我建议离开@echo(更好:用@true替换它以避免虚假的输出线)。
  2. 输出文件是中间文件,即Makefile中未明确提及,但模式规则需要。默认情况下,make删除所有中间文件。这里禁用自动删除的最简单方法是在没有先决条件的情况下提及.SECONDARY目标,即在某处添加一行只是说:

    .SECONDARY:

  3. 如果你真的需要这里的.PHONY,你必须没有模式规则。这在你的布局中是非常不受欢迎的,所以最好让它成为现实。

  4. 总的来说,我建议在这里采用更正​​统的布局。通常,您将交叉编译问题从Makefile中删除,并将主机板(autotools用语:主板是软件将运行的板)作为configure的参数。让configure从中央源代码树为每个主机板生成一个构建树,并构建在这些构建树中。