Makefile忽略模式中包含子目录的模式规则
考虑以下目录结构:Makefile忽略模式中包含子目录的模式规则,makefile,gnu-make,Makefile,Gnu Make,考虑以下目录结构: . bar/ foo/ test.ext1 _foo/ 我使用以下规则编写了一个makefile: _%.ext2: bar/%.ext1 # % should match foo/test echo $* 但是运行make\u foo/test.ext2会给出: make: *** No rule to make target '_foo/test.ext2'. Stop. 当我查看 -d -ffo/test.Ext2时,它甚至不
.
bar/
foo/
test.ext1
_foo/
我使用以下规则编写了一个makefile:
_%.ext2: bar/%.ext1 # % should match foo/test
echo $*
但是运行make\u foo/test.ext2
会给出:
make: *** No rule to make target '_foo/test.ext2'. Stop.
当我查看<代码> -d -ffo/test.Ext2时,它甚至不考虑上述规则,即它直接跳转到尝试内置规则。我不明白这里发生了什么,有人能给我解释一下吗
编辑: 我希望能够从栏中的任意文件生成,例如:
bar/foo/test-2.ext1
->\u foo/test-2.ext2
bar/baz/other.ext1
->\u baz/other.ext2
- 等等
保证存在\u foo
和\u baz
在目标\u foo/test.ext2
上调用时,规则\u%.ext2:bar/%.ext1
。ext2
将匹配该规则,其词干(%)等于foo
。要使规则起作用,需要有一个文件(或规则)来创建bar/%.ext1=bar/foo.ext1
根据OP,输入文件是bar/foo/test1.ext1
尝试调整依赖项:
_%/test.ext2: bar/%/test.ext1
echo $*
通过向makefile添加以下内容,我成功地避免了此问题:
TARGETS := $(patsubst bar/%,_%,$(patsubst %.ext1,%.ext2,$(wildcard bar/**/*.ext1)))
$(TARGETS): _%.ext2: bar/%.ext1 # % should match foo/test
echo $*
这基本上是预先构造目标(从bar/
中可用的文件),然后将规则应用于目标。但是,我不确定为什么模式规则适用于这种情况而不适用于原始情况,因此我仍然希望得到解释。这在以下部分中进行了解释:
当目标模式不包含斜杠(通常不包含斜杠)时,文件名中的目录名将从文件名中删除,然后再与目标前缀和后缀进行比较
及
当先决条件转换为文件名时,stem中的目录将添加到前面,而stem的其余部分将替换为%
因此,对于像\uux%.ext2
这样的模式,下划线与文件名匹配,而不是与目录名匹配。因此它不匹配\u foo/test.ext2
,但它将匹配foo/\u test.ext2
(并查找foo/bar/test.ext1
)。你自己看看:
$ cat Makefile
_%.ext2: bar/%.ext1
echo Making $@ from $<
$ make -dr _foo/test.ext2
...
Considering target file '_foo/test.ext2'.
File '_foo/test.ext2' does not exist.
Looking for an implicit rule for '_foo/test.ext2'.
No implicit rule found for '_foo/test.ext2'.
Finished prerequisites of target file '_foo/test.ext2'.
Must remake target '_foo/test.ext2'.
make: *** No rule to make target '_foo/test.ext2'. Stop.
$ make -dr foo/_test.ext2
...
Considering target file 'foo/_test.ext2'.
File 'foo/_test.ext2' does not exist.
Looking for an implicit rule for 'foo/_test.ext2'.
Trying pattern rule with stem 'test'.
Trying implicit prerequisite 'foo/bar/test.ext1'.
Trying pattern rule with stem 'test'.
Trying implicit prerequisite 'foo/bar/test.ext1'.
Looking for a rule with intermediate file 'foo/bar/test.ext1'.
Avoiding implicit rule recursion.
No implicit rule found for 'foo/_test.ext2'.
Finished prerequisites of target file 'foo/_test.ext2'.
Must remake target 'foo/_test.ext2'.
make: *** No rule to make target 'foo/_test.ext2'. Stop.
如果你想让同行评议同事紧张,你也可以使用一些第二个扩展魔法来生成适当的先决条件名称,例如:
$ cat Makefile
percent := %
.SECONDEXPANSION:
%.ext2: bar/$$(patsubst _$$(percent),$$(percent),$$(@D))/$$*.ext1
echo Making $@ from $<
$ make _foo/test.ext2
echo Making _foo/test.ext2 from bar/foo/test.ext1
Making _foo/test.ext2 from bar/foo/test.ext1
$cat Makefile
百分比:=%
.第二次扩展:
%.ext2:bar/$$(patsubst$$(百分比),$$(百分比),$$(@D))/$$*.ext1
回声从$<
$make\u foo/test.ext2
从bar/foo/test.ext1生成echo\u foo/test.ext2
从bar/foo/test.ext1生成_foo/test.ext2
注意:%
必须通过$(百分比)
变量引用,否则GNU make解析器可能会抱怨或误解patsubst
函数
您的最终方法是有效的,因为您的最终解决方案是静态模式规则。它没有应用相同的“strip directory”方法,而是只匹配字符串。这解决了问题,但牺牲了通用性,即我希望该规则适用于满足该类型匹配的所有文件。出于好奇,该规则不包括哪种情况?在问题中列举需求可能是个好主意。例如,假设有另一个目录,
bar/baz/other_file.ext1
。我希望能够生成_baz/另一个文件.ext2
(当然假设_baz
存在)。感谢您的澄清感谢您的严格解释!我确实读过手册,但我想我没有正确理解。
$ cat Makefile
_/%.ext2: bar/%.ext1
echo Making $@ from $<
$ make _/foo/test.ext2
echo Making _/foo/test.ext2 from bar/foo/test.ext1
Making _/foo/test.ext2 from bar/foo/test.ext1
$ cat Makefile
$(CURDIR)/_%.ext2: bar/%.ext1
echo Making $@ from $<
$ make $(pwd)/_foo/test.ext2
echo Making /path/to/curdir/_foo/test.ext2 from bar/foo/test.ext1
Making /path/to/curdir/_foo/test.ext2 from bar/foo/test.ext1
$ cat Makefile
./_%.ext2: bar/%.ext1
echo Making $@ from $<
$ make -dr ./_foo/test.ext2
...
Considering target file '_foo/test.ext2'.
File '_foo/test.ext2' does not exist.
Looking for an implicit rule for '_foo/test.ext2'.
No implicit rule found for '_foo/test.ext2'.
Finished prerequisites of target file '_foo/test.ext2'.
Must remake target '_foo/test.ext2'.
make: *** No rule to make target '_foo/test.ext2'. Stop.
$ cat Makefile
percent := %
.SECONDEXPANSION:
%.ext2: bar/$$(patsubst _$$(percent),$$(percent),$$(@D))/$$*.ext1
echo Making $@ from $<
$ make _foo/test.ext2
echo Making _foo/test.ext2 from bar/foo/test.ext1
Making _foo/test.ext2 from bar/foo/test.ext1