如何在Makefile运行期间重用包含时间戳的变量

时间:2014-01-12 23:19:44

标签: makefile

我正在编写一个简单的Makefile来处理我从一系列Markdown文本源创建的文档(PDF,HTML,LaTeX,EPUB,DOCX)。

现在我想将一些中间文件作为副本备份到一个单独的目录中,在过程中通过向其名称添加时间戳来重命名它们。

但是,我没有让它发挥作用。我定义了一个时间戳变量,如下所示:

.PHONY: timestamp
timestamp: ts := `/bin/date "+%Y-%m-%d---%H-%M-%S"`
timestamp:
        @echo Timestamp is $(ts)

%.tex: %.mmd timestamp
        # My commands to create the LaTeX go here. (Simplified for Stackoverflow)
        pandoc  -t latex  -f markdown  -o $(LATEXDIR)/$@  $<
        $(CP) $(LATEXDIR)/$@ $(BACKUPS)/$(ts)---$@    

(是的,我在Makefile中使用了标签 - 不要被上面的复制所迷惑,如果你从它上面复制'''''',那么

当我运行make timestamp时,我会看到预期的输出,例如Timestamp is 2014-11-01---22-11-10

但是正在运行make bookdraft.tex,...

  1. ...我的LaTeX文件最终在$(LATEXDIR)
  2. ...但备份副本的名称为---bookdraft.tex,而不是2014-11-01---22-11-10---bookdraft.tex
  3. 所以我的ts变量丢失了......

    我是Makefiles的初学者,几个小时的谷歌搜索和实验并没有把我带到任何地方。

    注意,我可以在当前目标内动态设置时间戳。但是,这将更改在同一make调用期间备份的每个其他目标的时间戳。但这不是我想要的 - 我希望每次调用make时将时间戳固定为相同的值。所以我想以某种方式在Makefile的开头设置timestamp变量,然后在make的当前运行中重复使用它。 (make的下一次运行应该重新设置值。)

    我想出了一个临时的解决方法,将时间戳写入名为.ts的文件中,然后再从那里读取它:

    timestamp:
            @echo `/bin/date "+%Y-%m-%d---%H-%M-%S"` > .ts
    

    然后再说:

    %.tex: %.mmd timestamp
            # My commands to create the LaTeX go here. (Simplified for Stackoverflow)
            pandoc  -t latex  -f markdown  -o $(LATEXDIR)/$@  $<
            $(CP) $(LATEXDIR)/$@ $(BACKUPS)/`/bin/cat .ts`---$@    
    

    但是,我不太喜欢这种管道磁带方法 - 我正在寻找一种更优雅的Makefile-ish解决方案。


    更新

    乔纳森莱弗勒提出了一个解决方案,但这不符合我的要求......或者他不明白我想要什么,因为我没有解释得很好,或者我没有正确地实施他的建议。无论如何,我现在可以更好地说明我不想要的东西。

    考虑这个 Makefile.leffler (在代码中正确完成<tabs>):

    ts := `/bin/date "+%Y-%m-%d---%H-%M-%S"`
    
    timestamp:
         @echo Timestamp is $(ts)
         @sleep 10
         @echo Timestamp is $(ts)
    
    dummy:
         @sleep 10
         @echo Timestamp is $(ts)
         @sleep 10
         @echo Timestamp is $(ts)
    

    当我运行make -f Makefile.leffler timestamp dummy时,输出为:

    Timestamp is 2014-01-13---01-58-43
    Timestamp is 2014-01-13---01-58-53
    Timestamp is 2014-01-13---01-59-03
    Timestamp is 2014-01-13---01-59-13
    

    那就是我想要的东西!我想要这个:

    Timestamp is 2014-01-13---01-58-43
    Timestamp is 2014-01-13---01-58-43
    Timestamp is 2014-01-13---01-58-43
    Timestamp is 2014-01-13---01-58-43
    

    我希望我的目标现在得到更好的澄清。


    解决方案/更新2:

    在修改了Jonathan的原始答案后,现在这是Makefile示例的解决方案:

    ts := $(shell /bin/date "+%Y-%m-%d---%H-%M-%S")
    
    timestamp:
         @echo Timestamp is $(ts)
         @sleep 10
         @echo Timestamp is $(ts)
    
    dummy:
         @sleep 10
         @echo Timestamp is $(ts)
         @sleep 10
         @echo Timestamp is $(ts)
    

    make -f Makefile.leffler timestamp dummy的输出现在完全符合我的要求:

    Timestamp is 2014-01-13---02-44-11
    Timestamp is 2014-01-13---02-44-11
    Timestamp is 2014-01-13---02-44-11
    Timestamp is 2014-01-13---02-44-11
    

1 个答案:

答案 0 :(得分:11)

不要让tstimestamp

为目标
ts := $(shell /bin/date "+%Y-%m-%d---%H-%M-%S")

timestamp:
    @echo Timestamp is $(ts)

%.tex: %.mmd
    # My commands to create the LaTeX go here. (Simplified for Stackoverflow)
    pandoc -t latex -f markdown -o $(LATEXDIR)/$@ $<
    $(CP) $(LATEXDIR)/$@ $(BACKUPS)/$(ts)---$@

这与先前提出的解决方案不同,它使用GNU make $(shell ...)函数。定义宏时会对此进行评估。通过此更改,修订问题中测试makefile的输出(例如):

$ make -f ts.mk
Timestamp is 2014-01-12---17-16-35
Timestamp is 2014-01-12---17-16-35
$ make -f ts.mk timestamp dummy
Timestamp is 2014-01-12---17-16-53
Timestamp is 2014-01-12---17-16-53
Timestamp is 2014-01-12---17-16-53
Timestamp is 2014-01-12---17-16-53
$

或者,在时间戳之前和之后使其更清晰(10秒是一个非常长的延迟,有时!),你可能会得到:

$ date; make -f ts.mk timestamp dummy; date
Sun Jan 12 17:19:02 PST 2014
Timestamp is 2014-01-12---17-19-02
Timestamp is 2014-01-12---17-19-02
Timestamp is 2014-01-12---17-19-02
Timestamp is 2014-01-12---17-19-02
Sun Jan 12 17:19:32 PST 2014
$