website/blog/2020-06-08-svg-makefile-slides.md
2020-06-09 13:46:31 +02:00

4.6 KiB

title: SVG + makefile = slide deck summary: "You don't need LibreOffice to prepare your presentation -- or: an introduction to makefiles" published: 2020-06-02


Text-based slides are boring and not effective. While preparing a presentation for my intermediary thesis' defence, I wanted to create something that would support my story better. I wanted to use graphics instead of words so the language centres of my dear audience's brains could focus on my speech rather than reading. Rather than importing slide-sized graphics in a GUI, I thought a makefile would be a nice way to do the trick.

Makefiles these days are commonly used as a shell script with multiple entry points. But they can do much more than that! You give it a filename, and it will build that file if its dependencies have been changed. Traditionally makefiles are used for C programs, but there's no reason you can't use them for any build you want. Even this website is built by a makefile! Want to join me and write one together?

Writing the makefile

Putting the name of our output file in variables will make it easier to change it later.

OUTPUT = slides.pdf

We'll make a list of SVGs in the current directory, and convert it into a list of PDF targets. Sorting is necessary to put your slides in the order you want. The $(:=) construct is used to go from %.svg to build/%.pdf.

SLIDES ::= $(sort $(wildcard *.svg))
SLIDES_PDF ::= $(SLIDES:%.svg=build/%.pdf)

I love this next rule. It teaches make that it should use Inkscape if it needs to create a PDF. $@ refers to the target (build/….pdf), and $< refers to the first dependency (….svg). Inkscape's --export-pdf filename option exports to PDF without opening the GUI.

TODO: isn't there a way to automatically depend on all parent directories?

build/%.pdf: %.svg build
	inkscape --export-pdf "$@" "$<"

Now we tell make that the final output can be created from the individual slides ($(SLIDES_PDF)) by calling pdfjoin.

Make will recursively make sure that all dependencies are up to date. Because we add the SVG source file as a dependency, it will know that the individual PDF files have to be rebuilt if their source was changed. And if any slide was changed, the end result will be updated too. But if there was no change, it won't; nothing is rebuilt unnecessarily!

TODO: DRY
TODO: Do we need to fix sh's space disease here?

$(OUTPUT): $(SLIDES_PDF)
	pdfjoin $(SLIDES_PDF) -o "$@"

If you look at the build/%.pdf rule, you see that it depends on build. With this rule, make will know how to create this directory.

build:
	mkdir -p "$@"

It is common to create a clean to clean up. Since clean is not a file, we have to mark the target as "phony". Failing to do so would result in TODO how to finish this sentence?

.PHONY: clean

clean:
	rm -rf "$(OUTPUT)" build/

One more thing: the default target, for when you call make without arguments, is the first one in the makefile (with some caveats). You could override this with .DEFAULT_GOAL := your_target_name_here, but it's just as easy to reorder the rules, which is what I've done in the summary below.

This is the finished makefile:

OUTPUT = slides.pdf

SLIDES ::= $(sort $(wildcard *.svg))
SLIDES_PDF ::= $(SLIDES:%.svg=build/%.pdf)

$(OUTPUT): $(SLIDES_PDF)
	pdfjoin $(SLIDES_PDF) -o "$@"

build/%.pdf: %.svg build
	inkscape --export-pdf "$@" "$<"

build:
	mkdir -p "$@"

.PHONY: clean
clean:
	rm -rf "$(OUTPUT)" build/

TODO: write about first rule being the default
TODO: split into 2 posts?

Further help with make

I'm using GNU make and I'll admit I don't know if this works in other flavours. GNU's documentation is installed on my system and accessible with info make (tab to jump to next link, enter to activate it, l to return to previous screen, Shift+h for help). When online you can also use the online documentation.

Creating and presenting slides

Create one SVG per slide, you can do that in Inkscape. Set the document size to something with the desired aspect ratio. In my experience this is 16:9 for newer projectors and 4:3 for older models.

To use the resulting slide deck during your presentation, I can recommend pdfpc. But any old PDF viewer that has a fullscreen mode will work, of course.