我写了以下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
变量不能被覆盖吗?如果是这样,这个问题怎么解决?否则,这段代码出了什么问题?
答案 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
规则。