【问题标题】:Declare all targets PHONY声明所有目标 PHONY
【发布时间】:2017-11-13 12:55:13
【问题描述】:

考虑一个很长的makefile 有许多目标,所有目标都是PHONY(意味着目标名称不代表现有文件)。

我可以:

.PHONY: a
a:
    do someting a

.PHONY: b
b:
    do someting b

.PHONY: c
c:
    do someting c

或者:

.PHONY: a b c
a:
    do someting a

b:
    do someting b

c:
    do someting c

第一个选项比较麻烦,第二个选项很容易出错,以后我添加目标时忘记声明为PHONY

是否有一种标准方法可以将makefile 中的所有目标声明为PHONY

【问题讨论】:

  • 如果 all 目标都是 PHONYmake 不是正确的工具,因为它与普通脚本相比没有任何优势... @ 987654331@ 将精确地制作命令行假冒给出的目标,如果您的目标都不依赖于其他目标,这将适用于您。
  • 我同意菲利克斯的观点。而且我认为第二个版本比第一个版本更标准。我认为这不容易出错,您应该以某种方式控制 Makefile 中的内容,无论其大小如何。
  • 我不同意 Felix 和 TimF。 Make 确实比“普通脚本”具有优势,因为您可以使用 make 来指定使用依赖项运行配方和外部脚本的顺序。您还可以使用 Makefile 作为一种干净的方式来存储和调用单个文件中的多个配方/脚本。这样,Makefile 本质上是一个命令目录,您可能不想一遍又一遍地键入。目标名称可以用作实际命令/脚本名称的别名。
  • @FelixPalmen 太没意义了,我一直都出于这个原因使用它。 Make 的语法比将参数传递给脚本要简单得多,然后必须通过 switch 语句的丑陋语法来解释。那么为什么不使用.PHONY 来达到它的目的呢? - 每次都会触发一个目标,无论它是否过时。关于 Make 的“整体思想”,你忘了提到“整体思想”的另一部分……依赖管理。就我而言,这就是为什么我更喜欢使用 Make 而不是在 shell 脚本中重写(和调试)依赖逻辑。
  • 这是 Facebook 等公司按照我描述的方式使用 Makefile 的示例 => github.com/graphql-python/graphene/blob/master/docs/Makefile

标签: makefile phony-target


【解决方案1】:

如果真的所有目标都是PHONY,这有点毫无意义。 make 的意思是“做必要的事情来更新我的输出”,如果什么是必要的? 的答案总是相同的,简单的脚本就可以了相同的工作,开销更少。

话虽如此,我可以想象这样一种情况,打算在命令行中给出的所有目标都应该是 PHONY -- 假设您要构建一些文档,例如这个:

all: doc1.pdf doc2.pdf doc3.pdf doc4.pdf doc5.pdf

manuals: doc3.pdf doc4.pdf

faqs: doc1.pdf

designdocs: doc2.pdf

apidocs: doc5.pdf

developerdocs: doc2.pdf doc5.pdf

userdocs: doc1.pdf doc3.pdf doc4.pdf

%.pdf: %.md
     $(somedocgenerator) -o $@ $<

那么您可以执行以下操作:

.PHONY: all $(MAKECMDGOALS)

这将动态地使命令行中给出的任何目标PHONY。请注意,您必须在此处包含您的 默认目标,因为可以在不明确给出的情况下调用它,只需键入 make

我不会推荐这种方法,因为它有两个缺点:

  • 对于不同风格的make,它的可移植性较差。
  • 如果有人决定make 像这里make doc3.pdf 这样的特定输出文件,它会行为不端
  • 如果您决定让您的一个 PHONY 目标依赖于另一个 PHONY 目标,也会出现问题。

因此,最好采用一行声明所有 PHONY 目标的方法。如果您的Makefile 真的很大,您可以将其拆分为多个文件并使用include -- 并在每个文件中有一个.PHONY: 行。

【讨论】:

  • 我不同意包含所有虚假目标的 Makefile 应该被任意脚本替换的前提。 Make 是一个非常多产的工具,它已成为构建大多数项目的事实上的标准。用项目中的任意构建脚本替换它会违反此标准,并可能在开发人员和消费者之间造成混淆。
  • 在您的项目中使用 Make 进行部门管理非常棒! Make 是一个很棒的工具,鉴于 2020 年软件开发的性质,逐个文件构建可能不是大多数人试图解决的用例。 .PHONY: % 会做大多数人想要的。
  • @JuliusEcker .PHONY: % 对我不起作用(GNU make 4.3)
  • make 的自动完成功能和已安装的巨大机会使其成为在项目中对工作流脚本进行分组的非常方便的工具,即使这不是该工具的预期用途。
【解决方案2】:

One way to do it:

.PHONY: $(shell sed -n -e '/^$$/ { n ; /^[^ .\#][^ ]*:/ { s/:.*$$// ; p ; } ; }' $(MAKEFILE_LIST))

即使对于提及为依赖项的目标也能完美运行。

【讨论】:

  • 实际回答问题
【解决方案3】:

只需使用MAKEFLAGS 并像这样设置选项--always-make

MAKEFLAGS += --always-make

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 2011-05-08
    • 2020-01-08
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多