[DTrace-devel] [PATCH v3 8/9] build: add configure script

Kris Van Hees kvanhees at kvh-deb-bpf.us.oracle.com
Tue Jan 30 18:32:40 UTC 2024


On Fri, Jan 26, 2024 at 01:58:48PM +0000, Nick Alcock wrote:
> 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 9a2078593cce..4cd0ef6a596c 100644
> --- a/GNUmakefile
> +++ b/GNUmakefile
> @@ -25,22 +25,10 @@ $(if $(subst sparc64,,$(subst aarch64,,$(subst x86_64,,$(ARCH)))), \
>  $(if $(subst Linux,,$(shell uname -s)), \
>      $(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)
> -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;}')
> @@ -85,30 +73,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)
> +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
> +
>  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=
> +
> +EOF
> +	make help-overrides-header help-overrides-option
> +        echo >&2
> +        make help-overrides
> +	cat >&2 <<'EOF'
> +Options controlling the compiler (pass on the command line):
> +
> +CC				C compiler (may be a cross-compiler)
> +CPP				Preprocessor, by default $(CC) -E
> +CPPFLAGS			Preprocessor flags
> +CFLAGS				Compiler flags
> +LDFLAGS				Linker flags
> +BPFC				Cross-compiler to BPF
> +BPFCPPFLAGS			BPF C preprocessor flags
> +BPFCFLAGS			BPF C compiler flags
> +BPFLD				BPF linker
> +
> +If passed to configure as command-line arguments, all the variables
> +above stick for future make invocations until "make clean".
> +
> +EOF
> +}
> +
> +rm -rf build/.config.new build/.config-vars.mk.new
> +trap 'rm -rf build/.config.new build/.config-vars.mk.new' ERR
> +
> +for option in "$@"; do
> +    case "$option" in
> +        --help) help; exit 1;;
> +	--prefix=*) write_make_var prefix "$option";;
> +        --objdir=*) write_make_var objdir "$option";;
> +        --libdir=*) write_make_var LIBDIR "$option";;
> +        --bindir=*) write_make_var BINDIR "$option";;
> +        --sbindir=*) write_make_var SBINDIR "$option";;
> +        --includedir=*) write_make_var INCLUDEDIR "$option";;
> +        --udevdir=*) write_make_var UDEVDIR "$option";;
> +        --systemd-unit-dir=*) write_make_var SYSTEMDUNITDIR "$option";;
> +        --docdir=*) write_make_var DOCDIR "$option";;
> +        --mandir=*) write_make_var MANDIR "$option";;
> +        --testdir=*) write_make_var TESTDIR "$option";;
> +        CC=*) write_make_var CC "$option";;
> +        CPP=*) write_make_var PREPROCESS "$option";;
> +        CFLAGS=*) write_make_var CFLAGS "$option";;
> +        CPPFLAGS=*) write_make_var CPPFLAGS "$option";;
> +        LDFLAGS=*) write_make_var LDFLAGS "$option";;
> +        BPFC=*) write_make_var BPFC "$option";;
> +        BPFCPPFLAGS=*) write_make_var BPFCPPFLAGS "$option";;
> +        BPFCFLAGS=*) write_make_var BPFCFLAGS "$option";;
> +        BPFLD=*) write_make_var BPFLD "$option";;
> +        --user-uid=*) write_make_var USER_UID "$option";;
> +        --dumpcap-group=*) write_make_var DUMPCAP_GROUP "$option";;
> +        --unpriv-uid=*) write_make_var UNPRIV_UID "$option";;
> +        --unpriv-home=*) write_make_var UNPRIV_HOME "$option";;
> +        --kernels=*) write_make_var KERNELS "$option";;
> +        --kernel-mod-dir=*) write_make_var KERNEL_MOD_DIR "$option";;
> +        --kernel-src-dir=*) write_make_var KERNEL_SRC_DIR "$option";;
> +        --kernel-obj-dir=*) write_make_var KERNEL_OBJ_DIR "$option";;

You seem to have missed the comments on this...  These make variables do not
actually exist.  We use KERNELMODDIR, KERNELSRCDIR, and KERNELOBJDIR.  So those
are the ones that ought to be set here (the --kernel-*-dir option names are ok
to use I think).

Should KERELSRCSUFFIX and KERNELBLDSUFFIX also be something that can be set
with the configure script?  (Those are introduced in a patch not part of this
series.)

> +        HAVE_ELF_GETSHDRSTRNDX=*) write_config_var ELF_GETSHDRSTRNDX "$option";;
> +        --with-libctf=*) write_config_var LIBCTF "$option";;
> +        HAVE_LIBCTF=*) write_config_var LIBCTF "$option";;
> +        HAVE_STRRSTR=*) write_config_var STRRSTR "$option";;
> +        --with-libsystemd=*) write_config_var LIBSYSTEMD "$option";;
> +        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
> +           exit 1;;
> +    esac
> +done
> +
> +echo 'Writing build/config-vars.mk'
> +rm -f build/config-vars.mk
> +[[ -f build/.config-vars.mk.new ]] && \
> +   mv -f build/.config-vars.mk.new build/config-vars.mk
> +
> +rm -rf build/.config
> +[[ -d build/.config.new ]] && \
> +    mv -f build/.config.new build/.config
> +
> +# Arrange for build/config.{h,mk} to exist as soon as this
> +# script ends, so that users can see that the files we said we
> +# wrote out are actually written out.  Don't use the makefile
> +# rules, to avoid having to wait for configuration test
> +# runs that are not needed at this stage.
> +echo 'Writing build/config.{h,mk}'
> +rm -f build/config.h build/config.mk
> +cat build/.config/*.h > build/config.h
> +cat build/.config/*.mk > build/config.mk
> +
> +exit 0
> +
> -- 
> 2.43.0.272.gce700b77fd
> 
> 



More information about the DTrace-devel mailing list