[Tex/LaTex] Makefile that prevents tex directory from being cluttered with build output

auxiliary-filescompilingmakefilexetex

I am using xelatex, biber and makeglossaries to generate my bachelor thesis. All of them are creating a huge amount of temporary files that are cluttering, not only my root document directory, but the whole directory structure of my thesis. Previously I've made extensive use of find and rm in a clean target of my Makefile to get rid of all the crap.

Currently my idea was to to copy all the content that is needed to build the thesis in a .build subdirectory and cd into that directory inside the Makefile before beginning to compile. I tried to use output-directory switches of xelatex and biber (makeglossaries doesn't have one), but with no luck. That's why i want to generate the pdf inside a subdirectory, that i can safely remove with all the content, after the compilation and copying the created pdfs, using rm -rf .build/*.

Here is the Makefile (the interesting part in the screen or print target, as you will):

#
# Makefile for Bachelorthesis
#
# @ supresses command output
#
# conditionals are not allowed to have a starting tab, 
# otherwise they will be sent to the shell
#
DEBUG='true'
ROOT_DIR=$(shell pwd)
BUILD_DIR=$(ROOT_DIR)/.build
XELATEX_OPTS=-output-directory=$(BUILD_DIR)
BIBER_OPTS=--output_directory=$(BUILD_DIR)
.PHONY : clearscr clean screen print

all: copy_sources screen print copy_output

copy_sources:
    rsync --verbose --checksum --recursive --human-readable --progress --exclude=output --exclude=.git* $(ROOT_DIR)/ $(ROOT_DIR)/.build

copy_output:
    cp --update $(BUILD_DIR)/*.pdf $(ROOT_DIR)/output

screen:
    @echo "Building screen version ..."
    @cd $(BUILD_DIR)
ifeq ($(DEBUG) , 'true')
    @echo "\n------------------ xelatex --------------------\n"     
    xelatex thesis $(XELATEX_OPTS) | grep --ignore-case warning
    @echo "\n------------------- biber ---------------------\n" 
    biber thesis $(BIBER_OPTS)
    @echo "\n--------------- makeglossaries ----------------\n"         
    makeglossaries thesis
    @echo "\n------------------ xelatex --------------------\n" 
    xelatex thesis $(XELATEX_OPTS) | grep --ignore-case warning     
else
    xelatex thesis $(XELATEX_OPTS) > /dev/null  
    biber thesis $(BIBER_OPTS) > /dev/null          
    makeglossaries thesis > /dev/null   
    xelatex thesis $(XELATEX_OPTS) > /dev/null          
endif

print:
    @echo "Building print version ..."
    cd $(BUILD_DIR)
ifeq ($(DEBUG) , 'true')
    @echo "\n------------------ xelatex --------------------\n" 
    xelatex thesis_print $(XELATEX_OPTS) | grep --ignore-case warning
    @echo "\n------------------- biber ---------------------\n"     
    biber thesis_print $(BIBER_OPTS)        
    @echo "\n--------------- makeglossaries ----------------\n" 
    makeglossaries thesis_print
    @echo "\n------------------ xelatex --------------------\n"     
    xelatex thesis_print $(XELATEX_OPTS) | grep --ignore-case warning       
else
    xelatex thesis_print $(XELATEX_OPTS) > /dev/null            
    biber thesis_print $(BIBER_OPTS) > /dev/null            
    makeglossaries thesis_print > /dev/null 
    xelatex thesis_print $(XELATEX_OPTS) > /dev/null            
endif

clean:
    @echo "I will clean up this mess ..."
    @rm -rf $(BUILD_DIR)/*
    # remove the following commands, if the build was started in the BUILD_DIR successfully
    @rm -f *.out *.nav *.snm *.toc *.log *.bcf *.bbl *.blg *.lof *.lol *.lot *.run.xml *.xdy *.glo *.glg *.gls *.idx *.ist *-blx.bib .*.bbl.swp *.mtc* *.maf
    @find . -name \*.aux  -type f -delete
    @find . -name \*.bbl  -type f -delete
    @find . -name \*.bak  -type f -delete
    @find . -name \*.blg  -type f -delete
    @find . -name \*.fls  -type f -delete
    @find . -name \*.fdb_latexmk  -type f -delete
    @find . -name \*.vsdx  -type f -delete
    @find $(ROOT_DIR) -name '*in Konflikt stehende*' -delete

clearscreen:
    clear

This is the root directory of the document after compiling, a horrible amount of temporary garbage:

    abstract.aux     _dump        synctooutput.sh   thesis.lol   thesis.mtc6       thesis_print.gls   thesis_print.mtc2  thesis_print.run.xml
abstract.tex     frontpage    synctooutput.sh~  thesis.lot   thesis.mtc7       thesis_print.ist   thesis_print.mtc3  thesis_print.tex
affidavit.aux    header       thesis.aux        thesis.maf   thesis.mtc8       thesis_print.lof   thesis_print.mtc4  thesis_print.toc
affidavit.tex    LICENSE      thesis.bcf        thesis.mtc   thesis.mtc9       thesis_print.log   thesis_print.mtc5  thesis.run.xml
appendix         license.aux  thesis.glg        thesis.mtc0  thesis.out        thesis_print.lol   thesis_print.mtc6  thesis.tex
attachments      license.tex  thesis.glo        thesis.mtc1  thesis.pdf        thesis_print.lot   thesis_print.mtc7  thesis.toc
bibliography     Makefile     thesis.gls        thesis.mtc2  thesis_print.aux  thesis_print.maf   thesis_print.mtc8  tikz_pgf
bibtexEntry.tex  output       thesis.ist        thesis.mtc3  thesis_print.bcf  thesis_print.mtc   thesis_print.mtc9  todos.sh
content          README       thesis.lof        thesis.mtc4  thesis_print.glg  thesis_print.mtc0  thesis_print.out   variables
document.tex     resources    thesis.log        thesis.mtc5  thesis_print.glo  thesis_print.mtc1  thesis_print.pdf

It seems that xelatex and co are not using the directory that was set by the output-directory-switch, instead they use the working directory of the Makefile. I've even tried it /wo the option only using the cd command before starting to compile, with the same result.

Please help me to get rid of all the temp files 🙂

Best Answer

I got it, maybe this helps someone else or it serves as an inspiration for creating Makefiles. The problem was the cd command and how make executes commands, like i mentioned i a comment above.

Makefile:

#
# Makefile for Bachelorthesis
#
#   Andreas Linz -- 10INB-T
#   HTWK-Leipzig, Fakultaet IMN
#   klingt.net@googlemail.com
#
# @ supresses command output
#
# conditionals are not allowed to have a starting tab, 
# otherwise they will be sent to the shell
#
DEBUG='true'
ROOT_DIR=$(shell pwd)
BUILD_DIR=$(ROOT_DIR)/.build
OUTPUT_DIR=$(ROOT_DIR)/output
#.PHONY : clearscr clean screen print

all: copy_sources screen print copy_output

copy_sources:
    @echo "Copying sources to build folder: $(BUILD_DIR)"
    @rsync --verbose --checksum --recursive --human-readable --progress --exclude=.build --exclude=.build_scripts --exclude=output --exclude=.git --exclude=.gitignore $(ROOT_DIR)/ $(ROOT_DIR)/.build

copy_output:
    @echo "Copying generated PDFs to output folder: $(OUTPUT_DIR)"
    @cp -f $(BUILD_DIR)/*.pdf $(OUTPUT_DIR)

screen:
    @echo "Building screen version ..."
ifeq ($(DEBUG) , 'true')
    .build_scripts/screen.sh $(BUILD_DIR) $(DEBUG) 
else
    .build_scripts/screen.sh $(BUILD_DIR) $(DEBUG)
endif

print:
    @echo "Building print version ..."
ifeq ($(DEBUG) , 'true')
    .build_scripts/print.sh $(BUILD_DIR) $(DEBUG)       
else
    .build_scripts/print.sh $(BUILD_DIR) $(DEBUG)
endif

clean_conflicts:
    @find $(ROOT_DIR) -name '*in Konflikt stehende*' -delete
    @find $(ROOT_DIR) -name '*conflicted copy*' -delete

clean: clean_conflicts
    @echo "I will clean up this mess ..."
    @cd $(BUILD_DIR); rm -r *

clean_all: clean
    @rm $(OUTPUT_DIR)/*

clearscreen:
    clear

# remove the following commands, if the build was started in the BUILD_DIR successfully
#   @rm -f *.out *.nav *.snm *.toc *.log *.bcf *.bbl *.blg *.lof *.lol *.lot *.run.xml *.xdy *.glo *.glg *.gls *.idx *.ist *-blx.bib .*.bbl.swp *.mtc* *.maf
#   @find . -name \*.aux  -type f -delete
#   @find . -name \*.bbl  -type f -delete
#   @find . -name \*.bak  -type f -delete
#   @find . -name \*.blg  -type f -delete
#   @find . -name \*.fls  -type f -delete
#   @find . -name \*.fdb_latexmk  -type f -delete
#   @find . -name \*.vsdx  -type f -delete
#   @find $(ROOT_DIR) -name '*in Konflikt stehende*' -delete

Build-Scripts:

screen.sh:

#!/bin/bash
#
# script for generating the print pdfs
# this script should be called from the Makefile in the document root
#
# check number of arguments with `$# -eq 0`
#

if [ $# == 2 ]; then
    echo "Changing directory to: $1"
    cd $1
    if [ $2 = 'true' ]; then
        echo "12345: $XELATEX_OPTS"
        echo -e "\n------------------ xelatex --------------------\n"     
        xelatex $XELATEX_OPTS thesis #|grep --ignore-case --extended-regex "info|warning|error|^\([A-Za-z0-9]*\)"
        echo -e "\n------------------- biber ---------------------\n" 
        biber $BIBER_OPTS thesis
        echo -e "\n--------------- makeglossaries ----------------\n"         
        makeglossaries thesis
        echo -e "\n------------------ xelatex --------------------\n" 
        xelatex $XELATEX_OPTS thesis > /dev/null
    else
        xelatex $XELATEX_OPTS thesis > /dev/null  
        biber $BIBER_OPTS thesis > /dev/null          
        makeglossaries thesis > /dev/null   
        xelatex $XELATEX_OPTS thesis > /dev/null
    fi
else
    echo "Number of arguments given: $#"
    echo "Usage: ./screen.sh path_to_build_dir [true/false]"
fi

print.sh:

#!/bin/bash
#
# script for generating the print pdfs
# this script should be called from the Makefile in the document root
#
# check number of arguments with `$# -eq 0`
#

XELATEX_OPTS=""
BIBER_OPTS=""

if [ $# == 2 ]; then
    echo "Changing directory to: $1"
    cd $1
    if [ $2 = 'true' ]; then
        echo -e "\n------------------ xelatex --------------------\n"     
        xelatex $XELATEX_OPTS thesis_print > /dev/null
        echo -e "\n------------------- biber ---------------------\n" 
        biber $BIBER_OPTS thesis_print 
        echo -e "\n--------------- makeglossaries ----------------\n"         
        makeglossaries thesis_print
        echo -e "\n------------------ xelatex --------------------\n" 
        xelatex $XELATEX_OPTS thesis_print | grep --ignore-case --extended-regex "info|warning|error|^\([A-Za-z0-9]*\)"
    else
        xelatex $XELATEX_OPTS thesis_print > /dev/null  
        biber $BIBER_OPTS thesis_print > /dev/null          
        makeglossaries thesis_print > /dev/null   
        xelatex $XELATEX_OPTS thesis_print > /dev/null
    fi
else
    echo "Number of arguments given: $#"
    echo "Usage: ./screen.sh path_to_build_dir [true/false]"
fi