【问题标题】:How can I create a time-based Makefile rule?如何创建基于时间的 Makefile 规则?
【发布时间】:2011-01-01 22:02:20
【问题描述】:

我想要一个 Makefile 目标,它仅在目标文件早于某个时间间隔时才重新构建。

例如,假设我有某种方法可以生成一个有效期为一天的密钥,但生成它需要很长时间。我可以在每次需要时重新生成它:

.PHONY: key
key:
    sleep 5 && echo generated > key
foo: key
    echo foo
bar: key
    echo bar

但是,在一天中,我可能会多次输入make foomake bar。每次等待都很烦人,我宁愿每天只吃一次这个费用。

【问题讨论】:

    标签: time makefile dependencies


    【解决方案1】:

    让生成的文件依赖于某个虚拟文件,例如 key-timestamp,然后每天都有一个 cron 作业 touch 该文件。

    【讨论】:

    • 虽然我相信这会起作用,但它需要每个想要编译此代码的开发人员进行额外的设置。如果没有设置 cron 条目,那么只要密钥过期,构建就会开始失败。
    【解决方案2】:

    要在特定时间后重建一个 make 目标,您需要一个帮助文件,依赖它并强制触摸帮助文件,例如(示例是每天):

    target:  target.helper
        script-or-rule
    
    target.helper: FORCE
        @touch -d -1day $@
    
    FORCE:
    

    【讨论】:

    • 这似乎需要 GNU touch,就像在 macOS 上一样:touch: illegal option -- d
    • 这似乎不能解决问题。如果我将sleep 5 添加到您的任一规则并运行make target,则每次运行需要5 秒,而不是5 秒一次然后立即运行。
    • 以这种方式添加睡眠命令应该只会延迟 5 秒而已。恕我直言,这不会导致您描述要去的地方。 touch 命令的可能替代品可能是 perl 此处如:@perl -e ' $$t = time - 3600*24; utime $$t, $$t, $@' 请注意,此行已被引用为生成文件顺便说一句。 “.PHONY”也是make 命令的gnu 扩展。
    • 是的,每执行一次make就会延迟执行5秒。问题的重点:我宁愿每天只吃一次这个费用。 5 秒应该每 24 个周期出现一次。
    • 对不起,我迷路了。我确信我的 Makefile 修复了您的初始请求“仅当目标文件早于某个时间间隔时才重建”。不需要睡眠,不需要 cronjob,只需要 Makefile,我这里的示例时间间隔是“1 天”。但是,在我看来,您提出的问题陈述略有不同。如果您能在这种情况下重新表述您的问题陈述,将会有所帮助。
    【解决方案3】:
    .PHONY: key.update key.check
    
    foo: key.check
        echo foo
    
    bar: key.check
        echo bar
    
    key.check: key
        @find key -mmin +1440 -exec make key.update \;
    
    key:
        make key.update
    
    key.update:
        sleep 5 && echo generated > key
    

    应该按预期工作,如果您无权访问find,则必须将其替换为类似的内容。基本上,将其替换为能够检测到该密钥已在 1 天或更长时间前被最后修改的内容。

    .PHONY 将强制规则运行。

    我还研究了order-only-prerequisites,这需要运行两次手头的makefile,每24小时只更新一次密钥。不太实用。

    然而,这是一个技巧,我不建议将其作为 makefile 的正常使用。

    【讨论】:

      【解决方案4】:

      如何保留在 make 运行期间计算的哨兵文件?

      sentinel_file_prefix  = sentinel_file.stamp
      sentinel_file         = $(sentinel_file_prefix).$(shell date +%Y%m%d)
      
      file_to_regenerate_every_day: $(sentinel_file)
          echo Usual make recipe
      
      $(sentinel_file):
          - rm $(sentinel_file_prefix).* 
          touch $@
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-11
        • 2014-01-23
        • 2015-02-04
        • 1970-01-01
        • 1970-01-01
        • 2014-09-27
        • 2021-04-01
        • 1970-01-01
        相关资源
        最近更新 更多