[DTrace-devel] [PATCH 5/5] build: add configure script

Kris Van Hees kris.van.hees at oracle.com
Tue Jan 2 19:29:52 UTC 2024


On Thu, Dec 21, 2023 at 01:49:19PM -0500, Kris Van Hees via DTrace-devel wrote:
> On Wed, Nov 29, 2023 at 04:08:29PM +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   | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 202 insertions(+), 38 deletions(-)
> >  create mode 100755 configure
> > 
> > diff --git a/GNUmakefile b/GNUmakefile
> > index 619b709bf78e..c39aa0d2b587 100644
> > --- a/GNUmakefile
> > +++ b/GNUmakefile
> > @@ -26,22 +26,10 @@ $(if $(subst sparc64-linux,,$(subst aarch64-linux,,$(subst x86_64-linux,,$(ARCHO
> >  $(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)
> > -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;}')
> > @@ -83,30 +71,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..187884a92067
> > --- /dev/null
> > +++ b/configure
> > @@ -0,0 +1,149 @@
> > +#!/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
> > +
> > +write_make_var()
> > +{
> > +    local val="$(printf "%s" "$2" | sed 's,^.*=,,')"
> > +
> > +    [[ ! -d build ]] && mkdir -p build
> > +
> > +    if [[ ! -f build/config-vars.mk ]]; then
> > +        echo 'Writing build/config-vars.mk'
> > +        echo '# This file is automatically generated.' > build/config-vars.mk
> > +    fi
> > +
> > +    printf '%s=%s\n' $1 "$val" >> build/config-vars.mk
> > +}
> > +
> > +write_config_var()
> > +{
> > +    local val="$(printf "%s" "$2" | sed 's,^.*=,,')"
> > +
> > +    if [[ ! -d build/.config ]]; then
> > +       mkdir -p build/.config
> > +       touch build/.config/dir.stamp
> > +        echo 'Writing build/config.{h,mk}'
> 
> This is a confusing message because it is not accurate.  The script is actually
> writing to build/.config/config.$1.{h,mk}.
> 
> > +    fi
> > +
> > +    case $val in
> > +        no) printf '# HAVE_%s undefined\n' $1 > build/.config/config.$1.mk
> > +            printf '/* #undef HAVE_%s */\n' $1 > build/.config/config.$1.h;;
> > +        yes|'') printf 'HAVE_%s=y\n' $1 > build/.config/config.$1.mk
> > +                printf '#define HAVE_%s 1\n' $1 > build/.config/config.$1.h;;
> > +    esac
> > +}
> > +
> > +rm -f build/config-vars.mk
> > +rm -rf build/.config
> 
> This is problematic because if I simply want to invoke configure --help to get
> the help output, I do not necessarily want my previous config to get deleted.
> Surely, some options like --help should *not* have any side effects like that.
> 
> In fact, ideally, I would prefer a failed configure run (if that is in fact
> even possible with this tiny script) to leave any previous config in place.
> I.e. only replace any existing config if configure is successful.
> 
> Right now, nothing that I see can cause a failure - which is also interesting
> because that means if I have something wrong in my tree and e.g. config-vars.mk
> is not writable, it does not seem an error will be reported.  In this version,
> obviously, the rm statements above would yield an error but since they really
> shouldn't be there IMHO, once they are removed, failing commands do not seem
> to be considered - i.e. no error checking.
> 
> > +
> > +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=
> > +
> > +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
> > +
> > +EOF
> > +	make help-overrides
> > +        cat >&2 <<'EOF'
> > +If passed to configure as command-line arguments, all the variables
> > +above stick for future make invocations until "make clean".
> > +
> > +EOF
> > +}
> > +
> > +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";;

Looking closer, these KERNEL_*_DIR variables do not actually get used by
anything in the makefiles or Build files.  Instead, we have KERNELMODDIR, etc.

And I expect that we should have similar options for setting KERNELSRCNAME or
KERNELSRCSUFFIX or whatever it ends up being called.

> > +        HAVE_ELF_GETSHDRSTRNDX=*) write_config_var HAVE_ELF_GETSHDRSTRNDX "$option";;
> > +        HAVE_LIBCTF=*) write_config_var HAVE_LIBCTF "$option";;
> > +        HAVE_STRRSTR=*) write_config_var HAVE_STRRSTR "$option";;
> > +        HAVE_LIBSYSTEMD=*) write_config_var HAVE_LIBSYSTEMD "$option";;
> > +        HAVE_FUSE_LOG=*) write_config_var HAVE_FUSE_LOG "$option";;
> > +        HAVE_LIBFUSE3=*) write_config_var HAVE_LIBFUSE3 "$option";;
> > +        HAVE_FUSE_NUMA=*) write_config_var HAVE_FUSE_NUMA "$option";;
> > +        HAVE_CLOSE_RANGE=*) write_config_var HAVE_CLOSE_RANGE "$option";;
> > +        HAVE_GETTID=*) write_config_var HAVE_GETTID "$option";;
> 
> Have you considered introducing options for these list --with-* and --without-*,
> especially for things like libctf, libsystemd, and fuse?  The others relate to
> functions that we have our own implementation for if the libraries do not 
> provide one (or we cannot verify they do), so perhaps something lihe
> --with-own-* or --without-own-* could apply?
> 
> That seems to be more configure-like and more consistent?  Or allow both?
> 
> > +	*) echo "Unknown option $option" >&2
> > +           exit 1;;
> > +    esac
> > +done
> > +
> > +exit 0
> > +
> > -- 
> > 2.42.0.271.g85384428f1
> > 
> > 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list