Pregunta

I've written the following 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

The Makefile provides two modes: a simple make file that doesn't output error and warning messages and a diagnostic mode such that pdflatex interacts with the user in order to locate the problem.

The makepdf.sh looks as follows:

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

Regardless of the fact whether make or make diagnostic is called, the program always runs in nonstopmode. Can't a Makefile variable been overwritten? If so, how can this problem be resolved? Otherwise, what is wrong with this code?

¿Fue útil?

Solución

This makefile is quite strange. Basically, not written correctly.

The most direct answer to your question is for you to realize that every line in a makefile recipe is invoked in a separate shell, and in UNIX/POSIX systems it's not possible for a process to impact the environment of its parent. That means that changes made to the environment in the shell that make invokes have no effect on the make process, or on any subsequent shells. So INTERACTION=batchmode is run in a shell and sets the INTERACTION variable to batchmode, then the shell exits and that setting is forgotten, then the next line is run with the previous setting. If you want variables to take effect you have to put them in the same logical line in the recipe.

However, there are even more fundamental problems with this makefile. First, you should never run make to invoke a recursive make. Always use the $(MAKE) variable.

Second, you shouldn't be running sub-makes anyway. The entire purpose of listing prerequisites in a makefile is to enforce an order on invocation of the rules; here you're trying to take over make's job by running commands recursively.

Third, assuming you're using GNU make you can use target-specific variables for what you want to do much more easily (see the GNU make manual). For example your makefile can be more correctly written like this (note, no recursion at all!):

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

It doesn't run the clean rule automatically after each build.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top