Pröper Gander

A Makefile is Fine, Too

I'm not sure where I first saw a link to "Your blog probably doesn't need a static site generator" by Zain Amro. Maybe it was on Mastodon. Maybe it was on that orange-tinted forum where Silicon Valley techies hang out and brag about their prowess. It doesn't really matter.

What matters is that they're right. If you want to write on the internet, tinkering with content management systems like WordPress or static site generators like Jekyll are just going to slow you down. Moreover, I find their process quite refreshing.

Today, my process is enjoyably unsophisticated. When I want to post something, I first write it in a text file, copy my last blog post’s HTML file, paste in my new article, make some slight adjustments, update my list of posts, add it to my RSS file, and that’s basically it.
However, I don't follow it myself. Simply copying over an existing file and wiping out the contents before starting something new isn't my style. Furthermore, I don't like having my files cluttered with a lot of boilerplate like the <head> element, and I absolutely loathe the necessity of repeating myself. It starts with typing the title twice, once in <head> and once in your page's heading for the user to see, but it can get worse from there. What if you want to provide navigation links on every page, but decide to change your navigation menu later on?

If you try to do all of this by hand, you're gonna have a bad time. This is one of the reasons we started using content management systems and blogging software in the first place.

Zain Amro solves this potential problem by dispensing with such niceties. Their website is unabashedly brutalist, and he makes no concessions to the expectations of nontechnical readers who happen upon his site by mistake. If they can't use their browser's back button to get around, that's evidently their problem.

I won't deny that I'm tempted, but I think there's a better way. Unix systems have had the M4 macro processor since 1977. It still survives as a tool for generating Sendmail configurations and a dependency for GNU Autoconf, but there is no reason why it can't be put to other uses. Most of the BSDs come with their own implementation, and if you don't already have it on your GNU/Linux installation, chances are you need only install the m4 package using your distribution's package mangler.

If you're wondering if it's hard to use M4: it isn't. If you've any experience as a programmer of any kind, I think you'll have little trouble picking up M4. It's not like the M4 manual page is especially long or hard to read.

The hard part is processing all of your pages so that the M4 macros get expanded and you actually end up with something you can push to a server. This is a process best automated. You could use a shell script, or a fancy build tool, but I prefer to stick to reliable classics like make.

.SUFFIXES: .m4 .m4html .html .xml

.m4html.html:
@m4 -P -E -I ./inc "$&lt;" | tidy -iuq -utf8 -w &gt; "$@"

.m4.xml:
@m4 -P -E -I ./inc "$&lt;" | grep "^[:blank:]" &gt; "$@"

SITE!=find src/ -name "*.m4html"
FEEDS!=find feeds/ -name "*.m4"
SITEMAPS!=find sitemaps/ -name "*.m4"

HTML=${SITE:.m4html=.html}
FEED=${FEEDS:.m4=.xml}
SITEMAP=${SITEMAPS:.m4=.xml}

SSH_OPTS=-o StrictHostKeyChecking=no
REMOTE_HOST=""
REMOTE_PATH=""

all: $(HTML) $(FEED) $(SITEMAP)
@mkdir dest
@cp -aR src/* dest/
@cp -a src/.htaccess dest/
@cp -a feeds/feed.xml dest/
@cp -a sitemaps/sitemap.xml dest/
@find dest/ -name '*.m4html' -print0 | xargs -0 -P 4 rm

deploy:
@openrsync --rsh="ssh ${SSH_OPTS}" \
--del -Dgloprv \
dest/ ${REMOTE_HOST}:${REMOTE_PATH}

clean:
@rm $(HTML)
@rm $(FEED)
@rm $(SITEMAP)
@rm -rf dest

Is this complicated? Perhaps a little. However, using make gives me some advantages that I might not get from other tools or a custom shell script:

  • make usually comes with any operating system that aspires toward POSIX compliance as part of the base system.
  • On an operating system like OpenBSD, you can be sure the developers are using make themselves to build the entire OS, so it's all but guaranteed to work unless you've messed up your makefile.
  • You can use the -j argument to get make to process jobs in parallel, which can dramatically decrease build times for large projects.
Of course, there are downsides to using make as well:
  • Writing your first makefile can be a daunting task. If you don't get it just right, make will balk.
  • Most tutorials available online are written for GNU make, which provides extensions and shortcuts that break compatibility with versions of make provided with the various BSDs.

If you can get past the pitfalls, I think that using classic tools like M4 and make can allow you to continue to automate some the less pleasant aspects of maintaining a website with a blog while retaining the sense of freedom one can find while writing raw HTML. It's how I've built this website. If you're interested in doing the same, I have a Git repository that you're welcome to clone and use as a starting point for your next project.

If you're interested in a bit of extra reading, the Wayback Machine has a couple of old Linux Journal articles that deal with M4 as a tool for building and maintaining websites.

Feel free to let me know if you find this helpful. Better still, let me know if you end up using this for a project of your own.