summaryrefslogtreecommitdiffstats
path: root/config/prelude.mk
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-04-16 18:43:49 -0400
committerTavian Barnes <tavianator@tavianator.com>2024-04-16 18:58:51 -0400
commitc4c063e9844f2bd2271b2e3391f59f872c66f69a (patch)
treed09c0852ae24c78e723e425306ae006fae16e076 /config/prelude.mk
parent98c539eeda8f9adfd22a3b2b6ece4fe1ca06b3b4 (diff)
downloadbfs-c4c063e9844f2bd2271b2e3391f59f872c66f69a.tar.xz
build: Refactor configuration
We now use a recursive make invocation to do the work of `make config`. The new implementation is also compatible with GNU make 3.81 found on macOS.
Diffstat (limited to 'config/prelude.mk')
-rw-r--r--config/prelude.mk164
1 files changed, 164 insertions, 0 deletions
diff --git a/config/prelude.mk b/config/prelude.mk
new file mode 100644
index 0000000..1d5fb83
--- /dev/null
+++ b/config/prelude.mk
@@ -0,0 +1,164 @@
+# Copyright © Tavian Barnes <tavianator@tavianator.com>
+# SPDX-License-Identifier: 0BSD
+
+# Common makefile utilities. Compatible with both GNU make and most BSD makes.
+
+# BSD make will chdir into ${.OBJDIR} by default, unless we tell it not to
+.OBJDIR: .
+
+# We don't use any suffix rules
+.SUFFIXES:
+
+# GNU make has $^ for the full list of targets, while BSD make has $> and the
+# long-form ${.ALLSRC}. We could write $^ $> to get them both, but that would
+# break if one of them implemented support for the other. So instead, bring
+# BSD's ${.ALLSRC} to GNU.
+.ALLSRC ?= $^
+
+# For out-of-tree builds, e.g.
+#
+# $ make config BUILDDIR=/path/to/build/dir
+# $ make BUILDDIR=/path/to/build/dir
+BUILDDIR ?= .
+
+# Shorthand for build subdirectories
+BIN := ${BUILDDIR}/bin
+GEN := ${BUILDDIR}/gen
+OBJ := ${BUILDDIR}/obj
+
+# GNU make strips a leading ./ from target names, so do the same for BSD make
+BIN := ${BIN:./%=%}
+GEN := ${GEN:./%=%}
+OBJ := ${OBJ:./%=%}
+
+# The configuration file generated by `make config`
+CONFIG := ${GEN}/config.mk
+
+# Installation paths
+DESTDIR ?=
+PREFIX ?= /usr
+MANDIR ?= ${PREFIX}/share/man
+
+# GNU make supports `export VAR`, but BSD make requires `export VAR=value`.
+# Sadly, GNU make gives a recursion error on `export VAR=${VAR}`.
+_BUILDDIR := ${BUILDDIR}
+export BUILDDIR=${_BUILDDIR}
+
+# Configurable executables; can be overridden with
+#
+# $ make config CC=clang
+CC ?= cc
+INSTALL ?= install
+MKDIR ?= mkdir -p
+PKG_CONFIG ?= pkg-config
+RM ?= rm -f
+
+# GNU and BSD make have incompatible syntax for conditionals, but we can do a
+# lot with just nested variable expansion. We use "y" as the canonical
+# truthy value, and "" (the empty string) as the canonical falsey value.
+#
+# To normalize a boolean, use ${TRUTHY,${VAR}}, which expands like this:
+#
+# VAR=y ${TRUTHY,${VAR}} => ${TRUTHY,y} => y
+# VAR=1 ${TRUTHY,${VAR}} => ${TRUTHY,1} => y
+# VAR=n ${TRUTHY,${VAR}} => ${TRUTHY,n} => [empty]
+# VAR=other ${TRUTHY,${VAR}} => ${TRUTHY,other} => [empty]
+# VAR= ${TRUTHY,${VAR}} => ${TRUTHY,} => [emtpy]
+#
+# Inspired by https://github.com/wahern/autoguess
+TRUTHY,y := y
+TRUTHY,1 := y
+
+# Boolean operators are also implemented with nested expansion
+NOT,y :=
+NOT, := y
+
+# Support up to 5 arguments
+AND,y := y
+AND,y,y := y
+AND,y,y,y := y
+AND,y,y,y,y := y
+AND,y,y,y,y,y := y
+
+# NOR can be defined without combinatorial explosion.
+# OR is just ${NOT,${NOR,...}}
+NOR, := y
+NOR,, := y
+NOR,,, := y
+NOR,,,, := y
+NOR,,,,, := y
+
+# Normalize ${V} to either "y" or ""
+IS_V := ${TRUTHY,${V}}
+
+# Suppress output unless V=1
+Q, := @
+Q := ${Q,${IS_V}}
+
+# Show full commands with `make V=1`, otherwise short summaries
+MSG = @msg() { \
+ MSG="$$1"; \
+ shift; \
+ test "${IS_V}" || printf '%s\n' "$$MSG"; \
+ test "$${1:-}" || return 0; \
+ test "${IS_V}" && printf '%s\n' "$$*"; \
+ "$$@"; \
+ }; \
+ msg
+
+# cat a file if V=1
+VCAT,y := @cat
+VCAT, := @:
+VCAT := ${VCAT,${IS_V}}
+
+# List all object files here, as they're needed by both `make config` and `make`
+
+# All object files except the entry point
+LIBBFS := \
+ ${OBJ}/src/alloc.o \
+ ${OBJ}/src/bar.o \
+ ${OBJ}/src/bfstd.o \
+ ${OBJ}/src/bftw.o \
+ ${OBJ}/src/color.o \
+ ${OBJ}/src/ctx.o \
+ ${OBJ}/src/diag.o \
+ ${OBJ}/src/dir.o \
+ ${OBJ}/src/dstring.o \
+ ${OBJ}/src/eval.o \
+ ${OBJ}/src/exec.o \
+ ${OBJ}/src/expr.o \
+ ${OBJ}/src/fsade.o \
+ ${OBJ}/src/ioq.o \
+ ${OBJ}/src/mtab.o \
+ ${OBJ}/src/opt.o \
+ ${OBJ}/src/parse.o \
+ ${OBJ}/src/printf.o \
+ ${OBJ}/src/pwcache.o \
+ ${OBJ}/src/stat.o \
+ ${OBJ}/src/thread.o \
+ ${OBJ}/src/trie.o \
+ ${OBJ}/src/typo.o \
+ ${OBJ}/src/version.o \
+ ${OBJ}/src/xregex.o \
+ ${OBJ}/src/xspawn.o \
+ ${OBJ}/src/xtime.o
+
+# Unit test objects
+UNIT_OBJS := \
+ ${OBJ}/tests/alloc.o \
+ ${OBJ}/tests/bfstd.o \
+ ${OBJ}/tests/bit.o \
+ ${OBJ}/tests/ioq.o \
+ ${OBJ}/tests/main.o \
+ ${OBJ}/tests/trie.o \
+ ${OBJ}/tests/xspawn.o \
+ ${OBJ}/tests/xtime.o
+
+# All object files
+OBJS := \
+ ${OBJ}/src/main.o \
+ ${OBJ}/tests/mksock.o \
+ ${OBJ}/tests/xspawnee.o \
+ ${OBJ}/tests/xtouch.o \
+ ${LIBBFS} \
+ ${UNIT_OBJS}