From dba692ca0fb44678fdcc7634d821f04eac2f8042 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 11 Jul 2023 14:30:52 -0400 Subject: build: Add liburing on Linux --- .github/workflows/codecov.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 783cc43..b06ea62 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -20,7 +20,8 @@ jobs: libattr1-dev \ libcap2-bin \ libcap-dev \ - libonig-dev + libonig-dev \ + liburing-dev - name: Generate coverage run: | -- cgit v1.2.3 From 2d0cd364b63e26d7ede70cc1d6f85bea87850d84 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 5 Oct 2023 17:29:52 -0400 Subject: ci: Install expect for unbuffer --- .github/workflows/ci.yml | 5 +++++ .github/workflows/codecov.yml | 1 + 2 files changed, 6 insertions(+) (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e781055..065fcfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: sudo dpkg --add-architecture i386 sudo apt-get update -y sudo apt-get install -y \ + expect \ gcc-multilib \ libgcc-s1:i386 \ acl \ @@ -49,6 +50,10 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Install dependencies + run: | + brew install expect + - name: Run tests run: | make -j$(sysctl -n hw.ncpu) distcheck diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index b06ea62..073479a 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -13,6 +13,7 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y \ + expect \ gcc \ acl \ libacl1-dev \ -- cgit v1.2.3 From 1117564e6f06860b826f0bc9d27e7d26b7e56eee Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 1 Jan 2024 23:43:47 -0500 Subject: ci: Update action and image versions --- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/codecov.yml | 4 ++-- .github/workflows/codeql.yml | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc0719e..38194f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,10 +6,10 @@ jobs: linux: name: Linux - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: | @@ -48,7 +48,7 @@ jobs: runs-on: macos-13 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: | @@ -64,14 +64,14 @@ jobs: if: ${{ github.repository_owner == 'tavianator' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 concurrency: spurion steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: tailscale/github-action@main + - uses: tailscale/github-action@v2 with: oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }} oauth-secret: ${{ secrets.TS_OAUTH_SECRET }} diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 073479a..9c2119b 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -4,10 +4,10 @@ on: [push] jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3a2f81f..71073c6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,7 +13,7 @@ on: jobs: analyze: name: Analyze - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: actions: read contents: read @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install dependencies run: | @@ -41,7 +41,7 @@ jobs: liburing-dev - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: cpp queries: +security-and-quality @@ -51,6 +51,6 @@ jobs: make -j$(nproc) all - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:cpp" -- cgit v1.2.3 From 1109843d017e0320f0d18bfc398e27ff25592dfb Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 4 Apr 2024 15:17:38 -0400 Subject: build: Don't use libattr We only rely on interfaces like listxattr() which are provided by the C library itself. --- .github/workflows/ci.yml | 3 --- .github/workflows/codecov.yml | 1 - .github/workflows/codeql.yml | 1 - GNUmakefile | 7 ------- README.md | 6 +++--- docs/BUILDING.md | 4 +--- 6 files changed, 4 insertions(+), 18 deletions(-) (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c1c89c..8e688fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,6 @@ jobs: libacl1-dev \ libacl1:i386 \ attr \ - libattr1-dev \ - libattr1:i386 \ libcap2-bin \ libcap-dev \ libcap2:i386 \ @@ -34,7 +32,6 @@ jobs: # Ubuntu doesn't let you install the -dev packages for both amd64 and # i386 at once, so we make our own symlinks to fix -m32 -lacl -l... sudo ln -s libacl.so.1 /lib/i386-linux-gnu/libacl.so - sudo ln -s libattr.so.1 /lib/i386-linux-gnu/libattr.so sudo ln -s libcap.so.2 /lib/i386-linux-gnu/libcap.so sudo ln -s libonig.so.5 /lib/i386-linux-gnu/libonig.so # Work around https://github.com/actions/runner-images/issues/9491 diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 9c2119b..d1dc351 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -18,7 +18,6 @@ jobs: acl \ libacl1-dev \ attr \ - libattr1-dev \ libcap2-bin \ libcap-dev \ libonig-dev \ diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 71073c6..c50b266 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,7 +34,6 @@ jobs: acl \ libacl1-dev \ attr \ - libattr1-dev \ libcap2-bin \ libcap-dev \ libonig-dev \ diff --git a/GNUmakefile b/GNUmakefile index 080fb17..8685ca3 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -125,7 +125,6 @@ endif # USE_ONIGURUMA ifeq ($(OS),Linux) ifndef NOLIBS USE_ACL := y -USE_ATTR := y USE_LIBCAP := y USE_LIBURING := y endif @@ -136,12 +135,6 @@ else LOCAL_CPPFLAGS += -DBFS_USE_SYS_ACL_H=0 endif -ifdef USE_ATTR -LOCAL_LDLIBS += -lattr -else -LOCAL_CPPFLAGS += -DBFS_USE_SYS_XATTR_H=0 -endif - ifdef USE_LIBCAP LOCAL_LDLIBS += -lcap else diff --git a/README.md b/README.md index 9992938..17226fd 100644 --- a/README.md +++ b/README.md @@ -293,7 +293,7 @@ Here's how to install them on some common platforms:
 Alpine Linux
-# apk add acl{,-dev} attr{,-dev} libcap{,-dev} liburing-dev oniguruma-dev
+# apk add acl{,-dev} attr libcap{,-dev} liburing-dev oniguruma-dev
 
 Arch Linux
 # pacman -S acl attr libcap liburing oniguruma
@@ -302,13 +302,13 @@ Here's how to install them on some common platforms:
 # apt install acl libacl1-dev attr libattr1-dev libcap2-bin libcap-dev liburing-dev libonig-dev
 
 Fedora
-# dnf install acl libacl-devel libattr-devel libcap-devel liburing-devel oniguruma-devel
+# dnf install acl libacl-devel attr libcap-devel liburing-devel oniguruma-devel
 
 NixOS
 # nix-env -i acl attr libcap liburing oniguruma
 
 Void Linux
-# xbps-install -S acl-{devel,progs} attr-{devel,progs} libcap-{devel,progs} liburing-devel oniguruma-devel
+# xbps-install -S acl-{devel,progs} attr-progs libcap-{devel,progs} liburing-devel oniguruma-devel
 
 Homebrew
 $ brew install oniguruma
diff --git a/docs/BUILDING.md b/docs/BUILDING.md
index 02f9756..7eb3a37 100644
--- a/docs/BUILDING.md
+++ b/docs/BUILDING.md
@@ -56,7 +56,7 @@ Here are some of the common ones; check the [`GNUmakefile`](/GNUmakefile) for mo
 | `CC`                             | The C compiler to use, e.g. `make CC=clang` |
 | `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | | `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | -| `USE_ACL`
`USE_ATTR`
... | Enable/disable [optional dependencies] | +| `USE_ACL`
`USE_LIBCAP`
... | 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` | @@ -73,13 +73,11 @@ These dependencies are optional, and can be turned off at build time if necessar | Dependency | Platforms | `make` flag | |-------------|------------|-----------------| | [acl] | Linux only | `USE_ACL` | -| [attr] | Linux only | `USE_ATTR` | | [libcap] | Linux only | `USE_LIBCAP` | | [liburing] | Linux only | `USE_LIBURING` | | [Oniguruma] | All | `USE_ONIGURUMA` | [acl]: https://savannah.nongnu.org/projects/acl -[attr]: https://savannah.nongnu.org/projects/attr [libcap]: https://sites.google.com/site/fullycapable/ [liburing]: https://github.com/axboe/liburing [Oniguruma]: https://github.com/kkos/oniguruma -- cgit v1.2.3 From c31577d102d87455f3f12086be4c0e2159fa5d35 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 8 Apr 2024 11:27:11 -0400 Subject: build: Add a separate configuration step --- .github/workflows/ci.yml | 23 +- .github/workflows/codecov.yml | 3 +- .github/workflows/codeql.yml | 1 + .gitignore | 2 + GNUmakefile | 372 ------------------------------ Makefile | 517 ++++++++++++++++++++++++++++++++++++++++++ README.md | 4 +- config/cc.sh | 12 + config/empty.c | 6 + config/libacl.c | 6 + config/libcap.c | 6 + config/liburing.c | 6 + config/oniguruma.c | 6 + config/pkg.sh | 44 ++++ config/pkgconf.sh | 64 ++++++ docs/BUILDING.md | 83 +++---- docs/USAGE.md | 2 +- src/config.h | 11 +- src/main.c | 1 + src/parse.c | 2 +- src/version.c | 6 + tests/run.sh | 2 +- tests/tests.mk | 10 +- 23 files changed, 757 insertions(+), 432 deletions(-) delete mode 100644 GNUmakefile create mode 100644 Makefile create mode 100755 config/cc.sh create mode 100644 config/empty.c create mode 100644 config/libacl.c create mode 100644 config/libcap.c create mode 100644 config/liburing.c create mode 100644 config/oniguruma.c create mode 100755 config/pkg.sh create mode 100755 config/pkgconf.sh create mode 100644 src/version.c (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51d06fb..78aa196 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,12 +53,13 @@ jobs: run: | brew install \ bash \ - expect + expect \ + make - name: Run tests run: | jobs=$(sysctl -n hw.ncpu) - make -j$jobs distcheck + gmake -j$jobs distcheck freebsd: name: FreeBSD @@ -79,8 +80,8 @@ jobs: pkg install -y \ bash \ expect \ - gmake \ oniguruma \ + pkgconf \ sudo \ tcl-wrapper pw useradd -n action -m -G wheel -s /usr/local/bin/bash @@ -89,7 +90,7 @@ jobs: run: | chown -R action:action . - sudo -u action gmake -j$(nproc) distcheck + sudo -u action make -j$(nproc) distcheck openbsd: name: OpenBSD @@ -119,6 +120,7 @@ jobs: run: | chown -R action:action . jobs=$(sysctl -n hw.ncpu) + doas -u action gmake config doas -u action gmake -j$jobs check TEST_FLAGS="--sudo=doas --verbose=skipped" netbsd: @@ -141,8 +143,8 @@ jobs: pkg_add \ bash \ clang \ - gmake \ oniguruma \ + pkgconf \ sudo \ tcl-expect useradd -m -G wheel -g =uid action @@ -152,7 +154,8 @@ jobs: PATH="/sbin:/usr/sbin:$PATH" chown -R action:action . jobs=$(sysctl -n hw.ncpu) - sudo -u action gmake -j$jobs check CC=clang LDFLAGS="-rpath /usr/pkg/lib" TEST_FLAGS="--sudo --verbose=skipped" + sudo -u action make config CC=clang + sudo -u action make -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" dragonflybsd: name: DragonFly BSD @@ -173,8 +176,8 @@ jobs: pkg install -y \ bash \ expect \ - gmake \ oniguruma \ + pkgconf \ sudo \ tcl-wrapper pw useradd -n action -m -G wheel -s /usr/local/bin/bash @@ -183,7 +186,8 @@ jobs: run: | chown -R action:action . jobs=$(sysctl -n hw.ncpu) - sudo -u action gmake -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" + sudo -u action make config + sudo -u action make -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" omnios: name: OmniOS @@ -215,4 +219,5 @@ jobs: PATH="/usr/xpg4/bin:$PATH" chown -R action:staff . jobs=$(getconf NPROCESSORS_ONLN) - sudo -u action gmake -j$jobs check LDFLAGS="-Wl,-rpath,/opt/ooce/lib/amd64" TEST_FLAGS="--sudo --verbose=skipped" + sudo -u action gmake config + 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 d1dc351..2abe531 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -25,7 +25,8 @@ jobs: - name: Generate coverage run: | - make -j$(nproc) gcov check TEST_FLAGS="--sudo" + make config GCOV=y + make -j$(nproc) check TEST_FLAGS="--sudo" gcov -abcfpu obj/*/*.o - uses: codecov/codecov-action@v3 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c50b266..a2c224a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -47,6 +47,7 @@ jobs: - name: Build run: | + make config make -j$(nproc) all - name: Perform CodeQL Analysis diff --git a/.gitignore b/.gitignore index 4ded7c4..84e47fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /bin/ +/gen/ /obj/ +/distcheck-*/ diff --git a/GNUmakefile b/GNUmakefile deleted file mode 100644 index 8685ca3..0000000 --- a/GNUmakefile +++ /dev/null @@ -1,372 +0,0 @@ -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -ifneq ($(wildcard .git),) -VERSION := $(shell git describe --always 2>/dev/null) -endif - -ifndef VERSION -VERSION := 3.1.3 -endif - -ifndef OS -OS := $(shell uname) -endif - -ifndef ARCH -ARCH := $(shell uname -m) -endif - -CC ?= gcc -INSTALL ?= install -MKDIR ?= mkdir -p -RM ?= rm -f - -export BUILDDIR ?= . -DESTDIR ?= -PREFIX ?= /usr -MANDIR ?= $(PREFIX)/share/man - -BIN := $(BUILDDIR)/bin -OBJ := $(BUILDDIR)/obj - -DEFAULT_CFLAGS := \ - -g \ - -Wall \ - -Wformat=2 \ - -Werror=implicit \ - -Wimplicit-fallthrough \ - -Wmissing-declarations \ - -Wshadow \ - -Wsign-compare \ - -Wstrict-prototypes - -CFLAGS ?= $(DEFAULT_CFLAGS) -LDFLAGS ?= -DEPFLAGS ?= -MD -MP -MF $(@:.o=.d) - -LOCAL_CPPFLAGS := \ - -D__EXTENSIONS__ \ - -D_ATFILE_SOURCE \ - -D_BSD_SOURCE \ - -D_DARWIN_C_SOURCE \ - -D_DEFAULT_SOURCE \ - -D_GNU_SOURCE \ - -D_LARGEFILE64_SOURCE \ - -D_POSIX_PTHREAD_SEMANTICS \ - -D_FILE_OFFSET_BITS=64 \ - -D_TIME_BITS=64 \ - -DBFS_VERSION=\"$(VERSION)\" - -LOCAL_CFLAGS := -std=c17 -pthread -LOCAL_LDFLAGS := -LOCAL_LDLIBS := - -ASAN := $(filter asan,$(MAKECMDGOALS)) -LSAN := $(filter lsan,$(MAKECMDGOALS)) -MSAN := $(filter msan,$(MAKECMDGOALS)) -TSAN := $(filter tsan,$(MAKECMDGOALS)) -UBSAN := $(filter ubsan,$(MAKECMDGOALS)) - -ifdef ASAN -LOCAL_CFLAGS += -fsanitize=address -SANITIZE := y -endif - -ifdef LSAN -LOCAL_CFLAGS += -fsanitize=leak -SANITIZE := y -endif - -ifdef MSAN -# msan needs all code instrumented -NOLIBS := y -LOCAL_CFLAGS += -fsanitize=memory -fsanitize-memory-track-origins -SANITIZE := y -endif - -ifdef TSAN -# tsan needs all code instrumented -NOLIBS := y -# https://github.com/google/sanitizers/issues/342 -LOCAL_CPPFLAGS += -DBFS_USE_TARGET_CLONES=0 -LOCAL_CFLAGS += -fsanitize=thread -SANITIZE := y -endif - -ifdef UBSAN -LOCAL_CFLAGS += -fsanitize=undefined -SANITIZE := y -endif - -ifdef SANITIZE -LOCAL_CFLAGS += -fno-sanitize-recover=all -endif - -ifndef NOLIBS -USE_ONIGURUMA := y -endif - -ifdef USE_ONIGURUMA -LOCAL_CPPFLAGS += -DBFS_USE_ONIGURUMA=1 - -ONIG_CONFIG := $(shell command -v onig-config 2>/dev/null) -ifdef ONIG_CONFIG -ONIG_CFLAGS := $(shell $(ONIG_CONFIG) --cflags) -ONIG_LDLIBS := $(shell $(ONIG_CONFIG) --libs) -else -ONIG_LDLIBS := -lonig -endif - -LOCAL_CFLAGS += $(ONIG_CFLAGS) -LOCAL_LDLIBS += $(ONIG_LDLIBS) -endif # USE_ONIGURUMA - -ifeq ($(OS),Linux) -ifndef NOLIBS -USE_ACL := y -USE_LIBCAP := y -USE_LIBURING := y -endif - -ifdef USE_ACL -LOCAL_LDLIBS += -lacl -else -LOCAL_CPPFLAGS += -DBFS_USE_SYS_ACL_H=0 -endif - -ifdef USE_LIBCAP -LOCAL_LDLIBS += -lcap -else -LOCAL_CPPFLAGS += -DBFS_USE_SYS_CAPABILITY_H=0 -endif - -ifdef USE_LIBURING -LOCAL_CPPFLAGS += -DBFS_USE_LIBURING=1 -LOCAL_LDLIBS += -luring -endif - -LOCAL_LDFLAGS += -Wl,--as-needed -LOCAL_LDLIBS += -lrt -endif # Linux - -ifeq ($(OS),NetBSD) -LOCAL_LDLIBS += -lutil -endif - -ifeq ($(OS),DragonFly) -LOCAL_LDLIBS += -lposix1e -endif - -ifeq ($(OS),SunOS) -LOCAL_LDLIBS += -lsocket -lnsl -endif - -ifneq ($(filter gcov,$(MAKECMDGOALS)),) -LOCAL_CFLAGS += --coverage -# gcov only intercepts fork()/exec() with -std=gnu* -LOCAL_CFLAGS := $(patsubst -std=c%,-std=gnu%,$(LOCAL_CFLAGS)) -endif - -ifneq ($(filter lint,$(MAKECMDGOALS)),) -LOCAL_CPPFLAGS += \ - -D_FORTIFY_SOURCE=3 \ - -DBFS_LINT -LOCAL_CFLAGS += -Werror -O2 -endif - -ifneq ($(filter release,$(MAKECMDGOALS)),) -LOCAL_CPPFLAGS += -DNDEBUG -CFLAGS := $(DEFAULT_CFLAGS) -O3 -flto=auto -endif - -ALL_CPPFLAGS = $(LOCAL_CPPFLAGS) $(CPPFLAGS) $(EXTRA_CPPFLAGS) -ALL_CFLAGS = $(ALL_CPPFLAGS) $(LOCAL_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $(DEPFLAGS) -ALL_LDFLAGS = $(ALL_CFLAGS) $(LOCAL_LDFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) -ALL_LDLIBS = $(LOCAL_LDLIBS) $(LDLIBS) $(EXTRA_LDLIBS) - -# Default make target -bfs: $(BIN)/bfs -.PHONY: bfs - -# Goals that are treated like flags by this makefile -FLAG_GOALS := asan lsan msan tsan ubsan gcov lint release - -# These are the remaining non-flag goals -GOALS := $(filter-out $(FLAG_GOALS),$(MAKECMDGOALS)) - -# Build the default goal if only flag goals are specified -FLAG_PREREQS := -ifndef GOALS -FLAG_PREREQS += bfs -endif - -# Make sure that "make release" builds everything, but "make release obj/src/main.o" doesn't -$(FLAG_GOALS): $(FLAG_PREREQS) - @: -.PHONY: $(FLAG_GOALS) - -all: bfs tests -.PHONY: all - -$(BIN)/%: - @$(MKDIR) $(@D) - +$(CC) $(ALL_LDFLAGS) $^ $(ALL_LDLIBS) -o $@ -ifeq ($(OS) $(SANITIZE),FreeBSD y) - elfctl -e +noaslr $@ -endif - -$(OBJ)/%.o: %.c $(OBJ)/FLAGS - @$(MKDIR) $(@D) - $(CC) $(ALL_CFLAGS) -c $< -o $@ - -# Save the full set of flags to rebuild everything when they change -$(OBJ)/FLAGS.new: - @$(MKDIR) $(@D) - @echo $(CC) : $(ALL_CFLAGS) : $(ALL_LDFLAGS) : $(ALL_LDLIBS) >$@ -.PHONY: $(OBJ)/FLAGS.new - -# Only update obj/FLAGS if obj/FLAGS.new is different -$(OBJ)/FLAGS: $(OBJ)/FLAGS.new - @test -e $@ && cmp -s $@ $< && rm $< || mv $< $@ - -# 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 - -# The main executable -$(BIN)/bfs: $(OBJ)/src/main.o $(LIBBFS) - -# Testing utilities -TEST_UTILS := \ - $(BIN)/tests/mksock \ - $(BIN)/tests/xspawnee \ - $(BIN)/tests/xtouch - -$(BIN)/tests/mksock: $(OBJ)/tests/mksock.o $(LIBBFS) - -$(BIN)/tests/xspawnee: $(OBJ)/tests/xspawnee.o - -$(BIN)/tests/xtouch: $(OBJ)/tests/xtouch.o $(LIBBFS) - -# All test binaries -TESTS := $(BIN)/tests/units $(TEST_UTILS) - -$(BIN)/tests/units: \ - $(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 \ - $(LIBBFS) - -# Build all the test binaries -tests: $(TESTS) -.PHONY: tests - -# Run the unit tests -unit-tests: $(BIN)/tests/units $(BIN)/tests/xspawnee - $< -.PHONY: unit-tests - -# The different flag combinations we check -INTEGRATIONS := default dfs ids eds j1 j2 j3 s -INTEGRATION_TESTS := $(INTEGRATIONS:%=check-%) - -check-default: $(BIN)/bfs $(TEST_UTILS) - +./tests/tests.sh --make="$(MAKE)" --bfs="$<" $(TEST_FLAGS) - -check-dfs check-ids check-eds: check-%: $(BIN)/bfs $(TEST_UTILS) - +./tests/tests.sh --make="$(MAKE)" --bfs="$< -S $*" $(TEST_FLAGS) - -check-j1 check-j2 check-j3 check-s: check-%: $(BIN)/bfs $(TEST_UTILS) - +./tests/tests.sh --make="$(MAKE)" --bfs="$< -$*" $(TEST_FLAGS) - -# Run the integration tests -integration-tests: $(INTEGRATION_TESTS) -.PHONY: integration-tests - -# Run all the tests -check: unit-tests integration-tests -.PHONY: check - -# Custom test flags for distcheck -DISTCHECK_FLAGS := -s TEST_FLAGS="--sudo --verbose=skipped" - -distcheck: - +$(MAKE) -B asan ubsan check $(DISTCHECK_FLAGS) -ifneq ($(OS),Darwin) - +$(MAKE) -B msan ubsan check CC=clang $(DISTCHECK_FLAGS) -endif - +$(MAKE) -B tsan ubsan check CC=clang $(DISTCHECK_FLAGS) -ifeq ($(OS) $(ARCH),Linux x86_64) - +$(MAKE) -B check EXTRA_CFLAGS="-m32" ONIG_CONFIG= USE_LIBURING= $(DISTCHECK_FLAGS) -endif - +$(MAKE) -B release check $(DISTCHECK_FLAGS) - +$(MAKE) -B check $(DISTCHECK_FLAGS) - +$(MAKE) check-install $(DISTCHECK_FLAGS) -.PHONY: distcheck - -clean: - $(RM) -r $(BIN) $(OBJ) -.PHONY: clean - -install: - $(MKDIR) $(DESTDIR)$(PREFIX)/bin - $(INSTALL) -m755 $(BIN)/bfs $(DESTDIR)$(PREFIX)/bin/bfs - $(MKDIR) $(DESTDIR)$(MANDIR)/man1 - $(INSTALL) -m644 docs/bfs.1 $(DESTDIR)$(MANDIR)/man1/bfs.1 - $(MKDIR) $(DESTDIR)$(PREFIX)/share/bash-completion/completions - $(INSTALL) -m644 completions/bfs.bash $(DESTDIR)$(PREFIX)/share/bash-completion/completions/bfs - $(MKDIR) $(DESTDIR)$(PREFIX)/share/zsh/site-functions - $(INSTALL) -m644 completions/bfs.zsh $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_bfs - $(MKDIR) $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d - $(INSTALL) -m644 completions/bfs.fish $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/bfs.fish -.PHONY: install - -uninstall: - $(RM) $(DESTDIR)$(PREFIX)/share/bash-completion/completions/bfs - $(RM) $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_bfs - $(RM) $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/bfs.fish - $(RM) $(DESTDIR)$(MANDIR)/man1/bfs.1 - $(RM) $(DESTDIR)$(PREFIX)/bin/bfs -.PHONY: uninstall - -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 -.PHONY: check-install - -.SUFFIXES: - --include $(wildcard $(OBJ)/*/*.d) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..326ee87 --- /dev/null +++ b/Makefile @@ -0,0 +1,517 @@ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# This Makefile implements the configuration and build steps for bfs. It is +# portable to both GNU make and the BSD make implementations (how that works +# is documented below). To build bfs, run +# +# $ make config +# $ make + +# The default build target +default: bfs +.PHONY: default + +# 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 ?= $^ + +# Platform detection +OS != uname +ARCH != uname -m + +# 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:./%=%} + +# Installation paths +DESTDIR ?= +PREFIX ?= /usr +MANDIR ?= ${PREFIX}/share/man + +# Configurable executables; can be overridden with +# +# $ make config CC=clang +CC ?= cc +INSTALL ?= install +MKDIR ?= mkdir -p +PKG_CONFIG ?= pkg-config +RM ?= rm -f + +# Configurable flags + +CPPFLAGS ?= +CFLAGS ?= \ + -g \ + -Wall \ + -Wformat=2 \ + -Werror=implicit \ + -Wimplicit-fallthrough \ + -Wmissing-declarations \ + -Wshadow \ + -Wsign-compare \ + -Wstrict-prototypes +LDFLAGS ?= +LDLIBS ?= + +EXTRA_CPPFLAGS ?= +EXTRA_CFLAGS ?= +EXTRA_LDFLAGS ?= +EXTRA_LDLIBS ?= + +GIT_VERSION != test -d .git && command -v git >/dev/null 2>&1 && git describe --always --dirty || echo 3.1.3 +VERSION ?= ${GIT_VERSION} + +# Immutable flags +export BFS_CPPFLAGS= \ + -D__EXTENSIONS__ \ + -D_ATFILE_SOURCE \ + -D_BSD_SOURCE \ + -D_DARWIN_C_SOURCE \ + -D_DEFAULT_SOURCE \ + -D_GNU_SOURCE \ + -D_LARGEFILE64_SOURCE \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_FILE_OFFSET_BITS=64 \ + -D_TIME_BITS=64 +export BFS_CFLAGS= -std=c17 -pthread + +# Platform-specific system libraries +LDLIBS,DragonFly := -lposix1e +LDLIBS,Linux := -lrt +LDLIBS,NetBSD := -lutil +LDLIBS,SunOS := -lsocket -lnsl +_BFS_LDLIBS := ${LDLIBS,${OS}} +export BFS_LDLIBS=${_BFS_LDLIBS} + +# Build profiles +ASAN ?= n +LSAN ?= n +MSAN ?= n +TSAN ?= n +UBSAN ?= n +GCOV ?= n +LINT ?= n +RELEASE ?= n + +export ASAN_CFLAGS= -fsanitize=address +export LSAN_CFLAGS= -fsanitize=leak +export MSAN_CFLAGS= -fsanitize=memory -fsanitize-memory-track-origins +export UBSAN_CFLAGS= -fsanitize=undefined + +# https://github.com/google/sanitizers/issues/342 +export TSAN_CPPFLAGS= -DBFS_USE_TARGET_CLONES=0 +export TSAN_CFLAGS= -fsanitize=thread + +SAN := ${ASAN}${LSAN}${MSAN}${TSAN}${UBSAN} +export SAN_CFLAGS= -fno-sanitize-recover=all + +# MSAN and TSAN both need all code to be instrumented +export NOLIBS= ${MSAN}${TSAN} + +# gcov only intercepts fork()/exec() with -std=gnu* +export GCOV_CFLAGS= --coverage -std=gnu17 + +export LINT_CPPFLAGS= -D_FORTIFY_SOURCE=3 -DBFS_LINT +export LINT_CFLAGS= -Werror -O2 + +export RELEASE_CPPFLAGS= -DNDEBUG +export RELEASE_CFLAGS= -O3 -flto=auto + +# Auto-detected library dependencies. Can be set manually with +# +# $ make config USE_LIBURING=n USE_ONIGURUMA=y +USE_LIBACL ?= +USE_LIBCAP ?= +USE_LIBURING ?= +USE_ONIGURUMA ?= + +# Save the new value of these variables, before they potentially get overridden +# by `-include ${CONFIG}` below + +_XPREFIX := ${PREFIX} +_XMANDIR := ${MANDIR} + +_XOS := ${OS} +_XARCH := ${ARCH} + +_XCC := ${CC} +_XINSTALL := ${INSTALL} +_XMKDIR := ${MKDIR} +_XRM := ${RM} + +_XCPPFLAGS := ${CPPFLAGS} +_XCFLAGS := ${CFLAGS} +_XLDFLAGS := ${LDFLAGS} +_XLDLIBS := ${LDLIBS} + +_XUSE_LIBACL := ${USE_LIBACL} +_XUSE_LIBCAP := ${USE_LIBCAP} +_XUSE_LIBURING := ${USE_LIBURING} +_XUSE_ONIGURUMA := ${USE_ONIGURUMA} + +# 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} +_PKG_CONFIG := ${PKG_CONFIG} + +export BUILDDIR=${_BUILDDIR} +export PKG_CONFIG=${_PKG_CONFIG} + +export XPREFIX=${_XPREFIX} +export XMANDIR=${_XMANDIR} + +export XOS=${_XOS} +export XARCH=${_XARCH} + +export XCC=${_XCC} +export XINSTALL=${_XINSTALL} +export XMKDIR=${_XMKDIR} +export XRM=${_XRM} + +export XCPPFLAGS=${_XCPPFLAGS} +export XCFLAGS=${_XCFLAGS} +export XLDFLAGS=${_XLDFLAGS} +export XLDLIBS=${_XLDLIBS} + +export XUSE_LIBACL=${_XUSE_LIBACL} +export XUSE_LIBCAP=${_XUSE_LIBCAP} +export XUSE_LIBURING=${_XUSE_LIBURING} +export XUSE_ONIGURUMA=${_XUSE_ONIGURUMA} + +# The configuration file generated by `make config` +CONFIG := ${GEN}/config.mk +-include ${CONFIG} + +## Configuration phase (`make config`) + +# External dependencies +PKGS := \ + ${GEN}/libacl.mk \ + ${GEN}/libcap.mk \ + ${GEN}/liburing.mk \ + ${GEN}/oniguruma.mk + +# Makefile fragments generated by `make config` +MKS := \ + ${GEN}/vars.mk \ + ${GEN}/deps.mk \ + ${GEN}/objs.mk \ + ${PKGS} + +# The configuration goal itself +config: ${MKS} + @printf 'include $${GEN}/%s\n' ${MKS:${GEN}/%=%} >${CONFIG} +.PHONY: config + +# Saves the configurable variables +${GEN}/vars.mk:: + @${XMKDIR} ${@D} + @printf 'PREFIX := %s\n' "$$XPREFIX" >$@ + @printf 'MANDIR := %s\n' "$$XMANDIR" >>$@ + @printf 'OS := %s\n' "$$XOS" >>$@ + @printf 'ARCH := %s\n' "$$XARCH" >>$@ + @printf 'CC := %s\n' "$$XCC" >>$@ + @printf 'INSTALL := %s\n' "$$XINSTALL" >>$@ + @printf 'MKDIR := %s\n' "$$XMKDIR" >>$@ + @printf 'RM := %s\n' "$$XRM" >>$@ + @printf 'CPPFLAGS := %s\n' "$$BFS_CPPFLAGS" >>$@ + @test "${TSAN}" != y || printf 'CPPFLAGS += %s\n' "$$TSAN_CPPFLAGS" >>$@ + @test "${LINT}" != y || printf 'CPPFLAGS += %s\n' "$$LINT_CPPFLAGS" >>$@ + @test "${RELEASE}" != y || printf 'CPPFLAGS += %s\n' "$$RELEASE_CPPFLAGS" >>$@ + @test -z "$$XCPPFLAGS" || printf 'CPPFLAGS += %s\n' "$$XCPPFLAGS" >>$@ + @test -z "$$EXTRA_CPPFLAGS" || printf 'CPPFLAGS += %s\n' "$$EXTRA_CPPFLAGS" >>$@ + @printf 'CFLAGS := %s\n' "$$BFS_CFLAGS" >>$@ + @test "${ASAN}" != y || printf 'CFLAGS += %s\n' "$$ASAN_CFLAGS" >>$@ + @test "${LSAN}" != y || printf 'CFLAGS += %s\n' "$$LSAN_CFLAGS" >>$@ + @test "${MSAN}" != y || printf 'CFLAGS += %s\n' "$$MSAN_CFLAGS" >>$@ + @test "${TSAN}" != y || printf 'CFLAGS += %s\n' "$$TSAN_CFLAGS" >>$@ + @test "${UBSAN}" != y || printf 'CFLAGS += %s\n' "$$UBSAN_CFLAGS" >>$@ + @case "${SAN}" in *y*) printf 'CFLAGS += %s\n' "$$SAN_CFLAGS" >>$@ ;; esac + @test "${GCOV}" != y || printf 'CFLAGS += %s\n' "$$GCOV_CFLAGS" >>$@ + @test "${LINT}" != y || printf 'CFLAGS += %s\n' "$$LINT_CFLAGS" >>$@ + @test "${RELEASE}" != y || printf 'CFLAGS += %s\n' "$$RELEASE_CFLAGS" >>$@ + @test -z "$$XCFLAGS" || printf 'CFLAGS += %s\n' "$$XCFLAGS" >>$@ + @test -z "$$EXTRA_CFLAGS" || printf 'CFLAGS += %s\n' "$$EXTRA_CFLAGS" >>$@ + @printf 'LDFLAGS := %s\n' "$$XLDFLAGS" >>$@ + @test -z "$$EXTRA_LDFLAGS" || printf 'LDFLAGS += %s\n' "$$EXTRA_LDFLAGS" >>$@ + @printf 'LDLIBS := %s\n' "$$XLDLIBS" >>$@ + @test -z "$$EXTRA_LDLIBS" || printf 'LDLIBS += %s\n' "$$EXTRA_LDLIBS" >>$@ + @test -z "$$BFS_LDLIBS" || printf 'LDLIBS += %s\n' "$$BFS_LDLIBS" >>$@ + @case "${OS}-${SAN}" in FreeBSD-*y*) printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ ;; esac + @cat $@ + +# Check for dependency generation support +${GEN}/deps.mk:: + @${MKDIR} ${@D} + @if config/cc.sh -MD -MP -MF /dev/null config/empty.c; then \ + echo 'DEPFLAGS = -MD -MP -MF $${@:.o=.d}'; \ + fi 2>$@.log | tee $@ + @printf -- '-include %s\n' ${OBJS:.o=.d} >>$@ + +# Lists file.o: file.c dependencies +${GEN}/objs.mk:: + @${MKDIR} ${@D} + @for obj in ${OBJS:${OBJ}/%.o=%}; do printf '$${OBJ}/%s.o: %s.c\n' "$$obj" "$$obj"; done >$@ + +# Auto-detect dependencies and their build flags +${PKGS}:: + @${MKDIR} ${@D} + @config/pkg.sh ${@:${GEN}/%.mk=%} >$@ 2>$@.log + @cat $@ + +# 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: `make %s` is no longer supported. ' $@ >&2 + @printf 'Use `make config %s=y` instead.\n' $$(echo $@ | tr '[a-z]' '[A-Z]') >&2 + @false + +## Build phase (`make`) + +# The main binary +bfs: ${BIN}/bfs +.PHONY: bfs + +# All binaries +BINS := \ + ${BIN}/bfs \ + ${BIN}/tests/mksock \ + ${BIN}/tests/units \ + ${BIN}/tests/xspawnee \ + ${BIN}/tests/xtouch + +all: ${BINS} +.PHONY: all + +# All object files except the entry point +LIBBFS := \ + ${OBJ}/src/alloc.o \ + ${OBJ}/src/bar.o \ + ${OBJ}/src/bfstd.o \ + ${OBJ}/src/bftw.o \ + ${OBJ}/src/color.o \ + ${OBJ}/src/ctx.o \ + ${OBJ}/src/diag.o \ + ${OBJ}/src/dir.o \ + ${OBJ}/src/dstring.o \ + ${OBJ}/src/eval.o \ + ${OBJ}/src/exec.o \ + ${OBJ}/src/expr.o \ + ${OBJ}/src/fsade.o \ + ${OBJ}/src/ioq.o \ + ${OBJ}/src/mtab.o \ + ${OBJ}/src/opt.o \ + ${OBJ}/src/parse.o \ + ${OBJ}/src/printf.o \ + ${OBJ}/src/pwcache.o \ + ${OBJ}/src/stat.o \ + ${OBJ}/src/thread.o \ + ${OBJ}/src/trie.o \ + ${OBJ}/src/typo.o \ + ${OBJ}/src/version.o \ + ${OBJ}/src/xregex.o \ + ${OBJ}/src/xspawn.o \ + ${OBJ}/src/xtime.o + +# Group relevant flags together +ALL_CFLAGS = ${CPPFLAGS} ${CFLAGS} ${DEPFLAGS} +ALL_LDFLAGS = ${CFLAGS} ${LDFLAGS} + +# The main binary +${BIN}/bfs: ${LIBBFS} ${OBJ}/src/main.o + +${BINS}: + @${MKDIR} ${@D} + +${CC} ${ALL_LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@ + ${POSTLINK} + +# All object files +OBJS := \ + ${OBJ}/src/main.o \ + ${OBJ}/tests/alloc.o \ + ${OBJ}/tests/bfstd.o \ + ${OBJ}/tests/bit.o \ + ${OBJ}/tests/ioq.o \ + ${OBJ}/tests/main.o \ + ${OBJ}/tests/mksock.o \ + ${OBJ}/tests/trie.o \ + ${OBJ}/tests/xspawn.o \ + ${OBJ}/tests/xspawnee.o \ + ${OBJ}/tests/xtime.o \ + ${OBJ}/tests/xtouch.o \ + ${LIBBFS} + +# Depend on ${CONFIG} to make sure `make config` runs first, and to rebuild when +# the configuration changes +${OBJS}: ${CONFIG} + @${MKDIR} ${@D} + ${CC} ${ALL_CFLAGS} -c ${@:${OBJ}/%.o=%.c} -o $@ + +# Save the version number to this file, but only update VERSION if it changes +${GEN}/NEWVERSION:: + @${MKDIR} ${@D} + @printf '%s\n' '${VERSION}' >$@ + +${GEN}/VERSION: ${GEN}/NEWVERSION + @test -e $@ && cmp -s $@ ${.ALLSRC} && rm ${.ALLSRC} || mv ${.ALLSRC} $@ + +# Rebuild version.c whenever the version number changes +${OBJ}/src/version.o: ${GEN}/VERSION +${OBJ}/src/version.o: CPPFLAGS := ${CPPFLAGS} -DBFS_VERSION='"${VERSION}"' + +# Clean all build products +clean:: + ${RM} -r ${BIN} ${OBJ} + +# Clean everything, including generated files +distclean: clean + ${RM} -r ${GEN} +.PHONY: distclean + +## Test phase (`make check`) + +# Unit test binaries +UTEST_BINS := \ + ${BIN}/tests/units \ + ${BIN}/tests/xspawnee + +# Integration test binaries +ITEST_BINS := \ + ${BIN}/tests/mksock \ + ${BIN}/tests/xtouch + +# Build (but don't run) test binaries +tests: ${UTEST_BINS} ${ITEST_BINS} +.PHONY: tests + +# Run all the tests +check: unit-tests integration-tests +.PHONY: check + +# Run the unit tests +unit-tests: ${UTEST_BINS} + ${BIN}/tests/units +.PHONY: unit-tests + +${BIN}/tests/units: \ + ${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 \ + ${LIBBFS} + +${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} + +./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} + +./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} + +./tests/tests.sh --make="${MAKE}" --bfs="${BIN}/bfs -${@:check-%=%}" ${TEST_FLAGS} + +# Run the integration tests +integration-tests: ${INTEGRATION_TESTS} +.PHONY: integration-tests + +${BIN}/tests/mksock: \ + ${OBJ}/tests/mksock.o \ + ${LIBBFS} + +${BIN}/tests/xtouch: \ + ${OBJ}/tests/xtouch.o \ + ${LIBBFS} + +# `make distcheck` configurations +DISTCHECKS := distcheck-asan distcheck-tsan distcheck-release + +# Don't use msan on macOS +IS_DARWIN,Darwin := y +IS_DARWIN := ${IS_DARWIN,${OS}} +DISTCHECK_MSAN, := distcheck-msan +DISTCHECKS += ${DISTCHECK_MSAN,${IS_DARWIN}} + +# Only add a 32-bit build on 64-bit Linux +DISTCHECK_M32,Linux,x86_64 := distcheck-m32 +DISTCHECKS += ${DISTCHECK_M32,${OS},${ARCH}} + +# Test multiple configurations +distcheck: ${DISTCHECKS} +.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_m32 := EXTRA_CFLAGS="-m32" PKG_CONFIG_PATH=/usr/lib32/pkgconfig USE_LIBURING=n +DISTCHECK_CONFIG_release := RELEASE=y + +${DISTCHECKS}:: + +${MAKE} -rs BUILDDIR=${BUILDDIR}/$@ config ${DISTCHECK_CONFIG_${@:distcheck-%=%}} + +${MAKE} -s BUILDDIR=${BUILDDIR}/$@ check TEST_FLAGS="--sudo --verbose=skipped" + +## Packaging (`make install`) + +DEST_PREFIX := ${DESTDIR}${PREFIX} +DEST_MANDIR := ${DESTDIR}${MANDIR} + +install:: + ${MKDIR} ${DEST_PREFIX}/bin + ${INSTALL} -m755 ${BIN}/bfs ${DEST_PREFIX}/bin/bfs + ${MKDIR} ${DEST_MANDIR}/man1 + ${INSTALL} -m644 docs/bfs.1 ${DEST_MANDIR}/man1/bfs.1 + ${MKDIR} ${DEST_PREFIX}/share/bash-completion/completions + ${INSTALL} -m644 completions/bfs.bash ${DEST_PREFIX}/share/bash-completion/completions/bfs + ${MKDIR} ${DEST_PREFIX}/share/zsh/site-functions + ${INSTALL} -m644 completions/bfs.zsh ${DEST_PREFIX}/share/zsh/site-functions/_bfs + ${MKDIR} ${DEST_PREFIX}/share/fish/vendor_completions.d + ${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 + +# 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 diff --git a/README.md b/README.md index 17226fd..b95c16b 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,7 @@ Once you have the dependencies, you can build bfs. 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 $ make This will build the `./bin/bfs` binary. @@ -342,7 +343,8 @@ 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 release + $ make config RELEASE=y + $ make Finally, if you want to install it globally, run diff --git a/config/cc.sh b/config/cc.sh new file mode 100755 index 0000000..04b142a --- /dev/null +++ b/config/cc.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Run the compiler and check if it succeeded + +printf '$ %s' "$XCC" >&2 +printf ' %q' "$@" >&2 +printf ' -o /dev/null\n' >&2 + +$XCC "$@" -o /dev/null diff --git a/config/empty.c b/config/empty.c new file mode 100644 index 0000000..4fa9a5b --- /dev/null +++ b/config/empty.c @@ -0,0 +1,6 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +int main(void) { + return 0; +} diff --git a/config/libacl.c b/config/libacl.c new file mode 100644 index 0000000..877cb69 --- /dev/null +++ b/config/libacl.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + acl_free(0); + return 0; +} diff --git a/config/libcap.c b/config/libcap.c new file mode 100644 index 0000000..64188ac --- /dev/null +++ b/config/libcap.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + cap_free(0); + return 0; +} diff --git a/config/liburing.c b/config/liburing.c new file mode 100644 index 0000000..456059c --- /dev/null +++ b/config/liburing.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + io_uring_free_probe(0); + return 0; +} diff --git a/config/oniguruma.c b/config/oniguruma.c new file mode 100644 index 0000000..b834fac --- /dev/null +++ b/config/oniguruma.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + onig_free(0); + return 0; +} diff --git a/config/pkg.sh b/config/pkg.sh new file mode 100755 index 0000000..6335b4b --- /dev/null +++ b/config/pkg.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# pkg-config wrapper that outputs a makefile fragment + +set -eu + +NAME="${1^^}" +declare -n XUSE="XUSE_$NAME" + +if [ "$XUSE" ]; then + USE="$XUSE" +elif [[ "$NOLIBS" == *y* ]]; then + USE=n +elif config/pkgconf.sh "$1"; then + USE=y +else + USE=n +fi + +printf '%s := %s\n' "USE_$NAME" "$USE" + +if [ "$USE" = y ]; then + printf 'CPPFLAGS += -DBFS_USE_%s=1\n' "$NAME" + + CFLAGS=$(config/pkgconf.sh --cflags "$1") + if [ "$CFLAGS" ]; then + printf 'CFLAGS += %s\n' "$CFLAGS" + fi + + LDFLAGS=$(config/pkgconf.sh --ldflags "$1") + if [ "$LDFLAGS" ]; then + printf 'LDFLAGS += %s\n' "$LDFLAGS" + fi + + LDLIBS=$(config/pkgconf.sh --ldlibs "$1") + if [ "$LDLIBS" ]; then + printf 'LDLIBS += %s\n' "$LDLIBS" + fi +else + printf 'CPPFLAGS += -DBFS_USE_%s=0\n' "$NAME" +fi diff --git a/config/pkgconf.sh b/config/pkgconf.sh new file mode 100755 index 0000000..070fad6 --- /dev/null +++ b/config/pkgconf.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# pkg-config wrapper with hardcoded fallbacks + +set -eu + +MODE= +if [[ "$1" == --* ]]; then + MODE="$1" + shift +fi + +if command -v "${PKG_CONFIG:-}" &>/dev/null; then + case "$MODE" in + --cflags) + "$PKG_CONFIG" --cflags "$@" + ;; + --ldflags) + "$PKG_CONFIG" --libs-only-L --libs-only-other "$@" + ;; + --ldlibs) + "$PKG_CONFIG" --libs-only-l "$@" + ;; + "") + "$PKG_CONFIG" "$@" + ;; + esac +else + for lib; do + case "$lib" in + libacl) + LDLIB=-lacl + ;; + libcap) + LDLIB=-lcap + ;; + liburing) + LDLIB=-luring + ;; + oniguruma) + LDLIB=-lonig + ;; + *) + printf 'error: Unknown package %s\n' "$lib" >&2 + exit 1 + esac + + case "$MODE" in + --ldlibs) + printf ' %s' "$LDLIB" + ;; + "") + config/cc.sh "config/$lib.c" "$LDLIB" || exit $? + ;; + esac + done + + if [ "$MODE" = "--ldlibs" ]; then + printf '\n' + fi +fi diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 7eb3a37..abf6185 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -7,9 +7,10 @@ Compiling `bfs` uses [GNU Make](https://www.gnu.org/software/make/) as its build system. A simple invocation of + $ make config $ make -should build `bfs` successfully, with no additional steps necessary. +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)`. @@ -17,25 +18,28 @@ 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 | | `make install` | Installs `bfs` (with man page, shell completions, etc.) | | `make uninstall` | Uninstalls `bfs` | +| `make clean` | Delete the build products | +| `make mrclean` | Delete all generated files, including the build configuration | -### Flag-like targets +### Build profiles -The build system provides a few shorthand targets for handy configurations: +The configuration system provides a few shorthand flags for handy configurations: -| Command | Description | -|----------------|-------------------------------------------------------------| -| `make release` | Build `bfs` with optimizations, LTO, and without assertions | -| `make asan` | Enable [AddressSanitizer] | -| `make lsan` | Enable [LeakSanitizer] | -| `make msan` | Enable [MemorySanitizer] | -| `make tsan` | Enable [ThreadSanitizer] | -| `make ubsan` | Enable [UndefinedBehaviorSanitizer] | -| `make gcov` | Enable [code coverage] | +| 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 @@ -44,38 +48,38 @@ The build system provides a few shorthand targets 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 flags and other targets (e.g. `make asan ubsan check`), but not all of them will work together. +You can combine multiple profiles (e.g. `make config ASAN=y UBSAN=y`), but not all of them will work together. ### Flags -Other flags are controlled with `make` variables and/or environment variables. -Here are some of the common ones; check the [`GNUmakefile`](/GNUmakefile) for more. - -| Flag | Description | -|----------------------------------|---------------------------------------------| -| `CC` | The C compiler to use, e.g. `make CC=clang` | -| `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | -| `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | -| `USE_ACL`
`USE_LIBCAP`
... | 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 | +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`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | +| `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | +| `USE_ACL`
`USE_LIBCAP`
... | 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 ### Dependencies `bfs` depends on some system libraries for some of its features. -These dependencies are optional, and can be turned off at build time if necessary by setting the appropriate variable to the empty string (e.g. `make USE_ONIGURUMA=`). +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`). -| Dependency | Platforms | `make` flag | -|-------------|------------|-----------------| -| [acl] | Linux only | `USE_ACL` | -| [libcap] | Linux only | `USE_LIBCAP` | -| [liburing] | Linux only | `USE_LIBURING` | -| [Oniguruma] | All | `USE_ONIGURUMA` | +| Dependency | Platforms | `make config` flag | +|-------------|------------|--------------------| +| [acl] | Linux only | `USE_ACL` | +| [libcap] | Linux only | `USE_LIBCAP` | +| [liburing] | Linux only | `USE_LIBURING` | +| [Oniguruma] | All | `USE_ONIGURUMA` | [acl]: https://savannah.nongnu.org/projects/acl [libcap]: https://sites.google.com/site/fullycapable/ @@ -84,21 +88,22 @@ These dependencies are optional, and can be turned off at build time if necessar ### Dependency tracking -The build system automatically tracks header dependencies with the `-M` family of compiler options (see `DEPFLAGS` in the [`GNUmakefile`](/GNUmakefile)). +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. +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 + $ make + $ make config RELEASE=y $ make - $ make release will build the project in debug mode and then rebuild it in release mode. -A side effect of this may be surprising: `make check` by itself will rebuild the project in the default configuration. -To test a different configuration, you'll have to repeat it (e.g. `make release check`). - Testing ------- diff --git a/docs/USAGE.md b/docs/USAGE.md index 071c95b..70f8475 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -7,8 +7,8 @@ When invoked with no arguments, `bfs` will list everything under the current dir ```console $ bfs . -./GNUmakefile ./LICENSE +./Makefile ./README.md ./completions ./docs diff --git a/src/config.h b/src/config.h index 506ad3e..2eff1fc 100644 --- a/src/config.h +++ b/src/config.h @@ -29,13 +29,14 @@ #ifndef BFS_COMMAND # define BFS_COMMAND "bfs" #endif -#ifndef BFS_VERSION -# define BFS_VERSION "3.1.3" -#endif #ifndef BFS_HOMEPAGE # define BFS_HOMEPAGE "https://tavianator.com/projects/bfs.html" #endif +// This is a symbol instead of a literal so we don't have to rebuild everything +// when the version number changes +extern const char bfs_version[]; + // Check for system headers #ifdef __has_include @@ -97,10 +98,10 @@ # define BFS_USE_PATHS_H BFS_HAS_PATHS_H #endif #ifndef BFS_USE_SYS_ACL_H -# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__) +# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__ && (!__linux__ || BFS_USE_LIBACL)) #endif #ifndef BFS_USE_SYS_CAPABILITY_H -# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__) +# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__ && (!__linux__ || BFS_USE_LIBCAP)) #endif #ifndef BFS_USE_SYS_EXTATTR_H # define BFS_USE_SYS_EXTATTR_H (BFS_HAS_SYS_EXTATTR_H && !__DragonFly__) diff --git a/src/main.c b/src/main.c index e120f03..b4d65ce 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ * - thread.h (multi-threading) * - trie.[ch] (a trie set/map implementation) * - typo.[ch] (fuzzy matching for typos) + * - version.c (defines the version number) * - xregex.[ch] (regular expression support) * - xspawn.[ch] (spawns processes) * - xtime.[ch] (date/time handling utilities) diff --git a/src/parse.c b/src/parse.c index 2dfcab2..38ebf3f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -2909,7 +2909,7 @@ static struct bfs_expr *parse_help(struct bfs_parser *parser, int arg1, int arg2 * "Parse" -version. */ static struct bfs_expr *parse_version(struct bfs_parser *parser, int arg1, int arg2) { - cfprintf(parser->ctx->cout, "${ex}%s${rs} ${bld}%s${rs}\n\n", BFS_COMMAND, BFS_VERSION); + cfprintf(parser->ctx->cout, "${ex}%s${rs} ${bld}%s${rs}\n\n", BFS_COMMAND, bfs_version); printf("%s\n", BFS_HOMEPAGE); diff --git a/src/version.c b/src/version.c new file mode 100644 index 0000000..736f3d5 --- /dev/null +++ b/src/version.c @@ -0,0 +1,6 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include "config.h" + +const char bfs_version[] = BFS_VERSION; diff --git a/tests/run.sh b/tests/run.sh index 720515d..ab1ed6d 100644 --- a/tests/run.sh +++ b/tests/run.sh @@ -156,7 +156,7 @@ comake() { -f "$TESTS/tests.mk" \ DONE=$DONE_PIPE \ READY=$READY_PIPE \ - "${TEST_CASES[@]/#/tests/}" \ + "${!TEST_CASES[@]}" \ /dev/null } diff --git a/tests/tests.mk b/tests/tests.mk index 5bf4f6c..035ca79 100644 --- a/tests/tests.mk +++ b/tests/tests.mk @@ -1,7 +1,13 @@ # Copyright © Tavian Barnes # SPDX-License-Identifier: 0BSD -# GNU makefile that exposes make's job control to tests.sh +# Makefile that exposes make's job control to tests.sh -tests/%: +# BSD make will chdir into ${.OBJDIR} by default, unless we tell it not to +.OBJDIR: . + +# Turn off implicit rules +.SUFFIXES: + +.DEFAULT:: bash -c 'printf . >&$(READY) && read -r -N1 -u$(DONE)' -- cgit v1.2.3 From 30e309de41aaca259c4d0a200daa42ba74cbc5a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 19:11:42 +0000 Subject: build(deps): bump codecov/codecov-action from 3 to 4 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3...v4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 2abe531..2245f40 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -29,7 +29,7 @@ jobs: make -j$(nproc) check TEST_FLAGS="--sudo" gcov -abcfpu obj/*/*.o - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true -- cgit v1.2.3 From 37caa3d71fd8bb4d0d9204e4a2f5cac234fa25fd Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 29 Apr 2024 15:30:39 -0400 Subject: 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. --- .github/workflows/ci.yml | 8 +- .github/workflows/codecov.yml | 2 +- .github/workflows/codeql.yml | 2 +- Makefile | 143 +++++++++++++++--------------- README.md | 4 +- bench/bench.sh | 6 +- build/cc.sh | 16 ++++ build/config.mk | 62 +++++++++++++ build/define-if.sh | 20 +++++ build/deps.mk | 18 ++++ build/empty.c | 6 ++ build/exports.mk | 20 +++++ build/flags.mk | 136 ++++++++++++++++++++++++++++ build/has/acl-get-entry.c | 8 ++ build/has/acl-get-file.c | 8 ++ build/has/acl-get-tag-type.c | 10 +++ build/has/acl-is-trivial-np.c | 12 +++ build/has/acl-trivial.c | 8 ++ build/has/aligned-alloc.c | 8 ++ build/has/confstr.c | 9 ++ build/has/extattr-get-file.c | 10 +++ build/has/extattr-get-link.c | 10 +++ build/has/extattr-list-file.c | 10 +++ build/has/extattr-list-link.c | 10 +++ build/has/fdclosedir.c | 8 ++ build/has/getdents.c | 10 +++ build/has/getdents64-syscall.c | 12 +++ build/has/getdents64.c | 10 +++ build/has/getprogname-gnu.c | 9 ++ build/has/getprogname.c | 9 ++ build/has/max-align-t.c | 8 ++ build/has/pipe2.c | 10 +++ build/has/posix-spawn-addfchdir-np.c | 11 +++ build/has/posix-spawn-addfchdir.c | 11 +++ build/has/st-acmtim.c | 12 +++ build/has/st-acmtimespec.c | 12 +++ build/has/st-birthtim.c | 9 ++ build/has/st-birthtimespec.c | 9 ++ build/has/st-flags.c | 9 ++ build/has/statx-syscall.c | 13 +++ build/has/statx.c | 11 +++ build/has/strerror-l.c | 11 +++ build/has/strerror-r-gnu.c | 11 +++ build/has/strerror-r-posix.c | 11 +++ build/has/tm-gmtoff.c | 9 ++ build/has/uselocale.c | 9 ++ build/header.mk | 69 +++++++++++++++ build/pkgconf.sh | 100 +++++++++++++++++++++ build/pkgs.mk | 36 ++++++++ build/prelude.mk | 133 ++++++++++++++++++++++++++++ build/use/libacl.c | 9 ++ build/use/libcap.c | 9 ++ build/use/libselinux.c | 9 ++ build/use/liburing.c | 9 ++ build/use/oniguruma.c | 9 ++ config/cc.sh | 16 ---- config/config.mk | 63 ------------- config/define-if.sh | 20 ----- config/deps.mk | 18 ---- config/empty.c | 6 -- config/exports.mk | 20 ----- config/flags.mk | 136 ---------------------------- config/has/acl-get-entry.c | 8 -- config/has/acl-get-file.c | 8 -- config/has/acl-get-tag-type.c | 10 --- config/has/acl-is-trivial-np.c | 12 --- config/has/acl-trivial.c | 8 -- config/has/aligned-alloc.c | 8 -- config/has/confstr.c | 9 -- config/has/extattr-get-file.c | 10 --- config/has/extattr-get-link.c | 10 --- config/has/extattr-list-file.c | 10 --- config/has/extattr-list-link.c | 10 --- config/has/fdclosedir.c | 8 -- config/has/getdents.c | 10 --- config/has/getdents64-syscall.c | 12 --- config/has/getdents64.c | 10 --- config/has/getprogname-gnu.c | 9 -- config/has/getprogname.c | 9 -- config/has/max-align-t.c | 8 -- config/has/pipe2.c | 10 --- config/has/posix-spawn-addfchdir-np.c | 11 --- config/has/posix-spawn-addfchdir.c | 11 --- config/has/st-acmtim.c | 12 --- config/has/st-acmtimespec.c | 12 --- config/has/st-birthtim.c | 9 -- config/has/st-birthtimespec.c | 9 -- config/has/st-flags.c | 9 -- config/has/statx-syscall.c | 13 --- config/has/statx.c | 11 --- config/has/strerror-l.c | 11 --- config/has/strerror-r-gnu.c | 11 --- config/has/strerror-r-posix.c | 11 --- config/has/tm-gmtoff.c | 9 -- config/has/uselocale.c | 9 -- config/header.mk | 69 --------------- config/pkgconf.sh | 100 --------------------- config/pkgs.mk | 36 -------- config/prelude.mk | 162 ---------------------------------- config/use/libacl.c | 9 -- config/use/libcap.c | 9 -- config/use/libselinux.c | 9 -- config/use/liburing.c | 9 -- config/use/oniguruma.c | 9 -- configure | 98 ++++++++++++++++++++ docs/BUILDING.md | 47 +++++----- tests/util.sh | 9 +- tests/xspawn.c | 15 +--- 108 files changed, 1199 insertions(+), 1141 deletions(-) create mode 100755 build/cc.sh create mode 100644 build/config.mk create mode 100755 build/define-if.sh create mode 100644 build/deps.mk create mode 100644 build/empty.c create mode 100644 build/exports.mk create mode 100644 build/flags.mk create mode 100644 build/has/acl-get-entry.c create mode 100644 build/has/acl-get-file.c create mode 100644 build/has/acl-get-tag-type.c create mode 100644 build/has/acl-is-trivial-np.c create mode 100644 build/has/acl-trivial.c create mode 100644 build/has/aligned-alloc.c create mode 100644 build/has/confstr.c create mode 100644 build/has/extattr-get-file.c create mode 100644 build/has/extattr-get-link.c create mode 100644 build/has/extattr-list-file.c create mode 100644 build/has/extattr-list-link.c create mode 100644 build/has/fdclosedir.c create mode 100644 build/has/getdents.c create mode 100644 build/has/getdents64-syscall.c create mode 100644 build/has/getdents64.c create mode 100644 build/has/getprogname-gnu.c create mode 100644 build/has/getprogname.c create mode 100644 build/has/max-align-t.c create mode 100644 build/has/pipe2.c create mode 100644 build/has/posix-spawn-addfchdir-np.c create mode 100644 build/has/posix-spawn-addfchdir.c create mode 100644 build/has/st-acmtim.c create mode 100644 build/has/st-acmtimespec.c create mode 100644 build/has/st-birthtim.c create mode 100644 build/has/st-birthtimespec.c create mode 100644 build/has/st-flags.c create mode 100644 build/has/statx-syscall.c create mode 100644 build/has/statx.c create mode 100644 build/has/strerror-l.c create mode 100644 build/has/strerror-r-gnu.c create mode 100644 build/has/strerror-r-posix.c create mode 100644 build/has/tm-gmtoff.c create mode 100644 build/has/uselocale.c create mode 100644 build/header.mk create mode 100755 build/pkgconf.sh create mode 100644 build/pkgs.mk create mode 100644 build/prelude.mk create mode 100644 build/use/libacl.c create mode 100644 build/use/libcap.c create mode 100644 build/use/libselinux.c create mode 100644 build/use/liburing.c create mode 100644 build/use/oniguruma.c delete mode 100755 config/cc.sh delete mode 100644 config/config.mk delete mode 100755 config/define-if.sh delete mode 100644 config/deps.mk delete mode 100644 config/empty.c delete mode 100644 config/exports.mk delete mode 100644 config/flags.mk delete mode 100644 config/has/acl-get-entry.c delete mode 100644 config/has/acl-get-file.c delete mode 100644 config/has/acl-get-tag-type.c delete mode 100644 config/has/acl-is-trivial-np.c delete mode 100644 config/has/acl-trivial.c delete mode 100644 config/has/aligned-alloc.c delete mode 100644 config/has/confstr.c delete mode 100644 config/has/extattr-get-file.c delete mode 100644 config/has/extattr-get-link.c delete mode 100644 config/has/extattr-list-file.c delete mode 100644 config/has/extattr-list-link.c delete mode 100644 config/has/fdclosedir.c delete mode 100644 config/has/getdents.c delete mode 100644 config/has/getdents64-syscall.c delete mode 100644 config/has/getdents64.c delete mode 100644 config/has/getprogname-gnu.c delete mode 100644 config/has/getprogname.c delete mode 100644 config/has/max-align-t.c delete mode 100644 config/has/pipe2.c delete mode 100644 config/has/posix-spawn-addfchdir-np.c delete mode 100644 config/has/posix-spawn-addfchdir.c delete mode 100644 config/has/st-acmtim.c delete mode 100644 config/has/st-acmtimespec.c delete mode 100644 config/has/st-birthtim.c delete mode 100644 config/has/st-birthtimespec.c delete mode 100644 config/has/st-flags.c delete mode 100644 config/has/statx-syscall.c delete mode 100644 config/has/statx.c delete mode 100644 config/has/strerror-l.c delete mode 100644 config/has/strerror-r-gnu.c delete mode 100644 config/has/strerror-r-posix.c delete mode 100644 config/has/tm-gmtoff.c delete mode 100644 config/has/uselocale.c delete mode 100644 config/header.mk delete mode 100755 config/pkgconf.sh delete mode 100644 config/pkgs.mk delete mode 100644 config/prelude.mk delete mode 100644 config/use/libacl.c delete mode 100644 config/use/libcap.c delete mode 100644 config/use/libselinux.c delete mode 100644 config/use/liburing.c delete mode 100644 config/use/oniguruma.c create mode 100755 configure (limited to '.github/workflows/codecov.yml') 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 diff --git a/Makefile b/Makefile index 981c322..2fb35fd 100644 --- a/Makefile +++ b/Makefile @@ -1,56 +1,50 @@ # Copyright © Tavian Barnes # 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 diff --git a/README.md b/README.md index b95c16b..922ebdc 100644 --- a/README.md +++ b/README.md @@ -333,7 +333,7 @@ Once you have the dependencies, you can build bfs. 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/build/cc.sh b/build/cc.sh new file mode 100755 index 0000000..45d51ca --- /dev/null +++ b/build/cc.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Run the compiler and check if it succeeded + +set -eu + +TMP=$(mktemp) +trap 'rm -f "$TMP"' EXIT + +( + set -x + $XCC $XCPPFLAGS $XCFLAGS $XLDFLAGS "$@" $XLDLIBS -o "$TMP" +) 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 +# 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/build/define-if.sh b/build/define-if.sh new file mode 100755 index 0000000..295ead8 --- /dev/null +++ b/build/define-if.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Output a C preprocessor definition based on whether a command succeeds + +set -eu + +SLUG="${1#build/}" +SLUG="${SLUG%.c}" +MACRO="BFS_$(printf '%s' "$SLUG" | tr '/a-z-' '_A-Z_')" +shift + +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..e8dd9fb --- /dev/null +++ b/build/deps.mk @@ -0,0 +1,18 @@ +# Copyright © Tavian Barnes +# 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/build/empty.c b/build/empty.c new file mode 100644 index 0000000..4fa9a5b --- /dev/null +++ b/build/empty.c @@ -0,0 +1,6 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +int main(void) { + return 0; +} diff --git a/build/exports.mk b/build/exports.mk new file mode 100644 index 0000000..ed19134 --- /dev/null +++ b/build/exports.mk @@ -0,0 +1,20 @@ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Makefile fragment that exports variables used by configuration scripts + +export XPREFIX=${PREFIX} +export XMANDIR=${MANDIR} + +export XCC=${CC} +export XINSTALL=${INSTALL} +export XMKDIR=${MKDIR} +export XPKG_CONFIG=${PKG_CONFIG} +export XRM=${RM} + +export XCPPFLAGS=${CPPFLAGS} +export XCFLAGS=${CFLAGS} +export XLDFLAGS=${LDFLAGS} +export XLDLIBS=${LDLIBS} + +export XNOLIBS=${NOLIBS} diff --git a/build/flags.mk b/build/flags.mk new file mode 100644 index 0000000..0a44e94 --- /dev/null +++ b/build/flags.mk @@ -0,0 +1,136 @@ +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Makefile that generates gen/flags.mk + +include build/prelude.mk +include gen/vars.mk + +# Configurable flags +CPPFLAGS ?= +CFLAGS ?= \ + -g \ + -Wall \ + -Wformat=2 \ + -Werror=implicit \ + -Wimplicit-fallthrough \ + -Wmissing-declarations \ + -Wshadow \ + -Wsign-compare \ + -Wstrict-prototypes +LDFLAGS ?= +LDLIBS ?= + +export XCPPFLAGS=${CPPFLAGS} +export XCFLAGS=${CFLAGS} +export XLDFLAGS=${LDFLAGS} +export XLDLIBS=${LDLIBS} + +# Immutable flags +export BFS_CPPFLAGS= \ + -Isrc \ + -Igen \ + -D__EXTENSIONS__ \ + -D_ATFILE_SOURCE \ + -D_BSD_SOURCE \ + -D_DARWIN_C_SOURCE \ + -D_DEFAULT_SOURCE \ + -D_GNU_SOURCE \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_FILE_OFFSET_BITS=64 \ + -D_TIME_BITS=64 +export BFS_CFLAGS= -std=c17 -pthread + +# Platform-specific system libraries +LDLIBS,DragonFly := -lposix1e +LDLIBS,Linux := -lrt +LDLIBS,NetBSD := -lutil +LDLIBS,SunOS := -lsec -lsocket -lnsl +export BFS_LDLIBS=${LDLIBS,${OS}} + +# Build profiles +_ASAN := ${TRUTHY,${ASAN}} +_LSAN := ${TRUTHY,${LSAN}} +_MSAN := ${TRUTHY,${MSAN}} +_TSAN := ${TRUTHY,${TSAN}} +_UBSAN := ${TRUTHY,${UBSAN}} +_GCOV := ${TRUTHY,${GCOV}} +_LINT := ${TRUTHY,${LINT}} +_RELEASE := ${TRUTHY,${RELEASE}} + +# https://github.com/google/sanitizers/issues/342 +TSAN_CPPFLAGS,y := -DBFS_USE_TARGET_CLONES=0 +export TSAN_CPPFLAGS=${TSAN_CPPFLAGS,${_TSAN}} + +ASAN_CFLAGS,y := -fsanitize=address +LSAN_CFLAGS,y := -fsanitize=leak +MSAN_CFLAGS,y := -fsanitize=memory -fsanitize-memory-track-origins +TSAN_CFLAGS,y := -fsanitize=thread +UBSAN_CFLAGS.y := -fsanitize=undefined + +export ASAN_CFLAGS=${ASAN_CFLAGS,${_ASAN}} +export LSAN_CFLAGS=${LSAN_CFLAGS,${_LSAN}} +export MSAN_CFLAGS=${MSAN_CFLAGS,${_MSAN}} +export TSAN_CFLAGS=${TSAN_CFLAGS,${_TSAN}} +export UBSAN_CFLAGS=${UBSAN_CFLAGS,${_UBSAN}} + +SAN_CFLAGS,y := -fno-sanitize-recover=all +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 +YESLIBS := ${NOT,${_MSAN}${_TSAN}} +NOLIBS ?= ${NOT,${YESLIBS}} +export XNOLIBS=${NOLIBS} + +# gcov only intercepts fork()/exec() with -std=gnu* +GCOV_CFLAGS,y := -std=gnu17 --coverage +export GCOV_CFLAGS=${GCOV_CFLAGS,${_GCOV}} + +LINT_CPPFLAGS,y := -D_FORTIFY_SOURCE=3 -DBFS_LINT +LINT_CFLAGS,y := -Werror -O2 + +export LINT_CPPFLAGS=${LINT_CPPFLAGS,${_LINT}} +export LINT_CFLAGS=${LINT_CFLAGS,${_LINT}} + +RELEASE_CPPFLAGS,y := -DNDEBUG +RELEASE_CFLAGS,y := -O3 -flto=auto + +export RELEASE_CPPFLAGS=${RELEASE_CPPFLAGS,${_RELEASE}} +export RELEASE_CFLAGS=${RELEASE_CFLAGS,${_RELEASE}} + +# Set a variable +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] $@" + printf '# %s\n' "$@" >$@ + ${SETVAR} CPPFLAGS "$$BFS_CPPFLAGS" + ${APPEND} CPPFLAGS "$$TSAN_CPPFLAGS" + ${APPEND} CPPFLAGS "$$LINT_CPPFLAGS" + ${APPEND} CPPFLAGS "$$RELEASE_CPPFLAGS" + ${APPEND} CPPFLAGS "$$XCPPFLAGS" + ${APPEND} CPPFLAGS "$$EXTRA_CPPFLAGS" + ${SETVAR} CFLAGS "$$BFS_CFLAGS" + ${APPEND} CFLAGS "$$ASAN_CFLAGS" + ${APPEND} CFLAGS "$$LSAN_CFLAGS" + ${APPEND} CFLAGS "$$MSAN_CFLAGS" + ${APPEND} CFLAGS "$$TSAN_CFLAGS" + ${APPEND} CFLAGS "$$UBSAN_CFLAGS" + ${APPEND} CFLAGS "$$SAN_CFLAGS" + ${APPEND} CFLAGS "$$GCOV_CFLAGS" + ${APPEND} CFLAGS "$$LINT_CFLAGS" + ${APPEND} CFLAGS "$$RELEASE_CFLAGS" + ${APPEND} CFLAGS "$$XCFLAGS" + ${APPEND} CFLAGS "$$EXTRA_CFLAGS" + ${SETVAR} LDFLAGS "$$XLDFLAGS" + ${SETVAR} LDLIBS "$$XLDLIBS" + ${APPEND} LDLIBS "$$EXTRA_LDLIBS" + ${APPEND} LDLIBS "$$BFS_LDLIBS" + ${SETVAR} NOLIBS "$$XNOLIBS" + test "${OS}-${SAN}" != FreeBSD-y || printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ + ${VCAT} $@ diff --git a/build/has/acl-get-entry.c b/build/has/acl-get-entry.c new file mode 100644 index 0000000..3cce771 --- /dev/null +++ b/build/has/acl-get-entry.c @@ -0,0 +1,8 @@ +#include +#include + +int main(void) { + acl_t acl = acl_get_file(".", ACL_TYPE_DEFAULT); + acl_entry_t entry; + return acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); +} diff --git a/build/has/acl-get-file.c b/build/has/acl-get-file.c new file mode 100644 index 0000000..89fbf23 --- /dev/null +++ b/build/has/acl-get-file.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int main(void) { + acl_t acl = acl_get_file(".", ACL_TYPE_DEFAULT); + return acl == (acl_t)NULL; +} diff --git a/build/has/acl-get-tag-type.c b/build/has/acl-get-tag-type.c new file mode 100644 index 0000000..2901956 --- /dev/null +++ b/build/has/acl-get-tag-type.c @@ -0,0 +1,10 @@ +#include +#include +#include + +int main(void) { + acl_entry_t entry; + memset(&entry, 0, sizeof(entry)); + acl_tag_t tag; + return acl_get_tag_type(entry, &tag); +} diff --git a/build/has/acl-is-trivial-np.c b/build/has/acl-is-trivial-np.c new file mode 100644 index 0000000..9ca9fc7 --- /dev/null +++ b/build/has/acl-is-trivial-np.c @@ -0,0 +1,12 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + acl_t acl = acl_get_fd(3); + int trivial; + acl_is_trivial_np(acl, &trivial); + return 0; +} diff --git a/build/has/acl-trivial.c b/build/has/acl-trivial.c new file mode 100644 index 0000000..7efc838 --- /dev/null +++ b/build/has/acl-trivial.c @@ -0,0 +1,8 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + return acl_trivial("."); +} diff --git a/build/has/aligned-alloc.c b/build/has/aligned-alloc.c new file mode 100644 index 0000000..4460038 --- /dev/null +++ b/build/has/aligned-alloc.c @@ -0,0 +1,8 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + return !aligned_alloc(_Alignof(void *), sizeof(void *)); +} diff --git a/build/has/confstr.c b/build/has/confstr.c new file mode 100644 index 0000000..58280b4 --- /dev/null +++ b/build/has/confstr.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + confstr(_CS_PATH, NULL, 0); + return 0; +} diff --git a/build/has/extattr-get-file.c b/build/has/extattr-get-file.c new file mode 100644 index 0000000..ac9cf96 --- /dev/null +++ b/build/has/extattr-get-file.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + return extattr_get_file("file", EXTATTR_NAMESPACE_USER, "xattr", NULL, 0); +} diff --git a/build/has/extattr-get-link.c b/build/has/extattr-get-link.c new file mode 100644 index 0000000..c35be5b --- /dev/null +++ b/build/has/extattr-get-link.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + return extattr_get_link("link", EXTATTR_NAMESPACE_USER, "xattr", NULL, 0); +} diff --git a/build/has/extattr-list-file.c b/build/has/extattr-list-file.c new file mode 100644 index 0000000..e68a8bb --- /dev/null +++ b/build/has/extattr-list-file.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + return extattr_list_file("file", EXTATTR_NAMESPACE_USER, NULL, 0); +} diff --git a/build/has/extattr-list-link.c b/build/has/extattr-list-link.c new file mode 100644 index 0000000..49f0ec2 --- /dev/null +++ b/build/has/extattr-list-link.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + return extattr_list_link("link", EXTATTR_NAMESPACE_USER, NULL, 0); +} diff --git a/build/has/fdclosedir.c b/build/has/fdclosedir.c new file mode 100644 index 0000000..f4ad1f5 --- /dev/null +++ b/build/has/fdclosedir.c @@ -0,0 +1,8 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + return fdclosedir(opendir(".")); +} diff --git a/build/has/getdents.c b/build/has/getdents.c new file mode 100644 index 0000000..d0d4228 --- /dev/null +++ b/build/has/getdents.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct dirent de; + getdents(3, &de, 1024); + return 0; +} diff --git a/build/has/getdents64-syscall.c b/build/has/getdents64-syscall.c new file mode 100644 index 0000000..4838c14 --- /dev/null +++ b/build/has/getdents64-syscall.c @@ -0,0 +1,12 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + struct dirent64 de; + syscall(SYS_getdents64, 3, &de, 1024); + return 0; +} diff --git a/build/has/getdents64.c b/build/has/getdents64.c new file mode 100644 index 0000000..1abf36d --- /dev/null +++ b/build/has/getdents64.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct dirent64 de; + getdents64(3, &de, 1024); + return 0; +} diff --git a/build/has/getprogname-gnu.c b/build/has/getprogname-gnu.c new file mode 100644 index 0000000..6b97c5e --- /dev/null +++ b/build/has/getprogname-gnu.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + const char *str = program_invocation_short_name; + return str[0]; +} diff --git a/build/has/getprogname.c b/build/has/getprogname.c new file mode 100644 index 0000000..83dc8e8 --- /dev/null +++ b/build/has/getprogname.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + const char *str = getprogname(); + return str[0]; +} diff --git a/build/has/max-align-t.c b/build/has/max-align-t.c new file mode 100644 index 0000000..96165ce --- /dev/null +++ b/build/has/max-align-t.c @@ -0,0 +1,8 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + return _Alignof(max_align_t); +} diff --git a/build/has/pipe2.c b/build/has/pipe2.c new file mode 100644 index 0000000..4cb43b5 --- /dev/null +++ b/build/has/pipe2.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + int fds[2]; + return pipe2(fds, O_CLOEXEC); +} diff --git a/build/has/posix-spawn-addfchdir-np.c b/build/has/posix-spawn-addfchdir-np.c new file mode 100644 index 0000000..b870a53 --- /dev/null +++ b/build/has/posix-spawn-addfchdir-np.c @@ -0,0 +1,11 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + posix_spawn_file_actions_t actions; + posix_spawn_file_actions_init(&actions); + posix_spawn_file_actions_addfchdir_np(&actions, 3); + return 0; +} diff --git a/build/has/posix-spawn-addfchdir.c b/build/has/posix-spawn-addfchdir.c new file mode 100644 index 0000000..c52ff81 --- /dev/null +++ b/build/has/posix-spawn-addfchdir.c @@ -0,0 +1,11 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + posix_spawn_file_actions_t actions; + posix_spawn_file_actions_init(&actions); + posix_spawn_file_actions_addfchdir(&actions, 3); + return 0; +} diff --git a/build/has/st-acmtim.c b/build/has/st-acmtim.c new file mode 100644 index 0000000..d687ab0 --- /dev/null +++ b/build/has/st-acmtim.c @@ -0,0 +1,12 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct stat sb = {0}; + unsigned int a = sb.st_atim.tv_sec; + unsigned int c = sb.st_ctim.tv_sec; + unsigned int m = sb.st_mtim.tv_sec; + return a + c + m; +} diff --git a/build/has/st-acmtimespec.c b/build/has/st-acmtimespec.c new file mode 100644 index 0000000..f747bc0 --- /dev/null +++ b/build/has/st-acmtimespec.c @@ -0,0 +1,12 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct stat sb = {0}; + unsigned int a = sb.st_atimespec.tv_sec; + unsigned int c = sb.st_ctimespec.tv_sec; + unsigned int m = sb.st_mtimespec.tv_sec; + return a + c + m; +} diff --git a/build/has/st-birthtim.c b/build/has/st-birthtim.c new file mode 100644 index 0000000..4964571 --- /dev/null +++ b/build/has/st-birthtim.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct stat sb = {0}; + return sb.st_birthtim.tv_sec; +} diff --git a/build/has/st-birthtimespec.c b/build/has/st-birthtimespec.c new file mode 100644 index 0000000..91a613f --- /dev/null +++ b/build/has/st-birthtimespec.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct stat sb = {0}; + return sb.st_birthtimespec.tv_sec; +} diff --git a/build/has/st-flags.c b/build/has/st-flags.c new file mode 100644 index 0000000..b1d0c32 --- /dev/null +++ b/build/has/st-flags.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct stat sb = {0}; + return sb.st_flags; +} diff --git a/build/has/statx-syscall.c b/build/has/statx-syscall.c new file mode 100644 index 0000000..87ec869 --- /dev/null +++ b/build/has/statx-syscall.c @@ -0,0 +1,13 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include +#include + +int main(void) { + struct statx sb; + syscall(SYS_statx, AT_FDCWD, ".", 0, STATX_BASIC_STATS, &sb); + return 0; +} diff --git a/build/has/statx.c b/build/has/statx.c new file mode 100644 index 0000000..65f1674 --- /dev/null +++ b/build/has/statx.c @@ -0,0 +1,11 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + struct statx sb; + statx(AT_FDCWD, ".", 0, STATX_BASIC_STATS, &sb); + return 0; +} diff --git a/build/has/strerror-l.c b/build/has/strerror-l.c new file mode 100644 index 0000000..3dcc4d7 --- /dev/null +++ b/build/has/strerror-l.c @@ -0,0 +1,11 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + locale_t locale = duplocale(LC_GLOBAL_LOCALE); + return !strerror_l(ENOMEM, locale); +} diff --git a/build/has/strerror-r-gnu.c b/build/has/strerror-r-gnu.c new file mode 100644 index 0000000..26ca0ee --- /dev/null +++ b/build/has/strerror-r-gnu.c @@ -0,0 +1,11 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + char buf[256]; + // Check that strerror_r() returns a pointer + return *strerror_r(ENOMEM, buf, sizeof(buf)); +} diff --git a/build/has/strerror-r-posix.c b/build/has/strerror-r-posix.c new file mode 100644 index 0000000..41b2d30 --- /dev/null +++ b/build/has/strerror-r-posix.c @@ -0,0 +1,11 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + char buf[256]; + // Check that strerror_r() returns an integer + return 2 * strerror_r(ENOMEM, buf, sizeof(buf)); +} diff --git a/build/has/tm-gmtoff.c b/build/has/tm-gmtoff.c new file mode 100644 index 0000000..543df48 --- /dev/null +++ b/build/has/tm-gmtoff.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct tm tm = {0}; + return tm.tm_gmtoff; +} diff --git a/build/has/uselocale.c b/build/has/uselocale.c new file mode 100644 index 0000000..a712ff8 --- /dev/null +++ b/build/has/uselocale.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + locale_t locale = uselocale((locale_t)0); + return locale == LC_GLOBAL_LOCALE; +} 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 +# 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/build/pkgconf.sh b/build/pkgconf.sh new file mode 100755 index 0000000..96e4bf1 --- /dev/null +++ b/build/pkgconf.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# pkg-config wrapper with hardcoded fallbacks + +set -eu + +MODE= +case "${1:-}" in + --*) + MODE="$1" + shift +esac + +if [ $# -lt 1 ]; then + exit +fi + +case "$XNOLIBS" in + y|1) + exit 1 +esac + +if [ -z "$MODE" ]; then + # Check whether the libraries exist at all + for LIB; do + # Check ${USE_$LIB} + USE_LIB="USE_$(printf '%s' "$LIB" | tr 'a-z-' 'A-Z_')" + eval "USE=\"\${$USE_LIB:-}\"" + case "$USE" in + y|1) + continue + ;; + n|0) + exit 1 + ;; + esac + + CFLAGS=$("$0" --cflags "$LIB") || exit 1 + LDFLAGS=$("$0" --ldflags "$LIB") || exit 1 + LDLIBS=$("$0" --ldlibs "$LIB") || exit 1 + build/cc.sh $CFLAGS $LDFLAGS build/use/$LIB.c $LDLIBS || exit 1 + done +fi + +# Defer to pkg-config if possible +if command -v "${XPKG_CONFIG:-}" >/dev/null 2>&1; then + case "$MODE" in + --cflags) + "$XPKG_CONFIG" --cflags "$@" + ;; + --ldflags) + "$XPKG_CONFIG" --libs-only-L --libs-only-other "$@" + ;; + --ldlibs) + "$XPKG_CONFIG" --libs-only-l "$@" + ;; + esac + + exit +fi + +# pkg-config unavailable, emulate it ourselves +CFLAGS="" +LDFLAGS="" +LDLIBS="" + +for LIB; do + case "$LIB" in + libacl) + LDLIB=-lacl + ;; + libcap) + LDLIB=-lcap + ;; + libselinux) + LDLIB=-lselinux + ;; + liburing) + LDLIB=-luring + ;; + oniguruma) + LDLIB=-lonig + ;; + *) + printf 'error: Unknown package %s\n' "$LIB" >&2 + exit 1 + ;; + esac + + LDLIBS="$LDLIBS$LDLIB " +done + +case "$MODE" in + --ldlibs) + printf '%s\n' "$LDLIBS" + ;; +esac 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 +# 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/build/prelude.mk b/build/prelude.mk new file mode 100644 index 0000000..b235fa9 --- /dev/null +++ b/build/prelude.mk @@ -0,0 +1,133 @@ +# Copyright © Tavian Barnes +# 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 "" +IS_V := ${TRUTHY,${V}} + +# Suppress output unless V=1 +Q, := @ +Q := ${Q,${IS_V}} + +# Show full commands with `make V=1`, otherwise short summaries +MSG = @msg() { \ + MSG="$$1"; \ + shift; \ + test "${IS_V}" || printf '%s\n' "$$MSG"; \ + test "$${1:-}" || return 0; \ + test "${IS_V}" && printf '%s\n' "$$*"; \ + "$$@"; \ + }; \ + msg + +# Maximum width of a short message, to align the ✔/✘ +MSG_WIDTH := 30 + +# cat a file if V=1 +VCAT,y := @cat +VCAT, := @: +VCAT := ${VCAT,${IS_V}} + +# 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/build/use/libacl.c b/build/use/libacl.c new file mode 100644 index 0000000..de1fe50 --- /dev/null +++ b/build/use/libacl.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + acl_free(0); + return 0; +} diff --git a/build/use/libcap.c b/build/use/libcap.c new file mode 100644 index 0000000..58e832c --- /dev/null +++ b/build/use/libcap.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + cap_free(0); + return 0; +} diff --git a/build/use/libselinux.c b/build/use/libselinux.c new file mode 100644 index 0000000..bca409d --- /dev/null +++ b/build/use/libselinux.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + freecon(0); + return 0; +} diff --git a/build/use/liburing.c b/build/use/liburing.c new file mode 100644 index 0000000..bea499a --- /dev/null +++ b/build/use/liburing.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + io_uring_free_probe(0); + return 0; +} diff --git a/build/use/oniguruma.c b/build/use/oniguruma.c new file mode 100644 index 0000000..cb17596 --- /dev/null +++ b/build/use/oniguruma.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + onig_free(0); + return 0; +} diff --git a/config/cc.sh b/config/cc.sh deleted file mode 100755 index 45d51ca..0000000 --- a/config/cc.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -# Run the compiler and check if it succeeded - -set -eu - -TMP=$(mktemp) -trap 'rm -f "$TMP"' EXIT - -( - set -x - $XCC $XCPPFLAGS $XCFLAGS $XLDFLAGS "$@" $XLDLIBS -o "$TMP" -) 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 -# 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/define-if.sh b/config/define-if.sh deleted file mode 100755 index 059c1ac..0000000 --- a/config/define-if.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -# Output a C preprocessor definition based on whether a command succeeds - -set -eu - -SLUG="${1#config/}" -SLUG="${SLUG%.c}" -MACRO="BFS_$(printf '%s' "$SLUG" | tr '/a-z-' '_A-Z_')" -shift - -if "$@"; then - printf '#define %s true\n' "$MACRO" -else - printf '#define %s false\n' "$MACRO" - exit 1 -fi 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 -# 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/empty.c b/config/empty.c deleted file mode 100644 index 4fa9a5b..0000000 --- a/config/empty.c +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -int main(void) { - return 0; -} diff --git a/config/exports.mk b/config/exports.mk deleted file mode 100644 index ed19134..0000000 --- a/config/exports.mk +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -# Makefile fragment that exports variables used by configuration scripts - -export XPREFIX=${PREFIX} -export XMANDIR=${MANDIR} - -export XCC=${CC} -export XINSTALL=${INSTALL} -export XMKDIR=${MKDIR} -export XPKG_CONFIG=${PKG_CONFIG} -export XRM=${RM} - -export XCPPFLAGS=${CPPFLAGS} -export XCFLAGS=${CFLAGS} -export XLDFLAGS=${LDFLAGS} -export XLDLIBS=${LDLIBS} - -export XNOLIBS=${NOLIBS} diff --git a/config/flags.mk b/config/flags.mk deleted file mode 100644 index 837c30f..0000000 --- a/config/flags.mk +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -# Makefile that generates gen/flags.mk - -include config/prelude.mk -include ${GEN}/vars.mk - -# Configurable flags -CPPFLAGS ?= -CFLAGS ?= \ - -g \ - -Wall \ - -Wformat=2 \ - -Werror=implicit \ - -Wimplicit-fallthrough \ - -Wmissing-declarations \ - -Wshadow \ - -Wsign-compare \ - -Wstrict-prototypes -LDFLAGS ?= -LDLIBS ?= - -export XCPPFLAGS=${CPPFLAGS} -export XCFLAGS=${CFLAGS} -export XLDFLAGS=${LDFLAGS} -export XLDLIBS=${LDLIBS} - -# Immutable flags -export BFS_CPPFLAGS= \ - -Isrc \ - -I${GEN} \ - -D__EXTENSIONS__ \ - -D_ATFILE_SOURCE \ - -D_BSD_SOURCE \ - -D_DARWIN_C_SOURCE \ - -D_DEFAULT_SOURCE \ - -D_GNU_SOURCE \ - -D_POSIX_PTHREAD_SEMANTICS \ - -D_FILE_OFFSET_BITS=64 \ - -D_TIME_BITS=64 -export BFS_CFLAGS= -std=c17 -pthread - -# Platform-specific system libraries -LDLIBS,DragonFly := -lposix1e -LDLIBS,Linux := -lrt -LDLIBS,NetBSD := -lutil -LDLIBS,SunOS := -lsec -lsocket -lnsl -export BFS_LDLIBS=${LDLIBS,${OS}} - -# Build profiles -_ASAN := ${TRUTHY,${ASAN}} -_LSAN := ${TRUTHY,${LSAN}} -_MSAN := ${TRUTHY,${MSAN}} -_TSAN := ${TRUTHY,${TSAN}} -_UBSAN := ${TRUTHY,${UBSAN}} -_GCOV := ${TRUTHY,${GCOV}} -_LINT := ${TRUTHY,${LINT}} -_RELEASE := ${TRUTHY,${RELEASE}} - -# https://github.com/google/sanitizers/issues/342 -TSAN_CPPFLAGS,y := -DBFS_USE_TARGET_CLONES=0 -export TSAN_CPPFLAGS=${TSAN_CPPFLAGS,${_TSAN}} - -ASAN_CFLAGS,y := -fsanitize=address -LSAN_CFLAGS,y := -fsanitize=leak -MSAN_CFLAGS,y := -fsanitize=memory -fsanitize-memory-track-origins -TSAN_CFLAGS,y := -fsanitize=thread -UBSAN_CFLAGS.y := -fsanitize=undefined - -export ASAN_CFLAGS=${ASAN_CFLAGS,${_ASAN}} -export LSAN_CFLAGS=${LSAN_CFLAGS,${_LSAN}} -export MSAN_CFLAGS=${MSAN_CFLAGS,${_MSAN}} -export TSAN_CFLAGS=${TSAN_CFLAGS,${_TSAN}} -export UBSAN_CFLAGS=${UBSAN_CFLAGS,${_UBSAN}} - -SAN_CFLAGS,y := -fno-sanitize-recover=all -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 -YESLIBS := ${NOT,${_MSAN}${_TSAN}} -NOLIBS ?= ${NOT,${YESLIBS}} -export XNOLIBS=${NOLIBS} - -# gcov only intercepts fork()/exec() with -std=gnu* -GCOV_CFLAGS,y := -std=gnu17 --coverage -export GCOV_CFLAGS=${GCOV_CFLAGS,${_GCOV}} - -LINT_CPPFLAGS,y := -D_FORTIFY_SOURCE=3 -DBFS_LINT -LINT_CFLAGS,y := -Werror -O2 - -export LINT_CPPFLAGS=${LINT_CPPFLAGS,${_LINT}} -export LINT_CFLAGS=${LINT_CFLAGS,${_LINT}} - -RELEASE_CPPFLAGS,y := -DNDEBUG -RELEASE_CFLAGS,y := -O3 -flto=auto - -export RELEASE_CPPFLAGS=${RELEASE_CPPFLAGS,${_RELEASE}} -export RELEASE_CFLAGS=${RELEASE_CFLAGS,${_RELEASE}} - -# Set a variable -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}" >$@ - ${SETVAR} CPPFLAGS "$$BFS_CPPFLAGS" - ${APPEND} CPPFLAGS "$$TSAN_CPPFLAGS" - ${APPEND} CPPFLAGS "$$LINT_CPPFLAGS" - ${APPEND} CPPFLAGS "$$RELEASE_CPPFLAGS" - ${APPEND} CPPFLAGS "$$XCPPFLAGS" - ${APPEND} CPPFLAGS "$$EXTRA_CPPFLAGS" - ${SETVAR} CFLAGS "$$BFS_CFLAGS" - ${APPEND} CFLAGS "$$ASAN_CFLAGS" - ${APPEND} CFLAGS "$$LSAN_CFLAGS" - ${APPEND} CFLAGS "$$MSAN_CFLAGS" - ${APPEND} CFLAGS "$$TSAN_CFLAGS" - ${APPEND} CFLAGS "$$UBSAN_CFLAGS" - ${APPEND} CFLAGS "$$SAN_CFLAGS" - ${APPEND} CFLAGS "$$GCOV_CFLAGS" - ${APPEND} CFLAGS "$$LINT_CFLAGS" - ${APPEND} CFLAGS "$$RELEASE_CFLAGS" - ${APPEND} CFLAGS "$$XCFLAGS" - ${APPEND} CFLAGS "$$EXTRA_CFLAGS" - ${SETVAR} LDFLAGS "$$XLDFLAGS" - ${SETVAR} LDLIBS "$$XLDLIBS" - ${APPEND} LDLIBS "$$EXTRA_LDLIBS" - ${APPEND} LDLIBS "$$BFS_LDLIBS" - ${SETVAR} NOLIBS "$$XNOLIBS" - test "${OS}-${SAN}" != FreeBSD-y || printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ - ${VCAT} $@ diff --git a/config/has/acl-get-entry.c b/config/has/acl-get-entry.c deleted file mode 100644 index 3cce771..0000000 --- a/config/has/acl-get-entry.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -int main(void) { - acl_t acl = acl_get_file(".", ACL_TYPE_DEFAULT); - acl_entry_t entry; - return acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); -} diff --git a/config/has/acl-get-file.c b/config/has/acl-get-file.c deleted file mode 100644 index 89fbf23..0000000 --- a/config/has/acl-get-file.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include -#include - -int main(void) { - acl_t acl = acl_get_file(".", ACL_TYPE_DEFAULT); - return acl == (acl_t)NULL; -} diff --git a/config/has/acl-get-tag-type.c b/config/has/acl-get-tag-type.c deleted file mode 100644 index 2901956..0000000 --- a/config/has/acl-get-tag-type.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include - -int main(void) { - acl_entry_t entry; - memset(&entry, 0, sizeof(entry)); - acl_tag_t tag; - return acl_get_tag_type(entry, &tag); -} diff --git a/config/has/acl-is-trivial-np.c b/config/has/acl-is-trivial-np.c deleted file mode 100644 index 9ca9fc7..0000000 --- a/config/has/acl-is-trivial-np.c +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include - -int main(void) { - acl_t acl = acl_get_fd(3); - int trivial; - acl_is_trivial_np(acl, &trivial); - return 0; -} diff --git a/config/has/acl-trivial.c b/config/has/acl-trivial.c deleted file mode 100644 index 7efc838..0000000 --- a/config/has/acl-trivial.c +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - return acl_trivial("."); -} diff --git a/config/has/aligned-alloc.c b/config/has/aligned-alloc.c deleted file mode 100644 index 4460038..0000000 --- a/config/has/aligned-alloc.c +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - return !aligned_alloc(_Alignof(void *), sizeof(void *)); -} diff --git a/config/has/confstr.c b/config/has/confstr.c deleted file mode 100644 index 58280b4..0000000 --- a/config/has/confstr.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - confstr(_CS_PATH, NULL, 0); - return 0; -} diff --git a/config/has/extattr-get-file.c b/config/has/extattr-get-file.c deleted file mode 100644 index ac9cf96..0000000 --- a/config/has/extattr-get-file.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include - -int main(void) { - return extattr_get_file("file", EXTATTR_NAMESPACE_USER, "xattr", NULL, 0); -} diff --git a/config/has/extattr-get-link.c b/config/has/extattr-get-link.c deleted file mode 100644 index c35be5b..0000000 --- a/config/has/extattr-get-link.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include - -int main(void) { - return extattr_get_link("link", EXTATTR_NAMESPACE_USER, "xattr", NULL, 0); -} diff --git a/config/has/extattr-list-file.c b/config/has/extattr-list-file.c deleted file mode 100644 index e68a8bb..0000000 --- a/config/has/extattr-list-file.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include - -int main(void) { - return extattr_list_file("file", EXTATTR_NAMESPACE_USER, NULL, 0); -} diff --git a/config/has/extattr-list-link.c b/config/has/extattr-list-link.c deleted file mode 100644 index 49f0ec2..0000000 --- a/config/has/extattr-list-link.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include - -int main(void) { - return extattr_list_link("link", EXTATTR_NAMESPACE_USER, NULL, 0); -} diff --git a/config/has/fdclosedir.c b/config/has/fdclosedir.c deleted file mode 100644 index f4ad1f5..0000000 --- a/config/has/fdclosedir.c +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - return fdclosedir(opendir(".")); -} diff --git a/config/has/getdents.c b/config/has/getdents.c deleted file mode 100644 index d0d4228..0000000 --- a/config/has/getdents.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct dirent de; - getdents(3, &de, 1024); - return 0; -} diff --git a/config/has/getdents64-syscall.c b/config/has/getdents64-syscall.c deleted file mode 100644 index 4838c14..0000000 --- a/config/has/getdents64-syscall.c +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include - -int main(void) { - struct dirent64 de; - syscall(SYS_getdents64, 3, &de, 1024); - return 0; -} diff --git a/config/has/getdents64.c b/config/has/getdents64.c deleted file mode 100644 index 1abf36d..0000000 --- a/config/has/getdents64.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct dirent64 de; - getdents64(3, &de, 1024); - return 0; -} diff --git a/config/has/getprogname-gnu.c b/config/has/getprogname-gnu.c deleted file mode 100644 index 6b97c5e..0000000 --- a/config/has/getprogname-gnu.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - const char *str = program_invocation_short_name; - return str[0]; -} diff --git a/config/has/getprogname.c b/config/has/getprogname.c deleted file mode 100644 index 83dc8e8..0000000 --- a/config/has/getprogname.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - const char *str = getprogname(); - return str[0]; -} diff --git a/config/has/max-align-t.c b/config/has/max-align-t.c deleted file mode 100644 index 96165ce..0000000 --- a/config/has/max-align-t.c +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - return _Alignof(max_align_t); -} diff --git a/config/has/pipe2.c b/config/has/pipe2.c deleted file mode 100644 index 4cb43b5..0000000 --- a/config/has/pipe2.c +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include - -int main(void) { - int fds[2]; - return pipe2(fds, O_CLOEXEC); -} diff --git a/config/has/posix-spawn-addfchdir-np.c b/config/has/posix-spawn-addfchdir-np.c deleted file mode 100644 index b870a53..0000000 --- a/config/has/posix-spawn-addfchdir-np.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - posix_spawn_file_actions_t actions; - posix_spawn_file_actions_init(&actions); - posix_spawn_file_actions_addfchdir_np(&actions, 3); - return 0; -} diff --git a/config/has/posix-spawn-addfchdir.c b/config/has/posix-spawn-addfchdir.c deleted file mode 100644 index c52ff81..0000000 --- a/config/has/posix-spawn-addfchdir.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - posix_spawn_file_actions_t actions; - posix_spawn_file_actions_init(&actions); - posix_spawn_file_actions_addfchdir(&actions, 3); - return 0; -} diff --git a/config/has/st-acmtim.c b/config/has/st-acmtim.c deleted file mode 100644 index d687ab0..0000000 --- a/config/has/st-acmtim.c +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct stat sb = {0}; - unsigned int a = sb.st_atim.tv_sec; - unsigned int c = sb.st_ctim.tv_sec; - unsigned int m = sb.st_mtim.tv_sec; - return a + c + m; -} diff --git a/config/has/st-acmtimespec.c b/config/has/st-acmtimespec.c deleted file mode 100644 index f747bc0..0000000 --- a/config/has/st-acmtimespec.c +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct stat sb = {0}; - unsigned int a = sb.st_atimespec.tv_sec; - unsigned int c = sb.st_ctimespec.tv_sec; - unsigned int m = sb.st_mtimespec.tv_sec; - return a + c + m; -} diff --git a/config/has/st-birthtim.c b/config/has/st-birthtim.c deleted file mode 100644 index 4964571..0000000 --- a/config/has/st-birthtim.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct stat sb = {0}; - return sb.st_birthtim.tv_sec; -} diff --git a/config/has/st-birthtimespec.c b/config/has/st-birthtimespec.c deleted file mode 100644 index 91a613f..0000000 --- a/config/has/st-birthtimespec.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct stat sb = {0}; - return sb.st_birthtimespec.tv_sec; -} diff --git a/config/has/st-flags.c b/config/has/st-flags.c deleted file mode 100644 index b1d0c32..0000000 --- a/config/has/st-flags.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct stat sb = {0}; - return sb.st_flags; -} diff --git a/config/has/statx-syscall.c b/config/has/statx-syscall.c deleted file mode 100644 index 87ec869..0000000 --- a/config/has/statx-syscall.c +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include -#include - -int main(void) { - struct statx sb; - syscall(SYS_statx, AT_FDCWD, ".", 0, STATX_BASIC_STATS, &sb); - return 0; -} diff --git a/config/has/statx.c b/config/has/statx.c deleted file mode 100644 index 65f1674..0000000 --- a/config/has/statx.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include - -int main(void) { - struct statx sb; - statx(AT_FDCWD, ".", 0, STATX_BASIC_STATS, &sb); - return 0; -} diff --git a/config/has/strerror-l.c b/config/has/strerror-l.c deleted file mode 100644 index 3dcc4d7..0000000 --- a/config/has/strerror-l.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include -#include - -int main(void) { - locale_t locale = duplocale(LC_GLOBAL_LOCALE); - return !strerror_l(ENOMEM, locale); -} diff --git a/config/has/strerror-r-gnu.c b/config/has/strerror-r-gnu.c deleted file mode 100644 index 26ca0ee..0000000 --- a/config/has/strerror-r-gnu.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include - -int main(void) { - char buf[256]; - // Check that strerror_r() returns a pointer - return *strerror_r(ENOMEM, buf, sizeof(buf)); -} diff --git a/config/has/strerror-r-posix.c b/config/has/strerror-r-posix.c deleted file mode 100644 index 41b2d30..0000000 --- a/config/has/strerror-r-posix.c +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include -#include - -int main(void) { - char buf[256]; - // Check that strerror_r() returns an integer - return 2 * strerror_r(ENOMEM, buf, sizeof(buf)); -} diff --git a/config/has/tm-gmtoff.c b/config/has/tm-gmtoff.c deleted file mode 100644 index 543df48..0000000 --- a/config/has/tm-gmtoff.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - struct tm tm = {0}; - return tm.tm_gmtoff; -} diff --git a/config/has/uselocale.c b/config/has/uselocale.c deleted file mode 100644 index a712ff8..0000000 --- a/config/has/uselocale.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - locale_t locale = uselocale((locale_t)0); - return locale == LC_GLOBAL_LOCALE; -} 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 -# 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/pkgconf.sh b/config/pkgconf.sh deleted file mode 100755 index 365ed61..0000000 --- a/config/pkgconf.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/sh - -# Copyright © Tavian Barnes -# SPDX-License-Identifier: 0BSD - -# pkg-config wrapper with hardcoded fallbacks - -set -eu - -MODE= -case "${1:-}" in - --*) - MODE="$1" - shift -esac - -if [ $# -lt 1 ]; then - exit -fi - -case "$XNOLIBS" in - y|1) - exit 1 -esac - -if [ -z "$MODE" ]; then - # Check whether the libraries exist at all - for LIB; do - # Check ${USE_$LIB} - USE_LIB="USE_$(printf '%s' "$LIB" | tr 'a-z-' 'A-Z_')" - eval "USE=\"\${$USE_LIB:-}\"" - case "$USE" in - y|1) - continue - ;; - n|0) - exit 1 - ;; - esac - - 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 - done -fi - -# Defer to pkg-config if possible -if command -v "${XPKG_CONFIG:-}" >/dev/null 2>&1; then - case "$MODE" in - --cflags) - "$XPKG_CONFIG" --cflags "$@" - ;; - --ldflags) - "$XPKG_CONFIG" --libs-only-L --libs-only-other "$@" - ;; - --ldlibs) - "$XPKG_CONFIG" --libs-only-l "$@" - ;; - esac - - exit -fi - -# pkg-config unavailable, emulate it ourselves -CFLAGS="" -LDFLAGS="" -LDLIBS="" - -for LIB; do - case "$LIB" in - libacl) - LDLIB=-lacl - ;; - libcap) - LDLIB=-lcap - ;; - libselinux) - LDLIB=-lselinux - ;; - liburing) - LDLIB=-luring - ;; - oniguruma) - LDLIB=-lonig - ;; - *) - printf 'error: Unknown package %s\n' "$LIB" >&2 - exit 1 - ;; - esac - - LDLIBS="$LDLIBS$LDLIB " -done - -case "$MODE" in - --ldlibs) - printf '%s\n' "$LDLIBS" - ;; -esac 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 -# 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/config/prelude.mk b/config/prelude.mk deleted file mode 100644 index 109e60c..0000000 --- a/config/prelude.mk +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright © Tavian Barnes -# 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 - -# 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 := 30 - -# cat a file if V=1 -VCAT,y := @cat -VCAT, := @: -VCAT := ${VCAT,${IS_V}} - -# All external dependencies -ALL_PKGS := \ - libacl \ - libcap \ - libselinux \ - liburing \ - oniguruma - -# 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/config/use/libacl.c b/config/use/libacl.c deleted file mode 100644 index de1fe50..0000000 --- a/config/use/libacl.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - acl_free(0); - return 0; -} diff --git a/config/use/libcap.c b/config/use/libcap.c deleted file mode 100644 index 58e832c..0000000 --- a/config/use/libcap.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - cap_free(0); - return 0; -} diff --git a/config/use/libselinux.c b/config/use/libselinux.c deleted file mode 100644 index bca409d..0000000 --- a/config/use/libselinux.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - freecon(0); - return 0; -} diff --git a/config/use/liburing.c b/config/use/liburing.c deleted file mode 100644 index bea499a..0000000 --- a/config/use/liburing.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - io_uring_free_probe(0); - return 0; -} diff --git a/config/use/oniguruma.c b/config/use/oniguruma.c deleted file mode 100644 index cb17596..0000000 --- a/config/use/oniguruma.c +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © Tavian Barnes -// SPDX-License-Identifier: 0BSD - -#include - -int main(void) { - onig_free(0); - return 0; -} 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 +# SPDX-License-Identifier: 0BSD + +# bfs build configuration script + +set -eu + +help() { + cat <] [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`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | | `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | | `USE_LIBACL`
`USE_LIBCAP`
... | 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: -- cgit v1.2.3 From 99260d347b91f9f7ede335b7f582cee34ead2b0c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 1 May 2024 14:23:20 -0400 Subject: build: Add some nice aliases to ./configure --- .github/workflows/ci.yml | 4 +- .github/workflows/codecov.yml | 2 +- Makefile | 10 +-- build/header.mk | 2 +- configure | 141 ++++++++++++++++++----------- docs/BUILDING.md | 200 ++++++++++++++++++++++++++---------------- 6 files changed, 221 insertions(+), 138 deletions(-) (limited to '.github/workflows/codecov.yml') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57f59f4..e47600b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: gmake \ oniguruma jobs=$(sysctl -n hw.ncpu) - MAKE=gmake ./configure + ./configure MAKE=gmake gmake -j$jobs check TEST_FLAGS="--sudo --verbose=skipped" netbsd: @@ -198,5 +198,5 @@ jobs: PATH="/usr/xpg4/bin:$PATH" chown -R action:staff . jobs=$(getconf NPROCESSORS_ONLN) - sudo -u action MAKE=gmake ./configure + 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 bb68927..6aaace6 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -25,7 +25,7 @@ jobs: - name: Generate coverage run: | - ./configure GCOV=y + ./configure --enable-gcov make -j$(nproc) check TEST_FLAGS="--sudo" gcov -abcfpu obj/*/*.o diff --git a/Makefile b/Makefile index cd8bb55..8a8ec6b 100644 --- a/Makefile +++ b/Makefile @@ -164,11 +164,11 @@ 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}:: @${MKDIR} $@ @@ -195,7 +195,7 @@ install:: ${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} "[INST] completions/bfs.fish" \ + ${MSG} "[INST] completions/bfs.fish" \ ${INSTALL} -m644 completions/bfs.fish ${DEST_PREFIX}/share/fish/vendor_completions.d/bfs.fish uninstall:: diff --git a/build/header.mk b/build/header.mk index 951f09b..a9157ad 100644 --- a/build/header.mk +++ b/build/header.mk @@ -53,7 +53,7 @@ gen/config.h: ${PKG_HEADERS} ${HEADERS} @printf '#define BFS_CONFIG_H\n' >>$@ @cat ${.ALLSRC} >>$@ @printf '#endif // BFS_CONFIG_H\n' >>$@ - @cat ${.ALLSRC:%=%.log} >$@.log + @cat ${.ALLSRC:%=%.log} >gen/config.log ${VCAT} $@ .PHONY: gen/config.h diff --git a/configure b/configure index 830628a..d42dec3 100755 --- a/configure +++ b/configure @@ -7,75 +7,117 @@ set -eu -help() { - cat <] [CC=...] [CFLAGS=...] [...] +# Default to `make` +MAKE="${MAKE:-make}" -Compiler configuration: +# 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 <&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 # make flag (-j2) or variable (CC=clang) + continue ;; + *) printf 'error: Unrecognized option "%s"\n\n' "$arg" >&2 - help >&2 + printf 'Run %s --help for more information.\n' "$0" >&2 exit 1 ;; esac @@ -89,10 +131,7 @@ 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 +# Set MAKEFLAGS to -j$(nproc) if it's unset +export MAKEFLAGS="${MAKEFLAGS-$j}" -${MAKE:-make} $j -rf build/config.mk "$@" +$MAKE -rf build/config.mk "$@" diff --git a/docs/BUILDING.md b/docs/BUILDING.md index db5d721..cb33c51 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -1,104 +1,101 @@ Building `bfs` ============== -Compiling ---------- - A simple invocation of $ ./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` | 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: + +
+MAKE=make
+    make implementation
+CC=cc
+    C compiler
+INSTALL=install
+    Copy files during make install
+MKDIR="mkdir -p"
+    Create directories
+PKG_CONFIG=pkg-config
+    Detect external libraries and required build flags
+RM="rm -f"
+    Delete files
+
+ +These flags will be used by the build process: + +
+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
+
### Build profiles -The configuration system provides a few shorthand flags for handy configurations: - -| Command | Description | -|-------------------------|-------------------------------------------------------------| -| `./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 -[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. `./configure ASAN=y UBSAN=y`), but not all of them will work together. - -### Flags - -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. `./configure CC=clang` | -| `CFLAGS`
`EXTRA_CFLAGS` | Override/add to the default compiler flags | -| `LDFLAGS`
`EXTRA_LDFLAGS` | Override/add to the linker flags | -| `USE_LIBACL`
`USE_LIBCAP`
... | Enable/disable [optional dependencies] | -| `TEST_FLAGS` | `tests.sh` flags for `make check` | -| `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: -### Dependencies +
+--enable-release
+    Enable optimizations, disable assertions
 
-`bfs` depends on some system libraries for some of its features.
-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`).
+--enable-asan
+--enable-lsan
+--enable-msan
+--enable-tsan
+--enable-ubsan
+    Enable sanitizers
 
-| Dependency   | Platforms  | `./configure` 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`    |
+--enable-gcov
+    Enable code coverage instrumentation
+
-[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 +You can combine multiple profiles (e.g. `./configure --enable-asan --enable-ubsan`), but not all of them will work together. -### Dependency tracking +### Dependencies -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. +`bfs` depends on some system libraries for some of its features. +External dependencies are auto-detected by default, but you can `--enable` or `--disable` them manually: -We also add a dependency on the current configuration, so you can change configurations and rebuild without having to `make clean`. -For example, +
+--enable-libacl      --disable-libacl
+--enable-libcap      --disable-libcap
+--enable-libselinux  --disable-libselinux
+--enable-liburing    --disable-liburing
+--enable-oniguruma   --disable-oniguruma
+
- $ ./configure - $ make - $ ./configure RELEASE=y - $ make +[`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=""`). -will build the project in debug mode and then rebuild it in release mode. +[`pkg-config`]: https://www.freedesktop.org/wiki/Software/pkg-config/ ### Out-of-tree builds @@ -110,6 +107,53 @@ You can set up an out-of-tree build by running the `configure` script from anoth $ make +Building +-------- + +### Targets + +The [`Makefile`](/Makefile) supports several different build targets: + +
+make
+    The default target; builds just the bfs binary
+make all
+    Builds everything, including the tests (but doesn't run them)
+
+make check
+    Builds everything, and runs all tests
+make unit-tests
+    Builds and runs the unit tests
+make integration-tests
+    Builds and runs the integration tests
+make distcheck
+    Builds and runs the tests in multiple different configurations
+
+make install
+    Installs bfs globally
+make uninstall
+    Uninstalls bfs
+
+make clean
+    Deletes all built files
+make distclean
+    Also deletes files generated by ./configure
+
+ + +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 ------- -- cgit v1.2.3