我试图在Makefile中为每个目标添加一些行为,而不修改目标 .
我目前的尝试是这样的:
%: $*
@echo 'Logging $* target'
.PHONY: test
test:
@echo 'Inside explicit test target'
当我运行 make test
时,我想匹配 %
模式规则,它将执行 test
作为先决条件( $*
扩展到模式词干),然后记录运行的目标 .
$ make test
Inside explicit test target
Logging test target
Instead ,会发生的事情是 make test
与显式的 test
目标相匹配(可能是因为它是一个更接近的匹配):
$ make test
Inside explicit test target
如何在不更改显式测试目标的情况下实现此功能?
编辑:另一次尝试......
.SECONDEXPANSION:
%: $$*
@echo 'Logging $* target'
结果是
$ make test
make: Circular Makefile <- Makefile dependency dropped.
inside actual test target
2 回答
我出现在你自己的答案中,这让我击败了你,你只关心触发对命令行提到的目标的初步行动 -
$(MAKECMDGOALS)
. 从帖子中我得到了你想要"every target in a Makefile"的这样一个动作,其中包括命令行目标先决条件的所有目标,或者如果没有命令行目标,则包括默认目标 .无论如何,您可能仍然对解决更普遍的问题感兴趣 .
您希望在每个目标的配方之前执行初步操作 . 您的问题是:如何在明确规则之前匹配模式规则?
这是一种解决问题的XY方式,因为
make
只会在没有给出明确的配方的情况下查阅模式规则以找到制作目标的方法 . 例如,您知道make
有一个预定义的模式规则,用于从.c
文件生成.o
文件 . 即便如此,如果我的makefile是:然后
make
打印test.o
,没有任何尝试找到test.c
并编译它 . 如果我的make文件是:然后
make
打印:不需要诉诸模式规则 . 但是如果我的makefile是:
然后
make
说:所以你可以按照你的问题所假设的方式重新开始,因为只有当目标没有其他动作时,才能激发你想要从模式规则中激发的初步动作 .
在这种情况下,两次发布尝试失败的原因是相当学术性的,您可能希望滚动到 The Chase .
在您的第一次尝试中,使用:
模式规则 - 由
make test
失业 - 相当于:因为
$*
仅假定配方中的值,而不是模式规则中的值 . 您可以通过制作makefile不提供配方的任何目标来使用此模式规则,例如,make nonsuch
将打印Logging nonsuch target
;但那是没用的 .第二次尝试,包括:
创建您打算创建的规则是否正确 . 但该规则的含义是:
使这条规则适用的每个目标成为其自身的先决条件 . 这将不可避免地导致所有此类目标的循环依赖性错误 . 如您所见,此循环不会影响您的
test
目标,因为它具有明确的配方并且不使用该规则 . 但它确实引发了令人惊讶的错误:这是因为
make
自动考虑的第一个目标是makefile本身 . 与test
目标不同,您没有makefile的配方;所以模式规则适用于它,使makefile依赖于它自己 .The Chase
您可以通过不同的方法实现您想要的目标 . 在实际项目中,很可能在任何makefile中都可以计算所有可能目标的列表 . 从这里你可以生成一个相应的辅助目标列表,比如target => target.prelim,其中target.prelim的唯一目的是激发目标所需的初步行动,当它应该而不是其他目的时;你可以得到
make
来生成一个order-only rules的列表,目标:| target.prelim,对于每个目标,这样在确定是否必须进行目标时不会考虑target.prelim,而是在需要进行目标时在目标之前进行 .这是一个例子:
一个示例会话:
我意识到这并没有按照我的要求回答我的问题,但它具有我想要的效果 - 尽可能在
Makefile
处理中执行shell
命令 .LOG
是一个延迟变量,因此在Make评估force
目标的先决条件列表之前不会展开 .在一个单一的Makefile,不需要
.SECONDEXPANSION:
部分,因为force
目标在MYVAR
设置后进行评估 .但是,如果我将
LOG
变量和force
变量移动到子makefile中,那么在MYVAR?=
行之前很容易include subMakefile
- 这是行不通的 .通过为
force
指定.SECONDEXPANSION
,将删除对订购的依赖 .