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

Nick Alcock nick.alcock at oracle.com
Fri Feb 2 18:37:42 UTC 2024


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 |  88 +++++++++++++-----------
 README.md   |  15 +++--
 configure   | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 249 insertions(+), 44 deletions(-)
 create mode 100755 configure

diff --git a/GNUmakefile b/GNUmakefile
index e7c7014d242f..a82c9d4f1f1f 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;}')
@@ -77,10 +65,10 @@ UNPRIV_HOME ?= /run/initramfs
 # For RPM builds, set KERNELMODDIR to the root of the rpmsrc tree, and set
 # KERNELSRCNAME and KERNELBLDNAME to the empty string.
 
-KERNELS = $(shell uname -r)
-KERNELMODDIR = /lib/modules
-KERNELSRCNAME = source
-KERNELBLDNAME = build
+KERNELS ?= $(shell uname -r)
+KERNELMODDIR ?= /lib/modules
+KERNELSRCNAME ?= source
+KERNELBLDNAME ?= build
 
 ifdef KERNELSRCDIR
 KERNELOBJDIR ?= $(KERNELSRCDIR)
@@ -90,32 +78,54 @@ 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)
-SYSTEMDPRESETDIR := $(prefix)/lib/systemd/system-preset
-SYSTEMDUNITDIR := $(prefix)/lib/systemd/system
-INSTSYSTEMDPRESETDIR := $(DESTDIR)$(SYSTEMDPRESETDIR)
-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)
+SYSTEMDPRESETDIR = $(prefix)/lib/systemd/system-preset
+SYSTEMDUNITDIR = $(prefix)/lib/systemd/system
+INSTSYSTEMDPRESETDIR = $(DESTDIR)$(SYSTEMDPRESETDIR)
+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 d0bf07e79970..9c50669447ed 100644
--- a/README.md
+++ b/README.md
@@ -121,7 +121,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
@@ -141,11 +141,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..2bf513f45d65
--- /dev/null
+++ b/configure
@@ -0,0 +1,190 @@
+#!/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
+				(default "/lib/modules")
+--kernel-src-dir=DIR		Source location of kernel tree for local builds
+--kernel-obj-dir=DIR		Kernel object directory (as passed to O=)
+--kernel-src-suffix=DIR		If --kernel-src-dir is not set, suffix of kernel
+				source directory (after kernel version) (default
+				"source"); seen under /lib/modules
+--kernel-obj-suffix=DIR		If --kernel-obj-dir is not set, suffix of kernel
+				object directory (after kernel version) (default
+				"build"); seen under /lib/modules
+
+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 KERNELMODDIR "$option";;
+        --kernel-src-dir=*) write_make_var KERNELSRCDIR "$option";;
+        --kernel-obj-dir=*) write_make_var KERNELOBJDIR "$option";;
+        --kernel-src-suffix=*) write_make_var KERNELSRCNAME "$option";;
+        --kernel-obj-suffix=*) write_make_var KERNELBLDNAME "$option";;
+        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