Makefile Workflow
Requirements
Makefiles can quickly become large and confusing. I found these steps keep them easy to understand later and quick to write.
1mkdir blog.rs
2cd !$
3for x in one two three
4do
5 fortune > posts/$x.md
6done
Three Steps
- Define variables up-front so you know what they all are.
- Define dependencies and patterns next, without recipes.
- Finally, define the recipes.
1## Variables
2
3markdown_articles = $(wildcard posts/*.md)
4
5output_articles = $(patsubst posts/%.md,public/%.html,$(markdown_articles))
6
7.DEFAULT_GOAL = out
8
9## Dependencies
10
11public/%.html: posts/%.md
12
13$(output_articles): | public/
14
15## Recipes
16
17%/:
18 mkdir $@
19
20public/%.html: posts/%.md
21 lowdown $< > $@
22
23.PHONY: out
24out: $(output_articles)
Variables
There are three types of variables which make recognizes.
I ignore this and only use foo = 1 2 3 whenever possible.
These variables resolve immediately, in order.
Dependencies
Making recipes is one thing, making dependencies should receive its own head-space.
If you get the ordering wrong, then make won't work, and you'll end up switching to autoconf or just, because you think there's something wrong with make.
An honest dependency chain allows short build times.
You may be tempted to lie in the Makefile to fix something which does not compile at the right time, or to split a recipe up.
But don't.
Putting in a false dependency will cause problems later, and brings shame to your ancestors.
Recipes
Lots of info
When make tells you too much, the output becomes meaningless.
Focus on what matters with info statements.
1public/%.html: posts/%.md
2 $(info Making $*)
3 lowdown $< > $@
Now you can use make -s to stop the constant planning reports, but still see what's being made.
Delete First
Recipes should be idempotent, i.e. they can run many times and the final output remains the same. You can do this easily by deleting a target before you start.
1generated/%.html: posts/%.md
2 $(info Making $*)
3 figlet ' $*' > $@
4 lowdown $< >> $@
The figlet use destroys anything in the original file.
Adding Variables to Recipes
Starting with concrete filenames and shifting to variables later makes writing easier.
That public/ directory should be a variable, but that can wait until the basic logic works.