diff options
-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 | 157 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | bench/bench.sh | 10 | ||||
-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/cc-define.sh) | 11 | ||||
-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) | 25 | ||||
-rw-r--r-- | build/has/acl-get-entry.c (renamed from config/acl-get-entry.c) | 0 | ||||
-rw-r--r-- | build/has/acl-get-file.c (renamed from config/acl-get-file.c) | 0 | ||||
-rw-r--r-- | build/has/acl-get-tag-type.c (renamed from config/acl-get-tag-type.c) | 0 | ||||
-rw-r--r-- | build/has/acl-is-trivial-np.c (renamed from config/acl-is-trivial-np.c) | 0 | ||||
-rw-r--r-- | build/has/acl-trivial.c (renamed from config/acl-trivial.c) | 0 | ||||
-rw-r--r-- | build/has/aligned-alloc.c (renamed from config/aligned-alloc.c) | 0 | ||||
-rw-r--r-- | build/has/confstr.c (renamed from config/confstr.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-get-file.c (renamed from config/extattr-get-file.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-get-link.c (renamed from config/extattr-get-link.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-list-file.c (renamed from config/extattr-list-file.c) | 0 | ||||
-rw-r--r-- | build/has/extattr-list-link.c (renamed from config/extattr-list-link.c) | 0 | ||||
-rw-r--r-- | build/has/fdclosedir.c (renamed from config/fdclosedir.c) | 0 | ||||
-rw-r--r-- | build/has/getdents.c (renamed from config/getdents.c) | 0 | ||||
-rw-r--r-- | build/has/getdents64-syscall.c (renamed from config/getdents64-syscall.c) | 0 | ||||
-rw-r--r-- | build/has/getdents64.c (renamed from config/getdents64.c) | 0 | ||||
-rw-r--r-- | build/has/getprogname-gnu.c (renamed from config/getprogname-gnu.c) | 0 | ||||
-rw-r--r-- | build/has/getprogname.c (renamed from config/getprogname.c) | 0 | ||||
-rw-r--r-- | build/has/max-align-t.c (renamed from config/max-align-t.c) | 0 | ||||
-rw-r--r-- | build/has/pipe2.c (renamed from config/pipe2.c) | 0 | ||||
-rw-r--r-- | build/has/posix-spawn-addfchdir-np.c (renamed from config/posix-spawn-addfchdir-np.c) | 0 | ||||
-rw-r--r-- | build/has/posix-spawn-addfchdir.c (renamed from config/posix-spawn-addfchdir.c) | 0 | ||||
-rw-r--r-- | build/has/st-acmtim.c (renamed from config/st-acmtim.c) | 0 | ||||
-rw-r--r-- | build/has/st-acmtimespec.c (renamed from config/st-acmtimespec.c) | 0 | ||||
-rw-r--r-- | build/has/st-birthtim.c (renamed from config/st-birthtim.c) | 0 | ||||
-rw-r--r-- | build/has/st-birthtimespec.c (renamed from config/st-birthtimespec.c) | 0 | ||||
-rw-r--r-- | build/has/st-flags.c (renamed from config/st-flags.c) | 0 | ||||
-rw-r--r-- | build/has/statx-syscall.c (renamed from config/statx-syscall.c) | 0 | ||||
-rw-r--r-- | build/has/statx.c (renamed from config/statx.c) | 0 | ||||
-rw-r--r-- | build/has/strerror-l.c (renamed from config/strerror-l.c) | 0 | ||||
-rw-r--r-- | build/has/strerror-r-gnu.c (renamed from config/strerror-r-gnu.c) | 0 | ||||
-rw-r--r-- | build/has/strerror-r-posix.c (renamed from config/strerror-r-posix.c) | 0 | ||||
-rw-r--r-- | build/has/tm-gmtoff.c (renamed from config/tm-gmtoff.c) | 0 | ||||
-rw-r--r-- | build/has/uselocale.c (renamed from config/uselocale.c) | 0 | ||||
-rw-r--r-- | build/header.mk | 66 | ||||
-rwxr-xr-x | build/msg-if.sh | 21 | ||||
-rwxr-xr-x | build/msg.sh | 62 | ||||
-rwxr-xr-x | build/pkgconf.sh (renamed from config/pkgconf.sh) | 2 | ||||
-rw-r--r-- | build/pkgs.mk | 33 | ||||
-rw-r--r-- | build/prelude.mk | 122 | ||||
-rw-r--r-- | build/use/libacl.c (renamed from config/libacl.c) | 0 | ||||
-rw-r--r-- | build/use/libcap.c (renamed from config/libcap.c) | 0 | ||||
-rw-r--r-- | build/use/libselinux.c (renamed from config/libselinux.c) | 0 | ||||
-rw-r--r-- | build/use/liburing.c (renamed from config/liburing.c) | 0 | ||||
-rw-r--r-- | build/use/oniguruma.c (renamed from config/oniguruma.c) | 0 | ||||
-rw-r--r-- | config/config.mk | 63 | ||||
-rw-r--r-- | config/deps.mk | 18 | ||||
-rw-r--r-- | config/header.mk | 70 | ||||
-rw-r--r-- | config/pkgs.mk | 42 | ||||
-rw-r--r-- | config/prelude.mk | 170 | ||||
-rwxr-xr-x | configure | 137 | ||||
-rw-r--r-- | docs/BUILDING.md | 211 | ||||
-rw-r--r-- | docs/CHANGELOG.md | 30 | ||||
-rw-r--r-- | tests/util.sh | 9 | ||||
-rw-r--r-- | tests/xspawn.c | 15 |
67 files changed, 798 insertions, 572 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3890bb0..e47600b 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 + ./configure MAKE=gmake 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 ./configure MAKE=gmake 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..6aaace6 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 --enable-gcov 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,111 +1,99 @@ # 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}:: +# 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 -# Group relevant flags together -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} ${CFLAGS} ${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} ${CPPFLAGS} ${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"; \ + echo "3.2"; \ 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 +105,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 @@ -176,15 +164,17 @@ distcheck: .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} $@ + @+cd $@ \ + && ../configure ${DISTCHECK_CONFIG_${@:distcheck-%=%}} \ + && ${MAKE} -s check TEST_FLAGS="--sudo --verbose=skipped" ## Packaging (`make install`) @@ -193,44 +183,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 --enable-release $ make Finally, if you want to install it globally, run diff --git a/bench/bench.sh b/bench/bench.sh index e4b5511..cf1ae49 100644 --- a/bench/bench.sh +++ b/bench/bench.sh @@ -221,7 +221,8 @@ setup() { fi echo "Building bfs ..." - as-user make -s -j"$nproc" release all + as-user ./configure --enable-release + as-user make -s -j"$nproc" all as-user mkdir -p bench/corpus @@ -253,7 +254,12 @@ setup() { echo "Building bfs $commit ..." cd "$worktree" as-user git checkout -qd "$commit" -- - as-user make -s -j"$nproc" release + if [ -e configure ]; then + as-user ./configure --enable-release + as-user make -s -j"$nproc" + else + as-user make -s -j"$nproc" release + fi if [ -e ./bin/bfs ]; then as-user cp ./bin/bfs "$bin/bfs-$commit" else 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..24873ec --- /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 + @+XMAKEFLAGS="$$MAKEFLAGS" ${MAKE} -sf build/flags.mk $@ +.PHONY: gen/flags.mk + +# Check for dependency generation support +gen/deps.mk: gen/flags.mk + @+XMAKEFLAGS="$$MAKEFLAGS" ${MAKE} -sf build/deps.mk $@ +.PHONY: gen/deps.mk + +# Auto-detect dependencies and their build flags +gen/pkgs.mk: gen/flags.mk + @+XMAKEFLAGS="$$MAKEFLAGS" ${MAKE} -sf build/pkgs.mk $@ +.PHONY: gen/pkgs.mk + +# Compile-time feature detection +gen/config.h: gen/config.mk + @+XMAKEFLAGS="$$MAKEFLAGS" ${MAKE} -sf build/header.mk $@ +.PHONY: gen/config.h diff --git a/config/cc-define.sh b/build/define-if.sh index edb5c87..295ead8 100755 --- a/config/cc-define.sh +++ b/build/define-if.sh @@ -3,17 +3,18 @@ # Copyright © Tavian Barnes <tavianator@tavianator.com> # SPDX-License-Identifier: 0BSD -# Output a C preprocessor definition based on whether a C source file could be -# compiled successfully +# Output a C preprocessor definition based on whether a command succeeds set -eu -SLUG="${1#config/}" +SLUG="${1#build/}" SLUG="${SLUG%.c}" -MACRO="BFS_HAS_$(printf '%s' "$SLUG" | tr 'a-z-' 'A-Z_')" +MACRO="BFS_$(printf '%s' "$SLUG" | tr '/a-z-' '_A-Z_')" +shift -if config/cc.sh "$1"; then +if "$@"; then printf '#define %s true\n' "$MACRO" else printf '#define %s false\n' "$MACRO" + exit 1 fi diff --git a/build/deps.mk b/build/deps.mk new file mode 100644 index 0000000..3db62b6 --- /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 'CPPFLAGS += -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 ee13f06..c911b22 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 \ @@ -75,12 +75,13 @@ export TSAN_CFLAGS=${TSAN_CFLAGS,${_TSAN}} export UBSAN_CFLAGS=${UBSAN_CFLAGS,${_UBSAN}} SAN_CFLAGS,y := -fno-sanitize-recover=all -NO_SAN := ${NOR,${_ASAN},${_LSAN},${_MSAN},${_TSAN},${_UBSAN}} -SAN := ${NOT,${NO_SAN}} +INSANE := ${NOT,${_ASAN}${_LSAN}${_MSAN}${_TSAN}${_UBSAN}} +SAN := ${NOT,${INSANE}} export SAN_CFLAGS=${SAN_CFLAGS,${SAN}} # MSAN and TSAN both need all code to be instrumented -NOLIBS ?= ${NOT,${NOR,${_MSAN},${_TSAN}}} +YESLIBS := ${NOT,${_MSAN}${_TSAN}} +NOLIBS ?= ${NOT,${YESLIBS}} export XNOLIBS=${NOLIBS} # gcov only intercepts fork()/exec() with -std=gnu* @@ -100,14 +101,14 @@ export RELEASE_CPPFLAGS=${RELEASE_CPPFLAGS,${_RELEASE}} export RELEASE_CFLAGS=${RELEASE_CFLAGS,${_RELEASE}} # Set a variable -SETVAR = printf '%s := %s\n' >>$@ +SETVAR = @printf '%s := %s\n' >>$@ # Append to a variable, if non-empty -APPEND = append() { test -z "$$2" || printf '%s += %s\n' "$$1" "$$2" >>$@; }; append +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" @@ -131,5 +132,5 @@ ${GEN}/flags.mk:: ${APPEND} LDLIBS "$$EXTRA_LDLIBS" ${APPEND} LDLIBS "$$BFS_LDLIBS" ${SETVAR} NOLIBS "$$XNOLIBS" - test "${OS}-${SAN}" != FreeBSD-y || printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ + @test "${OS}-${SAN}" != FreeBSD-y || printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ ${VCAT} $@ diff --git a/config/acl-get-entry.c b/build/has/acl-get-entry.c index 3cce771..3cce771 100644 --- a/config/acl-get-entry.c +++ b/build/has/acl-get-entry.c diff --git a/config/acl-get-file.c b/build/has/acl-get-file.c index 89fbf23..89fbf23 100644 --- a/config/acl-get-file.c +++ b/build/has/acl-get-file.c diff --git a/config/acl-get-tag-type.c b/build/has/acl-get-tag-type.c index 2901956..2901956 100644 --- a/config/acl-get-tag-type.c +++ b/build/has/acl-get-tag-type.c diff --git a/config/acl-is-trivial-np.c b/build/has/acl-is-trivial-np.c index 9ca9fc7..9ca9fc7 100644 --- a/config/acl-is-trivial-np.c +++ b/build/has/acl-is-trivial-np.c diff --git a/config/acl-trivial.c b/build/has/acl-trivial.c index 7efc838..7efc838 100644 --- a/config/acl-trivial.c +++ b/build/has/acl-trivial.c diff --git a/config/aligned-alloc.c b/build/has/aligned-alloc.c index 4460038..4460038 100644 --- a/config/aligned-alloc.c +++ b/build/has/aligned-alloc.c diff --git a/config/confstr.c b/build/has/confstr.c index 58280b4..58280b4 100644 --- a/config/confstr.c +++ b/build/has/confstr.c diff --git a/config/extattr-get-file.c b/build/has/extattr-get-file.c index ac9cf96..ac9cf96 100644 --- a/config/extattr-get-file.c +++ b/build/has/extattr-get-file.c diff --git a/config/extattr-get-link.c b/build/has/extattr-get-link.c index c35be5b..c35be5b 100644 --- a/config/extattr-get-link.c +++ b/build/has/extattr-get-link.c diff --git a/config/extattr-list-file.c b/build/has/extattr-list-file.c index e68a8bb..e68a8bb 100644 --- a/config/extattr-list-file.c +++ b/build/has/extattr-list-file.c diff --git a/config/extattr-list-link.c b/build/has/extattr-list-link.c index 49f0ec2..49f0ec2 100644 --- a/config/extattr-list-link.c +++ b/build/has/extattr-list-link.c diff --git a/config/fdclosedir.c b/build/has/fdclosedir.c index f4ad1f5..f4ad1f5 100644 --- a/config/fdclosedir.c +++ b/build/has/fdclosedir.c diff --git a/config/getdents.c b/build/has/getdents.c index d0d4228..d0d4228 100644 --- a/config/getdents.c +++ b/build/has/getdents.c diff --git a/config/getdents64-syscall.c b/build/has/getdents64-syscall.c index 4838c14..4838c14 100644 --- a/config/getdents64-syscall.c +++ b/build/has/getdents64-syscall.c diff --git a/config/getdents64.c b/build/has/getdents64.c index 1abf36d..1abf36d 100644 --- a/config/getdents64.c +++ b/build/has/getdents64.c diff --git a/config/getprogname-gnu.c b/build/has/getprogname-gnu.c index 6b97c5e..6b97c5e 100644 --- a/config/getprogname-gnu.c +++ b/build/has/getprogname-gnu.c diff --git a/config/getprogname.c b/build/has/getprogname.c index 83dc8e8..83dc8e8 100644 --- a/config/getprogname.c +++ b/build/has/getprogname.c diff --git a/config/max-align-t.c b/build/has/max-align-t.c index 96165ce..96165ce 100644 --- a/config/max-align-t.c +++ b/build/has/max-align-t.c diff --git a/config/pipe2.c b/build/has/pipe2.c index 4cb43b5..4cb43b5 100644 --- a/config/pipe2.c +++ b/build/has/pipe2.c diff --git a/config/posix-spawn-addfchdir-np.c b/build/has/posix-spawn-addfchdir-np.c index b870a53..b870a53 100644 --- a/config/posix-spawn-addfchdir-np.c +++ b/build/has/posix-spawn-addfchdir-np.c diff --git a/config/posix-spawn-addfchdir.c b/build/has/posix-spawn-addfchdir.c index c52ff81..c52ff81 100644 --- a/config/posix-spawn-addfchdir.c +++ b/build/has/posix-spawn-addfchdir.c diff --git a/config/st-acmtim.c b/build/has/st-acmtim.c index d687ab0..d687ab0 100644 --- a/config/st-acmtim.c +++ b/build/has/st-acmtim.c diff --git a/config/st-acmtimespec.c b/build/has/st-acmtimespec.c index f747bc0..f747bc0 100644 --- a/config/st-acmtimespec.c +++ b/build/has/st-acmtimespec.c diff --git a/config/st-birthtim.c b/build/has/st-birthtim.c index 4964571..4964571 100644 --- a/config/st-birthtim.c +++ b/build/has/st-birthtim.c diff --git a/config/st-birthtimespec.c b/build/has/st-birthtimespec.c index 91a613f..91a613f 100644 --- a/config/st-birthtimespec.c +++ b/build/has/st-birthtimespec.c diff --git a/config/st-flags.c b/build/has/st-flags.c index b1d0c32..b1d0c32 100644 --- a/config/st-flags.c +++ b/build/has/st-flags.c diff --git a/config/statx-syscall.c b/build/has/statx-syscall.c index 87ec869..87ec869 100644 --- a/config/statx-syscall.c +++ b/build/has/statx-syscall.c diff --git a/config/statx.c b/build/has/statx.c index 65f1674..65f1674 100644 --- a/config/statx.c +++ b/build/has/statx.c diff --git a/config/strerror-l.c b/build/has/strerror-l.c index 3dcc4d7..3dcc4d7 100644 --- a/config/strerror-l.c +++ b/build/has/strerror-l.c diff --git a/config/strerror-r-gnu.c b/build/has/strerror-r-gnu.c index 26ca0ee..26ca0ee 100644 --- a/config/strerror-r-gnu.c +++ b/build/has/strerror-r-gnu.c diff --git a/config/strerror-r-posix.c b/build/has/strerror-r-posix.c index 41b2d30..41b2d30 100644 --- a/config/strerror-r-posix.c +++ b/build/has/strerror-r-posix.c diff --git a/config/tm-gmtoff.c b/build/has/tm-gmtoff.c index 543df48..543df48 100644 --- a/config/tm-gmtoff.c +++ b/build/has/tm-gmtoff.c diff --git a/config/uselocale.c b/build/has/uselocale.c index a712ff8..a712ff8 100644 --- a/config/uselocale.c +++ b/build/has/uselocale.c diff --git a/build/header.mk b/build/header.mk new file mode 100644 index 0000000..a9157ad --- /dev/null +++ b/build/header.mk @@ -0,0 +1,66 @@ +# 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} >gen/config.log + ${VCAT} $@ +.PHONY: gen/config.h + +# The short name of the config test +SLUG = ${@:gen/%.h=%} + +${HEADERS}:: + @${MKDIR} ${@D} + @build/define-if.sh ${SLUG} build/cc.sh build/${SLUG}.c >$@ 2>$@.log; \ + build/msg-if.sh "[ CC ] ${SLUG}.c" test $$? -eq 0 diff --git a/build/msg-if.sh b/build/msg-if.sh new file mode 100755 index 0000000..8112aea --- /dev/null +++ b/build/msg-if.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# Print a success/failure indicator from a makefile: +# +# $ ./configure +# [ CC ] use/liburing.c ✘ +# [ CC ] use/oniguruma.c ✔ + +set -eu + +MSG="$1" +shift + +if "$@"; then + build/msg.sh "$(printf '%-37s ✔' "$MSG")" +else + build/msg.sh "$(printf '%-37s ✘' "$MSG")" +fi diff --git a/build/msg.sh b/build/msg.sh new file mode 100755 index 0000000..a7da31b --- /dev/null +++ b/build/msg.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# Print a message from a makefile: +# +# $ make -s +# $ make +# [ CC ] src/main.c +# $ make V=1 +# cc -Isrc -Igen -D... + +set -eu + +# Get the $MAKEFLAGS from the top-level make invocation +MFLAGS="${XMAKEFLAGS-${MAKEFLAGS-}}" + +# Check if make should be quiet (make -s) +is_quiet() { + # GNU make puts single-letter flags in the first word of $MAKEFLAGS, + # without a leading dash + case "${MFLAGS%% *}" in + -*) : ;; + *s*) return 0 ;; + esac + + # BSD make puts each flag separately like -r -s -j 48 + for flag in $MFLAGS; do + case "$flag" in + # Ignore things like --jobserver-auth + --*) continue ;; + # Skip variable assignments + *=*) break ;; + -*s*) return 0 ;; + esac + done + + return 1 +} + +# Check if make should be loud (make V=1) +is_loud() { + test "$XV" +} + +MSG="$1" +shift + +if ! is_quiet && ! is_loud; then + printf '%s\n' "$MSG" +fi + +if [ $# -eq 0 ]; then + exit +fi + +if is_loud; then + printf '%s\n' "$*" +fi + +"$@" diff --git a/config/pkgconf.sh b/build/pkgconf.sh index 2fb2f1e..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/$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..39b550d --- /dev/null +++ b/build/pkgs.mk @@ -0,0 +1,33 @@ +# 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} + @build/define-if.sh use/${PKG} build/pkgconf.sh ${PKG} >$@ 2>$@.log; \ + build/msg-if.sh "[ CC ] use/${PKG}.c" test $$? -eq 0; diff --git a/build/prelude.mk b/build/prelude.mk new file mode 100644 index 0000000..5be26cb --- /dev/null +++ b/build/prelude.mk @@ -0,0 +1,122 @@ +# 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 ?= $^ + +# Installation paths +DESTDIR ?= +PREFIX ?= /usr +MANDIR ?= ${PREFIX}/share/man + +# Configurable executables +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 + +# Normalize ${V} to either "y" or "" +export XV=${TRUTHY,${V}} + +# Suppress output unless V=1 +Q, := @ +Q := ${Q,${XV}} + +# Show full commands with `make V=1`, otherwise short summaries +MSG = @build/msg.sh + +# cat a file if V=1 +VCAT,y := @cat +VCAT, := @: +VCAT := ${VCAT,${XV}} + +# All external dependencies +ALL_PKGS := \ + libacl \ + libcap \ + libselinux \ + liburing \ + oniguruma + +# 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 + +# 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} diff --git a/config/libacl.c b/build/use/libacl.c index de1fe50..de1fe50 100644 --- a/config/libacl.c +++ b/build/use/libacl.c diff --git a/config/libcap.c b/build/use/libcap.c index 58e832c..58e832c 100644 --- a/config/libcap.c +++ b/build/use/libcap.c diff --git a/config/libselinux.c b/build/use/libselinux.c index bca409d..bca409d 100644 --- a/config/libselinux.c +++ b/build/use/libselinux.c diff --git a/config/liburing.c b/build/use/liburing.c index bea499a..bea499a 100644 --- a/config/liburing.c +++ b/build/use/liburing.c diff --git a/config/oniguruma.c b/build/use/oniguruma.c index cb17596..cb17596 100644 --- a/config/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 ccc36d3..0000000 --- a/config/header.mk +++ /dev/null @@ -1,70 +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}/acl-get-entry.h \ - ${GEN}/acl-get-file.h \ - ${GEN}/acl-get-tag-type.h \ - ${GEN}/acl-is-trivial-np.h \ - ${GEN}/acl-trivial.h \ - ${GEN}/aligned-alloc.h \ - ${GEN}/confstr.h \ - ${GEN}/extattr-get-file.h \ - ${GEN}/extattr-get-link.h \ - ${GEN}/extattr-list-file.h \ - ${GEN}/extattr-list-link.h \ - ${GEN}/fdclosedir.h \ - ${GEN}/getdents.h \ - ${GEN}/getdents64.h \ - ${GEN}/getdents64-syscall.h \ - ${GEN}/getprogname.h \ - ${GEN}/getprogname-gnu.h \ - ${GEN}/max-align-t.h \ - ${GEN}/pipe2.h \ - ${GEN}/posix-spawn-addfchdir.h \ - ${GEN}/posix-spawn-addfchdir-np.h \ - ${GEN}/st-acmtim.h \ - ${GEN}/st-acmtimespec.h \ - ${GEN}/st-birthtim.h \ - ${GEN}/st-birthtimespec.h \ - ${GEN}/st-flags.h \ - ${GEN}/statx.h \ - ${GEN}/statx-syscall.h \ - ${GEN}/strerror-l.h \ - ${GEN}/strerror-r-gnu.h \ - ${GEN}/strerror-r-posix.h \ - ${GEN}/tm-gmtoff.h \ - ${GEN}/uselocale.h - -${GEN}/config.h: ${HEADERS} - ${MSG} "[ GEN] ${TGT}" - printf '// %s\n' "${TGT}" >$@ - printf '#ifndef BFS_CONFIG_H\n' >>$@ - printf '#define BFS_CONFIG_H\n' >>$@ - printf '#define BFS_USE_%s true\n' $$(printf '%s\n' ${PKGS} | tr 'a-z-' 'A-Z_') >>$@ - cat ${.ALLSRC} >>$@ - printf '#endif // BFS_CONFIG_H\n' >>$@ - cat ${.ALLSRC:%=%.log} >$@.log - ${RM} ${.ALLSRC} ${.ALLSRC:%=%.log} - ${VCAT} $@ -.PHONY: ${GEN}/config.h - -# The C source file to attempt to compile -CSRC = ${@:${GEN}/%.h=config/%.c} - -${HEADERS}:: - config/cc-define.sh ${CSRC} >$@ 2>$@.log - if ! [ "${IS_V}" ]; then \ - if grep -q 'true$$' $@; then \ - printf '[ CC ] %-${MSG_WIDTH}s ✔\n' ${CSRC}; \ - else \ - printf '[ CC ] %-${MSG_WIDTH}s ✘\n' ${CSRC}; \ - fi; \ - fi diff --git a/config/pkgs.mk b/config/pkgs.mk deleted file mode 100644 index 2c100ab..0000000 --- a/config/pkgs.mk +++ /dev/null @@ -1,42 +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 - -# External dependencies -USE_PKGS := \ - ${GEN}/libacl.use \ - ${GEN}/libcap.use \ - ${GEN}/libselinux.use \ - ${GEN}/liburing.use \ - ${GEN}/oniguruma.use - -${GEN}/pkgs.mk: ${USE_PKGS} - ${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 $$(cat ${.ALLSRC}) >>$@ - ${VCAT} $@ -.PHONY: ${GEN}/pkgs.mk - -# Convert ${GEN}/foo.use to foo -PKG = ${@:${GEN}/%.use=%} - -${USE_PKGS}:: - if config/pkgconf.sh ${PKG} 2>$@.log; then \ - printf '%s\n' ${PKG} >$@; \ - test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✔\n' config/${PKG}.c; \ - else \ - : >$@; \ - test "${IS_V}" || printf '[ CC ] %-${MSG_WIDTH}s ✘\n' config/${PKG}.c; \ - fi diff --git a/config/prelude.mk b/config/prelude.mk deleted file mode 100644 index e1e7a4d..0000000 --- a/config/prelude.mk +++ /dev/null @@ -1,170 +0,0 @@ -# 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}} - -# 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"; \ - shift; \ - test "${IS_V}" || printf '%s\n' "$$MSG"; \ - test "$${1:-}" || return 0; \ - test "${IS_V}" && printf '%s\n' "$$*"; \ - "$$@"; \ - }; \ - msg - -# Maximum width of a short message, to align the ✔/✘ -MSG_WIDTH := 33 - -# 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/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 - -# All object files -OBJS := \ - ${OBJ}/src/main.o \ - ${OBJ}/tests/mksock.o \ - ${OBJ}/tests/xspawnee.o \ - ${OBJ}/tests/xtouch.o \ - ${LIBBFS} \ - ${UNIT_OBJS} diff --git a/configure b/configure new file mode 100755 index 0000000..d42dec3 --- /dev/null +++ b/configure @@ -0,0 +1,137 @@ +#!/bin/sh + +# Copyright © Tavian Barnes <tavianator@tavianator.com> +# SPDX-License-Identifier: 0BSD + +# bfs build configuration script + +set -eu + +# Default to `make` +MAKE="${MAKE:-make}" + +# Pass -j$(nproc) unless MAKEFLAGS is set +if [ "${MAKEFLAGS+y}" ]; then + j="" +else + j="-j$({ nproc || sysctl -n hw.ncpu || getconf _NPROCESSORS_ONLN || echo 1; } 2>/dev/null)" +fi + +for arg; do + case "$arg" in + -h|--help) + cat <<EOF +Usage: + + \$ $0 [--enable-*|--disable-*] [CC=...] [CFLAGS=...] [...] + \$ $MAKE $j + +Variables set in the environment or on the command line will be picked up: + + MAKE + The make implementation to use + CC + The C compiler to use + + CPPFLAGS="-I... -D..." + CFLAGS="-W... -f..." + LDFLAGS="-L... -Wl,..." + Preprocessor/compiler/linker flags + + LDLIBS="-l... -l..." + Dynamic libraries to link + + EXTRA_{CPPFLAGS,CFLAGS,LDFLAGS,LDLIBS} + Adds to the default flags, instead of replacing them + +The default flags result in a plain debug build. Other build profiles include: + + --enable-release + Enable optimizations, disable assertions + --enable-{asan,lsan,msan,tsan,ubsan} + Enable sanitizers + --enable-gcov + Enable code coverage instrumentation + +External dependencies are auto-detected by default, but you can --enable or +--disable them manually: + + --enable-libacl --disable-libacl + --enable-libcap --disable-libcap + --enable-libselinux --disable-libselinux + --enable-liburing --disable-liburing + --enable-oniguruma --disable-oniguruma + +Packaging: + + --prefix=/path + Set the installation prefix (default: /usr) + +This script is a thin wrapper around a makefile-based configuration system. +Any other arguments will be passed directly to the $MAKE invocation, e.g. + + \$ $0 $j V=1 +EOF + exit 0 + ;; + + --enable-*|--disable-*) + case "$arg" in + --enable-*) yn=y ;; + --disable-*) yn=n ;; + esac + + name="${arg#--*able-}" + NAME=$(printf '%s' "$name" | tr 'a-z-' 'A-Z_') + case "$name" in + libacl|libcap|libselinux|liburing|oniguruma) + shift + set -- "$@" "USE_$NAME=$yn" + ;; + release|asan|lsan|msan|tsan|ubsan|lint|gcov) + shift + set -- "$@" "$NAME=$yn" + ;; + *) + printf 'error: Unrecognized option "%s"\n\n' "$arg" >&2 + printf 'Run %s --help for more information.\n' "$0" >&2 + exit 1 + ;; + esac + ;; + + --prefix=*) + shift + set -- "$@" "PREFIX=${arg#*=}" + ;; + + MAKE=*) + MAKE="${arg#*=}" + shift + ;; + + # make flag (-j2) or variable (CC=clang) + -*|*=*) + continue + ;; + + *) + printf 'error: Unrecognized option "%s"\n\n' "$arg" >&2 + printf 'Run %s --help for more information.\n' "$0" >&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 + +# Set MAKEFLAGS to -j$(nproc) if it's unset +export MAKEFLAGS="${MAKEFLAGS-$j}" + +$MAKE -rf build/config.mk "$@" diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 4ed139c..cb33c51 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -1,110 +1,157 @@ 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. -As usual with `make`, you can run a [parallel build](https://www.gnu.org/software/make/manual/html_node/Parallel.html) with `-j`. -For example, to use all your cores, run `make -j$(nproc)`. -### Targets -| 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 | -| `make install` | Installs `bfs` (with man page, shell completions, etc.) | -| `make uninstall` | Uninstalls `bfs` | -| `make clean` | Delete the build products | -| `make distclean` | Delete all generated files, including the build configuration | +Configuration +------------- + +```console +$ ./configure --help +Usage: + + $ ./configure [--enable-*|--disable-*] [CC=...] [CFLAGS=...] [...] + $ make + +... +``` + +### Variables + +Variables set in the environment or on the command line will be picked up: +These variables specify binaries to run during the configuration and build process: + +<pre> +<b>MAKE</b>=<i>make</i> + <a href="https://en.wikipedia.org/wiki/Make_(software)">make</a> implementation +<b>CC</b>=<i>cc</i> + C compiler +<b>INSTALL</b>=<i>install</i> + Copy files during <i>make install</i> +<b>MKDIR</b>="<i>mkdir -p</i>" + Create directories +<b>PKG_CONFIG</b>=<i>pkg-config</i> + Detect external libraries and required build flags +<b>RM</b>="<i>rm -f</i>" + Delete files +</pre> + +These flags will be used by the build process: + +<pre> +<b>CPPFLAGS</b>="<i>-I... -D...</i>" +<b>CFLAGS</b>="<i>-W... -f...</i>" +<b>LDFLAGS</b>="<i>-L... -Wl,...</i>" + Preprocessor/compiler/linker flags + +<b>LDLIBS</b>="<i>-l... -l...</i>" + Dynamic libraries to link + +<b>EXTRA_</b>{<b>CPPFLAGS</b>,<b>CFLAGS</b>,<b>LDFLAGS</b>,<b>LDLIBS</b>}="<i>...</i>" + Adds to the default flags, instead of replacing them +</pre> ### Build profiles -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] | - -[AddressSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizer -[LeakSanitizer]: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode -[MemorySanitizer]: https://github.com/google/sanitizers/wiki/MemorySanitizer -[ThreadSanitizer]: https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual -[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. - -### Flags - -Other flags can be specified on the `make config` 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` | -| `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 | - -[optional dependencies]: #dependencies +The default flags result in a plain debug build. +Other build profiles can be enabled: + +<pre> +--enable-release + Enable optimizations, disable assertions + +--enable-<a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">asan</a> +--enable-<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#stand-alone-mode">lsan</a> +--enable-<a href="https://github.com/google/sanitizers/wiki/MemorySanitizer">msan</a> +--enable-<a href="https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual">tsan</a> +--enable-<a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">ubsan</a> + Enable sanitizers + +--enable-<a href="https://gcc.gnu.org/onlinedocs/gcc/gcov/introduction-to-gcov.html">gcov</a> + Enable code coverage instrumentation +</pre> + +You can combine multiple profiles (e.g. `./configure --enable-asan --enable-ubsan`), but not all of them will work together. ### 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`). +External dependencies are auto-detected by default, but you can `--enable` or `--disable` them manually: -| Dependency | Platforms | `make config` flag | -|--------------|------------|--------------------| -| [libacl] | Linux only | `USE_LIBACL` | -| [libcap] | Linux only | `USE_LIBCAP` | -| [liburing] | Linux only | `USE_LIBURING` | -| [libselinux] | Linux only | `USE_LIBSELINUX` | -| [Oniguruma] | All | `USE_ONIGURUMA` | +<pre> +--enable-<a href="https://savannah.nongnu.org/projects/acl">libacl</a> --disable-libacl +--enable-<a href="https://sites.google.com/site/fullycapable/">libcap</a> --disable-libcap +--enable-<a href="https://github.com/SELinuxProject/selinux">libselinux</a> --disable-libselinux +--enable-<a href="https://github.com/axboe/liburing">liburing</a> --disable-liburing +--enable-<a href="https://github.com/kkos/oniguruma">oniguruma</a> --disable-oniguruma +</pre> -[libacl]: https://savannah.nongnu.org/projects/acl -[libcap]: https://sites.google.com/site/fullycapable/ -[libselinux]: https://github.com/SELinuxProject/selinux -[liburing]: https://github.com/axboe/liburing -[Oniguruma]: https://github.com/kkos/oniguruma +[`pkg-config`] is used, if available, to detect these libraries and any additional build flags they may require. +If this is undesireable, disable it by setting `PKG_CONFIG` to the empty string (`./configure PKG_CONFIG=""`). -### Dependency tracking +[`pkg-config`]: https://www.freedesktop.org/wiki/Software/pkg-config/ -The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`Makefile`](/Makefile)). -So if you edit a header file, `make` will rebuild the necessary object files ensuring they don't go out of sync. +### Out-of-tree builds -We also add a dependency on the current configuration, so you can change configurations and rebuild without having to `make clean`. +You can set up an out-of-tree build by running the `configure` script from another directory, for example: -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 - $ make - $ make config RELEASE=y + $ mkdir out + $ cd out + $ ../configure $ make -will build the project in debug mode and then rebuild it in release mode. + +Building +-------- + +### Targets + +The [`Makefile`](/Makefile) supports several different build targets: + +<pre> +make + The default target; builds just the <i>bfs</i> binary +make <b>all</b> + Builds everything, including the tests (but doesn't run them) + +make <b>check</b> + Builds everything, and runs all tests +make <b>unit-tests</b> + Builds and runs the unit tests +make <b>integration-tests</b> + Builds and runs the integration tests +make <b>distcheck</b> + Builds and runs the tests in multiple different configurations + +make <b>install</b> + Installs bfs globally +make <b>uninstall</b> + Uninstalls bfs + +make <b>clean</b> + Deletes all built files +make <b>distclean</b> + Also deletes files generated by ./configure +</pre> + + +Troubleshooting +--------------- + +If the build fails or behaves unexpectedly, start by enabling verbose mode: + + $ ./configure V=1 + $ make V=1 + +This will print the generated configuration and the exact commands that are executed. + +You can also check the file `gen/config.log`, which contains any errors from commands run during the configuration phase. Testing diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 672c2b4..62b6480 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,36 @@ 3.* === +3.2 +--- + +**May 2, 2024** + +### New features + +- New `-limit N` action that quits immediately after `N` results + +- Implemented `-context` (from GNU find) for matching SELinux contexts ([#27](https://github.com/tavianator/bfs/issues/27)) + +- Implemented `-printf %Z` for printing SELinux contexts + +### Changes + +- The build system has been rewritten, and there is now a configure step: + + $ ./configure + $ make + + See `./configure --help` or [docs/BUILDING.md](/docs/BUILDING.md) for more details. + +- Improved platform support + - Implemented `-acl` on Solaris/Illumos + - Implemented `-xattr` on DragonFly BSD + +### Bug fixes + +- Fixed some rarely-used code paths that clean up after allocation failures + 3.1.3 ----- 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: |