This is a post about a recent use I’ve found for make. I generally use make for my C++ projects and think that it’s timestamp based dependencies make life much easier. It also means you only have to think about how you want to build the project once, after that you just type
Recently I have found make useful for a less standard task. As the name of this article suggests I have been using make to build LaTex, the mark up language. I used to generally use TexMaker the cross-platform editor/IDE but I was just making something small so I thought I’d do it in emacs rather than install TexMaker. I then decided that I would use emacs for a larger project but calling pdflatex and opening a pdf was overhead every time I wanted to see a change (also deleting temporary files, because they look untidy). So I then decided that I would write a script to do this, but quickly thought that if it’s been made I would just want to open the pdf. So if I just made a script it would be a few command lines but make would do it all for me. So I quickly decided that make was the way to go.
The full file is here on my box account as usual.
This is the top of the file, the target (the .tex file) and the output name (the pdf).
# Targets TEX_NAME = OUTPUT_NAME =
These are the lines which needs to change to make different projects. That is one of the really useful things about make, it is very reusable. I can just give it new file names and it will know the rest, so it speeds up the building process.
Next are a few common commands:
# common commands REMOVE_TEMP_FILES = @rm -f $(OUTPUT_NAME).[!p][!d][!f] *~ *.pyc MAKE_PDF = @pdflatex $(TEX_NAME).tex -job-name=$(OUTPUT_NAME)
Line 6 is potentially dangerous, as it deletes all files with the output name which don’t have the extension pdf. This is because I generally call the tex file and the pdf different names (usually differing by underscores/spaces) and I delete the .log, .aux … files unless I need them for checking what is going wrong. Also on this line you’ll notice I delete files ending in ~ and .pyc files. The ~ files are temporary emacs files and the .pyc is a python bytecode files which clutter up my directories.
Note: if you want to use this file you probably want to change line 6!
Next there is the command for opening the pdf. Now, because I run this on windows (through cygwin) and linux I need to get information about the platfom. This is done by calling
uname to get a description of the system. Then there are two if loops to set the commands depending on the system. Here is that code:
# set a different PDF opening command for each OS OS := $(shell uname -o) OPEN_PDF = @echo "No pdf opening application set." ifeq ($(OS), GNU/Linux) OPEN_PDF = @evince $(OUTPUT_NAME).pdf & endif ifeq ($(OS), Cygwin) OPEN_PDF = @cygstart $(OUTPUT_NAME).pdf endif
Notice that if it not set then it will default to outputting an error.
Now we come to the dependencies which live at the bottom of make files. Here are mine:
open: $(OUTPUT_NAME).pdf # Remove temporary/unecessary files $(REMOVE_TEMP_FILES) $(OPEN_PDF) $(OUTPUT_NAME).pdf: $(TEX_NAME).tex $(MAKE_PDF) @echo -e "\033[01;32;40m" @echo "PDF made." @echo -e "\033[01;37;40m" refs: FRC # make twice so that the references/labels/contents are correct $(MAKE_PDF) @echo -e "\n\n" @echo -e "\033[01;32;40m" @echo "First round of making PDF." @echo -e "\033[01;37;40m" @echo -e "\n\n" $(MAKE_PDF) @echo -e "\033[01;32;40m" @echo "PDF made twice." @echo -e "\033[01;37;40m" # Remove temporary/unecessary files $(REMOVE_TEMP_FILES) $(OPEN_PDF) $(OUTPUT_NAME).pdf & FRC: # fake target
As is usual for make files these are in descending order of when they are made. This means that the desired output is the first item, open, which will open the created pdf. The line
open: $(OUTPUT_NAME).pdf means that there is a dependency of
$(OUTPUT_NAME).pdf which of course makes sense as you cannot open a pdf before it is made. Then below that, spaced by a tab, are the commands to make the target. In this case of course it is the open pdf command.
Next we have where the pdf is actually made, the line
$(OUTPUT_NAME).pdf: $(TEX_NAME).tex. This says that the pdf depends on the .tex file so that whenever the .tex file is newer, the pdf needs to be remade. Then I call the make pdf command I defined earlier and print, in green, that the pdf has been made.
The refs target is a quirk of LaTex because if you just make a changed .tex file once the table of contents, labels and references are not correct. So to get around this you make twice, but you don’t want to always do that so I have made a refs target. This target means that the references will be made and so when it opens (because the .tex has changed so open will be made) the contents etc. will be correct. I also output when the first and second make have finished.
The whole file is here.