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

Kur*_*fle 6 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)---$@    
Run Code Online (Sandbox Code Playgroud)

(是的,我在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

所以我的ts变量迷失了......

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

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

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

timestamp:
        @echo `/bin/date "+%Y-%m-%d---%H-%M-%S"` > .ts
Run Code Online (Sandbox Code Playgroud)

然后:

%.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`---$@    
Run Code Online (Sandbox Code Playgroud)

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


更新:

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

考虑一下这个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)
Run Code Online (Sandbox Code Playgroud)

当我运行时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
Run Code Online (Sandbox Code Playgroud)

不是我想要的!我要这个:

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
Run Code Online (Sandbox Code Playgroud)

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


解决方案/更新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)
Run Code Online (Sandbox Code Playgroud)

输出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
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 11

不要ts以目标为条件timestamp:

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)---$@
Run Code Online (Sandbox Code Playgroud)

这与使用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
$
Run Code Online (Sandbox Code Playgroud)

或者,使用时间戳之前和之后使其更清晰(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
$
Run Code Online (Sandbox Code Playgroud)