diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-04-29 15:30:39 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-04-29 16:25:46 -0400 |
commit | 37caa3d71fd8bb4d0d9204e4a2f5cac234fa25fd (patch) | |
tree | af4dd493b89a17dfdce2957dac90f068decf1667 | |
parent | b8ed989642b9f0f6c1301bcff6f1498935cbd81c (diff) | |
download | bfs-37caa3d71fd8bb4d0d9204e4a2f5cac234fa25fd.tar.xz |
build: Replace `make config` with a `./configure` script
This lets us do more traditional out-of-tree builds like
$ ../path/to/bfs/configure
$ make
The .mk files are moved from ./config to ./build, mostly so that
./configure will auto-complete easily.
-rw-r--r-- | .github/workflows/ci.yml | 8 | ||||
-rw-r--r-- | .github/workflows/codecov.yml | 2 | ||||
-rw-r--r-- | .github/workflows/codeql.yml | 2 | ||||
-rw-r--r-- | Makefile | 143 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | bench/bench.sh | 6 | ||||
-rwxr-xr-x | build/cc.sh (renamed from config/cc.sh) | 0 | ||||
-rw-r--r-- | build/config.mk | 62 | ||||
-rwxr-xr-x | build/define-if.sh (renamed from config/define-if.sh) | 2 | ||||
-rw-r--r-- | build/deps.mk | 18 | ||||
-rw-r--r-- | build/empty.c (renamed from config/empty.c) | 0 | ||||
-rw-r--r-- | build/exports.mk (renamed from config/exports.mk) | 0 | ||||
-rw-r--r-- | build/flags.mk (renamed from config/flags.mk) | 12 | ||||
-rw-r--r-- | build/has/acl-get-entry.c (renamed from config/has/acl-get-entry.c) | 0 | ||||
-rw-r--r-- | build/has/acl-get-file.c (renamed from config/has/acl-get-file.c) | 0 | ||||
-rw-r--r-- | build/has/acl-get-tag-type.c (renamed from config/has/acl-get-tag-type.c) | 0 | ||||
-rw-r--r-- | build/has/acl-is-trivial-np.c (renamed from config/has/acl-is-trivial-np.c) | 0 | ||||
-rw-r--r-- | build/has/acl-trivial.c (renamed from config/has/acl-trivial.c) | 0 | ||||
-rw-r--r-- | build/has/aligned-alloc.c (renamed from config/has/aligned-alloc.c) | 0 | ||||
-rw-r--r-- | build/has/confstr.c (renamed from config/has/confstr.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-get-file.c (renamed from config/has/extattr-get-file.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-get-link.c (renamed from config/has/extattr-get-link.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-list-file.c (renamed from config/has/extattr-list-file.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-list-link.c (renamed from config/has/extattr-list-link.c) | 0 | ||||
-rw-r--r-- | build/has/fdclosedir.c (renamed from config/has/fdclosedir.c) | 0 | ||||
-rw-r--r-- | build/has/getdents.c (renamed from config/has/getdents.c) | 0 | ||||
-rw-r--r-- | build/has/getdents64-syscall.c (renamed from config/has/getdents64-syscall.c) | 0 | ||||
-rw-r--r-- | build/has/getdents64.c (renamed from config/has/getdents64.c) | 0 | ||||
-rw-r--r-- | build/has/getprogname-gnu.c (renamed from config/has/getprogname-gnu.c) | 0 | ||||
-rw-r--r-- | build/has/getprogname.c (renamed from config/has/getprogname.c) | 0 | ||||
-rw-r--r-- | build/has/max-align-t.c (renamed from config/has/max-align-t.c) | 0 | ||||
-rw-r--r-- | build/has/pipe2.c (renamed from config/has/pipe2.c) | 0 | ||||
-rw-r--r-- | build/has/posix-spawn-addfchdir-np.c (renamed from config/has/posix-spawn-addfchdir-np.c) | 0 | ||||
-rw-r--r-- | build/has/posix-spawn-addfchdir.c (renamed from config/has/posix-spawn-addfchdir.c) | 0 | ||||
-rw-r--r-- | build/has/st-acmtim.c (renamed from config/has/st-acmtim.c) | 0 | ||||
-rw-r--r-- | build/has/st-acmtimespec.c (renamed from config/has/st-acmtimespec.c) | 0 | ||||
-rw-r--r-- | build/has/st-birthtim.c (renamed from config/has/st-birthtim.c) | 0 | ||||
-rw-r--r-- | build/has/st-birthtimespec.c (renamed from config/has/st-birthtimespec.c) | 0 | ||||
-rw-r--r-- | build/has/st-flags.c (renamed from config/has/st-flags.c) | 0 | ||||
-rw-r--r-- | build/has/statx-syscall.c (renamed from config/has/statx-syscall.c) | 0 | ||||
-rw-r--r-- | build/has/statx.c (renamed from config/has/statx.c) | 0 | ||||
-rw-r--r-- | build/has/strerror-l.c (renamed from config/has/strerror-l.c) | 0 | ||||
-rw-r--r-- | build/has/strerror-r-gnu.c (renamed from config/has/strerror-r-gnu.c) | 0 | ||||
-rw-r--r-- | build/has/strerror-r-posix.c (renamed from config/has/strerror-r-posix.c) | 0 | ||||
-rw-r--r-- | build/has/tm-gmtoff.c (renamed from config/has/tm-gmtoff.c) | 0 | ||||
-rw-r--r-- | build/has/uselocale.c (renamed from config/has/uselocale.c) | 0 | ||||
-rw-r--r-- | build/header.mk | 69 | ||||
-rwxr-xr-x | build/pkgconf.sh (renamed from config/pkgconf.sh) | 2 | ||||
-rw-r--r-- | build/pkgs.mk | 36 | ||||
-rw-r--r-- | build/prelude.mk (renamed from config/prelude.mk) | 111 | ||||
-rw-r--r-- | build/use/libacl.c (renamed from config/use/libacl.c) | 0 | ||||
-rw-r--r-- | build/use/libcap.c (renamed from config/use/libcap.c) | 0 | ||||
-rw-r--r-- | build/use/libselinux.c (renamed from config/use/libselinux.c) | 0 | ||||
-rw-r--r-- | build/use/liburing.c (renamed from config/use/liburing.c) | 0 | ||||
-rw-r--r-- | build/use/oniguruma.c (renamed from config/use/oniguruma.c) | 0 | ||||
-rw-r--r-- | config/config.mk | 63 | ||||
-rw-r--r-- | config/deps.mk | 18 | ||||
-rw-r--r-- | config/header.mk | 69 | ||||
-rw-r--r-- | config/pkgs.mk | 36 | ||||
-rwxr-xr-x | configure | 98 | ||||
-rw-r--r-- | docs/BUILDING.md | 47 | ||||
-rw-r--r-- | tests/util.sh | 9 | ||||
-rw-r--r-- | tests/xspawn.c | 15 |
63 files changed, 445 insertions, 387 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3890bb0..57f59f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: gmake \ oniguruma jobs=$(sysctl -n hw.ncpu) - gmake -j$jobs config + MAKE=gmake ./configure gmake -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" netbsd: @@ -133,7 +133,7 @@ jobs: pkgconf \ tcl-expect jobs=$(sysctl -n hw.ncpu) - make -j$jobs config + ./configure make -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" dragonflybsd: @@ -165,7 +165,7 @@ jobs: run: | chown -R action:action . jobs=$(sysctl -n hw.ncpu) - sudo -u action make config + sudo -u action ./configure sudo -u action make -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" omnios: @@ -198,5 +198,5 @@ jobs: PATH="/usr/xpg4/bin:$PATH" chown -R action:staff . jobs=$(getconf NPROCESSORS_ONLN) - sudo -u action gmake config + sudo -u action MAKE=gmake ./configure sudo -u action gmake -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 2245f40..bb68927 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -25,7 +25,7 @@ jobs: - name: Generate coverage run: | - make config GCOV=y + ./configure GCOV=y make -j$(nproc) check TEST_FLAGS="--sudo" gcov -abcfpu obj/*/*.o diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c21fda5..a0b8fe3 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: - name: Configure run: | - make -j$(nproc) config + ./configure - name: Initialize CodeQL uses: github/codeql-action/init@v3 @@ -1,56 +1,50 @@ # 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 %s=y` instead.\n' \ + "${MAKE}" $@ $$(echo $@ | tr 'a-z' 'A-Z') >&2 @false -# Print an error if `make` is run before `make config` -${CONFIG}:: +# Print an error if `make` is run before `./configure` +gen/config.mk:: @if ! [ -e $@ ]; then \ - printf 'error: You must run `%s config` before `%s`.\n' "${MAKE}" "${MAKE}" >&2; \ + printf 'error: You must run `./configure` before `%s`.\n' "${MAKE}" >&2; \ false; \ fi ## 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/units \ + bin/tests/xspawnee \ + bin/tests/xtouch all: ${BINS} .PHONY: all @@ -60,52 +54,50 @@ ALL_CFLAGS = ${CPPFLAGS} ${CFLAGS} ${DEPFLAGS} ALL_LDFLAGS = ${CFLAGS} ${LDFLAGS} # The main binary -${BIN}/bfs: ${LIBBFS} ${OBJ}/src/main.o +bin/bfs: ${LIBBFS} obj/src/main.o ${BINS}: @${MKDIR} ${@D} - +${MSG} "[ LD ] ${TGT}" ${CC} ${ALL_LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@ + +${MSG} "[ LD ] $@" ${CC} ${ALL_LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@ ${POSTLINK} # Get the .c file for a .o file -_CSRC = ${@:${OBJ}/%.o=%.c} -CSRC = ${_CSRC:gen/%=${GEN}/%} +CSRC = ${@:obj/%.o=%.c} -# Depend on ${CONFIG} to make sure `make config` runs first, and to rebuild when -# the configuration changes -${OBJS}: ${CONFIG} +# Rebuild when the configuration changes +${OBJS}: gen/config.mk @${MKDIR} ${@D} - ${MSG} "[ CC ] ${_CSRC}" ${CC} ${ALL_CFLAGS} -c ${CSRC} -o $@ + ${MSG} "[ CC ] ${CSRC}" ${CC} ${ALL_CFLAGS} -c ${CSRC} -o $@ # Save the version number to this file, but only update version.c if it changes -${GEN}/version.c.new:: +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; \ + elif test -e src/../.git && command -v git >/dev/null 2>&1; then \ + git -C src/.. describe --always --dirty; \ else \ echo "3.1.3"; \ fi | tr -d '\n' >>$@ @printf '";\n' >>$@ -${GEN}/version.c: ${GEN}/version.c.new +gen/version.c: gen/version.c.new @test -e $@ && cmp -s $@ ${.ALLSRC} && rm ${.ALLSRC} || mv ${.ALLSRC} $@ -${OBJ}/gen/version.o: ${GEN}/version.c +obj/gen/version.o: gen/version.c ## 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/xtouch # Build (but don't run) test binaries tests: ${UTEST_BINS} ${ITEST_BINS} @@ -117,45 +109,45 @@ 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: \ +bin/tests/units: \ ${UNIT_OBJS} \ ${LIBBFS} -${BIN}/tests/xspawnee: \ - ${OBJ}/tests/xspawnee.o +bin/tests/xspawnee: \ + 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 \ +bin/tests/mksock: \ + obj/tests/mksock.o \ ${LIBBFS} -${BIN}/tests/xtouch: \ - ${OBJ}/tests/xtouch.o \ +bin/tests/xtouch: \ + obj/tests/xtouch.o \ ${LIBBFS} # `make distcheck` configurations @@ -183,8 +175,10 @@ DISTCHECK_CONFIG_m32 := EXTRA_CFLAGS="-m32" PKG_CONFIG_LIBDIR=/usr/lib32/pkgconf DISTCHECK_CONFIG_release := RELEASE=y ${DISTCHECKS}:: - +${MAKE} -rs BUILDDIR=${BUILDDIR}/$@ config ${DISTCHECK_CONFIG_${@:distcheck-%=%}} - +${MAKE} -s BUILDDIR=${BUILDDIR}/$@ check TEST_FLAGS="--sudo --verbose=skipped" + @${MKDIR} $@ + @+cd $@ \ + && ../configure ${DISTCHECK_CONFIG_${@:distcheck-%=%}} \ + && ${MAKE} -s check TEST_FLAGS="--sudo --verbose=skipped" ## Packaging (`make install`) @@ -193,44 +187,49 @@ 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 ## 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} + ${RM} -r gen ${DISTCHECKS} .PHONY: distclean @@ -333,7 +333,7 @@ Once you have the dependencies, you can build <code>bfs</code>. Download one of the [releases](https://github.com/tavianator/bfs/releases) or clone the [git repo](https://github.com/tavianator/bfs). Then run - $ make config + $ ./configure $ make This will build the `./bin/bfs` binary. @@ -343,7 +343,7 @@ Run the test suite to make sure it works correctly: If you're interested in speed, you may want to build the release version instead: - $ make config RELEASE=y + $ ./configure RELEASE=y $ make Finally, if you want to install it globally, run diff --git a/bench/bench.sh b/bench/bench.sh index 1526fe5..ba46599 100644 --- a/bench/bench.sh +++ b/bench/bench.sh @@ -221,7 +221,7 @@ setup() { fi echo "Building bfs ..." - as-user make -s -j"$nproc" RELEASE=y + as-user ./configure RELEASE=y as-user make -s -j"$nproc" all as-user mkdir -p bench/corpus @@ -254,8 +254,8 @@ setup() { echo "Building bfs $commit ..." cd "$worktree" as-user git checkout -qd "$commit" -- - if [ -e config ]; then - as-user make -s -j"$nproc" config RELEASE=1 + if [ -e configure ]; then + as-user ./configure RELEASE=1 as-user make -s -j"$nproc" else as-user make -s -j"$nproc" release diff --git a/config/cc.sh b/build/cc.sh index 45d51ca..45d51ca 100755 --- a/config/cc.sh +++ b/build/cc.sh diff --git a/build/config.mk b/build/config.mk new file mode 100644 index 0000000..153838d --- /dev/null +++ b/build/config.mk @@ -0,0 +1,62 @@ +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# Makefile that implements `./configure` + +include build/prelude.mk +include build/exports.mk + +# All configuration steps +config: gen/config.mk gen/config.h +.PHONY: config + +# Makefile fragments generated by `./configure` +MKS := \ + gen/vars.mk \ + gen/flags.mk \ + gen/deps.mk \ + gen/pkgs.mk + +# The main configuration file, which includes the others +gen/config.mk: ${MKS} + ${MSG} "[ GEN] $@" + @printf '# %s\n' "$@" >$@ + @printf 'include %s\n' ${.ALLSRC} >>$@ + ${VCAT} gen/config.mk +.PHONY: gen/config.mk + +# Saves the configurable variables +gen/vars.mk:: + @${MKDIR} ${@D} + ${MSG} "[ GEN] $@" + @printf '# %s\n' "$@" >$@ + @printf 'PREFIX := %s\n' "$$XPREFIX" >>$@ + @printf 'MANDIR := %s\n' "$$XMANDIR" >>$@ + @printf 'OS := %s\n' "$${OS:-$$(uname)}" >>$@ + @printf 'CC := %s\n' "$$XCC" >>$@ + @printf 'INSTALL := %s\n' "$$XINSTALL" >>$@ + @printf 'MKDIR := %s\n' "$$XMKDIR" >>$@ + @printf 'PKG_CONFIG := %s\n' "$$XPKG_CONFIG" >>$@ + @printf 'RM := %s\n' "$$XRM" >>$@ + ${VCAT} $@ + +# Sets the build flags. This depends on vars.mk and uses a recursive make so +# that the default flags can depend on variables like ${OS}. +gen/flags.mk: gen/vars.mk + @+${MAKE} -sf build/flags.mk $@ +.PHONY: gen/flags.mk + +# Check for dependency generation support +gen/deps.mk: gen/flags.mk + @+${MAKE} -sf build/deps.mk $@ +.PHONY: gen/deps.mk + +# Auto-detect dependencies and their build flags +gen/pkgs.mk: gen/flags.mk + @+${MAKE} -sf build/pkgs.mk $@ +.PHONY: gen/pkgs.mk + +# Compile-time feature detection +gen/config.h: gen/config.mk + @+${MAKE} -sf build/header.mk $@ +.PHONY: gen/config.h diff --git a/config/define-if.sh b/build/define-if.sh index 059c1ac..295ead8 100755 --- a/config/define-if.sh +++ b/build/define-if.sh @@ -7,7 +7,7 @@ set -eu -SLUG="${1#config/}" +SLUG="${1#build/}" SLUG="${SLUG%.c}" MACRO="BFS_$(printf '%s' "$SLUG" | tr '/a-z-' '_A-Z_')" shift diff --git a/build/deps.mk b/build/deps.mk new file mode 100644 index 0000000..e8dd9fb --- /dev/null +++ b/build/deps.mk @@ -0,0 +1,18 @@ +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# Makefile that generates gen/deps.mk + +include build/prelude.mk +include gen/vars.mk +include gen/flags.mk +include build/exports.mk + +gen/deps.mk:: + ${MSG} "[ GEN] $@" + printf '# %s\n' "$@" >$@ + if build/cc.sh -MD -MP -MF /dev/null build/empty.c; then \ + printf 'DEPFLAGS := -MD -MP\n'; \ + fi >>$@ 2>$@.log + ${VCAT} $@ + printf -- '-include %s\n' ${OBJS:.o=.d} >>$@ diff --git a/config/empty.c b/build/empty.c index 4fa9a5b..4fa9a5b 100644 --- a/config/empty.c +++ b/build/empty.c diff --git a/config/exports.mk b/build/exports.mk index ed19134..ed19134 100644 --- a/config/exports.mk +++ b/build/exports.mk diff --git a/config/flags.mk b/build/flags.mk index 837c30f..0a44e94 100644 --- a/config/flags.mk +++ b/build/flags.mk @@ -3,8 +3,8 @@ # Makefile that generates gen/flags.mk -include config/prelude.mk -include ${GEN}/vars.mk +include build/prelude.mk +include gen/vars.mk # Configurable flags CPPFLAGS ?= @@ -29,7 +29,7 @@ export XLDLIBS=${LDLIBS} # Immutable flags export BFS_CPPFLAGS= \ -Isrc \ - -I${GEN} \ + -Igen \ -D__EXTENSIONS__ \ -D_ATFILE_SOURCE \ -D_BSD_SOURCE \ @@ -106,9 +106,9 @@ SETVAR = printf '%s := %s\n' >>$@ # Append to a variable, if non-empty APPEND = append() { test -z "$$2" || printf '%s += %s\n' "$$1" "$$2" >>$@; }; append -${GEN}/flags.mk:: - ${MSG} "[ GEN] ${TGT}" - printf '# %s\n' "${TGT}" >$@ +gen/flags.mk:: + ${MSG} "[ GEN] $@" + printf '# %s\n' "$@" >$@ ${SETVAR} CPPFLAGS "$$BFS_CPPFLAGS" ${APPEND} CPPFLAGS "$$TSAN_CPPFLAGS" ${APPEND} CPPFLAGS "$$LINT_CPPFLAGS" diff --git a/config/has/acl-get-entry.c b/build/has/acl-get-entry.c index 3cce771..3cce771 100644 --- a/config/has/acl-get-entry.c +++ b/build/has/acl-get-entry.c diff --git a/config/has/acl-get-file.c b/build/has/acl-get-file.c index 89fbf23..89fbf23 100644 --- a/config/has/acl-get-file.c +++ b/build/has/acl-get-file.c diff --git a/config/has/acl-get-tag-type.c b/build/has/acl-get-tag-type.c index 2901956..2901956 100644 --- a/config/has/acl-get-tag-type.c +++ b/build/has/acl-get-tag-type.c diff --git a/config/has/acl-is-trivial-np.c b/build/has/acl-is-trivial-np.c index 9ca9fc7..9ca9fc7 100644 --- a/config/has/acl-is-trivial-np.c +++ b/build/has/acl-is-trivial-np.c diff --git a/config/has/acl-trivial.c b/build/has/acl-trivial.c index 7efc838..7efc838 100644 --- a/config/has/acl-trivial.c +++ b/build/has/acl-trivial.c diff --git a/config/has/aligned-alloc.c b/build/has/aligned-alloc.c index 4460038..4460038 100644 --- a/config/has/aligned-alloc.c +++ b/build/has/aligned-alloc.c diff --git a/config/has/confstr.c b/build/has/confstr.c index 58280b4..58280b4 100644 --- a/config/has/confstr.c +++ b/build/has/confstr.c diff --git a/config/has/extattr-get-file.c b/build/has/extattr-get-file.c index ac9cf96..ac9cf96 100644 --- a/config/has/extattr-get-file.c +++ b/build/has/extattr-get-file.c diff --git a/config/has/extattr-get-link.c b/build/has/extattr-get-link.c index c35be5b..c35be5b 100644 --- a/config/has/extattr-get-link.c +++ b/build/has/extattr-get-link.c diff --git a/config/has/extattr-list-file.c b/build/has/extattr-list-file.c index e68a8bb..e68a8bb 100644 --- a/config/has/extattr-list-file.c +++ b/build/has/extattr-list-file.c diff --git a/config/has/extattr-list-link.c b/build/has/extattr-list-link.c index 49f0ec2..49f0ec2 100644 --- a/config/has/extattr-list-link.c +++ b/build/has/extattr-list-link.c diff --git a/config/has/fdclosedir.c b/build/has/fdclosedir.c index f4ad1f5..f4ad1f5 100644 --- a/config/has/fdclosedir.c +++ b/build/has/fdclosedir.c diff --git a/config/has/getdents.c b/build/has/getdents.c index d0d4228..d0d4228 100644 --- a/config/has/getdents.c +++ b/build/has/getdents.c diff --git a/config/has/getdents64-syscall.c b/build/has/getdents64-syscall.c index 4838c14..4838c14 100644 --- a/config/has/getdents64-syscall.c +++ b/build/has/getdents64-syscall.c diff --git a/config/has/getdents64.c b/build/has/getdents64.c index 1abf36d..1abf36d 100644 --- a/config/has/getdents64.c +++ b/build/has/getdents64.c diff --git a/config/has/getprogname-gnu.c b/build/has/getprogname-gnu.c index 6b97c5e..6b97c5e 100644 --- a/config/has/getprogname-gnu.c +++ b/build/has/getprogname-gnu.c diff --git a/config/has/getprogname.c b/build/has/getprogname.c index 83dc8e8..83dc8e8 100644 --- a/config/has/getprogname.c +++ b/build/has/getprogname.c diff --git a/config/has/max-align-t.c b/build/has/max-align-t.c index 96165ce..96165ce 100644 --- a/config/has/max-align-t.c +++ b/build/has/max-align-t.c diff --git a/config/has/pipe2.c b/build/has/pipe2.c index 4cb43b5..4cb43b5 100644 --- a/config/has/pipe2.c +++ b/build/has/pipe2.c diff --git a/config/has/posix-spawn-addfchdir-np.c b/build/has/posix-spawn-addfchdir-np.c index b870a53..b870a53 100644 --- a/config/has/posix-spawn-addfchdir-np.c +++ b/build/has/posix-spawn-addfchdir-np.c diff --git a/config/has/posix-spawn-addfchdir.c b/build/has/posix-spawn-addfchdir.c index c52ff81..c52ff81 100644 --- a/config/has/posix-spawn-addfchdir.c +++ b/build/has/posix-spawn-addfchdir.c diff --git a/config/has/st-acmtim.c b/build/has/st-acmtim.c index d687ab0..d687ab0 100644 --- a/config/has/st-acmtim.c +++ b/build/has/st-acmtim.c diff --git a/config/has/st-acmtimespec.c b/build/has/st-acmtimespec.c index f747bc0..f747bc0 100644 --- a/config/has/st-acmtimespec.c +++ b/build/has/st-acmtimespec.c diff --git a/config/has/st-birthtim.c b/build/has/st-birthtim.c index 4964571..4964571 100644 --- a/config/has/st-birthtim.c +++ b/build/has/st-birthtim.c diff --git a/config/has/st-birthtimespec.c b/build/has/st-birthtimespec.c index 91a613f..91a613f 100644 --- a/config/has/st-birthtimespec.c +++ b/build/has/st-birthtimespec.c diff --git a/config/has/st-flags.c b/build/has/st-flags.c index b1d0c32..b1d0c32 100644 --- a/config/has/st-flags.c +++ b/build/has/st-flags.c diff --git a/config/has/statx-syscall.c b/build/has/statx-syscall.c index 87ec869..87ec869 100644 --- a/config/has/statx-syscall.c +++ b/build/has/statx-syscall.c diff --git a/config/has/statx.c b/build/has/statx.c index 65f1674..65f1674 100644 --- a/config/has/statx.c +++ b/build/has/statx.c diff --git a/config/has/strerror-l.c b/build/has/strerror-l.c index 3dcc4d7..3dcc4d7 100644 --- a/config/has/strerror-l.c +++ b/build/has/strerror-l.c diff --git a/config/has/strerror-r-gnu.c b/build/has/strerror-r-gnu.c index 26ca0ee..26ca0ee 100644 --- a/config/has/strerror-r-gnu.c +++ b/build/has/strerror-r-gnu.c diff --git a/config/has/strerror-r-posix.c b/build/has/strerror-r-posix.c index 41b2d30..41b2d30 100644 --- a/config/has/strerror-r-posix.c +++ b/build/has/strerror-r-posix.c diff --git a/config/has/tm-gmtoff.c b/build/has/tm-gmtoff.c index 543df48..543df48 100644 --- a/config/has/tm-gmtoff.c +++ b/build/has/tm-gmtoff.c diff --git a/config/has/uselocale.c b/build/has/uselocale.c index a712ff8..a712ff8 100644 --- a/config/has/uselocale.c +++ b/build/has/uselocale.c diff --git a/build/header.mk b/build/header.mk new file mode 100644 index 0000000..3f77ca5 --- /dev/null +++ b/build/header.mk @@ -0,0 +1,69 @@ +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# Makefile that generates gen/config.h + +include build/prelude.mk +include gen/config.mk +include build/exports.mk + +# All header fragments we generate +HEADERS := \ + gen/has/acl-get-entry.h \ + gen/has/acl-get-file.h \ + gen/has/acl-get-tag-type.h \ + gen/has/acl-is-trivial-np.h \ + gen/has/acl-trivial.h \ + gen/has/aligned-alloc.h \ + gen/has/confstr.h \ + gen/has/extattr-get-file.h \ + gen/has/extattr-get-link.h \ + gen/has/extattr-list-file.h \ + gen/has/extattr-list-link.h \ + gen/has/fdclosedir.h \ + gen/has/getdents.h \ + gen/has/getdents64.h \ + gen/has/getdents64-syscall.h \ + gen/has/getprogname.h \ + gen/has/getprogname-gnu.h \ + gen/has/max-align-t.h \ + gen/has/pipe2.h \ + gen/has/posix-spawn-addfchdir.h \ + gen/has/posix-spawn-addfchdir-np.h \ + gen/has/st-acmtim.h \ + gen/has/st-acmtimespec.h \ + gen/has/st-birthtim.h \ + gen/has/st-birthtimespec.h \ + gen/has/st-flags.h \ + gen/has/statx.h \ + gen/has/statx-syscall.h \ + gen/has/strerror-l.h \ + gen/has/strerror-r-gnu.h \ + gen/has/strerror-r-posix.h \ + gen/has/tm-gmtoff.h \ + gen/has/uselocale.h + +# Previously generated by pkgs.mk +PKG_HEADERS := ${ALL_PKGS:%=gen/use/%.h} + +gen/config.h: ${PKG_HEADERS} ${HEADERS} + ${MSG} "[ GEN] $@" + printf '// %s\n' "$@" >$@ + printf '#ifndef BFS_CONFIG_H\n' >>$@ + printf '#define BFS_CONFIG_H\n' >>$@ + cat ${.ALLSRC} >>$@ + printf '#endif // BFS_CONFIG_H\n' >>$@ + cat ${.ALLSRC:%=%.log} >$@.log + ${VCAT} $@ +.PHONY: gen/config.h + +# The short name of the config test +SLUG = ${@:gen/%.h=%} + +${HEADERS}:: + ${MKDIR} ${@D} + if build/define-if.sh ${SLUG} build/cc.sh build/${SLUG}.c >$@ 2>$@.log; then \ + test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✔\n' ${SLUG}.c; \ + else \ + test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✘\n' ${SLUG}.c; \ + fi diff --git a/config/pkgconf.sh b/build/pkgconf.sh index 365ed61..96e4bf1 100755 --- a/config/pkgconf.sh +++ b/build/pkgconf.sh @@ -41,7 +41,7 @@ if [ -z "$MODE" ]; then CFLAGS=$("$0" --cflags "$LIB") || exit 1 LDFLAGS=$("$0" --ldflags "$LIB") || exit 1 LDLIBS=$("$0" --ldlibs "$LIB") || exit 1 - config/cc.sh $CFLAGS $LDFLAGS config/use/$LIB.c $LDLIBS || exit 1 + build/cc.sh $CFLAGS $LDFLAGS build/use/$LIB.c $LDLIBS || exit 1 done fi diff --git a/build/pkgs.mk b/build/pkgs.mk new file mode 100644 index 0000000..51ca664 --- /dev/null +++ b/build/pkgs.mk @@ -0,0 +1,36 @@ +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# Makefile that generates gen/pkgs.mk + +include build/prelude.mk +include gen/vars.mk +include gen/flags.mk +include build/exports.mk + +HEADERS := ${ALL_PKGS:%=gen/use/%.h} + +gen/pkgs.mk: ${HEADERS} + ${MSG} "[ GEN] $@" + printf '# %s\n' "$@" >$@ + gen() { \ + printf 'PKGS := %s\n' "$$*"; \ + printf 'CFLAGS += %s\n' "$$(build/pkgconf.sh --cflags "$$@")"; \ + printf 'LDFLAGS += %s\n' "$$(build/pkgconf.sh --ldflags "$$@")"; \ + printf 'LDLIBS := %s $${LDLIBS}\n' "$$(build/pkgconf.sh --ldlibs "$$@")"; \ + }; \ + gen $$(grep -l ' true$$' ${.ALLSRC} | sed 's|.*/\(.*\)\.h|\1|') >>$@ + ${VCAT} $@ + +.PHONY: gen/pkgs.mk + +# Convert gen/use/foo.h to foo +PKG = ${@:gen/use/%.h=%} + +${HEADERS}:: + ${MKDIR} ${@D} + if build/define-if.sh use/${PKG} build/pkgconf.sh ${PKG} >$@ 2>$@.log; then \ + test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✔\n' use/${PKG}.c; \ + else \ + test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✘\n' use/${PKG}.c; \ + fi diff --git a/config/prelude.mk b/build/prelude.mk index 109e60c..b235fa9 100644 --- a/config/prelude.mk +++ b/build/prelude.mk @@ -15,38 +15,12 @@ # 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 +# Configurable executables CC ?= cc INSTALL ?= install MKDIR ?= mkdir -p @@ -79,9 +53,6 @@ IS_V := ${TRUTHY,${V}} Q, := @ Q := ${Q,${IS_V}} -# The current target, with ${BUILDDIR} stripped for shorter messages -TGT = ${@:${BUILDDIR}/%=%} - # Show full commands with `make V=1`, otherwise short summaries MSG = @msg() { \ MSG="$$1"; \ @@ -109,54 +80,54 @@ ALL_PKGS := \ liburing \ oniguruma -# List all object files here, as they're needed by both `make config` and `make` +# List all object files here, as they're needed by both `./configure` 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/xregex.o \ - ${OBJ}/src/xspawn.o \ - ${OBJ}/src/xtime.o \ - ${OBJ}/gen/version.o + 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/xregex.o \ + obj/src/xspawn.o \ + obj/src/xtime.o \ + obj/gen/version.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 + 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 \ + obj/src/main.o \ + obj/tests/mksock.o \ + obj/tests/xspawnee.o \ + obj/tests/xtouch.o \ ${LIBBFS} \ ${UNIT_OBJS} diff --git a/config/use/libacl.c b/build/use/libacl.c index de1fe50..de1fe50 100644 --- a/config/use/libacl.c +++ b/build/use/libacl.c diff --git a/config/use/libcap.c b/build/use/libcap.c index 58e832c..58e832c 100644 --- a/config/use/libcap.c +++ b/build/use/libcap.c diff --git a/config/use/libselinux.c b/build/use/libselinux.c index bca409d..bca409d 100644 --- a/config/use/libselinux.c +++ b/build/use/libselinux.c diff --git a/config/use/liburing.c b/build/use/liburing.c index bea499a..bea499a 100644 --- a/config/use/liburing.c +++ b/build/use/liburing.c diff --git a/config/use/oniguruma.c b/build/use/oniguruma.c index cb17596..cb17596 100644 --- a/config/use/oniguruma.c +++ b/build/use/oniguruma.c diff --git a/config/config.mk b/config/config.mk deleted file mode 100644 index 280c6ac..0000000 --- a/config/config.mk +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright © Tavian Barnes <tavianator@tavianator.com> -# SPDX-License-Identifier: 0BSD - -# Makefile fragment that implements `make config` - -include config/prelude.mk -include config/exports.mk - -# All configuration steps -config: ${CONFIG} ${GEN}/config.h -.PHONY: config - -# Makefile fragments generated by `make config` -MKS := \ - ${GEN}/vars.mk \ - ${GEN}/flags.mk \ - ${GEN}/deps.mk \ - ${GEN}/pkgs.mk - -# The main configuration file, which includes the others -${CONFIG}: ${MKS} - ${MSG} "[ GEN] ${TGT}" - @printf '# %s\n' "${TGT}" >$@ - @printf 'include $${GEN}/%s\n' ${MKS:${GEN}/%=%} >>$@ - ${VCAT} ${CONFIG} -.PHONY: ${CONFIG} - -# Saves the configurable variables -${GEN}/vars.mk:: - @${MKDIR} ${@D} - ${MSG} "[ GEN] ${TGT}" - @printf '# %s\n' "${TGT}" >$@ - @printf 'PREFIX := %s\n' "$$XPREFIX" >>$@ - @printf 'MANDIR := %s\n' "$$XMANDIR" >>$@ - @printf 'OS := %s\n' "$${OS:-$$(uname)}" >>$@ - @printf 'CC := %s\n' "$$XCC" >>$@ - @printf 'INSTALL := %s\n' "$$XINSTALL" >>$@ - @printf 'MKDIR := %s\n' "$$XMKDIR" >>$@ - @printf 'PKG_CONFIG := %s\n' "$$XPKG_CONFIG" >>$@ - @printf 'RM := %s\n' "$$XRM" >>$@ - @printf 'PKGS :=\n' >>$@ - ${VCAT} $@ - -# Sets the build flags. This depends on vars.mk and uses a recursive make so -# that the default flags can depend on variables like ${OS}. -${GEN}/flags.mk: ${GEN}/vars.mk - @+${MAKE} -sf config/flags.mk $@ -.PHONY: ${GEN}/flags.mk - -# Check for dependency generation support -${GEN}/deps.mk: ${GEN}/flags.mk - @+${MAKE} -sf config/deps.mk $@ -.PHONY: ${GEN}/deps.mk - -# Auto-detect dependencies and their build flags -${GEN}/pkgs.mk: ${GEN}/flags.mk - @+${MAKE} -sf config/pkgs.mk $@ -.PHONY: ${GEN}/pkgs.mk - -# Compile-time feature detection -${GEN}/config.h: ${CONFIG} - @+${MAKE} -sf config/header.mk $@ -.PHONY: ${GEN}/config.h diff --git a/config/deps.mk b/config/deps.mk deleted file mode 100644 index ac394a5..0000000 --- a/config/deps.mk +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright © Tavian Barnes <tavianator@tavianator.com> -# SPDX-License-Identifier: 0BSD - -# Makefile that generates gen/deps.mk - -include config/prelude.mk -include ${GEN}/vars.mk -include ${GEN}/flags.mk -include config/exports.mk - -${GEN}/deps.mk:: - ${MSG} "[ GEN] ${TGT}" - printf '# %s\n' "${TGT}" >$@ - if config/cc.sh -MD -MP -MF /dev/null config/empty.c; then \ - printf 'DEPFLAGS = -MD -MP\n'; \ - fi >>$@ 2>$@.log - ${VCAT} $@ - printf -- '-include %s\n' ${OBJS:.o=.d} >>$@ diff --git a/config/header.mk b/config/header.mk deleted file mode 100644 index 50ad5e8..0000000 --- a/config/header.mk +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright © Tavian Barnes <tavianator@tavianator.com> -# SPDX-License-Identifier: 0BSD - -# Makefile that generates gen/config.h - -include config/prelude.mk -include ${GEN}/config.mk -include config/exports.mk - -# All header fragments we generate -HEADERS := \ - ${GEN}/has/acl-get-entry.h \ - ${GEN}/has/acl-get-file.h \ - ${GEN}/has/acl-get-tag-type.h \ - ${GEN}/has/acl-is-trivial-np.h \ - ${GEN}/has/acl-trivial.h \ - ${GEN}/has/aligned-alloc.h \ - ${GEN}/has/confstr.h \ - ${GEN}/has/extattr-get-file.h \ - ${GEN}/has/extattr-get-link.h \ - ${GEN}/has/extattr-list-file.h \ - ${GEN}/has/extattr-list-link.h \ - ${GEN}/has/fdclosedir.h \ - ${GEN}/has/getdents.h \ - ${GEN}/has/getdents64.h \ - ${GEN}/has/getdents64-syscall.h \ - ${GEN}/has/getprogname.h \ - ${GEN}/has/getprogname-gnu.h \ - ${GEN}/has/max-align-t.h \ - ${GEN}/has/pipe2.h \ - ${GEN}/has/posix-spawn-addfchdir.h \ - ${GEN}/has/posix-spawn-addfchdir-np.h \ - ${GEN}/has/st-acmtim.h \ - ${GEN}/has/st-acmtimespec.h \ - ${GEN}/has/st-birthtim.h \ - ${GEN}/has/st-birthtimespec.h \ - ${GEN}/has/st-flags.h \ - ${GEN}/has/statx.h \ - ${GEN}/has/statx-syscall.h \ - ${GEN}/has/strerror-l.h \ - ${GEN}/has/strerror-r-gnu.h \ - ${GEN}/has/strerror-r-posix.h \ - ${GEN}/has/tm-gmtoff.h \ - ${GEN}/has/uselocale.h - -# Previously generated by pkgs.mk -PKG_HEADERS := ${ALL_PKGS:%=${GEN}/use/%.h} - -${GEN}/config.h: ${PKG_HEADERS} ${HEADERS} - ${MSG} "[ GEN] ${TGT}" - printf '// %s\n' "${TGT}" >$@ - printf '#ifndef BFS_CONFIG_H\n' >>$@ - printf '#define BFS_CONFIG_H\n' >>$@ - cat ${.ALLSRC} >>$@ - printf '#endif // BFS_CONFIG_H\n' >>$@ - cat ${.ALLSRC:%=%.log} >$@.log - ${VCAT} $@ -.PHONY: ${GEN}/config.h - -# The short name of the config test -SLUG = ${@:${GEN}/%.h=%} - -${HEADERS}:: - ${MKDIR} ${@D} - if config/define-if.sh ${SLUG} config/cc.sh config/${SLUG}.c >$@ 2>$@.log; then \ - test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✔\n' ${SLUG}.c; \ - else \ - test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✘\n' ${SLUG}.c; \ - fi diff --git a/config/pkgs.mk b/config/pkgs.mk deleted file mode 100644 index 898f262..0000000 --- a/config/pkgs.mk +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright © Tavian Barnes <tavianator@tavianator.com> -# SPDX-License-Identifier: 0BSD - -# Makefile that generates gen/pkgs.mk - -include config/prelude.mk -include ${GEN}/vars.mk -include ${GEN}/flags.mk -include config/exports.mk - -HEADERS := ${ALL_PKGS:%=${GEN}/use/%.h} - -${GEN}/pkgs.mk: ${HEADERS} - ${MSG} "[ GEN] ${TGT}" - printf '# %s\n' "${TGT}" >$@ - gen() { \ - printf 'PKGS := %s\n' "$$*"; \ - printf 'CFLAGS += %s\n' "$$(config/pkgconf.sh --cflags "$$@")"; \ - printf 'LDFLAGS += %s\n' "$$(config/pkgconf.sh --ldflags "$$@")"; \ - printf 'LDLIBS := %s $${LDLIBS}\n' "$$(config/pkgconf.sh --ldlibs "$$@")"; \ - }; \ - gen $$(grep -l ' true$$' ${.ALLSRC} | sed 's|.*/\(.*\)\.h|\1|') >>$@ - ${VCAT} $@ - -.PHONY: ${GEN}/pkgs.mk - -# Convert ${GEN}/use/foo.h to foo -PKG = ${@:${GEN}/use/%.h=%} - -${HEADERS}:: - ${MKDIR} ${@D} - if config/define-if.sh use/${PKG} config/pkgconf.sh ${PKG} >$@ 2>$@.log; then \ - test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✔\n' use/${PKG}.c; \ - else \ - test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✘\n' use/${PKG}.c; \ - fi diff --git a/configure b/configure new file mode 100755 index 0000000..6920212 --- /dev/null +++ b/configure @@ -0,0 +1,98 @@ +#!/bin/sh + +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# bfs build configuration script + +set -eu + +help() { + cat <<EOF +Usage: $0 [-j<N>] [CC=...] [CFLAGS=...] [...] + +Compiler configuration: + + CC + The C compiler to use + CPPFLAGS + C preprocessor flags + CFLAGS + C compiler flags + LDFLAGS + Linker flags + LDLIBS + Dynamic libraries to link + + EXTRA_CPPFLAGS + EXTRA_CFLAGS + EXTRA_LDFLAGS + EXTRA_LDLIBS + Adds to the default flags, instead of replacing them + +Build profiles: + + RELEASE=y + Enable optimizations, disable assertions + ASAN=y + LSAN=y + MSAN=y + TSAN=y + UBSAN=y + Enable sanitizers + GCOV=y + Enable code coverage instrumentation + +External dependencies: + + PKG_CONFIG + The pkg-config binary to use + + USE_LIBACL=[y|n] + USE_LIBCAP=[y|n] + USE_LIBSELINUX=[y|n] + USE_LIBURIG=[y|n] + USE_ONIGURUMA=[y|n] + Enable or disable external dependencies + +Packaging configuration: + + PREFIX + Set the installation prefix (default: /usr) + MANDIR + Set the man page directory (default: \$PREFIX/share/man) +EOF +} + +for arg; do + case "$arg" in + --help) + help + exit 0 + ;; + -*|*=*) + continue # make flag (-j2) or variable (CC=clang) + ;; + *) + printf 'error: Unrecognized option "%s"\n\n' "$arg" >&2 + help >&2 + exit 1 + ;; + esac +done + +# Get the relative path to the source tree based on how the script was run +DIR=$(dirname -- "$0") + +# Set up symbolic links for out-of-tree builds +for f in Makefile build completions docs src tests; do + test -e "$f" || ln -s "$DIR/$f" "$f" +done + +# Infer -jN unless MAKEFLAGS is set +j= +if ! [ "${MAKEFLAGS+y}" ]; then + j="-j$({ nproc || sysctl -n hw.ncpu || getconf _NPROCESSORS_ONLN || echo 1; } 2>/dev/null)" +fi + +${MAKE:-make} $j -rsf build/config.mk "$@" diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 4ed139c..db5d721 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -4,10 +4,9 @@ Building `bfs` Compiling --------- -`bfs` uses [GNU Make](https://www.gnu.org/software/make/) as its build system. A simple invocation of - $ make config + $ ./configure $ make should build `bfs` successfully. @@ -18,7 +17,6 @@ For example, to use all your cores, run `make -j$(nproc)`. | Command | Description | |------------------|---------------------------------------------------------------| -| `make config` | Configures the build system | | `make` | Builds just the `bfs` binary | | `make all` | Builds everything, including the tests (but doesn't run them) | | `make check` | Builds everything, and runs the tests | @@ -33,13 +31,13 @@ The configuration system provides a few shorthand flags for handy configurations | Command | Description | |-------------------------|-------------------------------------------------------------| -| `make config RELEASE=y` | Build `bfs` with optimizations, LTO, and without assertions | -| `make config ASAN=y` | Enable [AddressSanitizer] | -| `make config LSAN=y` | Enable [LeakSanitizer] | -| `make config MSAN=y` | Enable [MemorySanitizer] | -| `make config TSAN=y` | Enable [ThreadSanitizer] | -| `make config UBSAN=y` | Enable [UndefinedBehaviorSanitizer] | -| `make config GCOV=y` | Enable [code coverage] | +| `./configure RELEASE=y` | Build `bfs` with optimizations, LTO, and without assertions | +| `./configure ASAN=y` | Enable [AddressSanitizer] | +| `./configure LSAN=y` | Enable [LeakSanitizer] | +| `./configure MSAN=y` | Enable [MemorySanitizer] | +| `./configure TSAN=y` | Enable [ThreadSanitizer] | +| `./configure UBSAN=y` | Enable [UndefinedBehaviorSanitizer] | +| `./configure GCOV=y` | Enable [code coverage] | [AddressSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizer [LeakSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode @@ -48,21 +46,20 @@ The configuration system provides a few shorthand flags for handy configurations [UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html [code coverage]: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html -You can combine multiple profiles (e.g. `make config ASAN=y UBSAN=y`), but not all of them will work together. +You can combine multiple profiles (e.g. `./configure ASAN=y UBSAN=y`), but not all of them will work together. ### Flags -Other flags can be specified on the `make config` command line or in the environment. +Other flags can be specified on the `./configure` command line or in the environment. Here are some of the common ones; check the [`Makefile`](/Makefile) for more. | Flag | Description | |-------------------------------------|----------------------------------------------------| -| `CC` | The C compiler to use, e.g. `make config CC=clang` | +| `CC` | The C compiler to use, e.g. `./configure CC=clang` | | `CFLAGS`<br>`EXTRA_CFLAGS` | Override/add to the default compiler flags | | `LDFLAGS`<br>`EXTRA_LDFLAGS` | Override/add to the linker flags | | `USE_LIBACL`<br>`USE_LIBCAP`<br>... | Enable/disable [optional dependencies] | | `TEST_FLAGS` | `tests.sh` flags for `make check` | -| `BUILDDIR` | The build output directory (default: `.`) | | `DESTDIR` | The root directory for `make install` | | `PREFIX` | The installation prefix (default: `/usr`) | | `MANDIR` | The man page installation directory | @@ -72,9 +69,9 @@ Here are some of the common ones; check the [`Makefile`](/Makefile) for more. ### Dependencies `bfs` depends on some system libraries for some of its features. -These dependencies are optional, and can be turned off in `make config` if necessary by setting the appropriate variable to `n` (e.g. `make config USE_ONIGURUMA=n`). +These dependencies are optional, and can be turned off in `./configure` if necessary by setting the appropriate variable to `n` (e.g. `./configure USE_ONIGURUMA=n`). -| Dependency | Platforms | `make config` flag | +| Dependency | Platforms | `./configure` flag | |--------------|------------|--------------------| | [libacl] | Linux only | `USE_LIBACL` | | [libcap] | Linux only | `USE_LIBCAP` | @@ -90,22 +87,28 @@ These dependencies are optional, and can be turned off in `make config` if neces ### Dependency tracking -The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`Makefile`](/Makefile)). +The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in [`build/deps.mk`](/build/deps.mk)). So if you edit a header file, `make` will rebuild the necessary object files ensuring they don't go out of sync. We also add a dependency on the current configuration, so you can change configurations and rebuild without having to `make clean`. - -We go one step further than most build systems by tracking the flags that were used for the previous compilation. -That means you can change configurations without having to `make clean`. For example, - $ make config + $ ./configure $ make - $ make config RELEASE=y + $ ./configure RELEASE=y $ make will build the project in debug mode and then rebuild it in release mode. +### Out-of-tree builds + +You can set up an out-of-tree build by running the `configure` script from another directory, for example: + + $ mkdir out + $ cd out + $ ../configure + $ make + Testing ------- diff --git a/tests/util.sh b/tests/util.sh index 7dba9fb..3969db5 100644 --- a/tests/util.sh +++ b/tests/util.sh @@ -12,12 +12,9 @@ _realpath() ( ) # Globals -TESTS=$(_realpath "$TESTS") -if [ "${BUILDDIR-}" ]; then - BIN=$(_realpath "$BUILDDIR/bin") -else - BIN=$(_realpath "$TESTS/../bin") -fi +ROOT=$(_realpath "$(dirname -- "$TESTS")") +TESTS="$ROOT/tests" +BIN="$ROOT/bin" MKSOCK="$BIN/tests/mksock" XTOUCH="$BIN/tests/xtouch" UNAME=$(uname) diff --git a/tests/xspawn.c b/tests/xspawn.c index 7362aa5..785ea48 100644 --- a/tests/xspawn.c +++ b/tests/xspawn.c @@ -64,27 +64,20 @@ static bool check_use_path(bool use_posix) { spawn.flags &= ~BFS_SPAWN_USE_POSIX; } - const char *builddir = getenv("BUILDDIR"); - dchar *bin = dstrprintf("%s/bin", builddir ? builddir : "."); - ret &= bfs_pcheck(bin, "dstrprintf()"); - if (!ret) { - goto destroy; - } - - ret &= bfs_pcheck(bfs_spawn_addopen(&spawn, 10, bin, O_RDONLY | O_DIRECTORY, 0) == 0); + ret &= bfs_pcheck(bfs_spawn_addopen(&spawn, 10, "bin", O_RDONLY | O_DIRECTORY, 0) == 0); ret &= bfs_pcheck(bfs_spawn_adddup2(&spawn, 10, 11) == 0); ret &= bfs_pcheck(bfs_spawn_addclose(&spawn, 10) == 0); ret &= bfs_pcheck(bfs_spawn_addfchdir(&spawn, 11) == 0); ret &= bfs_pcheck(bfs_spawn_addclose(&spawn, 11) == 0); if (!ret) { - goto bin; + goto destroy; } // Check that $PATH is resolved in the parent's environment char **envp; ret &= bfs_pcheck(envp = envdup()); if (!ret) { - goto bin; + goto destroy; } // Check that $PATH is resolved after the file actions @@ -138,8 +131,6 @@ env: free(*var); } free(envp); -bin: - dstrfree(bin); destroy: ret &= bfs_pcheck(bfs_spawn_destroy(&spawn) == 0); out: |