[DTrace-devel] [PATCH v2 9/9] build: add configure script
Sam James
sam at gentoo.org
Thu Jan 25 13:47:46 UTC 2024
Nick Alcock <nick.alcock at oracle.com> writes:
> This serves three purposes:
> - let you bake configuration into build/config.* so that you don't
> need to specify the same arguments to make repeatedly
> - provide a somewhat familiar interface to builders
> - provide more documentation for bits of the build configuration
> which there was no place to document (notably Make variables
> overridden by the user, which were documented only
> intermittently in comments in the top-level GNUmakefile).
>
> It is *not* generated by Autoconf but is a short and hopefully
> comprehensible shell script.
>
> Internally it's fairly boring.
>
> Overrides of makefile variables go into a new config-vars.mk, which is
> written as a unit, since their construction is very cheap and they don't
> need the variable-by-variable, test-by-test construction process used for
> variables that end up in config.{mk,h}.
>
> Some of the help (for all the Makeconfig overrides) is printed by calling
> "make help-overrides", which ultimately derives it from the Makeconfig
> itself. (Unfortunately I can't see a way to generate the actual
> write_config_var invocations from the same place, so there's still a bit of
> extra work to do when you add new Makeconfig tests.)
>
> The rest of the "make help" -- and really most of the configure script -- is
> duplicative of stuff already in the GNUmakefile, but I can't see a way to
> automate its generation without ending up with *way* more automation than we
> have duplicated code here.
>
> In the GNUmakefile, the biggest impact is making all the paths normal
> recursively evaluated variables, so that they can pick up
> configure-generated paths (which are defined later), and moving most of the
> rest of the non-configure-modified variables down below the inclusion of
> config-vars.mk. This gives the desired properties for defaulting:
>
> - doing nothing causes the assignments in the Makefile to kick in
> - defining stuff via configure causes them to be overridden by
> further assignments in the config-vars.mk (which values are then
> picked up by the moved-down assignments
> - passing stuff on the make command line does what that normally
> does, and suppresses the corresponding in-makefile variable
> assignments, both in GNUmakefile itself and in config-vars.mk,
> thus overriding both the defaults and configure-generated paths
>
> Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
> ---
> GNUmakefile | 76 ++++++++++++----------
> README.md | 15 +++--
> configure | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 234 insertions(+), 38 deletions(-)
> create mode 100755 configure
>
> diff --git a/GNUmakefile b/GNUmakefile
> index 5713bb6a8f38..031840fe3857 100644
> --- a/GNUmakefile
> +++ b/GNUmakefile
> @@ -26,22 +26,10 @@ $(if $(subst sparc64,,$(subst aarch64,,$(subst x86_64,,$(ARCH)))), \
> $(if $(filter %-linux,$(ARCHOS)),, \
> $(error "Error: DTrace only supports Linux"))
>
> +# Variables overridable by the command line and configure scripts.
> +
> CFLAGS ?= -O2 -Wall -pedantic -Wno-unknown-pragmas
> LDFLAGS ?=
> -BITNESS := 64
> -NATIVE_BITNESS_ONLY := $(shell echo 'int main (void) { }' | gcc -x c -o /dev/null -m32 - 2>/dev/null || echo t)
$(CC) here, we might be pointed to a specific version of GCC or similar
> -ARCHINC := $(subst sparc64,sparc,$(subst aarch64,arm64,$(subst x86_64,i386,$(ARCH))))
> -INVARIANT_CFLAGS := -std=gnu99 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 $(if $(NATIVE_BITNESS_ONLY),-DNATIVE_BITNESS_ONLY) -D_DT_VERSION=\"$(VERSION)\"
> -CPPFLAGS += -Iinclude -Iuts/common -Iinclude/$(ARCHINC) -I$(objdir)
> -
> -export CC = gcc
> -override CFLAGS += $(INVARIANT_CFLAGS)
> -PREPROCESS = $(CC) -E
> -export BPFC = bpf-unknown-none-gcc
> -
> -BPFCPPFLAGS += -D$(subst sparc64,__sparc,$(subst aarch64,__aarch64__,$(subst x86_64,__amd64,$(ARCH))))
> -BPFCFLAGS ?= -O2 -Wall -Wno-unknown-pragmas
> -export BPFLD = bpf-unknown-none-ld
>
> # The first non-system uid on this system.
> USER_UID := $(shell grep '^UID_MIN' /etc/login.defs | awk '{print $$2;}')
> @@ -86,30 +74,52 @@ KERNELARCH := $(subst sparc64,sparc,$(subst aarch64,arm64,$(subst x86_64,x86,$(A
>
> # Paths.
>
> -prefix = /usr
> +prefix ?= /usr
> export objdir := $(abspath build)
> -LIBDIR := $(prefix)/lib$(BITNESS)
> -INSTLIBDIR := $(DESTDIR)$(LIBDIR)
> -BINDIR := $(prefix)/bin
> -INSTBINDIR := $(DESTDIR)$(BINDIR)
> -INCLUDEDIR := $(prefix)/include
> -INSTINCLUDEDIR := $(DESTDIR)$(INCLUDEDIR)
> -SBINDIR := $(prefix)/sbin
> -INSTSBINDIR := $(DESTDIR)$(SBINDIR)
> -UDEVDIR := $(prefix)/lib/udev/rules.d
> -INSTUDEVDIR := $(DESTDIR)$(UDEVDIR)
> -SYSTEMDUNITDIR := $(prefix)/lib/systemd/system
> -INSTSYSTEMDUNITDIR := $(DESTDIR)$(SYSTEMDUNITDIR)
> -DOCDIR := $(prefix)/share/doc/dtrace-$(VERSION)
> -INSTDOCDIR := $(DESTDIR)$(DOCDIR)
> -MANDIR := $(prefix)/share/man/man8
> -INSTMANDIR := $(DESTDIR)$(MANDIR)
> -TESTDIR := $(prefix)/lib$(BITNESS)/dtrace/testsuite
> -INSTTESTDIR := $(DESTDIR)$(TESTDIR)
> +LIBDIR = $(prefix)/lib$(BITNESS)
> +INSTLIBDIR = $(DESTDIR)$(LIBDIR)
> +BINDIR = $(prefix)/bin
> +INSTBINDIR = $(DESTDIR)$(BINDIR)
> +INCLUDEDIR = $(prefix)/include
> +INSTINCLUDEDIR = $(DESTDIR)$(INCLUDEDIR)
> +SBINDIR = $(prefix)/sbin
> +INSTSBINDIR = $(DESTDIR)$(SBINDIR)
> +UDEVDIR = $(prefix)/lib/udev/rules.d
> +INSTUDEVDIR = $(DESTDIR)$(UDEVDIR)
> +SYSTEMDUNITDIR = $(prefix)/lib/systemd/system
> +INSTSYSTEMDUNITDIR = $(DESTDIR)$(SYSTEMDUNITDIR)
> +DOCDIR = $(prefix)/share/doc/dtrace-$(VERSION)
> +INSTDOCDIR = $(DESTDIR)$(DOCDIR)
> +MANDIR = $(prefix)/share/man/man8
> +INSTMANDIR = $(DESTDIR)$(MANDIR)
> +TESTDIR = $(prefix)/lib$(BITNESS)/dtrace/testsuite
> +INSTTESTDIR = $(DESTDIR)$(TESTDIR)
> TARGETS =
>
> DTRACE ?= $(objdir)/dtrace
>
> +# configure overrides (themselves overridden by explicit command-line options).
> +
> +-include $(objdir)/config-vars.mk
> +
> +# Variables derived from the above.
> +
> +BITNESS := 64
> +NATIVE_BITNESS_ONLY := $(shell echo 'int main (void) { }' | gcc -x c -o /dev/null -m32 - 2>/dev/null || echo t)
$(CC) again
> +ARCHINC := $(subst sparc64,sparc,$(subst aarch64,arm64,$(subst x86_64,i386,$(ARCH))))
> +
> +INVARIANT_CFLAGS := -std=gnu99 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 $(if $(NATIVE_BITNESS_ONLY),-DNATIVE_BITNESS_ONLY) -D_DT_VERSION=\"$(VERSION)\"
> +CPPFLAGS += -Iinclude -Iuts/common -Iinclude/$(ARCHINC) -I$(objdir)
> +
> +export CC = gcc
> +override CFLAGS += $(INVARIANT_CFLAGS)
> +PREPROCESS = $(CC) -E
> +export BPFC = bpf-unknown-none-gcc
Are these overridable too? We may not have exactly the same tuple name
(undecided yet).
> +
> +BPFCPPFLAGS += -D$(subst sparc64,__sparc,$(subst aarch64,__aarch64__,$(subst x86_64,__amd64,$(ARCH))))
> +BPFCFLAGS ?= -O2 -Wall -Wno-unknown-pragmas
> +export BPFLD = bpf-unknown-none-ld
> +
> all::
>
> # Include everything.
> diff --git a/README.md b/README.md
> index 01bdf8173562..f3b0c5b7df1b 100644
> --- a/README.md
> +++ b/README.md
> @@ -191,7 +191,7 @@ sudo make install
>
> Some distributions install the BPF gcc and binutils under different names. You
> can specify the executables to use using the **BPFC** and **BPFLD** variables.
> -E.g. on Debian you would use:
> +E.g. on Debian you could use:
>
> ```
> make BPFC=bpf-gcc BPFLD=bpf-ld
> @@ -209,11 +209,16 @@ make KERNELS="5.16.8"
> as long as the source tree that kernel was built with remains where it was
> when that kernel was installed.
>
> -See the GNUmakefile for more options (building translators against multiple
> -different kernels at once, building against kernel sources found in
> -different places, building against a kernel built with O=, etc.)
> +See `./configure --help`, `make help`, and the top-level GNUmakefile for a
> +full list of options (building translators against multiple different
> +kernels at once, building against kernel sources found in different places,
> +building against a kernel built with O=, installing in different places,
> +etc.)
>
> -'make help' might also be of interest.
> +Some of the options (e.g., those specifying paths) may need to be specified
> +when installing as well as when building. To avoid this, you can use the
> +configure script: it bakes variable settings into the makefile so that they
> +persist across multiple invocations, including `make install`.
>
> ## 3. Testing
>
> diff --git a/configure b/configure
> new file mode 100755
> index 000000000000..8582a87071b5
> --- /dev/null
> +++ b/configure
> @@ -0,0 +1,181 @@
> +#!/bin/bash
> +# Allow user overrides of configuration options.
> +#
> +# Oracle Linux DTrace.
> +# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
> +# Licensed under the Universal Permissive License v 1.0 as shown at
> +# http://oss.oracle.com/licenses/upl.
> +
> +set -e
> +
> +# We write everything to temporary files first, then rename them atomically
> +# into their final resting places once everything has completed, to avoid
> +# partial results in case of error.
> +
> +# config-vars.mk is cheap to reproduce, so it's written out as a unit.
> +write_make_var()
> +{
> + local val="$(printf "%s" "$2" | sed 's,^.*=,,')"
> +
> + [[ ! -d build ]] && mkdir -p build
> +
> + if [[ ! -f build/.config-vars.mk.new ]]; then
> + echo '# This file is automatically generated.' > build/.config-vars.mk.new
> + fi
> +
> + printf '%s=%s\n' $1 "$val" >> build/.config-vars.mk.new
> +}
> +
> +# Write out build/.config/*.mk and build/.config/*.h, which are the same
> +# things written out by the Makeconfig fragments: each corresponds to one
> +# test, to minimize test reinvocations, since config.mk tests can be quite
> +# expensive to run.
> +
> +write_config_var()
> +{
> + local val="$(printf "%s" "$2" | sed 's,^.*=,,')"
> +
> + if [[ ! -d build/.config.new ]]; then
> + mkdir -p build/.config.new
> + touch build/.config.new/.dir.stamp
> + fi
> +
> + case $val in
> + no) printf '# HAVE_%s undefined\n' $1 > build/.config.new/config.$1.mk
> + printf '/* #undef HAVE_%s */\n' $1 > build/.config.new/config.$1.h;;
> + yes|'') printf 'HAVE_%s=y\n' $1 > build/.config.new/config.$1.mk
> + printf '#define HAVE_%s 1\n' $1 > build/.config.new/config.$1.h;;
> + esac
> +}
> +
> +help()
> +{
> + cat >&2 <<'EOF'
> +Installation paths:
> +
> +--prefix=/usr Prefix of all installed paths
> +--objdir=build Build directory
> +--libdir=PREFIX/lib64 Library directory
> +--bindir=PREFIX/sbin Binary directory
> +--sbindir=PREFIX/sbin Alias for --bindir
> +--includedir=PREFIX/include #include directory
> +--mandir=PREFIX/share/man/man8 Manpage directory
> +--udevdir=PREFIX/lib/udev/rules.d udev rules directory
> +--systemd-unit-dir=PREFIX/lib/systemd/system systemd unit directory
> +--docdir=PREFIX/share/doc/dtrace Documentation directory
> +--testdir=LIBDIR/dtrace/testsuite Testsuite install directory
> +
> +Options relating to the user environment (may need customization on
> +some systems, see GNUmakefile)
> +
> +--user-uid=UID The first non-system uid on the system
> +--dumpcap-group=GROUP Group one must run as to invoke $DUMPCAP
> +--unpriv-uid=UID A uid suitable for unprivileged processes;
> + may be negative
> +--unpriv-home=/run/initramfs Non-writable directory to use as $HOME for
> + unprivileged processes
> +
> +Options relating to kernels (for local builds against a running kernel
> +built locally, none of these should be needed):
> +
> +--kernels="6.1 6.2 6.3" Space-separated list of kernel versions to
> + produce translators for
> +--kernel-mod-dir=DIR Directory used to search for kernel build trees
> +--kernel-src-dir=DIR Source location of kernel tree for local builds
> +--kernel-obj-dir=DIR O= passed to local kernels built with O=
Thank you for this!
> [...]
> + HAVE_LIBSYSTEMD=*) write_config_var LIBSYSTEMD "$option";;
> + HAVE_FUSE_LOG=*) write_config_var FUSE_LOG "$option";;
> + --with-libfuse3=*) write_config_var LIBFUSE3 "$option";;
> + HAVE_LIBFUSE3=*) write_config_var LIBFUSE3 "$option";;
> + HAVE_FUSE_NUMA=*) write_config_var FUSE_NUMA "$option";;
> + HAVE_CLOSE_RANGE=*) write_config_var CLOSE_RANGE "$option";;
> + HAVE_GETTID=*) write_config_var GETTID "$option";;
> + *) echo "Unknown option $option" >&2
This allows disabling the use of e.g. fuse3 even if it's detected on the
system, right? If so, great.
More information about the DTrace-devel
mailing list