在单个 makefile 中从相同源代码构建多个配置
我有一小组 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 标记...
%.mycommontargets
:由于某种原因,如果我删除@echo
,我会收到一条错误消息:make: *** 没有规则可以创建“v12target”所需的目标“Rev12Output.mycommontargets”。停止。
为什么会发生这种情况,我需要做什么才能摆脱它?
如果我将
<前><代码>$ 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@echo
保留在原处,则构建会成功完成。但随后 make 决定继续删除输出!为什么要这样做?是什么决定了它何时执行此操作以及何时不执行此操作?我以前从未意识到 make 甚至有能力删除这样的文件;它与增量构建的整个理念背道而驰,我认为 make 应该可以提供帮助。我宁愿保留所有中间文件和输出文件...
- 将
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...
%.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?
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...
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
输出文件是中间文件,即在Makefile 中没有明确提及,但模式规则需要。默认情况下,make 会删除所有中间文件。在这里禁用自动删除的最简单方法是在没有先决条件的情况下提及
.SECONDARY
目标,即在某处添加一行:.SECONDARY :
如果您确实需要此处的 .PHONY,则可以必须生活在没有模式规则的情况下。这在你的布局中是非常不受欢迎的,所以最好顺其自然。
总的来说,我建议这里采用更正统的布局。通常,您会将交叉编译问题排除在 Makefile 之外,并将主板(自动工具用语:主板是软件将在其上运行的主板)作为
configure
的参数。让configure从中央源树为每个主机板生成一个构建树,并在这些构建树中进行构建。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 :
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.