从同一 Makefile 中的配方更改 make 变量并调用另一个规则?

Posted

技术标签:

【中文标题】从同一 Makefile 中的配方更改 make 变量并调用另一个规则?【英文标题】:Change a make variable, and call another rule, from a recipe in same Makefile? 【发布时间】:2014-12-10 13:08:42 【问题描述】:

我已经看过How to manually call another target from a make target?,但我的问题有点不同;考虑这个例子(注意,***.com 将选项卡更改为显示中的空格;但如果您尝试编辑,选项卡会保留在源代码中):

TEXENGINE=pdflatex

pdflatex:
    echo the engine is $(TEXENGINE)

lualatex:
    TEXENGINE=lualatex
    echo Here I want to call the pdflatex rule, to check $(TEXENGINE) there!

在这里,如果我运行默认目标 (pdflatex),我会得到预期的输出:

$ make pdflatex 
echo the engine is pdflatex
the engine is pdflatex

但是,对于目标lualatex,我想:

make变量TEXENGINE改为lualatex,然后 调用与pdflatex 相同的代码(使用它)。

我怎么能这样做?

显然,在我的 lualatex 规则中,我什至无法更改 TEXENGINE 变量,因为我在尝试时得到了这个:

$ make lualatex 
TEXENGINE=lualatex
echo Here I want to call the pdflatex rule, to check pdflatex there!
Here I want to call the pdflatex rule, to check pdflatex there!

...所以我真的很想知道 Makefiles 中是否有可能发生这样的事情。

【问题讨论】:

首先,如果您使用它来检查任意内容,我不会称该目标为pdflatex。我建议checkEngine 之类的东西,然后改成.PHONY 谢谢,@OliverCharlesworth - 不过,我认为这很好,因为在这个用例中pdflatex 是默认值,所以我只得到makemake pdflatex 的相同结果(然后用例是通过将引擎指定为make 的目标来更改引擎,如make lualatex)。干杯! 好吧,这取决于你 ;)(我觉得这是相当混乱和不好的做法......)你能不能只做 make TEXENGINE=whatever,并构建一组通用的目标/规则,使用用户指定的TEXENGINE 变量? 再次感谢@OliverCharlesworth - 我同意这是不好的做法,尤其是对于代码构建;但是在这种情况下,这种makefile的增长方式将非常有限,所以我敢于忽略不良做法以换取命令行便利:)否则,我会忘记make上的所有变量命令行-在下面写下我的答案时才想起。干杯! 【参考方案1】:

使用target-specific variable

目标特定变量还有一个特殊功能:当您定义目标特定变量时,该变量值也对该目标的所有先决条件及其所有先决条件等有效(除非这些先决条件覆盖具有自己的目标特定变量值的变量)。

TEXENGINE=pdflatex

pdflatex:
    echo the engine is $(TEXENGINE)

lualatex: TEXENGINE=lualatex
lualatex: pdflatex
    echo Here I want to call the pdflatex rule, to check $(TEXENGINE) there!

输出是:

$ make pdflatex
echo the engine is pdflatex
the engine is pdflatex
$ make lualatex
echo the engine is lualatex
the engine is lualatex
echo Here I want to call the pdflatex rule, to check lualatex there!
Here I want to call the pdflatex rule, to check lualatex there!

【讨论】:

感谢@JonathanWakely - 一开始我很困惑,因为先决条件会在lualatex 之前调用pdflatex;但后来我测试并实现将lualatex: 目标一分为二避免了这个陷阱——而且该解决方案在没有递归make 调用的情况下也可以工作,这很棒。也感谢关于“目标特定变量”的说明。干杯! 更具体地说,如果您在 lualatex 中不需要做任何事情,而这不仅仅是 pdflatex 所做的,那么您不需要 lualatex 目标上的配方正文一点也不。只需两行lualatex: 就足够了。 你能定义多个变量吗?【参考方案2】:

好吧,我设法找到了一种解决方法,但我不太了解它 - 因此将不胜感激。对我来说,这些链接有帮助:

Set a variable from within a rule make : rule call rule Passing additional variables from command line to make

所以这里是修改后的例子——显然,为了事后从规则中调用规则(不是作为先决条件,而是作为post必要条件),我只能递归调用make,同时在其命令行上指定了新的变量值:

TEXENGINE=pdflatex

pdflatex:
    echo the engine is $(TEXENGINE)

lualatex:
    echo Here I want to call the pdflatex rule, to check $(TEXENGINE) there!
    $(MAKE) TEXENGINE=lualatex pdflatex

输出比我想要的要详细一些,但它确实有效:

$ make lualatex 
echo Here I want to call the pdflatex rule, to check pdflatex there!
Here I want to call the pdflatex rule, to check pdflatex there!
make TEXENGINE=lualatex pdflatex
make[1]: Entering directory `/tmp'
echo the engine is lualatex
the engine is lualatex
make[1]: Leaving directory `/tmp'

...这是我想要的纯命令行交互方式,但我知道这不是最好的解决方案(请参阅下面的@JonathanWakely 评论)

【讨论】:

您的规则在这里执行的是运行make 的另一个实例并显式覆盖TEXENGINE 变量。命令行上定义的变量优先于环境或 makefile 中定义的变量,因此当第二个 make 运行时,它使用覆盖的值。这种方法的缺点是你运行make 两次,所以如果它必须做很多工作来检查先决条件的状态,那么你需要做两次所有的工作。

以上是关于从同一 Makefile 中的配方更改 make 变量并调用另一个规则?的主要内容,如果未能解决你的问题,请参考以下文章

在Make中,如何使配方仅在特定的退出代码上失败?

makefile--隐式规则

Makefile学习13——理解make的解析行为

更改 makefile 以处理“make all”命令

从 IDE 调用 Makefile 以进行调试/发布

make命令和makefile