【问题标题】:Make dependencies execute multiple times even though the dependency has been run explicitly beforehand即使依赖项已事先显式运行,也使依赖项执行多次
【发布时间】:2018-11-19 01:35:27
【问题描述】:

我有一个 makefile,它由几个具有一些依赖关系的目标组成。 一个小结构如下所示

pgdynamic_setup:
    cd $(PGDYNAMICDIR);  . /opt/Modules/init/sh; module load <tool_name>; totem2 -lmwait $(PGDYNAMIC_APACHE_LN) $(BATCH_NOBATCH) dynamic_setup.tcl | tee -i ./logs/$@.log

pgdynamic_current: pgdynamic_setup
    cd $(PGDYNAMICDIR);  . /opt/Modules/init/sh; module load <tool_name>; <tool_name> dynamic_current.tcl | tee -i ./logs/$@.log

pgdynamic_cdev: pgdynamic_setup
    cd $(PGDYNAMICDIR);  . /opt/Modules/init/sh; module load <tool_name>; <tool_name> dynamic_cdev.tcl | tee -i ./logs/$@.log

pgdynamic_tool: pgdynamic_current
    cd $(PGDYNAMICDIR);  . /opt/Modules/init/sh; module load <tool_name>; <tool_name> dynamic.tcl | tee -i ./logs/$@.log

我没有太多编写 Makefile 的经验。问题是,当我运行make pgdynamic_setup,然后make pgdynamic_current make 执行两个目标(pgdynamic_setuppgdynamic_current)。但由于我已经明确运行pgdynamic_setup,我希望make 只执行目标pgdynamic_current

这不是 MWE。当我用一些touchcat 命令尝试相同的概念时,它只是按预期工作。我猜这个结构有问题。任何人都可以在结构的基础上帮助我,因为我无法提供一个有效的 MWE。抱歉,提前谢谢。

【问题讨论】:

    标签: makefile dependencies


    【解决方案1】:

    通过比较您计算机上存在的文件的时间戳来制作作品。它不维护一些已运行规则的内部数据库:它将先决条件文件的时间戳与目标文件的时间戳进行比较。

    如果您使用touch 编写此makefile,您会将目标创建为本地磁盘上的文件,因此make 可以查看哪些规则已运行,哪些未运行。

    在您的“真实”示例中,您没有创建任何文件(您的规则不会生成名为 pgdynamic_toolpgdynamic_current 等的文件),因此 make 不知道上次运行这些规则的时间。

    如果你想让 make 跳过已经运行的规则,你必须在运行时在磁盘上创建具有这些名称的文件,以便 make 知道它。您可以使用touch $@ 来执行此操作。

    ETA 你想要这样的东西:

    pgdynamic_setup:
            cd $(PGDYNAMICDIR);  . /opt/Modules/init/sh; module load <tool_name>; totem2 -lmwait $(PGDYNAMIC_APACHE_LN) $(BATCH_NOBATCH) dynamic_setup.tcl | tee -i ./logs/$@.log
            touch $@
    

    【讨论】:

    • 所以我将目标规则更改为:pgdynamic_setup: cd $(PGDYNAMICDIR);触摸 $@; . /选择/模块/初始化/sh;模块加载 ;图腾2 -lmwait $(PGDYNAMIC_APACHE_LN) $(BATCH_NOBATCH) dynamic_setup.tcl | tee -i ./logs/$@.log pgdynamic_current: pgdynamic_setup cd $(PGDYNAMICDIR);触摸 $@; . /选择/模块/初始化/sh;模块加载 ; dynamic_current.tcl | tee -i ./logs/$@.log 但它仍在运行 pgdynamic_setup 虽然它已经运行了。
    • 我知道出了什么问题。对于每个目标,我都会进入另一个目录并在那里创建一些文件并做一些工作。所以 touch$@ 需要在我的案例的开头。现在的问题是,由于我的工作被分派到 lsf,我再也看不到这些 pgdynamic_setup 或 pgdynamic_spcurrent 文件了。因此,完全没有机会通过删除 pgdynamic_setup 或 pgdynamic_spcurrent 文件来强制 make 重新运行目标。我在这里遇到了一个混乱的情况:(
    • 我示例中的前 3 个规则在 $(PGDYNAMICDIR) 目录中创建了 3 个特定文件。如何使“make”依赖于这些文件?
    • 您不应该先触摸文件。如果您这样做,那么即使命令失败并且不会重新运行,它们也会被更新。 make recipe 中的每一行都在不同的 shell 中运行,因此您应该在每个文件的 recipe 末尾添加一个新行,即 touch $@。这确保了它仅在前面的命令成功并且它将触及正确的文件时运行(因为没有cd 有效)。
    • 我真的不明白你关于“3 条规则”的最后评论是什么意思。在 cmets 中讨论复杂的事情非常困难。我建议您使用更多详细信息更新您的问题或提出一个新问题。
    猜你喜欢
    • 2017-12-13
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 2021-02-02
    • 2015-02-28
    • 2015-05-07
    • 2022-09-23
    相关资源
    最近更新 更多