我正在使用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
没有做到这一点,当我这样做时,Make仍然会删除%.fig.py
!
答案 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/bar1
和foo2/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建议的那样。这需要我删除珍贵的文件,如果我想重建数字,但我可以忍受。