.PHONY 模式规则:匹配带有前导斜线的模式
.PHONY pattern rule: match pattern with leading slash
我正在尝试简化 Makefile。在那,我试图有一个删除文件的模式规则:
.PHONY:
rm-%:
rm $*
其中 % 将包含文件名(通常是带前导斜杠的绝对路径)。
然后我只是声明 rm-/some/file 是 make uninstall
的依赖项,并期望 make 匹配此模式规则。
然而,它咬我。我做了一些测试并意识到问题是前导斜杠与该模式规则不匹配:
~/src/test$ cat Makefile
.PHONY:
a-/%:
$(info /$*)
.PHONY:
b-%:
$(info $*)
.PHONY:
foo: a-/as/d
@:
.PHONY:
bar: b-/as/d
@:
~/src/test$ make foo
/as/d
~/src/test$ make bar
make: *** No rule to make target 'b-/as/d', needed by 'bar'. Stop.
~/src/test$
为什么我需要在模式规则中指定前导斜杠(而不是其他斜杠)?
GNU make 文档是这样说的:
the ‘%’ matches any nonempty substring, while other characters match
only themselves
https://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html#Pattern-Intro
编辑: 修复关于 .PHONY:
的一些拼写错误,使用后缀而不是 answers/comments 中建议的前缀,并进一步测试:
正如我最初怀疑的那样,.PHONY:
正在做一些奇怪的事情:
~/src/test/$ tree a b c d
a
└── a
b
└── b
c
└── c
d
└── d
0 directories, 4 files
~/src/test$ cat Makefile
%-rmdir:
rmdir $(@D)
%-rm:
rm $*
.PHONY: ./a/.-rmdir
./a/.-rmdir: ./a/a-rm
.PHONY: ./b/-rmdir
./b/-rmdir: ./b/b-rm
./c/.-rmdir: ./c/c-rm
./d/-rmdir: ./d/d-rm
.PHONY: foo
foo: ./a/.-rmdir ./b/-rmdir ./c/.-rmdir ./d/-rmdir
$(info foo)
~/src/test$ make foo
rm a/a
rm b/b
rm c/c
rmdir c
rm d/d
rmdir d
foo
您需要检查 How Patterns Match 上的部分,您会在其中找到以下文本:
When the target pattern does not contain a slash (and it usually does
not), directory names in the file names are removed from the file name
before it is compared with the target prefix and suffix.
(以及有关其工作原理的更多详细信息)。
根据文档和@MadScientist 的回答,这是 how patterns match。但解决方法非常简单:用后缀规则替换您的前缀规则,这样目录修改就不会妨碍了。
示例:
$ cat Makefile
.PHONY: %-clean
%-clean:
$(info $*)
.PHONY: foo
foo: /as/d-clean
@:
.PHONY: bar
bar: ./as/d-clean
@:
输出:
$ make foo
/as/d
$ make bar
as/d
顺便说一句。请注意 .PHONY:
需要目标名称,它不会自动应用于后面的目标。
我正在尝试简化 Makefile。在那,我试图有一个删除文件的模式规则:
.PHONY:
rm-%:
rm $*
其中 % 将包含文件名(通常是带前导斜杠的绝对路径)。
然后我只是声明 rm-/some/file 是 make uninstall
的依赖项,并期望 make 匹配此模式规则。
然而,它咬我。我做了一些测试并意识到问题是前导斜杠与该模式规则不匹配:
~/src/test$ cat Makefile
.PHONY:
a-/%:
$(info /$*)
.PHONY:
b-%:
$(info $*)
.PHONY:
foo: a-/as/d
@:
.PHONY:
bar: b-/as/d
@:
~/src/test$ make foo
/as/d
~/src/test$ make bar
make: *** No rule to make target 'b-/as/d', needed by 'bar'. Stop.
~/src/test$
为什么我需要在模式规则中指定前导斜杠(而不是其他斜杠)?
GNU make 文档是这样说的:
the ‘%’ matches any nonempty substring, while other characters match only themselves
https://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html#Pattern-Intro
编辑: 修复关于 .PHONY:
的一些拼写错误,使用后缀而不是 answers/comments 中建议的前缀,并进一步测试:
正如我最初怀疑的那样,.PHONY:
正在做一些奇怪的事情:
~/src/test/$ tree a b c d
a
└── a
b
└── b
c
└── c
d
└── d
0 directories, 4 files
~/src/test$ cat Makefile
%-rmdir:
rmdir $(@D)
%-rm:
rm $*
.PHONY: ./a/.-rmdir
./a/.-rmdir: ./a/a-rm
.PHONY: ./b/-rmdir
./b/-rmdir: ./b/b-rm
./c/.-rmdir: ./c/c-rm
./d/-rmdir: ./d/d-rm
.PHONY: foo
foo: ./a/.-rmdir ./b/-rmdir ./c/.-rmdir ./d/-rmdir
$(info foo)
~/src/test$ make foo
rm a/a
rm b/b
rm c/c
rmdir c
rm d/d
rmdir d
foo
您需要检查 How Patterns Match 上的部分,您会在其中找到以下文本:
When the target pattern does not contain a slash (and it usually does not), directory names in the file names are removed from the file name before it is compared with the target prefix and suffix.
(以及有关其工作原理的更多详细信息)。
根据文档和@MadScientist 的回答,这是 how patterns match。但解决方法非常简单:用后缀规则替换您的前缀规则,这样目录修改就不会妨碍了。
示例:
$ cat Makefile
.PHONY: %-clean
%-clean:
$(info $*)
.PHONY: foo
foo: /as/d-clean
@:
.PHONY: bar
bar: ./as/d-clean
@:
输出:
$ make foo
/as/d
$ make bar
as/d
顺便说一句。请注意 .PHONY:
需要目标名称,它不会自动应用于后面的目标。