规则使用gnumake对新生成的文件运行命令

时间:2017-07-04 09:44:19

标签: gnu-make

我是make的新手。我有一个生成三个乳胶文件的perl脚本。我想创建一个makefile来执行perl脚本,然后在新生成的tex文件上运行lualatex。到目前为止,我有以下内容:

make:
    perl diff.pl
pdf:
    make
    $(eval LIST := $(shell ls *.tex))
    lualatex $(LIST).tex
    make clean

clean:
    rm -rf *.log *.aux

输出:

lualatex FLAT_FLAT_AVDD.tex FLAT_FLAT_VDD.tex FLAT_FLAT_VSS.tex.tex

我只得到一个pdf FLAT_FLAT_AVDD.pdf 。 如何在所有文件上运行lualatex? 我可以声明三个变量,然后运行make。但是,我该如何自动化呢? make中是否有循环概念?使用"硬编码"实现这一目标的更好方法是什么?文件名?

感谢。 编辑: 我试图合并foreach

make:
    perl diff.pl

list: 
    $(eval LIST := $(shell ls *.tex))

pdf:
    make list
    $(foreach tex,$(LIST),$(lualatex $(tex)))
    make clean

clean:
    rm -rf *.log *.aux

然后我跑了,make pdf 我在终端获得了以下输出。

dedehog01:tislam1:243 > make pdf
make list
make[1]: Entering directory `/home/tislam1/Documents/THESIS/Script_v0.1/BOX_approach/Modified_Layout_mesh/IR_Report_mesh/flat_flat/make'
make[1]: `list' is up to date.
make[1]: Leaving directory `/home/tislam1/Documents/THESIS/Script_v0.1/BOX_approach/Modified_Layout_mesh/IR_Report_mesh/flat_flat/make'
make clean
make[1]: Entering directory `/home/tislam1/Documents/THESIS/Script_v0.1/BOX_approach/Modified_Layout_mesh/IR_Report_mesh/flat_flat/make'
rm -rf *.log *.aux
make[1]: Leaving directory `/home/tislam1/Documents/THESIS/Script_v0.1/BOX_approach/Modified_Layout_mesh/IR_Report_mesh/flat_flat/make'

2 个答案:

答案 0 :(得分:0)

如果要在每个make调用上运行perl脚本,make就不是很有用了。 shell脚本也可以这样做。但是如果你真的想把所有这些都放到makefile中:

.PHONY: all clean

all:
    perl diff.pl && \
    for t in *.tex; do \
        lualatex $$t; \
    done

clean:
    rm -rf *.log *.aux

否则,您必须事先知道LaTeX来源列表。你应该坚持使用make target-prerequisites理念,即表达所有依赖关系和相应的配方:

LATEXSOURCES := foo.tex bar.tex ... cuz.tex
PDFS := $(patsubst %.tex,%.pdf,$(LATEXSOURCES))

all: $(PDFS)

$(LATEXSOURCES): diff.pl
    perl diff.pl

$(PDFS): %.pdf: %.tex
    lualatex $<

clean:
    rm -rf *.log *.aux

但是,正如bobbogo注意到的那样,使用第二个选项,perl脚本将运行与LaTeX源文件一样多的次数。模式规则解决了这个问题:

LATEXSOURCES := foo.tex bar.tex ... cuz.tex
PDFS := $(patsubst %.tex,%.pdf,$(LATEXSOURCES))

all: $(PDFS)

$(LATEXSOURCES): %.tex: diff.pl
    @echo "Rebuilding $(LATEXSOURCES)"
    perl diff.pl

$(PDFS): %.pdf: %.tex
    lualatex $<

clean:
    rm -rf *.log *.aux

现在我们有一个真正的解决方案:

  • 仅在缺少一个LaTeX源文件或者自上次构建后更改perl脚本时重建LaTeX源文件,
  • 只执行一次perl脚本来构建所有LaTeX源文件,
  • 表示各种文件之间的所有依赖关系。

但是仍然存在一个问题:如果只丢失一个LaTeX源文件而其他文件是最新的,则将运行perl脚本,将重建所有LaTeX源文件,因此它们的最后修改时间将因此改变了。只会编译丢失的一个,但是在下一个make调用中,其他的也将被重新编译,这是一种浪费。 bobbogo使用中间LaTeX资源的建议解决了这个问题。

答案 1 :(得分:0)

假设您事先知道三个.tex文件的名称,您可以无条件地运行 perl ,然后只有在新文件实际上有所不同时才更新.tex文件来自旧的。 制作将处理此罚款。

tex := 1.tex 2.tex 3.tex
intermediates := ${tex:%.tex=%-new.tex}# 1-new.tex 2-new.tex 3-new.tex
pdfs := ${intermediates:%.tex=%.pdf}# 1-new.pdf etc.

.PHONY: perl
perl: ; perl diff.pl

${intermediates}: %-new.tex: %.tex | perl
    cmp -s $< $@ || mv $< $@

${pdfs}: %.pdf: %.tex
    lualatex $<

.PHONY: all
all: ${pdfs}
    : $@ Success

假设perl产生1.tex2.tex3.tex

  • 我们无条件地运行perl,生成这三个文件的新副本。
  • 然后我们从1-new.tex更新1.tex,但仅当两个文件不同时
  • 制作会发现任何已更改的文件,并根据需要运行 lualatex

这是并行安全的(对任何makefile的一个很好的测试)。与-j3一起运行,即可立即运行3份 lualatex 。你有4个CPU吗?