标记辅助目标并检查编辑

时间:2013-06-18 11:13:37

标签: makefile

我正在使用Make来提取和生成科学报告的数字。它是声明性的,非常适合写下数据的位置以及如何将数据转换为数字。我的makefile看起来有点像这样(plots是主要目标):

plots: some_specific_figure.png some_other_figure.png yet_another_figure.png

%.png: %.fig.py
    $(GENFIG) $<

%.fig.py: %.raw.fig.py
    cp $< $@

some_specific_figure.raw.fig.py:
    $(GETDATA) some/super/specific/simulation/results/directory/ $@

some_other_figure.raw.fig.py:
    $(GETDATA) some/different/arbitrary/simulation/directory/ $@

yet_another_figure.raw.fig.py:
    # etcetera

现在,最后,我想手动编辑这些*.fig.py文件(some_specific_figure.fig.pysome_other_figure.fig.py等),因为原始提取的数据不存在不包含正确的绘图/轴/线标题,轴范围等。

我想要做什么,是

  • 如果数据目录不存在,则从数据目录中提取%.fig.raw.py。将其复制到%.fig.py以便稍后进行修改。
  • 构建后保留%.fig.py文件。
  • 只需从现有%.png构建%.fig.py,而不使用%.raw.fig.py文件覆盖它。如果%.fig.py存在或已被编辑,那么Make应该只使用它。

这样做的简单/简洁方法是什么?标记.SECONDARY: %.fig.py没有做到这一点,当我这样做时,Make仍然会删除%.fig.py

2 个答案:

答案 0 :(得分:2)

<强>扩展

如果我理解你的问题,你需要制作%.fig.py(如果它不存在)并保持原样,如果它存在的话。

首先,如果您不想删除中间文件,则应将它们定义为珍贵文件:

.PRECIOUS: %.fig.py %.fig.raw.py

另一方面,如果%.fig.py依赖于%.raw.fig.py,如果编辑后者,则会重建它。因此,只有在处理%.fig.py时,才能使%.raw.fig.py不依赖并创建%.fig.py

示例Makefile:

#!/usr/bin/make -f

.PHONY: plots clean

plots: a.png

%.png: %.fig.py
        echo +$@+ $<
        touch $@

%.fig.py: 
        echo Construct $(@:.fig.py=.fig.raw.py)
        touch $(@:.fig.py=.fig.raw.py)
        echo +$@+
        touch $@

.PRECIOUS: %.fig.py

clean:
        echo [Clean]
        rm -f *.png *.fig.py *.fig.raw.py

如果a.png不存在则输出:

$ ./a.mak 
echo Construct a.fig.raw.py
Construct a.fig.raw.py
touch a.fig.raw.py
echo +a.fig.py+
+a.fig.py+
touch a.fig.py
echo +a.png+ a.fig.py
+a.png+ a.fig.py
touch a.png

所以它创建a.fig.raw.py,然后是a.fig.py,最后是a.png`。中间文件不会被删除。

编辑a.fig.raw.py时的输出(我使用touch a.fig.raw.py):

$ touch a.fig.raw.py
$ ./a.mak 
make: Nothing to be done for `plots'.

编辑a.fig.py时的输出:

$ touch a.fig.py; ./a.mak
echo +a.png+ a.fig.py
+a.png+ a.fig.py
touch a.png

在这种情况下,a.png会重新制作,但根本不会触及a.fig.raw.py

<强> ADDED

其他有趣的问题如何完成makefile依赖于目录。例如。某些文件已创建到目录foo1/bar1foo2/bar2中。如果写入其中一个新文件,则应创建文件foo<n>_bar<n>.png

这是makefile:

#!/usr/bin/make -f

.PHONY: clean plots

DIRS := foo1/bar1 foo2/bar2
TARGETS := $(addsuffix .png,$(subst /,_,$(DIRS)))

plots: $(TARGETS)

# Avoid to try to remake the makefile itself
a.mak: ;
# Avoid to try to remake the dirs
$(DIRS): ;

%.png: %.fig.py
        touch "$@"

%.fig.py: %.raw.fig.py
        if [ -s "$@" ]; then touch "$@"; else cp "$<" "$@"; fi

.PRECIOUS: %.fig.py %.raw.fig.py

clean:
        echo [Clean]
        rm -f *.png *.fig.py *.fig.raw.py

.SECONDEXPANSION:
%.raw.fig.py: $$(subst _,/,%)
        echo Check dirs
        touch "$@"

测试输出:

$ ./a.mak clean
echo [Clean]
[Clean]
rm -f *.png *.fig.py *.fig.raw.py

$ ./a.mak      
echo Check dirs
Check dirs
touch foo1_bar1.raw.fig.py
touch foo1_bar1.fig.py
touch foo1_bar1.png
echo Check dirs
Check dirs
touch foo2_bar2.raw.fig.py
touch foo2_bar2.fig.py
touch foo2_bar2.png

$ touch foo1

$ ./a.mak
make: Nothing to be done for `plots'.

$ touch foo1/bar1

$ ./a.mak
echo Check dirs
Check dirs
touch foo1_bar1.raw.fig.py
touch foo1_bar1.fig.py
touch foo1_bar1.png

$ vim foo1_bar1.fig.py

$ ./a.mak
touch "foo1_bar1.png"

$ ./a.mak
make: Nothing to be done for `plots'.

答案 1 :(得分:0)

我最终做的只是检查%.fig.py是否存在:

%.fig.py: %.raw.fig.py
    test -s $@ || cp $< $@

并标记为.PRECIOUS,正如@TrueY建议的那样。这需要我删除珍贵的文件,如果我想重建数字,但我可以忍受。