0

我正在使用 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.py,some_other_figure.fig.py等),因为提取的原始数据不包含正确的绘图/轴/线标题、轴范围等。

我想做的事情是

  • %.fig.raw.py如果数据目录不存在,则从数据目录中提取。复制它以%.fig.py允许以后编辑。
  • 构建后保留%.fig.py文件。
  • 只需%.png从现有文件构建%.fig.py而不用%.raw.fig.py文件覆盖它。如果%.fig.py存在或已被编辑,Make 应该只使用它。

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

4

2 回答 2

2

扩展

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

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

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

另一方面,如果%.fig.py依赖于%.raw.fig.py它将被重建,如果后者被编辑。所以 make%.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.png` a.fig.py。中间文件不会被删除。

输出如果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根本没有被触及。

添加

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

这是生成文件:

#!/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'.
于 2013-06-18T14:05:26.143 回答
0

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

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

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

于 2013-06-19T15:53:04.327 回答