根据make的类型覆盖makefile变量

时间:2013-12-16 00:49:18

标签: linux makefile pdflatex

我写了以下Makefile

INTERACTION=nonstopmode

all:
    make read.pdf > /dev/null
    make clean > /dev/null
diagnostic:
    INTERACTION=batchmode
    make read.pdf
    make clean
%.pdf: %.tex biblio.bib
    bash makepdf.sh $(INTERACTION) $<
clean:
    rm -f *.aux *.log *.bbl *.bak *.blg *.toc *.out *.glg *.glo *.gls *.ist *~ *.*~* *.backup

Makefile提供了两种模式:一个不输出错误和警告消息的简单make文件和一个诊断模式,以便pdflatex与用户交互以找到问题。

makepdf.sh如下所示:

filename=$(basename $2)
filename="${filename%.*}"
pdflatex -interaction=$1 $2 
makeglossaries "$filename" 2
makeindex "$filename" 2
pdflatex -interaction=$1 $2
echo $1

无论调用make还是make diagnostic,程序始终都在nonstopmode中运行。 Makefile变量不能被覆盖吗?如果是这样,这个问题怎么解决?否则,这段代码出了什么问题?

1 个答案:

答案 0 :(得分:2)

这个makefile很奇怪。基本上,写得不正确。

您问题的最直接答案是让您意识到makefile配方中的每一行都在一个单独的shell中调用,而在UNIX / POSIX系统中,进程不可能影响其父级的环境。这意味着对shell中的环境所做的更改对make进程或任何后续shell都没有影响。因此,INTERACTION=batchmode在shell中运行并将INTERACTION变量设置为batchmode,然后shell退出并忘记该设置,然后使用之前的设置运行下一行。如果希望变量生效,则必须将它们放在配方中的相同逻辑行中。

然而,这个makefile还有更多的基本问题。首先,您应该从不运行make来调用递归make。始终使用$(MAKE)变量。

其次,你不应该运行子制作。在makefile中列出先决条件的整个目的是强制执行调用规则的顺序;在这里,你试图通过递归运行命令来接管make的工作。

第三,假设您正在使用GNU make,您可以更轻松地使用特定于目标的变量(请参阅GNU make手册)。例如,你的makefile可以更正确地编写(注意,根本没有递归!):

INTERACTION = nonstopmode

all: read.pdf

diagnostic: INTERACTION = batchmode
diagnostic: all

%.pdf: %.tex biblio.bib
        bash makepdf.sh $(INTERACTION) $<

clean:
        rm -f *.aux *.log *.bbl *.bak *.blg *.toc *.out *.glg *.glo *.gls *.ist *~ *.*~* *.backup

每次构建后,它都不会自动运行clean规则。