Source of the LaTeX+SVGs to PDF makefile is available to download, use, change, tinker and fork at Github._


I wrote last week about how figures can be transfered from a Microsoft Word document into a LaTeX document by extracting them as vector images using Inkscape, and saved as Scalable Vector Graphic files (SVG).

Unfortunately, SVG images can’t be embedded directly into documents compiled with LaTeX, because LaTeX doesn’t process images, it only includes them. However, SVGs can be easily exported to PDF from inkscape, or exported as a PDF and a LaTeX file (PDF+LaTeX) so as to pass the formatting of text in the image to LaTeX at the time that the final document is compiled.

Using PDF+LaTeX means:

  • Text will be set in the body font.

  • Maths notation ($…$) can be used.

  • The figure can contain linked \ref{}s and \cite{}ations.

  • And you still get to use one of the main advantages of LaTeX: that layout and sytyling are divorced from content.

A more detailed explaination of using PDF+LaTeX is available here (or direct PDF download)

However, if you’ve got more than a few figures in your document, remembering to export a PDF+LaTeX copy every time you change, adjust or amend any figure is tedious and error prone. “Did you remember to export the image when you adjusted it?”, “Will you notice the change is missing when you proof read your document?”, “Didn’t you already fix that figure?”

If only there was a simpler way…

Compiling the images using Inkscape

Instead of having to use the GUI (graphical user interface) of Inkscape to export each image, Inkscape also has a CLI (command line interface) that allows for batch file control. So a command like:

inkscape --export-pdf=image.pdf --export-latex --export-area-drawing image.svg

will create image.pdf and image.pdf_tex, ready to be included in a LaTeX file, using:

      \begin{figure}
      \centering
      \def\svgwidth{\columnwidth}
      \import{images/}{image.pdf_tex}
      \caption{This in an Image}
      \label{im:image}
    \end{figure}

Compiling the PDF with make

The obvious way of dealing with keeping the compiled PDF up-to-date is to use a makefile.

A makefile is a structured set of rules that GNU make uses to compile the target file(s) from source files(s), but only if any of the source files have changed since the creation time of the target file (and if the target file exists).

Essentially, using make allows you to type make from the directory of your LaTeX source file and have it build the latest, most up to date copy of your document if any of the text or images have changed.

In search of LaTeX makefiles, I came across some that were overkill, like the UltimateLatexMakefile and Roels-latex-makefile (a fork of UltimaeLatexMakefile) and some too simple to do what I wanted, even though my document structure is fairly modest.

project_folder/
  |-- makefile
  |-- Document.tex
  |-- (Chapter1.tex, Chapter2.tex, …)
  |-- References.bib
  \-- images/
       |-- Image1.svg
       |-- Image2.svg
       |-- …

In the folder containing the project is: the makefile, with the LaTeX and BibTeX source files; and the SVG for each figure in an images subfolder. I prefer putting the images in their own folder to keep the LaTeX source directory more tidy.

What I settled on in the end was a heavily cut-down version of the UltimateLatexMakefile, with additional code to make use of Inkscape in the images folder. This means only the SVG file for each figure is needed to build the document, reducing the number of steps and complexity of producing figures.

Here’s the makefile I settled on; also available to download, use, change, tinker and fork at Github:

    # LaTeX+SVG to PDF
    # ================
    # A Makefile to create pdf files from LaTeX source with embedded SVG images.

    # Requires:
    # 	Inkscape http://inkscape.org for svg to pdf conversion

    # run:
    # 	make
    # 	make all
    # 	make pdf
    # 	make images
    # or:
    # 	make clean-all
    # 	make clean
    # 	make clean-pdf
    # 	make tidy
    # 	make clean-images

    # Choose your compiler:
    LATEX	= xelatex -interaction=batchmode
    BIBTEX	= bibtex

    # Set sub-folder location of svg image sources
    GRAPHIC_DIR = images

    # TeX input and pdf output files
    SRC	:= $(shell egrep -l '^[^%]*\\begin\{document\}' *.tex)
    PDF	= $(SRC:%.tex=%.pdf)
    # Finding the required images
    FIGSRC	:= $(wildcard $(GRAPHIC_DIR)/*.svg)
    FIG	:= $(FIGSRC:%.svg=%.pdf)
    FIGTEX	:= $(FIGSRC:%.svg=%.pdf_tex)

    RERUN = "There were undefined references."
    RERUNBIB = "No file.*\.bib|Citation.*undefined"

    COPY = if test -r $(<:%.tex=%.toc); then cp $(<:%.tex=%.toc) $(<:%.tex=%.toc.bak); fi
    RM = rm -f

    .PHONY : all pdf images clean-all clean clean-pdf tidy clean-images

    all : images pdf


    # Generate pdf output file
    pdf: $(PDF)

    $(PDF) : $(SRC) $(wildcard *.tex) $(wildcard *.bib) $(FIG) $(FIGTEX)
    	# Run LaTeX
    	$(COPY); $(LATEX) $< && true
    	# Run BibTeX if needed
    	egrep -c $(RERUNBIB) $(<:%.tex=%.log) && $(BIBTEX) $(<:%.tex=%) && $(COPY) && $(LATEX) $<; true
    	# Rerun LaTeX if necessary
    	egrep -c $(RERUN) $(<:%.tex=%.log) && $(COPY) && $(LATEX) $<; true
    	# Rerun LaTeX if necessary (a second time)
    	egrep -c $(RERUN) $(<:%.tex=%.log) && $(COPY) && $(LATEX) $<; true
    	# Check the TOC is consistent, else run again
    	if cmp -s $(<:%.tex=%.toc) $(<:%.tex=%.toc.bak); then true; else $(LATEX) $< ; fi; true
    	$(RM) $(<:%.tex=%.toc.bak)
    	# Display relevant warnings
    	egrep -i "(Reference|Citation|Label).*(undefined|multiply defined)" $(<:%.tex=%.log)


    # Export pdf (and pdf_TeX) file from each svg image
    images : $(FIG) $(FIGTEX)

    $(GRAPHIC_DIR)/%.pdf $(GRAPHIC_DIR)/%.pdf_tex : $(GRAPHIC_DIR)/%.svg

    	inkscape --export-pdf=$(<:.svg=.pdf) --export-latex --export-area-page $<


    clean-all : tidy clean-images

    # Clean pdf output only. e.g. for: make clean && make
    clean : clean-pdf

    clean-pdf :
    	rm -f $(PDF)

    # Tidy up output files
    tidy :
    	rm -f $(PDF) $(PDF:%.pdf=%.aux) $(PDF:%.pdf=%.bbl) $(PDF:%.pdf=%.blg) $(PDF:%.pdf=%.lof) $(PDF:%.pdf=%.log) $(PDF:%.pdf=%.lot) $(PDF:%.pdf=%.out) $(PDF:%.pdf=%.toc)

    # Clean up image outputs
    clean-images :
    	rm -f $(FIG) $(FIGTEX)