[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