Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile忽略模式中包含子目录的模式规则_Makefile_Gnu Make - Fatal编程技术网

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