【问题标题】:.PHONY pattern rule: match pattern with leading slash.PHONY 模式规则:匹配模式与前导斜杠
【发布时间】:2021-06-08 08:53:57
【问题描述】:

我正在尝试简化 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 文档是这样说的:

'%' 匹配任何非空子字符串,而其他字符匹配 只有他们自己

https://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html#Pattern-Intro


编辑:修正一些关于 .PHONY: 的拼写错误,使用答案/cmets 中建议的后缀而不是前缀,并进一步测试:

正如我最初所怀疑的那样,.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

【问题讨论】:

  • 请注意,我不知道您在.PHONY pattern rule 的问题标题中是什么意思,但是您没有在此处声明 anything .PHONY,因为它的先决条件列表是空的。但是,无论如何,虚假与您的问题无关。
  • @MadScientist D'oh,这是一个错字。无论如何,我只是添加了该信息以防它触发一些不同的行为,但我想它不会。
  • @MadScientist,你能回顾一下我添加的测试吗?看起来 .PHONY: 正在做某事...
  • 询问时请清楚说明您显示的结果有什么问题(您期望的不同)。您需要花费大量时间来解决您试图自行解决的问题。但是,是的,正如其他问题所提到的,.PHONY 目标永远没有资格通过隐式规则进行查找。这是声明目标.PHONY: 以提高性能的主要原因之一。如果您只关心在不提高性能的情况下确保重建,您可以使用 FORCE 技巧。
  • 我关于“不做任何事情”的原始评论仅涉及您最初的问题/makefile,其中.PHONY 目标没有先决条件。那是无操作的。

标签: makefile gnu-make


【解决方案1】:

您需要检查How Patterns Match 上的部分,您会在其中找到此文本:

当目标模式不包含斜杠时(通常包含 不),文件名中的目录名从文件名中删除 在与目标前缀和后缀进行比较之前。

(以及有关其工作原理的更多详细信息)。

【讨论】:

  • 所以,我需要创建 %.rm 和 %.rmdir 形式的规则来解决这个问题,对吧?其中 % 是要删除的文件或目录的名称
  • 应该可以。或者,像您一样包含/:通过在模式中添加/,您可以删除上面的特殊情况处理。
  • 那个(包括开头的 /)又咬了我一口:rm-./as/d/f 不符合任何规则
【解决方案2】:

根据文档和@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: 需要目标名称,它不会自动应用于后面的目标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2013-05-15
    • 2012-07-17
    • 2022-11-10
    • 1970-01-01
    相关资源
    最近更新 更多