summaryrefslogtreecommitdiffstats
path: root/Makefile
diff options
context:
space:
mode:
Diffstat (limited to 'Makefile')
-rw-r--r--Makefile282
1 files changed, 179 insertions, 103 deletions
diff --git a/Makefile b/Makefile
index 1d26d12..5e6d25c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,109 +1,127 @@
# Copyright © Tavian Barnes <tavianator@tavianator.com>
# SPDX-License-Identifier: 0BSD
-# This Makefile implements the configuration and build steps for bfs. It is
-# portable to both GNU make and most BSD make implementations. To build bfs,
-# run
+# To build bfs, run
#
-# $ make config
+# $ ./configure
# $ make
# Utilities and GNU/BSD portability
-include config/prelude.mk
+include build/prelude.mk
# The default build target
default: bfs
.PHONY: default
# Include the generated build config, if it exists
--include ${CONFIG}
+-include gen/config.mk
-## Configuration phase (`make config`)
-
-# The configuration goal itself
-config::
- @+${MAKE} -sf config/config.mk
+## Configuration phase (`./configure`)
# bfs used to have flag-like targets (`make release`, `make asan ubsan`, etc.).
# Direct users to the new configuration system.
asan lsan msan tsan ubsan gcov lint release::
- @printf 'error: `%s %s` is no longer supported. ' "${MAKE}" $@ >&2
- @printf 'Use `%s config %s=y` instead.\n' "${MAKE}" $$(echo $@ | tr 'a-z' 'A-Z') >&2
+ @printf 'error: `%s %s` is no longer supported. Use `./configure --enable-%s` instead.\n' \
+ "${MAKE}" $@ $@ >&2
@false
-# Print an error if `make` is run before `make config`
-${CONFIG}::
- @if ! [ -e $@ ]; then \
- printf 'error: You must run `%s config` before `%s`.\n' "${MAKE}" "${MAKE}" >&2; \
+# Print an error if `make` is run before `./configure`
+gen/config.mk::
+ if ! [ -e $@ ]; then \
+ printf 'error: You must run `./configure` before `%s`.\n' "${MAKE}" >&2; \
false; \
fi
+.SILENT: gen/config.mk
## Build phase (`make`)
# The main binary
-bfs: ${BIN}/bfs
+bfs: bin/bfs
.PHONY: bfs
# All binaries
BINS := \
- ${BIN}/bfs \
- ${BIN}/tests/mksock \
- ${BIN}/tests/units \
- ${BIN}/tests/xspawnee \
- ${BIN}/tests/xtouch
+ bin/bfs \
+ bin/tests/mksock \
+ bin/tests/ptyx \
+ bin/tests/units \
+ bin/tests/xspawnee \
+ bin/tests/xtouch \
+ bin/bench/ioq
all: ${BINS}
.PHONY: all
-# Group relevant flags together
-ALL_CFLAGS = ${CPPFLAGS} ${CFLAGS} ${DEPFLAGS}
-ALL_LDFLAGS = ${CFLAGS} ${LDFLAGS}
+# 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/sighook.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
+
+# All object files
+OBJS := ${LIBBFS}
# The main binary
-${BIN}/bfs: ${LIBBFS} ${OBJ}/src/main.o
+bin/bfs: obj/src/main.o ${LIBBFS}
+OBJS += obj/src/main.o
${BINS}:
@${MKDIR} ${@D}
- +${MSG} "[ LD ] ${TGT}" ${CC} ${ALL_LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@
+ +${MSG} "[ LD ] $@" ${CC} ${_CFLAGS} ${_LDFLAGS} $^ ${_LDLIBS} -o $@
${POSTLINK}
# Get the .c file for a .o file
-_CSRC = ${@:${OBJ}/%.o=%.c}
-CSRC = ${_CSRC:gen/%=${GEN}/%}
-
-# Depend on ${CONFIG} to make sure `make config` runs first, and to rebuild when
-# the configuration changes
-${OBJS}: ${CONFIG}
- @${MKDIR} ${@D}
- ${MSG} "[ CC ] ${_CSRC}" ${CC} ${ALL_CFLAGS} -c ${CSRC} -o $@
+CSRC = ${@:obj/%.o=%.c}
# Save the version number to this file, but only update version.c if it changes
-${GEN}/version.c.new::
- @${MKDIR} ${@D}
- @printf 'const char bfs_version[] = "' >$@
- @if [ "$$VERSION" ]; then \
- printf '%s' "$$VERSION"; \
- elif test -d .git && command -v git >/dev/null 2>&1; then \
- git describe --always --dirty; \
- else \
- echo "3.1.3"; \
- fi | tr -d '\n' >>$@
- @printf '";\n' >>$@
-
-${GEN}/version.c: ${GEN}/version.c.new
- @test -e $@ && cmp -s $@ ${.ALLSRC} && rm ${.ALLSRC} || mv ${.ALLSRC} $@
+gen/version.i.new::
+ ${MKDIR} ${@D}
+ build/version.sh | tr -d '\n' | build/embed.sh >$@
+.SILENT: gen/version.i.new
+
+gen/version.i: gen/version.i.new
+ test -e $@ && cmp -s $@ $^ && ${RM} $^ || mv $^ $@
+.SILENT: gen/version.i
+
+obj/src/version.o: gen/version.i
## Test phase (`make check`)
# Unit test binaries
UTEST_BINS := \
- ${BIN}/tests/units \
- ${BIN}/tests/xspawnee
+ bin/tests/units \
+ bin/tests/xspawnee
# Integration test binaries
ITEST_BINS := \
- ${BIN}/tests/mksock \
- ${BIN}/tests/xtouch
+ bin/tests/mksock \
+ bin/tests/ptyx \
+ bin/tests/xtouch
# Build (but don't run) test binaries
tests: ${UTEST_BINS} ${ITEST_BINS}
@@ -115,46 +133,59 @@ check: unit-tests integration-tests
# Run the unit tests
unit-tests: ${UTEST_BINS}
- ${MSG} "[TEST] tests/units" ${BIN}/tests/units
+ ${MSG} "[TEST] tests/units" bin/tests/units
.PHONY: unit-tests
-${BIN}/tests/units: \
- ${UNIT_OBJS} \
- ${LIBBFS}
-
-${BIN}/tests/xspawnee: \
- ${OBJ}/tests/xspawnee.o
+# Unit test objects
+UNIT_OBJS := \
+ obj/tests/alloc.o \
+ obj/tests/bfstd.o \
+ obj/tests/bit.o \
+ obj/tests/ioq.o \
+ obj/tests/list.o \
+ obj/tests/main.o \
+ obj/tests/sighook.o \
+ obj/tests/trie.o \
+ obj/tests/xspawn.o \
+ obj/tests/xtime.o
+
+bin/tests/units: ${UNIT_OBJS} ${LIBBFS}
+OBJS += ${UNIT_OBJS}
+
+bin/tests/xspawnee: obj/tests/xspawnee.o
+OBJS += obj/tests/xspawnee.o
# The different flag combinations we check
INTEGRATIONS := default dfs ids eds j1 j2 j3 s
INTEGRATION_TESTS := ${INTEGRATIONS:%=check-%}
# Check just `bfs`
-check-default: ${BIN}/bfs ${ITEST_BINS}
+check-default: bin/bfs ${ITEST_BINS}
+${MSG} "[TEST] bfs" \
- ./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs" ${TEST_FLAGS}
+ ./tests/tests.sh --make="${MAKE}" --bfs="bin/bfs" ${TEST_FLAGS}
# Check the different search strategies
-check-dfs check-ids check-eds: ${BIN}/bfs ${ITEST_BINS}
+check-dfs check-ids check-eds: bin/bfs ${ITEST_BINS}
+${MSG} "[TEST] bfs -S ${@:check-%=%}" \
- ./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs -S ${@:check-%=%}" ${TEST_FLAGS}
+ ./tests/tests.sh --make="${MAKE}" --bfs="bin/bfs -S ${@:check-%=%}" ${TEST_FLAGS}
# Check various flags
-check-j1 check-j2 check-j3 check-s: ${BIN}/bfs ${ITEST_BINS}
+check-j1 check-j2 check-j3 check-s: bin/bfs ${ITEST_BINS}
+${MSG} "[TEST] bfs -${@:check-%=%}" \
- ./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs -${@:check-%=%}" ${TEST_FLAGS}
+ ./tests/tests.sh --make="${MAKE}" --bfs="bin/bfs -${@:check-%=%}" ${TEST_FLAGS}
# Run the integration tests
integration-tests: ${INTEGRATION_TESTS}
.PHONY: integration-tests
-${BIN}/tests/mksock: \
- ${OBJ}/tests/mksock.o \
- ${LIBBFS}
+bin/tests/mksock: obj/tests/mksock.o ${LIBBFS}
+OBJS += obj/tests/mksock.o
+
+bin/tests/ptyx: obj/tests/ptyx.o ${LIBBFS}
+OBJS += obj/tests/ptyx.o
-${BIN}/tests/xtouch: \
- ${OBJ}/tests/xtouch.o \
- ${LIBBFS}
+bin/tests/xtouch: obj/tests/xtouch.o ${LIBBFS}
+OBJS += obj/tests/xtouch.o
# `make distcheck` configurations
DISTCHECKS := \
@@ -166,69 +197,114 @@ DISTCHECKS := \
# Test multiple configurations
distcheck:
- @+${MAKE} -s distcheck-asan
- @+test "$$(uname)" = Darwin || ${MAKE} -s distcheck-msan
- @+${MAKE} -s distcheck-tsan
- @+test "$$(uname)-$$(uname -m)" != Linux-x86_64 || ${MAKE} -s distcheck-m32
- @+${MAKE} -s distcheck-release
+ @+${MAKE} distcheck-asan
+ @+test "$$(uname)" = Darwin || ${MAKE} distcheck-msan
+ @+test "$$(uname)" = FreeBSD || ${MAKE} distcheck-tsan
+ @+test "$$(uname)-$$(uname -m)" != Linux-x86_64 || ${MAKE} distcheck-m32
+ @+${MAKE} distcheck-release
+ @+${MAKE} -C distcheck-release check-install
+ @+test "$$(uname)" != Linux || ${MAKE} check-man
.PHONY: distcheck
# Per-distcheck configuration
-DISTCHECK_CONFIG_asan := ASAN=y UBSAN=y
-DISTCHECK_CONFIG_msan := MSAN=y UBSAN=y CC=clang
-DISTCHECK_CONFIG_tsan := TSAN=y UBSAN=y CC=clang
+DISTCHECK_CONFIG_asan := --enable-asan --enable-ubsan
+DISTCHECK_CONFIG_msan := --enable-msan --enable-ubsan CC=clang
+DISTCHECK_CONFIG_tsan := --enable-tsan --enable-ubsan CC=clang
DISTCHECK_CONFIG_m32 := EXTRA_CFLAGS="-m32" PKG_CONFIG_LIBDIR=/usr/lib32/pkgconfig
-DISTCHECK_CONFIG_release := RELEASE=y
+DISTCHECK_CONFIG_release := --enable-release
${DISTCHECKS}::
- +${MAKE} -rs BUILDDIR=${BUILDDIR}/$@ config ${DISTCHECK_CONFIG_${@:distcheck-%=%}}
- +${MAKE} -s BUILDDIR=${BUILDDIR}/$@ check TEST_FLAGS="--sudo --verbose=skipped"
+ @${MKDIR} $@
+ @test "$${GITHUB_ACTIONS-}" != true || printf '::group::%s\n' $@
+ @+cd $@ \
+ && ../configure MAKE="${MAKE}" ${DISTCHECK_CONFIG_${@:distcheck-%=%}} \
+ && ${MAKE} check TEST_FLAGS="--sudo --verbose=skipped"
+ @test "$${GITHUB_ACTIONS-}" != true || printf '::endgroup::\n'
+
+## Benchmarks (`make bench`)
+
+bench: bin/bench/ioq
+.PHONY: bench
-## Packaging (`make install`)
+bin/bench/ioq: obj/bench/ioq.o ${LIBBFS}
+OBJS += obj/bench/ioq.o
+
+## Automatic dependency tracking
+
+# Rebuild when the configuration changes
+${OBJS}: gen/config.mk
+ @${MKDIR} ${@D}
+ ${MSG} "[ CC ] ${CSRC}" ${CC} ${_CPPFLAGS} ${_CFLAGS} -c ${CSRC} -o $@
+
+# Include any generated dependency files
+-include ${OBJS:.o=.d}
+
+## Packaging (`make dist`, `make install`)
+
+TARBALL = bfs-$$(build/version.sh).tar.gz
+
+dist:
+ ${MSG} "[DIST] ${TARBALL}" git archive HEAD -o ${TARBALL}
+
+distsign: dist
+ ${MSG} "[SIGN] ${TARBALL}" ssh-keygen -Y sign -q -f $$(git config user.signingkey) -n file ${TARBALL}
+
+.PHONY: dist distsign
DEST_PREFIX := ${DESTDIR}${PREFIX}
DEST_MANDIR := ${DESTDIR}${MANDIR}
install::
${Q}${MKDIR} ${DEST_PREFIX}/bin
- ${MSG} "[INSTALL] bin/bfs" \
- ${INSTALL} -m755 ${BIN}/bfs ${DEST_PREFIX}/bin/bfs
+ ${MSG} "[INST] bin/bfs" \
+ ${INSTALL} -m755 bin/bfs ${DEST_PREFIX}/bin/bfs
${Q}${MKDIR} ${DEST_MANDIR}/man1
- ${MSG} "[INSTALL] man/man1/bfs.1" \
+ ${MSG} "[INST] man/man1/bfs.1" \
${INSTALL} -m644 docs/bfs.1 ${DEST_MANDIR}/man1/bfs.1
${Q}${MKDIR} ${DEST_PREFIX}/share/bash-completion/completions
- ${MSG} "[INSTALL] completions/bfs.bash" \
+ ${MSG} "[INST] completions/bfs.bash" \
${INSTALL} -m644 completions/bfs.bash ${DEST_PREFIX}/share/bash-completion/completions/bfs
${Q}${MKDIR} ${DEST_PREFIX}/share/zsh/site-functions
- ${MSG} "[INSTALL] completions/bfs.zsh" \
+ ${MSG} "[INST] completions/bfs.zsh" \
${INSTALL} -m644 completions/bfs.zsh ${DEST_PREFIX}/share/zsh/site-functions/_bfs
${Q}${MKDIR} ${DEST_PREFIX}/share/fish/vendor_completions.d
- ${MSG} "[INSTALL] completions/bfs.fish" \
+ ${MSG} "[INST] completions/bfs.fish" \
${INSTALL} -m644 completions/bfs.fish ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish
uninstall::
- ${RM} ${DEST_PREFIX}/share/bash-completion/completions/bfs
- ${RM} ${DEST_PREFIX}/share/zsh/site-functions/_bfs
- ${RM} ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish
- ${RM} ${DEST_MANDIR}/man1/bfs.1
- ${RM} ${DEST_PREFIX}/bin/bfs
+ ${MSG} "[ RM ] completions/bfs.bash" \
+ ${RM} ${DEST_PREFIX}/share/bash-completion/completions/bfs
+ ${MSG} "[ RM ] completions/bfs.zsh" \
+ ${RM} ${DEST_PREFIX}/share/zsh/site-functions/_bfs
+ ${MSG} "[ RM ] completions/bfs.fish" \
+ ${RM} ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish
+ ${MSG} "[ RM ] man/man1/bfs.1" \
+ ${RM} ${DEST_MANDIR}/man1/bfs.1
+ ${MSG} "[ RM ] bin/bfs" \
+ ${RM} ${DEST_PREFIX}/bin/bfs
# Check that `make install` works and `make uninstall` removes everything
check-install::
- +${MAKE} install DESTDIR=${BUILDDIR}/pkg
- +${MAKE} uninstall DESTDIR=${BUILDDIR}/pkg
- ${BIN}/bfs ${BUILDDIR}/pkg -not -type d -print -exit 1
- ${RM} -r ${BUILDDIR}/pkg
+ +${MAKE} install DESTDIR=pkg
+ +${MAKE} uninstall DESTDIR=pkg
+ bin/bfs pkg -not -type d -print -exit 1
+ ${RM} -r pkg
+
+# Check man page markup
+check-man::
+ ${MSG} "[LINT] docs/bfs.1"
+ ${Q}groff -man -rCHECKSTYLE=3 -ww -b -z docs/bfs.1
+ ${Q}mandoc -Tlint -Wwarning docs/bfs.1
## Cleanup (`make clean`)
# Clean all build products
clean::
${MSG} "[ RM ] bin obj" \
- ${RM} -r ${BIN} ${OBJ}
+ ${RM} -r bin obj
# Clean everything, including generated files
distclean: clean
- ${MSG} "[ RM ] gen" \
- ${RM} -r ${GEN} ${DISTCHECKS}
+ ${MSG} "[ RM ] gen distcheck-*" \
+ ${RM} -r gen ${DISTCHECKS}
.PHONY: distclean