【问题标题】:Best practice for makefile calling other makefilemakefile 调用其他 makefile 的最佳实践
【发布时间】:2020-08-22 23:22:04
【问题描述】:

我有一个 Makefile,它针对特定目标调用另一个 Makefile。假设主 Makefile 包含

some_dir/some_target:
    cd some_dir && make some_target

并且 some_dir/Makefile 包含

some_target: file1 file2
    do_stuff

这是我的难题:主 Makefile 中目标的依赖关系应该是什么?如果我没有放置依赖项,那么根据 GNU make 手册,some_dir/Makefile 只会在 some_dir/some_target 不存在时被调用。我可以从some_dir/Makefile 复制依赖项。但是,这会造成以后更改子目录的 Makefile 中的依赖关系并忘记更新主 Makefile 的危险。

有没有办法告诉主Makefile,“我不知道目标是否过期。去问另一个Makefile”?

【问题讨论】:

    标签: makefile


    【解决方案1】:

    有没有办法告诉主Makefile,“我不知道目标是否过期。去问另一个Makefile”?

    没有专门用于委派给另一个 makefile 的规定,但您可以通过确保始终运行相关目标的配方来获得类似的结果。对此有一些机制和约定。

    老派的方法是声明对不存在且从未实际构建的目标的依赖。您可能会看到这样的目标被命名为FORCE,尽管这只是一个约定。名称没有直接意义。示例:

    some_dir/some_target: FORCE
        cd some_dir && make some_target
    
    # Dummy target
    FORCE:
    

    只要工作目录中实际上没有名为FORCE 的文件,FORCE 目标最初将被认为已过期,因此将构建每个直接或间接依赖它的目标(另见下文)。

    当然,其中有一个弱点:如果确实创建了一个名为 FORCE 的文件怎么办?不管这不太可能,如果它发生,它会破坏整个计划。一些make 的实现,尤其是GNU 的,有一种特定于实现的方法来解决这个问题。 GNU 的方法是识别一个名为.PHONY 的特殊内置目标(不要忽略前面的.)。 .PHONY 的所有先决条件在每次构建时都被认为是过时的,尽管文件系统上有任何内容。由于 make 不承认该约定的实现不太可能因其使用而受到困扰,因此使用它几乎没有缺点:

    .PHONY: FORCE
    

    您也可以跳过FORCE,直接声明some_dir/some_target 本身是假的,正如另一个答案所暗示的那样,但这至少存在两个问题:

    • 不是通常意义上的假货。您希望构建该目标。因此,将其声明为虚假会令人困惑。

    • 如果您碰巧尝试将这种方法与无法识别.PHONYmake 一起使用,那么整个方案就会崩溃。如果您改为使用中间假目标(例如上面的FORCE),那么即使使用这样的makes,您的makefile 仍然可以工作,除非在极少数情况下会创建一个与虚拟目标名称相同的文件。

    但请注意,无论实施如何,任何此类方案都有一个明显的缺点:如果您强制 some_dir/some_target 在每次构建时都被视为过期,那么子make 将无条件运行,那么直接或间接依赖于some_dir/some_target 的所有其他目标也将每次都重新构建。另一方面,如果你不强制重建它,那么它可能不会在应该重建的时候重建,正如你已经认识到的那样。这是著名论文Recursive Make Considered Harmful 的主题。那么,作为替代方案,您应该考虑使用递归make

    【讨论】:

    • "如果你强制 some_dir/some_target 在每次构建时都被认为是过时的......那么直接或间接依赖于 X 的所有其他目标也将每次都重新构建......作为替代方案,那么,您应该考虑不使用递归 make” - 对于值得处理的问题,我建议使用 make 以外的其他东西(CMake 或 Meson),而不是“扁平化”makefile。
    【解决方案2】:

    一个选项是强制子制作:

    dummy := $(shell $(MAKE) -C some_dir some_target)
    
    top_target: some_dir/some_target
        ...
    

    【讨论】:

      【解决方案3】:

      “我不知道目标是否已过时” - 你可以使用.PHONY

      .PHONY: some_dir/some_target
      some_dir/some_target:
          cd some_dir && make some_target
      

      https://www.gnu.org/software/make/manual/html_node/Special-Targets.html#Special-Targets:

      特殊目标 .PHONY 的先决条件被认为是虚假目标。当需要考虑这样的目标时,make 将无条件地运行它的配方,无论是否存在具有该名称的文件或它的最后修改时间是什么。

      【讨论】:

        猜你喜欢
        • 2015-10-16
        • 2010-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多