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. --- 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 +++ 49 files changed, 988 insertions(+) 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 (limited to 'build') 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; +} -- cgit v1.2.3 From 1f06941a7cc586c78152ca67dec0551106977b08 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 30 Apr 2024 15:07:06 -0400 Subject: build: Listen to make -s --- Makefile | 8 ++------ build/config.mk | 8 ++++---- build/deps.mk | 8 ++++---- build/flags.mk | 8 ++++---- build/header.mk | 21 +++++++++----------- build/msg-if.sh | 21 ++++++++++++++++++++ build/msg.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ build/pkgs.mk | 13 +++++------- build/prelude.mk | 21 +++++--------------- configure | 2 +- 10 files changed, 115 insertions(+), 55 deletions(-) create mode 100755 build/msg-if.sh create mode 100755 build/msg.sh (limited to 'build') diff --git a/Makefile b/Makefile index 2fb35fd..cd8bb55 100644 --- a/Makefile +++ b/Makefile @@ -49,16 +49,12 @@ BINS := \ all: ${BINS} .PHONY: all -# Group relevant flags together -ALL_CFLAGS = ${CPPFLAGS} ${CFLAGS} ${DEPFLAGS} -ALL_LDFLAGS = ${CFLAGS} ${LDFLAGS} - # The main binary bin/bfs: ${LIBBFS} obj/src/main.o ${BINS}: @${MKDIR} ${@D} - +${MSG} "[ LD ] $@" ${CC} ${ALL_LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@ + +${MSG} "[ LD ] $@" ${CC} ${CFLAGS} ${LDFLAGS} ${.ALLSRC} ${LDLIBS} -o $@ ${POSTLINK} # Get the .c file for a .o file @@ -67,7 +63,7 @@ CSRC = ${@:obj/%.o=%.c} # Rebuild when the configuration changes ${OBJS}: gen/config.mk @${MKDIR} ${@D} - ${MSG} "[ CC ] ${CSRC}" ${CC} ${ALL_CFLAGS} -c ${CSRC} -o $@ + ${MSG} "[ CC ] ${CSRC}" ${CC} ${CPPFLAGS} ${CFLAGS} -c ${CSRC} -o $@ # Save the version number to this file, but only update version.c if it changes gen/version.c.new:: diff --git a/build/config.mk b/build/config.mk index 153838d..24873ec 100644 --- a/build/config.mk +++ b/build/config.mk @@ -43,20 +43,20 @@ gen/vars.mk:: # 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 $@ + @+XMAKEFLAGS="$$MAKEFLAGS" ${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 $@ + @+XMAKEFLAGS="$$MAKEFLAGS" ${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 $@ + @+XMAKEFLAGS="$$MAKEFLAGS" ${MAKE} -sf build/pkgs.mk $@ .PHONY: gen/pkgs.mk # Compile-time feature detection gen/config.h: gen/config.mk - @+${MAKE} -sf build/header.mk $@ + @+XMAKEFLAGS="$$MAKEFLAGS" ${MAKE} -sf build/header.mk $@ .PHONY: gen/config.h diff --git a/build/deps.mk b/build/deps.mk index e8dd9fb..3db62b6 100644 --- a/build/deps.mk +++ b/build/deps.mk @@ -10,9 +10,9 @@ 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'; \ + @printf '# %s\n' "$@" >$@ + @if build/cc.sh -MD -MP -MF /dev/null build/empty.c; then \ + printf 'CPPFLAGS += -MD -MP\n'; \ fi >>$@ 2>$@.log ${VCAT} $@ - printf -- '-include %s\n' ${OBJS:.o=.d} >>$@ + @printf -- '-include %s\n' ${OBJS:.o=.d} >>$@ diff --git a/build/flags.mk b/build/flags.mk index 0a44e94..c911b22 100644 --- a/build/flags.mk +++ b/build/flags.mk @@ -101,14 +101,14 @@ export RELEASE_CPPFLAGS=${RELEASE_CPPFLAGS,${_RELEASE}} export RELEASE_CFLAGS=${RELEASE_CFLAGS,${_RELEASE}} # Set a variable -SETVAR = printf '%s := %s\n' >>$@ +SETVAR = @printf '%s := %s\n' >>$@ # Append to a variable, if non-empty -APPEND = append() { test -z "$$2" || printf '%s += %s\n' "$$1" "$$2" >>$@; }; append +APPEND = @append() { test -z "$$2" || printf '%s += %s\n' "$$1" "$$2" >>$@; }; append gen/flags.mk:: ${MSG} "[ GEN] $@" - printf '# %s\n' "$@" >$@ + @printf '# %s\n' "$@" >$@ ${SETVAR} CPPFLAGS "$$BFS_CPPFLAGS" ${APPEND} CPPFLAGS "$$TSAN_CPPFLAGS" ${APPEND} CPPFLAGS "$$LINT_CPPFLAGS" @@ -132,5 +132,5 @@ gen/flags.mk:: ${APPEND} LDLIBS "$$EXTRA_LDLIBS" ${APPEND} LDLIBS "$$BFS_LDLIBS" ${SETVAR} NOLIBS "$$XNOLIBS" - test "${OS}-${SAN}" != FreeBSD-y || printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ + @test "${OS}-${SAN}" != FreeBSD-y || printf 'POSTLINK = elfctl -e +noaslr $$@\n' >>$@ ${VCAT} $@ diff --git a/build/header.mk b/build/header.mk index 3f77ca5..951f09b 100644 --- a/build/header.mk +++ b/build/header.mk @@ -48,12 +48,12 @@ 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 + @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 @@ -61,9 +61,6 @@ gen/config.h: ${PKG_HEADERS} ${HEADERS} 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 + @${MKDIR} ${@D} + @build/define-if.sh ${SLUG} build/cc.sh build/${SLUG}.c >$@ 2>$@.log; \ + build/msg-if.sh "[ CC ] ${SLUG}.c" test $$? -eq 0 diff --git a/build/msg-if.sh b/build/msg-if.sh new file mode 100755 index 0000000..8112aea --- /dev/null +++ b/build/msg-if.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Print a success/failure indicator from a makefile: +# +# $ ./configure +# [ CC ] use/liburing.c ✘ +# [ CC ] use/oniguruma.c ✔ + +set -eu + +MSG="$1" +shift + +if "$@"; then + build/msg.sh "$(printf '%-37s ✔' "$MSG")" +else + build/msg.sh "$(printf '%-37s ✘' "$MSG")" +fi diff --git a/build/msg.sh b/build/msg.sh new file mode 100755 index 0000000..8b4714e --- /dev/null +++ b/build/msg.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# Copyright © Tavian Barnes +# SPDX-License-Identifier: 0BSD + +# Print a message from a makefile: +# +# $ make -s +# $ make +# [ CC ] src/main.c +# $ make V=1 +# cc -Isrc -Igen -D... + +set -eu + +# Get the $MAKEFLAGS from the top-level make invocation +MFLAGS="${XMAKEFLAGS-${MAKEFLAGS-}}" + +# Check if make should be quiet (make -s) +is_quiet() { + # GNU make puts single-letter flags in the first word of $MAKEFLAGS, + # without a leading dash + case "${MFLAGS%% *}" in + -*) : ;; + *s*) return 0 ;; + esac + + # BSD make puts each flag separately like -r -s -j 48 + for flag in $MFLAGS; do + case "$flag" in + # Ignore things like --jobserver-auth + --*) continue ;; + -*s*) return 0 ;; + esac + done + + return 1 +} + +# Check if make should be loud (make V=1) +is_loud() { + test "$XV" +} + +MSG="$1" +shift + +if ! is_quiet && ! is_loud; then + printf '%s\n' "$MSG" +fi + +if [ $# -eq 0 ]; then + exit +fi + +if is_loud; then + printf '%s\n' "$*" +fi + +"$@" diff --git a/build/pkgs.mk b/build/pkgs.mk index 51ca664..39b550d 100644 --- a/build/pkgs.mk +++ b/build/pkgs.mk @@ -12,8 +12,8 @@ HEADERS := ${ALL_PKGS:%=gen/use/%.h} gen/pkgs.mk: ${HEADERS} ${MSG} "[ GEN] $@" - printf '# %s\n' "$@" >$@ - 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 "$$@")"; \ @@ -28,9 +28,6 @@ gen/pkgs.mk: ${HEADERS} 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 + @${MKDIR} ${@D} + @build/define-if.sh use/${PKG} build/pkgconf.sh ${PKG} >$@ 2>$@.log; \ + build/msg-if.sh "[ CC ] use/${PKG}.c" test $$? -eq 0; diff --git a/build/prelude.mk b/build/prelude.mk index b235fa9..5be26cb 100644 --- a/build/prelude.mk +++ b/build/prelude.mk @@ -44,33 +44,22 @@ TRUTHY,y := y TRUTHY,1 := y # Boolean operators are also implemented with nested expansion -NOT, := y +NOT, := y # Normalize ${V} to either "y" or "" -IS_V := ${TRUTHY,${V}} +export XV=${TRUTHY,${V}} # Suppress output unless V=1 Q, := @ -Q := ${Q,${IS_V}} +Q := ${Q,${XV}} # 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 +MSG = @build/msg.sh # cat a file if V=1 VCAT,y := @cat VCAT, := @: -VCAT := ${VCAT,${IS_V}} +VCAT := ${VCAT,${XV}} # All external dependencies ALL_PKGS := \ diff --git a/configure b/configure index 6920212..830628a 100755 --- a/configure +++ b/configure @@ -95,4 +95,4 @@ 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 "$@" +${MAKE:-make} $j -rf build/config.mk "$@" -- 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 'build') 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 From c74947f39063218f3cbd884e4ebaafe8dfc9302c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 3 May 2024 15:54:35 -0400 Subject: build: Don't look for -s inside VAR=val in $MAKEFLAGS --- build/msg.sh | 2 ++ 1 file changed, 2 insertions(+) (limited to 'build') diff --git a/build/msg.sh b/build/msg.sh index 8b4714e..a7da31b 100755 --- a/build/msg.sh +++ b/build/msg.sh @@ -30,6 +30,8 @@ is_quiet() { case "$flag" in # Ignore things like --jobserver-auth --*) continue ;; + # Skip variable assignments + *=*) break ;; -*s*) return 0 ;; esac done -- cgit v1.2.3 From f976c98d334dce9ba30aa7da4427bb530aeea536 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 6 May 2024 16:04:05 -0400 Subject: xtime: Use the libc's timegm() if present --- build/has/timegm.c | 9 +++++++++ build/header.mk | 1 + src/xtime.c | 36 +++++++++++++++++++++++++++++++++--- tests/xtime.c | 12 ++++++++---- 4 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 build/has/timegm.c (limited to 'build') diff --git a/build/has/timegm.c b/build/has/timegm.c new file mode 100644 index 0000000..6e2d155 --- /dev/null +++ b/build/has/timegm.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include + +int main(void) { + struct tm tm = {0}; + return (int)timegm(&tm); +} diff --git a/build/header.mk b/build/header.mk index a9157ad..d235fd0 100644 --- a/build/header.mk +++ b/build/header.mk @@ -40,6 +40,7 @@ HEADERS := \ gen/has/strerror-l.h \ gen/has/strerror-r-gnu.h \ gen/has/strerror-r-posix.h \ + gen/has/timegm.h \ gen/has/tm-gmtoff.h \ gen/has/uselocale.h diff --git a/src/xtime.c b/src/xtime.c index 91ed915..c3537e7 100644 --- a/src/xtime.c +++ b/src/xtime.c @@ -12,13 +12,13 @@ #include int xmktime(struct tm *tm, time_t *timep) { - *timep = mktime(tm); + time_t time = mktime(tm); - if (*timep == -1) { + if (time == -1) { int error = errno; struct tm tmp; - if (!localtime_r(timep, &tmp)) { + if (!localtime_r(&time, &tmp)) { bfs_bug("localtime_r(-1): %s", xstrerror(errno)); return -1; } @@ -30,9 +30,37 @@ int xmktime(struct tm *tm, time_t *timep) { } } + *timep = time; + return 0; +} + +#if BFS_HAS_TIMEGM + +int xtimegm(struct tm *tm, time_t *timep) { + time_t time = timegm(tm); + + if (time == -1) { + int error = errno; + + struct tm tmp; + if (!gmtime_r(&time, &tmp)) { + bfs_bug("gmtime_r(-1): %s", xstrerror(errno)); + return -1; + } + + if (tm->tm_year != tmp.tm_year || tm->tm_yday != tmp.tm_yday + || tm->tm_hour != tmp.tm_hour || tm->tm_min != tmp.tm_min || tm->tm_sec != tmp.tm_sec) { + errno = error; + return -1; + } + } + + *timep = time; return 0; } +#else + static int safe_add(int *value, int delta) { if (*value >= 0) { if (delta > INT_MAX - *value) { @@ -147,6 +175,8 @@ overflow: return -1; } +#endif // !BFS_HAS_TIMEGM + /** Parse a decimal digit. */ static int xgetdigit(char c) { int ret = c - '0'; diff --git a/tests/xtime.c b/tests/xtime.c index a7c63d2..d9d6c5c 100644 --- a/tests/xtime.c +++ b/tests/xtime.c @@ -137,6 +137,7 @@ static bool check_one_xtimegm(const struct tm *tm) { return ret; } +#if !BFS_HAS_TIMEGM /** Check an overflowing xtimegm() call. */ static bool check_xtimegm_overflow(const struct tm *tm) { struct tm copy = *tm; @@ -154,6 +155,7 @@ static bool check_xtimegm_overflow(const struct tm *tm) { return ret; } +#endif /** xtimegm() tests. */ static bool check_xtimegm(void) { @@ -173,11 +175,13 @@ static bool check_xtimegm(void) { ret &= check_one_xtimegm(&tm); } +#if !BFS_HAS_TIMEGM // Check integer overflow cases - check_xtimegm_overflow(&(struct tm) { .tm_sec = INT_MAX, .tm_min = INT_MAX }); - check_xtimegm_overflow(&(struct tm) { .tm_min = INT_MAX, .tm_hour = INT_MAX }); - check_xtimegm_overflow(&(struct tm) { .tm_hour = INT_MAX, .tm_mday = INT_MAX }); - check_xtimegm_overflow(&(struct tm) { .tm_mon = INT_MAX, .tm_year = INT_MAX }); + ret &= check_xtimegm_overflow(&(struct tm) { .tm_sec = INT_MAX, .tm_min = INT_MAX }); + ret &= check_xtimegm_overflow(&(struct tm) { .tm_min = INT_MAX, .tm_hour = INT_MAX }); + ret &= check_xtimegm_overflow(&(struct tm) { .tm_hour = INT_MAX, .tm_mday = INT_MAX }); + ret &= check_xtimegm_overflow(&(struct tm) { .tm_mon = INT_MAX, .tm_year = INT_MAX }); +#endif return ret; } -- cgit v1.2.3 From 39b51c6d6e947778bf2b63fc9586a3236665881e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 7 May 2024 13:07:45 -0400 Subject: build: Add checks for strtofflags() and string_to_flags() --- build/has/string-to-flags.c | 9 +++++++++ build/has/strtofflags.c | 9 +++++++++ build/header.mk | 2 ++ src/bfstd.c | 16 +++++++++------- 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 build/has/string-to-flags.c create mode 100644 build/has/strtofflags.c (limited to 'build') diff --git a/build/has/string-to-flags.c b/build/has/string-to-flags.c new file mode 100644 index 0000000..027d72c --- /dev/null +++ b/build/has/string-to-flags.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + return string_to_flags(NULL, NULL, NULL); +} diff --git a/build/has/strtofflags.c b/build/has/strtofflags.c new file mode 100644 index 0000000..73ecbcb --- /dev/null +++ b/build/has/strtofflags.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + return strtofflags(NULL, NULL, NULL); +} diff --git a/build/header.mk b/build/header.mk index d235fd0..2cd13fa 100644 --- a/build/header.mk +++ b/build/header.mk @@ -40,6 +40,8 @@ HEADERS := \ gen/has/strerror-l.h \ gen/has/strerror-r-gnu.h \ gen/has/strerror-r-posix.h \ + gen/has/string-to-flags.h \ + gen/has/strtofflags.h \ gen/has/timegm.h \ gen/has/tm-gmtoff.h \ gen/has/uselocale.h diff --git a/src/bfstd.c b/src/bfstd.c index f8ce871..0ac3a72 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -637,8 +637,14 @@ error: return NULL; } +#if BFS_HAS_STRTOFFLAGS +# define BFS_STRTOFFLAGS strtofflags +#elif BFS_HAS_STRING_TO_FLAGS +# define BFS_STRTOFFLAGS string_to_flags +#endif + int xstrtofflags(const char **str, unsigned long long *set, unsigned long long *clear) { -#if BSD && !__GNU__ +#ifdef BFS_STRTOFFLAGS char *str_arg = (char *)*str; #if __OpenBSD__ @@ -649,11 +655,7 @@ int xstrtofflags(const char **str, unsigned long long *set, unsigned long long * bfs_fflags_t set_arg = 0; bfs_fflags_t clear_arg = 0; -#if __NetBSD__ - int ret = string_to_flags(&str_arg, &set_arg, &clear_arg); -#else - int ret = strtofflags(&str_arg, &set_arg, &clear_arg); -#endif + int ret = BFS_STRTOFFLAGS(&str_arg, &set_arg, &clear_arg); *str = str_arg; *set = set_arg; @@ -663,7 +665,7 @@ int xstrtofflags(const char **str, unsigned long long *set, unsigned long long * errno = EINVAL; } return ret; -#else // !BSD +#else // !BFS_STRTOFFLAGS errno = ENOTSUP; return -1; #endif -- cgit v1.2.3 From c7320b94af8db53b0a4b0a96e37d6e81a0d4a68c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 7 May 2024 13:24:06 -0400 Subject: build: Add a check for getmntinfo() --- build/has/getmntinfo.c | 10 ++++++++++ build/header.mk | 1 + src/mtab.c | 3 +-- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 build/has/getmntinfo.c (limited to 'build') diff --git a/build/has/getmntinfo.c b/build/has/getmntinfo.c new file mode 100644 index 0000000..90ef5fb --- /dev/null +++ b/build/has/getmntinfo.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include +#include + +int main(void) { + return getmntinfo(NULL, MNT_WAIT); +} diff --git a/build/header.mk b/build/header.mk index 2cd13fa..52dcb6a 100644 --- a/build/header.mk +++ b/build/header.mk @@ -24,6 +24,7 @@ HEADERS := \ gen/has/getdents.h \ gen/has/getdents64.h \ gen/has/getdents64-syscall.h \ + gen/has/getmntinfo.h \ gen/has/getprogname.h \ gen/has/getprogname-gnu.h \ gen/has/max-align-t.h \ diff --git a/src/mtab.c b/src/mtab.c index 9ea8d4a..9befde3 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -15,7 +15,7 @@ #if !defined(BFS_USE_MNTENT) && BFS_USE_MNTENT_H # define BFS_USE_MNTENT true -#elif !defined(BFS_USE_MNTINFO) && BSD +#elif !defined(BFS_USE_MNTINFO) && BFS_HAS_GETMNTINFO # define BFS_USE_MNTINFO true #elif !defined(BFS_USE_MNTTAB) && __SVR4 # define BFS_USE_MNTTAB true @@ -27,7 +27,6 @@ # include #elif BFS_USE_MNTINFO # include -# include #elif BFS_USE_MNTTAB # include # include -- cgit v1.2.3 From 3908e7ef7ecaffd7b54228d09baeb1db83b0e45d Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 7 May 2024 13:34:19 -0400 Subject: build: Check for 1- and 2-argument getmntent() variants --- build/has/getmntent-1.c | 9 +++++++++ build/has/getmntent-2.c | 10 ++++++++++ build/header.mk | 2 ++ src/mtab.c | 4 ++-- 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 build/has/getmntent-1.c create mode 100644 build/has/getmntent-2.c (limited to 'build') diff --git a/build/has/getmntent-1.c b/build/has/getmntent-1.c new file mode 100644 index 0000000..9854dcd --- /dev/null +++ b/build/has/getmntent-1.c @@ -0,0 +1,9 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + return !getmntent(stdin); +} diff --git a/build/has/getmntent-2.c b/build/has/getmntent-2.c new file mode 100644 index 0000000..71f0220 --- /dev/null +++ b/build/has/getmntent-2.c @@ -0,0 +1,10 @@ +// Copyright © Tavian Barnes +// SPDX-License-Identifier: 0BSD + +#include +#include + +int main(void) { + struct mnttab mnt; + return getmntent(stdin, &mnt); +} diff --git a/build/header.mk b/build/header.mk index 52dcb6a..da6de68 100644 --- a/build/header.mk +++ b/build/header.mk @@ -24,6 +24,8 @@ HEADERS := \ gen/has/getdents.h \ gen/has/getdents64.h \ gen/has/getdents64-syscall.h \ + gen/has/getmntent-1.h \ + gen/has/getmntent-2.h \ gen/has/getmntinfo.h \ gen/has/getprogname.h \ gen/has/getprogname-gnu.h \ diff --git a/src/mtab.c b/src/mtab.c index 9befde3..0377fea 100644 --- a/src/mtab.c +++ b/src/mtab.c @@ -13,11 +13,11 @@ #include #include -#if !defined(BFS_USE_MNTENT) && BFS_USE_MNTENT_H +#if !defined(BFS_USE_MNTENT) && BFS_HAS_GETMNTENT_1 # define BFS_USE_MNTENT true #elif !defined(BFS_USE_MNTINFO) && BFS_HAS_GETMNTINFO # define BFS_USE_MNTINFO true -#elif !defined(BFS_USE_MNTTAB) && __SVR4 +#elif !defined(BFS_USE_MNTTAB) && BFS_HAS_GETMNTENT_2 # define BFS_USE_MNTTAB true #endif -- cgit v1.2.3 From c5cf2cf90834f2f56b2940d2a499a1a614ebfd21 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 7 May 2024 14:51:41 -0400 Subject: build/has/getdents: Squelch warnings --- build/has/getdents.c | 5 ++--- build/has/getdents64-syscall.c | 5 ++--- build/has/getdents64.c | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'build') diff --git a/build/has/getdents.c b/build/has/getdents.c index d0d4228..579898f 100644 --- a/build/has/getdents.c +++ b/build/has/getdents.c @@ -4,7 +4,6 @@ #include int main(void) { - struct dirent de; - getdents(3, &de, 1024); - return 0; + char buf[1024]; + return getdents(3, (void *)buf, sizeof(buf)); } diff --git a/build/has/getdents64-syscall.c b/build/has/getdents64-syscall.c index 4838c14..7642d93 100644 --- a/build/has/getdents64-syscall.c +++ b/build/has/getdents64-syscall.c @@ -6,7 +6,6 @@ #include int main(void) { - struct dirent64 de; - syscall(SYS_getdents64, 3, &de, 1024); - return 0; + char buf[1024]; + return syscall(SYS_getdents64, 3, (void *)buf, sizeof(buf)); } diff --git a/build/has/getdents64.c b/build/has/getdents64.c index 1abf36d..d8e8062 100644 --- a/build/has/getdents64.c +++ b/build/has/getdents64.c @@ -4,7 +4,6 @@ #include int main(void) { - struct dirent64 de; - getdents64(3, &de, 1024); - return 0; + char buf[1024]; + return getdents64(3, (void *)buf, sizeof(buf)); } -- cgit v1.2.3