summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2026-05-26 09:45:57 -0300
committerEuAndreh <eu@euandre.org>2026-05-26 09:45:57 -0300
commita9a82ee41bb907c6fdfdfc44e2710b35a5ecb6d3 (patch)
treef1fce005679a8851693725f4ed7f393259af1b09
parentMakefile: Slim to ~25 lines via include of mkwb's site.mk (diff)
downloadpapo.im-a9a82ee41bb907c6fdfdfc44e2710b35a5ecb6d3.tar.gz
papo.im-a9a82ee41bb907c6fdfdfc44e2710b35a5ecb6d3.tar.xz
mkdeps.sh: Inline mkwb rules into deps.mk instead of includeHEADmain
deps.mk is now fully self-contained: ~340 lines of canonical mkwb rules are appended via `mkwb rules` (which now prints content). No make-time external file dependency, no GNU $(shell). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-rw-r--r--deps.mk468
-rwxr-xr-xmkdeps.sh11
2 files changed, 473 insertions, 6 deletions
diff --git a/deps.mk b/deps.mk
index 3455d37..7861e51 100644
--- a/deps.mk
+++ b/deps.mk
@@ -221,4 +221,470 @@ src/content/en/incidents/categories.txt src/content/en/incidents/feed.xml: $(art
src/content/en/incidents/categories.htmllisting src/content/en/incidents/categories.xml: src/content/en/incidents/categories.txt
src/content/en/incidents/categories.xml.gz: src/content/en/incidents/categories.xml
-include /home/andreh/.usr/var/mkg/share/mkwb/site.mk
+## mkwb canonical site rules. Sites consume this content by
+## inlining it at the end of their generated deps.mk: mkdeps.sh
+## runs `mkwb rules` (which cats this file) so deps.mk ends up
+## self-contained -- no make-time `include` of an external file.
+## The site Makefile only needs an `all:` anchor followed by
+## `include deps.mk`. Order matters: `all:` must come first
+## (otherwise deps.mk's first target becomes the default), and
+## the canonical rules below must follow deps.mk's variable
+## assignments so that `all: $(derived-assets)` can resolve its
+## prereq list at parse time.
+##
+## The including Makefile is expected to define at minimum:
+##
+## NAME -- site name (used for SRCDIR/HTMLDIR install paths)
+## VERSION
+## DATE
+##
+## To override any of PREFIX / BINDIR / SHAREDIR / SRCDIR /
+## HTMLDIR / PUBURL / BASEURL / FFMFLAGS, set them AFTER the
+## include (plain `=`, POSIX -- no `?=` conditional assignment),
+## or pass `-e` to make to let env vars take precedence.
+
+
+
+## Default values. Sites override AFTER the include or via env.
+PREFIX = /usr
+BINDIR = $(PREFIX)/bin
+LIBDIR = $(PREFIX)/lib
+INCLUDEDIR = $(PREFIX)/include
+SHAREDIR = $(PREFIX)/share
+LOCALEDIR = $(SHAREDIR)/locale
+MANDIR = $(SHAREDIR)/man
+DOCDIR = $(SHAREDIR)/doc/$(NAME)
+HTMLDIR = $(SHAREDIR)/html/$(NAME)
+SRCDIR = $(PREFIX)/src/$(NAME)
+DESTDIR =
+PUBURL = public.asc.txt
+BASEURL = /
+FFMFLAGS = -y -hide_banner -loglevel warning
+
+
+
+.SUFFIXES:
+.SUFFIXES: .adoc .conf .snippets .indexentry .feedentry .mapentry .sortdata .xml
+.SUFFIXES: .htmlbody .htmlheader .htmlfooter .htmllisting .html .links .caslinks
+.SUFFIXES: .txt .categorydata .gz .torrent .flac .ogg .ps .pdf .sentinel
+
+.adoc.conf:
+ mkwb conf src/global.conf $< > $@
+
+.adoc.htmlbody:
+ mkwb htmlbody $< > $@
+
+.htmlbody.html:
+ mkwb html $< > $@
+
+.conf.htmlheader:
+ mkwb html -H $< > $@
+
+.conf.htmlfooter:
+ mkwb html -F $< > $@
+
+.adoc.snippets:
+ mkwb snippets $< > $@
+
+.conf.indexentry:
+ mkwb indexentry $< > $@
+
+.htmlbody.feedentry:
+ mkwb feedentry $< > $@
+
+.conf.mapentry:
+ mkwb mapentry $< > $@
+
+.conf.sortdata:
+ mkwb sortdata $< > $@
+
+.conf.categorydata:
+ mkwb categorydata $< > $@
+
+.adoc.links:
+ mkwb links $< > $@
+
+.links.caslinks:
+ grep -Ev '^(link|image):' $< | xargs -I_ sh -c '\
+ printf "%s\n" "_" | sha256sum | \
+ printf "%s\t%s\n" "`cut -d" " -f1`" "_"' > $@
+
+.flac.ogg:
+ ffmpeg $(FFMFLAGS) -i $< -ar 48000 -vn -c:a libvorbis -b:a 320k $@
+
+.adoc.ps:
+ eslaides < $< > $@
+
+.ps.pdf:
+ ps2pdf - < $< > $@
+
+
+
+## Derived file lists from auto-generated source lists in deps.mk.
+listings.adoc = $(categories.adoc) $(indexes.adoc)
+sources.adoc = $(articles.adoc) $(listings.adoc) $(pages.adoc)
+sources.htmlbody = $(sources.adoc:.adoc=.htmlbody)
+sources.html = $(sources.adoc:.adoc=.html)
+sources.snippets = $(sources.adoc:.adoc=.snippets)
+sources.snippets.gz = $(sources.adoc:.adoc=.snippets.gz)
+sources.conf = $(sources.adoc:.adoc=.conf)
+sources.links = $(sources.adoc:.adoc=.links)
+sources.caslinks = $(sources.adoc:.adoc=.caslinks)
+sources.mapentry = $(sources.adoc:.adoc=.mapentry)
+articles.indexentry = $(articles.adoc:.adoc=.indexentry)
+articles.feedentry = $(articles.adoc:.adoc=.feedentry)
+articles.sortdata = $(articles.adoc:.adoc=.sortdata)
+articles.categorydata = $(articles.adoc:.adoc=.categorydata)
+listings.htmlheader = $(listings.adoc:.adoc=.htmlheader)
+listings.htmlfooter = $(listings.adoc:.adoc=.htmlfooter)
+listings.html = $(listings.adoc:.adoc=.html)
+indexes.htmllisting = $(indexes.adoc:.adoc=.htmllisting)
+categories.htmllisting = $(categories.adoc:.adoc=.htmllisting)
+categories.txt = $(categories.adoc:.adoc=.txt)
+categories.xml = $(categories.adoc:.adoc=.xml)
+categories.xml.gz = $(categories.adoc:.adoc=.xml.gz)
+sources.media.torrent = $(sources.media:=.torrent)
+slides.ps = $(slides.adoc:.adoc=.ps)
+slides.pdf = $(slides.adoc:.adoc=.pdf)
+
+sources = \
+ $(sources.adoc) \
+ $(sources.extras) \
+ $(images.svg) \
+ src/content/favicon.ico \
+ src/content/favicon.png \
+ src/content/style.css \
+ src/content/$(PUBURL) \
+
+dynamic-contents = \
+ $(sources.html) \
+ $(slides.pdf) \
+ $(feeds.xml) \
+ $(sources.media.torrent) \
+ src/content/sitemap.xml \
+
+static-contents = \
+ $(sources.extras) \
+ $(images.svg) \
+ src/content/favicon.ico \
+ src/content/favicon.png \
+ src/content/style.css \
+ src/content/$(PUBURL) \
+ src/content/.well-known/security.txt \
+
+dynamic-contents.gz = $(dynamic-contents:=.gz)
+
+static-contents.gz = \
+ $(images.svg:=.gz) \
+ src/content/favicon.ico.gz \
+ src/content/style.css.gz \
+ src/content/$(PUBURL).gz \
+ src/content/.well-known/security.txt.gz \
+
+contents.gz = \
+ $(dynamic-contents.gz) \
+ $(static-contents.gz) \
+
+contents = \
+ $(dynamic-contents) \
+ $(static-contents) \
+
+all-filelists = \
+ $(sources.snippets) \
+ $(sources.snippets.gz) \
+ $(categories.xml) \
+ $(categories.xml.gz) \
+
+all-contents = \
+ $(contents) \
+ $(contents.gz) \
+
+captured-assets = \
+ src/content/$(PUBURL) \
+ src/content/favicon.ico \
+ src/content/favicon.png \
+
+captured-assets.sentinel = $(captured-assets:=.sentinel)
+
+derived-assets = \
+ $(dynamic-contents) \
+ $(contents.gz) \
+ $(sources.html) \
+ $(sources.htmlbody) \
+ $(sources.snippets) \
+ $(sources.snippets.gz) \
+ $(sources.conf) \
+ $(sources.links) \
+ $(sources.caslinks) \
+ $(sources.mapentry) \
+ src/dyn.conf \
+ src/base.conf \
+ src/global.conf \
+ $(articles.indexentry) \
+ $(articles.feedentry) \
+ $(articles.sortdata) \
+ $(articles.categorydata) \
+ $(listings.htmlheader) \
+ $(listings.htmlfooter) \
+ $(listings.html) \
+ $(indexes.htmllisting) \
+ $(categories.htmllisting) \
+ $(categories.txt) \
+ $(categories.xml) \
+ $(categories.xml.gz) \
+ $(slides.ps) \
+ $(slides.pdf) \
+ email.txt \
+ baseurl.txt \
+ fingerprint.txt \
+ expiry.txt \
+ expiry-epoch.txt \
+ now.txt \
+ src/content/.well-known/security.txt \
+ src/all-contents.txt \
+ src/all-filelists.txt \
+ src/all-symlinks.txt \
+ src/install.txt \
+ src/sort-expected.txt \
+ src/sort-given.txt \
+ src/sources.txt \
+ install.txt \
+ sources.txt \
+ src/content/.gitignore \
+ $(captured-assets.sentinel) \
+
+side-assets = \
+ src/collections/*/*/*/*/*/*.html.*.txt \
+ src/collections/*/*/*/*/*/*.txt.gz \
+ src/collections/*/*/index.html.*.txt \
+ src/collections/*/*/sortdata.txt \
+ src/collections/*/*/feed.*.xml \
+ src/collections/*/*/feed.*.xml.gz \
+ src/collections/*/*/*.sortdata \
+ src/pages/*/*.html.*.txt \
+ src/content/.well-known/ \
+ `cat src/all-symlinks.txt 2>/dev/null` \
+ `cat src/linkonly-dirs.txt 2>/dev/null` \
+
+
+
+## Default target -- builds all derived + captured artifacts.
+all: $(derived-assets) $(captured-assets)
+
+
+$(sources.conf): src/global.conf
+
+
+src/content/.gitignore: src/symlinks.txt
+ cd src/content/ && mkwb symlinks ../symlinks.txt > $(@F)
+
+src/dyn.conf: email.txt baseurl.txt fingerprint.txt
+ printf "export url_pre='%s'\n" "`cat baseurl.txt`" > $@
+ printf "export email='%s'\n" "`cat email.txt`" >> $@
+ printf "export publickey='%s'\n" "`cat fingerprint.txt`" >> $@
+ printf "export publickey_url='$(PUBURL)'\n" >> $@
+ printf 'export sourcecode_url="$$url_pre/git/$(NAME)"\n' >> $@
+
+src/base.conf: src/dyn.conf src/static.conf
+ cat src/dyn.conf src/static.conf > $@
+
+src/global.conf: src/base.conf
+ mkwb conf -G src/base.conf > $@
+
+$(listings.html):
+ cat $*.htmlheader $*.htmlbody $*.htmllisting $*.htmlfooter > $@
+
+$(indexes.htmllisting):
+ mkwb indexbody $*.conf > $@
+
+$(categories.htmllisting):
+ mkwb categoriesbody $*.conf > $@
+
+$(categories.txt): src/global.conf
+ mkwb categories src/global.conf $(@D) > $@
+
+$(categories.xml):
+ for f in `cat $*.txt`; do \
+ c="`printf '%s\n' "$$f" | cut -d. -f2`"; \
+ mkwb feed src/global.conf "$$f" > $(@D)/feed."$$c".xml; \
+ printf '%s\n' $(@D)/feed."$$c".xml; \
+ done > $@
+
+$(feeds.xml):
+ mkwb feed src/global.conf $(@D)/sortdata.txt > $@
+
+$(contents.gz):
+ gzip -9fk $*
+ touch $@
+
+$(sources.snippets.gz) $(categories.xml.gz):
+ if [ -s $* ]; then gzip -9fk `cat $*`; fi
+ sed 's/$$/.gz/' $* > $@
+
+src/content/$(PUBURL).gz: src/content/$(PUBURL).sentinel
+src/content/$(PUBURL).sentinel: email.txt
+ gpg --export --armour "`cat email.txt`" | ifne ifnew $*
+ touch $@
+
+src/content/favicon.ico.gz: src/content/favicon.ico.sentinel
+src/content/favicon.ico.sentinel: src/content/img/favicon.svg
+ convert src/content/img/favicon.svg -strip ico:- | ifnew $*
+ touch $@
+
+src/content/favicon.png.sentinel: src/content/img/favicon.svg
+ convert src/content/img/favicon.svg -strip png:- | ifnew $*
+ touch $@
+
+$(sources.media.torrent):
+ F="`printf '%s\n' $* | cut -d/ -f3-`" && \
+ mktorrent -xfd -n $(*F) -o $@ -w "https://$(NAME)$(BASEURL)$${F}" $*
+
+src/content/sitemap.xml.gz: src/content/sitemap.xml
+src/content/sitemap.xml: $(sources.mapentry)
+ mkwb sitemap $(sources.mapentry) > $@
+
+email.txt: meta.capim
+ cat meta.capim | awk '$$1 == ":email" && $$0=$$2' | tr -d '"' > $@
+
+baseurl.txt: meta.capim
+ cat meta.capim | awk '$$1 == ":baseurl" && $$0=$$2' | tr -d '"' > $@
+
+fingerprint.txt: src/content/$(PUBURL)
+ gpg --always-trust --no-keyring --show-key --with-colons \
+ src/content/$(PUBURL) | \
+ awk -F: '/^pub:/ { print $$5 }' > $@
+
+expiry.txt: src/content/$(PUBURL)
+ gpg --always-trust --no-keyring --show-key --with-colons \
+ src/content/$(PUBURL) | \
+ awk -F: '/^pub:/ { print $$7 }' | \
+ xargs -I% date -Is -d@% > $@
+
+expiry-epoch.txt: expiry.txt
+ date -d "`cat expiry.txt`" '+%s' > $@
+
+now.txt:
+ now > $@
+
+src/content/.well-known/security.txt.gz: src/content/.well-known/security.txt
+src/content/.well-known/security.txt: email.txt baseurl.txt expiry.txt
+ mkdir -p $(@D)
+ printf 'Contact: mailto:%s\n' "`cat email.txt`" > $@
+ printf 'Expires: %s\n' "`cat expiry.txt`" >> $@
+ printf 'Encryption: %s/$(PUBURL)\n' "`cat baseurl.txt`" >> $@
+ printf 'Preferred-Languages: en, pt, fr, eo, es, de\n' >> $@
+
+src/sources.txt:
+ printf '%s\n' $(sources) > $@
+
+src/all-contents.txt:
+ printf '%s\n' $(all-contents) > $@
+
+src/all-filelists.txt: src/all-symlinks.txt
+ printf '%s\n' $(all-filelists) src/all-symlinks.txt > $@
+
+src/all-symlinks.txt: src/content/.gitignore
+ sed 's|^|src/content|' src/content/.gitignore > $@
+
+src/install.txt: src/all-contents.txt src/all-filelists.txt $(all-filelists)
+ cat src/all-contents.txt `cat src/all-filelists.txt` > $@
+
+sources.txt: src/sources.txt
+install.txt: src/install.txt
+sources.txt install.txt:
+ sed 's|^src/content/||' src/$(@F) > $@
+
+
+
+## ---- check-unit-* targets ---------------------------------------
+
+src/sort-expected.txt:
+ dirname $(articles.adoc) | env LANG=POSIX.UTF-8 sort | uniq -c | \
+ awk '{ printf "%s\t%s\n", $$2, $$1 }' > $@
+
+src/sort-given.txt: $(sources.conf) src/sort-expected.txt
+ awk '{ \
+ "grep \"^export sort=\" " $$1 "/*.conf | wc -l" | getline cnt; \
+ printf "%s\t%s\n", $$1, cnt; \
+ }' src/sort-expected.txt > $@
+
+check-unit-sorting: src/sort-expected.txt src/sort-given.txt
+ diff -U10 src/sort-expected.txt src/sort-given.txt
+
+
+.SUFFIXES: .updatedat-check
+sources.updatedat-check = $(sources.adoc:.adoc=.updatedat-check)
+$(sources.updatedat-check):
+ . ./$*.conf && if [ -n "$$updatedat_epoch" ] && \
+ [ "$$updatedat_epoch" -le "$$date_epoch" ]; then exit 3; fi
+
+check-unit-updatedat: $(sources.updatedat-check)
+
+
+.SUFFIXES: .links-internal-check
+sources.links-internal-check = $(sources.adoc:.adoc=.links-internal-check)
+$(sources.links-internal-check): $(sources.html) $(slides.pdf)
+ grep -E '^(link|image):' $*.links | cut -d: -f2- | \
+ xargs -I% test -e $(*D)/%
+
+check-unit-links-internal: $(sources.links-internal-check)
+
+
+check-unit-links-external:
+
+
+symlink-deps = \
+ $(sources.html) \
+ $(feeds.xml) \
+ $(categories.xml) \
+ src/content/.well-known/security.txt \
+ $(sources.media.torrent) \
+
+check-unit-links-symlinks: src/all-symlinks.txt $(symlink-deps)
+ find `cat src/all-symlinks.txt` | xargs -n1 test -e
+
+
+check-unit-links: check-unit-links-internal check-unit-links-external
+check-unit-links: check-unit-links-symlinks
+
+
+MAXSIZE = 52428800 # from spec: https://www.sitemaps.org/protocol.html
+check-unit-sitemap-size: src/content/sitemap.xml
+ test "`stat --printf='%s' src/content/sitemap.xml`" -le $(MAXSIZE)
+
+check-unit-sitemap-count: src/content/sitemap.xml
+ test "`grep -cF '</url>' src/content/sitemap.xml`" -le 50000
+
+check-unit-sitemap: check-unit-sitemap-count check-unit-sitemap-size
+
+
+check-unit-expiry: expiry-epoch.txt now.txt
+ test "`cat expiry-epoch.txt`" -gt "`cat now.txt`"
+
+
+check-unit: check-unit-sorting check-unit-updatedat check-unit-links
+check-unit: check-unit-sitemap check-unit-expiry
+
+
+## ---- standard housekeeping --------------------------------------
+
+## Remove all derived artifacts produced during the build.
+clean:
+ rm -rf $(derived-assets) $(side-assets)
+
+
+## Install into $(DESTDIR)$(PREFIX).
+install: all
+ rsync --mkpath -a --files-from=install.txt src/content/ \
+ '$(DESTDIR)$(HTMLDIR)'
+ rsync --mkpath -a --files-from=sources.txt src/content/ \
+ '$(DESTDIR)$(SRCDIR)'
+
+## Remove what install placed.
+uninstall:
+ rm -rf \
+ '$(DESTDIR)$(SRCDIR)' \
+ '$(DESTDIR)$(HTMLDIR)' \
+
+
+ALWAYS:
diff --git a/mkdeps.sh b/mkdeps.sh
index 58b4515..95d8d00 100755
--- a/mkdeps.sh
+++ b/mkdeps.sh
@@ -165,8 +165,9 @@ for langlink in src/collections/*; do
done
done
-## Pull in the canonical mkwb rules. Placed at the end of deps.mk
-## so that the variable assignments above are visible when site.mk
-## parses `all: $(derived-assets)` and its prereq list expands at
-## parse time (no GNU $(shell) needed in the site Makefile).
-printf '\ninclude %s\n' "`mkwb rules`"
+## Inline the canonical mkwb rules at the end of deps.mk so that
+## the variable assignments above are visible when those rules
+## parse `all: $(derived-assets)` and its prereq list expands at
+## parse time. Self-contained -- no make-time include needed.
+echo
+mkwb rules