Wed Sep 9 03:14:06 PM EDT 2026
gnumakefile is great and can do a lot.
MD_FILES := $(wildcard *.md)
binfiles := $(wildcard files.*)
HTML_FILES := $(MD_FILES:.md=.html)
.PHONY: all stats
all: $(HTML_FILES) .push stats
$(HTML_FILES): %.html : %.md
title="$*" ; title=$$(echo $$title | sed -e 's/^index$$/rattlebones/') ; pandoc -f markdown -t html $< -o $*.html --standalone --css=files.style.css --metadata title="$$title" --lua-filter=links-to-html.lua
neocities upload $*.html
.push: $(binfiles) Makefile
neocities upload $^
touch .push
clean:
-rm -v *.html
stats:
/usr/local/bin/neocities info > stats
git log -p stats | grep -e views -e updated -e hits | head -n 20
i recommend reading [1]. make is very good at building things, especially c programs. it has a lot of potential for scripting and metaprogramming with nice features for parallel execution and can be simpler than a bash script for some of the same tasks. the combination of make and bash can blow away python for simplicity and performance for some very narrow applications.
static patterns are one way to get make to move mountains in one recipe but the official make docs arent very clear. I found a better example here [1]. I used this in my site makefile to make it only rebuild the markdown files that are newer than the corresponding html files.
# This is INCORRECT
objects = main.o utils.o
$(objects): %.o: src/%.c
gcc -c $< -o $@
The problem is that the % in %.o matches main and utils, but the % in src/%.c is trying to match main or utils in a different path. Make gets confused.
Corrective Action & Sample Code
You need to make sure the wildcard matches consistently. You can use the patsubst function to help. A simpler and more common way is to define the rule correctly from the start.
# This is the CORRECT way
objects = main.o utils.o
$(objects): %.o: %.c
gcc -c $< -o $@
1 https://runebook.dev/en/docs/gnu_make/static-pattern 2 https://www.gnu.org/software/make/manual/make.html