在单个 makefile 中从相同源代码构建多个配置

发布于 2024-12-15 22:01:20 字数 2104 浏览 0 评论 0原文

我有一小组 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

想法是 < code>all 目标构建了多个不同的目标 - 每个硬件版本对应一个目标。由于除了配置变量列表之外,每个版本的构建过程都是相同的,因此它会调用许多 vXXtarget 目标,这些目标设置变量,然后调用通用目标:%.mycommontargets 。然后,该目标开始生成实际的输出文件。

注意 TODO 标记...

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

    make: *** 没有规则可以创建“v12target”所需的目标“Rev12Output.mycommontargets”。停止。
    

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

  2. 如果我将 @echo 保留在原处,则构建会成功完成。但随后 make 决定继续删除输出!

    <前><代码>$ 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 的正确方法是什么?

我想我可以将 @echo 保留在原处,然后将每个目标添加到 .PRECIOUS 中。但是,尽管我没有太多的 make 经验,但我有一种强烈的感觉,如果我必须使用像 @echo 这样的 hack 并使用更晦涩的特殊内容,我就做错了目标如 .PRECIOUS。只是感觉不太对劲。

(很抱歉在 1 个问题的空间里问了 3 个问题,但我感觉它们密切相关......)

I have a small set of source code files for C. I'm trying to piece together a Makefile for them that builds several different outputs from the same set of source code. Each output is customized using target-specific variables.

(The real-world example is firmware that runs on several different circuit board revisions but is built from the same source code and customized using conditional compilation.)

Here's an example Makefile illustrating the problems I've running into:

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 
lt; $@

%.hex: %.elf
    cp 
lt; $@

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

The idea is that the all target builds several different targets - one for each hardware revision. Because the build process for each is identical except for a list of configuration variables, it calls a number of vXXtarget targets which set variables and then call a common target: %.mycommontargets. This target then sets about generating the actual output files.

Notice the TODO marks...

  1. %.mycommontargets: for some reason, if I remove the @echo I get an error message:

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

    Why does this happen and what do I need to do to get rid of it?

  2. If I leave the @echo in place, the build does successfully complete. But then make decides to go ahead and delete the outputs anyway!

    $ 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
    

    Why does make do this? What decides when it will do this and when it does not? I never previously realized make even had the capability to delete files like this; it runs counter to the whole idea of incremental builds, which I thought make was supposed to help out with. I'd rather have all intermediate and output files retained...

  3. What's the correct way of adding the mycommontargets pattern to .PHONY?

I suppose I could just leave @echo in place and then add each target to .PRECIOUS. But even though I don't have a lot of experience with make, I have a strong feeling that I'm doing it wrong if I have to use a hack like @echo and use a more obscure special target like .PRECIOUS. Just doesn't feel right.

(Apologies for appearing to ask 3 questions in the space for 1 question, but I have the feeling they are strongly related...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦幻的味道 2024-12-22 22:01:20
  1. 问题是每个非虚假目标都需要一个规则来实现。但是,您不能使模式规则的目标变得虚假。对于您的情况,我建议保留 @echo (更好:将其替换为 @true 以避免出现虚假的输出行)。
  2. 输出文件是中间文件,即在Makefile 中没有明确提及,但模式规则需要。默认情况下,make 会删除所有中间文件。在这里禁用自动删除的最简单方法是在没有先决条件的情况下提及 .SECONDARY 目标,即在某处添加一行:

    .SECONDARY :

  3. 如果您确实需要此处的 .PHONY,则可以必须生活在没有模式规则的情况下。这在你的布局中是非常不受欢迎的,所以最好顺其自然。

总的来说,我建议这里采用更正​​统的布局。通常,您会将交叉编译问题排除在 Makefile 之外,并将主板(自动工具用语:主板是软件将在其上运行的主板)作为 configure 的参数。让configure从中央源树为每个主机板生成一个构建树,并在这些构建树中进行构建。

  1. The problem is that each non-phony target needs a rule to make it. However, you can't make the targets of pattern rules phony. In your case, I'd advise to leave the @echo (better: replace it by @true to avoid a spurious line of output).
  2. The output files are intermediate files, i.e. not mentioned explicitly in the Makefile, but required by pattern rules. By default, make deletes all intermediate files. The easiest way to disable auto-deletion here is to mention the .SECONDARY target without prerequisites, i.e. add a line somewhere just saying:

    .SECONDARY :

  3. If you really need the .PHONY here, you have to live w/o pattern rules. Which is quite undesirable in your layout, so better let it be.

Overall, I'd suggest a more orthodox layout here. Normally, you'd leave cross-compiling issues out of the Makefile and give the host board (autotools parlance: the host board is the board the software will run on) as an argument to configure. Let configure generate one build tree per host board from a central source tree, and build in these build trees.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文