考虑以下目录结构:
.
bar/
foo/
test.ext1
_foo/
Run Code Online (Sandbox Code Playgroud)
我用以下规则编写了一个 makefile:
_%.ext2: bar/%.ext1 # % should match foo/test
echo $*
Run Code Online (Sandbox Code Playgroud)
然而运行make _foo/test.ext2给出:
make: *** No rule to make target '_foo/test.ext2'. Stop.
Run Code Online (Sandbox Code Playgroud)
当我查看时make -d _foo/test.ext2,它甚至没有考虑上述规则,即它直接跳到尝试内置规则。我不明白这里发生了什么,有人可以向我解释一下吗?
编辑:我希望能够从 中的任意文件生成bar,例如:
bar/foo/test-2.ext1->_foo/test-2.ext2bar/baz/another.ext1->_baz/another.ext2_foo和的存在_baz是有保证的。
手册中对此进行了解释:
当目标模式不包含斜杠(通常不包含)时,在与目标前缀和后缀进行比较之前,会从文件名中删除文件名中的目录名。
和
当先决条件转换为文件名时,主干中的目录将添加到前面,而主干的其余部分将替换
%
因此,像下划线这样的模式_%.ext2与文件名匹配,而不是目录名。所以它不匹配,_foo/test.ext2但它会匹配foo/_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.
Run Code Online (Sandbox Code Playgroud)
解决这个问题最简单的方法是让目标包含斜杠。如果您可以将输出移动到其他地方,您可以这样做,即:
$ cat Makefile
OBJDIR := obj
$(OBJDIR)/_%.ext2: bar/%.ext1
echo Making $@ from $<
$ make obj/_foo/test.ext2
echo Making obj/_foo/test.ext2 from bar/foo/test.ext1
Making obj/_foo/test.ext2 from bar/foo/test.ext1
Run Code Online (Sandbox Code Playgroud)
甚至
$ 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
Run Code Online (Sandbox Code Playgroud)
如果你不能这样做,你可以尝试通过完整路径引用,即:
$ 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
Run Code Online (Sandbox Code Playgroud)
请注意,使用./不起作用,因为 GNU make./从目标开始的条带使得模式不再匹配:
$ 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.
Run Code Online (Sandbox Code Playgroud)
如果您想让同行评审同事感到紧张,您还可以使用一些第二扩展魔法来生成正确的先决条件名称,例如:
$ 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
Run Code Online (Sandbox Code Playgroud)
注意:%必须通过变量引用$(percent),否则 GNU make 解析器可能会抱怨或误解该patsubst函数。
您的最终方法有效,因为您的最终解决方案是静态模式规则。它不应用相同的“条带目录”方法,而是仅匹配字符串。
| 归档时间: |
|
| 查看次数: |
1392 次 |
| 最近记录: |