From 9dd998cdc047543b8d3433461c4f9e38f634bd74 Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Thu, 30 Mar 2017 12:06:49 -0700 Subject: [PATCH] Add a configure script to generate the CONFIG file Add a configure script in the root of the repository that looks and feels like one that would be generated by autotools. This script simply generates a CONFIG file for you, which used to be done by hand. Now to build SPDK you can do the following: ./configure --with-dpdk=path make Change-Id: I44ebb91f0cb1468b86da4c0033ac1406595d4967 Signed-off-by: Ben Walker --- .gitignore | 1 + Makefile | 4 +- README.md | 66 +++++++++------ autobuild.sh | 14 +--- autopackage.sh | 3 +- configure | 167 +++++++++++++++++++++++++++++++++++++ mk/spdk.common.mk | 1 + scripts/autotest_common.sh | 22 +++-- scripts/genconfig.py | 49 ++++++----- 9 files changed, 263 insertions(+), 64 deletions(-) create mode 100755 configure diff --git a/.gitignore b/.gitignore index 866343986d..1ae3d855a7 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ cscope.out dpdk-* CUnit-Memory-Dump.xml config.h +CONFIG.local *VC.db .vscode .project diff --git a/Makefile b/Makefile index 930ea5b724..d2916971ef 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk DIRS-y += lib test examples app -.PHONY: all clean $(DIRS-y) config.h +.PHONY: all clean $(DIRS-y) config.h CONFIG.local all: $(DIRS-y) clean: $(DIRS-y) @@ -50,7 +50,7 @@ examples: lib $(DIRS-y): config.h -config.h: CONFIG scripts/genconfig.py +config.h: CONFIG CONFIG.local scripts/genconfig.py $(Q)python scripts/genconfig.py $(MAKEFLAGS) > $@.tmp; \ cmp -s $@.tmp $@ || mv $@.tmp $@ ; \ rm -f $@.tmp diff --git a/README.md b/README.md index f596e6a2a5..e889f37f65 100644 --- a/README.md +++ b/README.md @@ -67,41 +67,55 @@ FreeBSD: 4) (cd dpdk-17.02 && gmake install T=x86_64-native-bsdapp-clang DESTDIR=.) -Build Configuration -=================== - -Optional components and other build-time configuration are controlled by the `CONFIG` file -in the root SPDK directory. `CONFIG` is a Makefile fragment that may be edited before building to -control which options are enabled. - -Boolean (on/off) options are configured with a 'y' (yes) or 'n' (no). For example, this line of -`CONFIG` controls whether the optional RDMA (libibverbs) support is enabled: - - CONFIG_RDMA?=n - -To enable RDMA, this line of CONFIG may be modified to contain 'y' instead of 'n'. - -Alternatively, `CONFIG` options may also be overrriden on the `make` command line: - - make CONFIG_RDMA=y - -The options specified on the `make` command line take precedence over the default values in -`CONFIG`. - Building ======== -Once the prerequisites are installed, run 'make' within the SPDK directory -to build the SPDK libraries and examples. -If you followed the instructions above for building DPDK: +Once the prerequisites are installed, building follows the common configure +and make pattern. If you followed the instructions above for building DPDK: Linux: - make DPDK_DIR=./dpdk-17.02/x86_64-native-linuxapp-gcc + ./configure --with-dpdk=./dpdk-17.02/x86_64-native-linuxapp-gcc + make FreeBSD: - gmake DPDK_DIR=./dpdk-17.02/x86_64-native-bsdapp-clang + ./configure --with-dpdk=./dpdk-17.02/x86_64-native-bsdapp-clang + gmake + +Advanced Build Options +====================== + +Optional components and other build-time configuration are controlled by +settings in two Makefile fragments in the root of the repository. `CONFIG` +contains the base settings. Running the `configure` script generates a new +file, `CONFIG.local`, that contains overrides to the base `CONFIG` file. For +advanced configuration, there are a number of additional options to `configure` +that may be used, or `CONFIG.local` can simply be created and edited by hand. A +description of all possible options is located in `CONFIG`. + +Boolean (on/off) options are configured with a 'y' (yes) or 'n' (no). For +example, this line of `CONFIG` controls whether the optional RDMA (libibverbs) +support is enabled: + + CONFIG_RDMA?=n + +To enable RDMA, this line may be added to `CONFIG.local` with a 'y' instead of +'n'. For the majority of options this can be done using the `configure` script. +For example: + + ./configure --with-dpdk=./dpdk-17.02/x86_64-native-linuxapp-gcc --with-rdma + +Additionally, `CONFIG` options may also be overrriden on the `make` command +line: + + make CONFIG_RDMA=y + +The options specified on the `make` command line take precedence over the +default values in `CONFIG` and `CONFIG.local`. This can be useful if you, for +example, generate a `CONFIG.local` using the `configure` script and then have +one or two options (i.e. debug builds) that you wish to turn on and off +frequently. Hugepages and Device Binding ============================ diff --git a/autobuild.sh b/autobuild.sh index 7d70dd43d8..47167f10f1 100755 --- a/autobuild.sh +++ b/autobuild.sh @@ -14,16 +14,10 @@ cd $rootdir date -u git describe --tags -if [ -d /usr/src/fio ]; then - MAKECONFIG="$MAKECONFIG CONFIG_FIO_PLUGIN=y FIO_SOURCE_DIR=/usr/src/fio" -fi - -if [ -d /usr/include/rbd ] && [ -d /usr/include/rados ]; then - MAKECONFIG="$MAKECONFIG CONFIG_RBD=y" -fi - timing_enter autobuild +./configure $config_params + timing_enter check_format ./scripts/check_format.sh timing_exit check_format @@ -41,7 +35,7 @@ $MAKE $MAKEFLAGS clean timing_enter scanbuild_make fail=0 -time $scanbuild $MAKE $MAKEFLAGS DPDK_DIR=$DPDK_DIR $MAKECONFIG || fail=1 +time $scanbuild $MAKE $MAKEFLAGS || fail=1 if [ $fail -eq 1 ]; then if [ -d $out/scan-build-tmp ]; then scanoutput=$(ls -1 $out/scan-build-tmp/) @@ -61,7 +55,7 @@ timing_exit scanbuild_make STAT1=`stat examples/nvme/identify/identify` sleep 1 touch lib/nvme/nvme_internal.h -$MAKE $MAKEFLAGS DPDK_DIR=$DPDK_DIR $MAKECONFIG +$MAKE $MAKEFLAGS STAT2=`stat examples/nvme/identify/identify` if [ "$STAT1" == "$STAT2" ]; then diff --git a/autopackage.sh b/autopackage.sh index e9017b1dba..7f5959b2a5 100755 --- a/autopackage.sh +++ b/autopackage.sh @@ -33,7 +33,8 @@ echo "tmpdir=$tmpdir" tar -C "$tmpdir" -xf $tarball ( cd "$tmpdir"/spdk-* - time $MAKE ${MAKEFLAGS} DPDK_DIR=$DPDK_DIR CONFIG_DEBUG=n CONFIG_WERROR=y + ./configure $config_params --disable-debug --enable-werror + time $MAKE ${MAKEFLAGS} ) rm -rf "$tmpdir" diff --git a/configure b/configure new file mode 100755 index 0000000000..b6370ad6e6 --- /dev/null +++ b/configure @@ -0,0 +1,167 @@ +#!/usr/bin/env bash + +set -e + +function usage() +{ + echo "'configure' configures SPDK to compile on supported platforms." + echo "" + echo "Usage: ./configure [OPTION]..." + echo "" + echo "Defaults for the options are specified in brackets." + echo "" + echo "General:" + echo " -h, --help Display this help and exit" + echo " --enable-debug Configure for debug builds" + echo " --enable-werror Treat compiler warnings as errors" + echo " --enable-asan Enable address sanitizer" + echo " --enable-ubsan Enable undefined behavior sanitizer" + echo " --enable-coverage Enable code coverage tracking" + echo " --with-env=path Use an alternate environment implementation" + echo "" + echo "Specifying Dependencies:" + echo "--with-DEPENDENCY[=path] Use the given dependency. Optionally, provide the" + echo " path." + echo "--without-DEPENDENCY Do not link to the given dependency. This may" + echo " disable features and components." + echo "" + echo "Valid dependencies are listed below." + echo " dpdk Required unless providing an alternate env implementation." + echo " example: /usr/share/dpdk/x86_64-default-linuxapp-gcc" + echo " fio Required to build fio_plugin." + echo " example: /usr/src/fio" + echo " rbd [disabled]" + echo " No path required." + echo " rdma [disabled]" + echo " No path required." + echo "" +} + +for i in "$@"; do + case "$i" in + -h|--help) + usage + exit 0 + ;; + --enable-debug) + CONFIG_DEBUG=y + ;; + --disable-debug) + CONFIG_DEBUG=n + ;; + --enable-asan) + CONFIG_ASAN=y + ;; + --disable-asan) + CONFIG_ASAN=n + ;; + --enable-ubsan) + CONFIG_UBSAN=y + ;; + --disable-ubsan) + CONFIG_UBSAN=n + ;; + --enable-coverage) + CONFIG_COVERAGE=y + ;; + --disable-coverage) + CONFIG_COVERAGE=n + ;; + --enable-werror) + CONFIG_WERROR=y + ;; + --disable-werror) + CONFIG_WERROR=n + ;; + --with-env=*) + CONFIG_ENV="${i#*=}" + ;; + --with-rbd) + CONFIG_RBD=y + ;; + --without-rbd) + CONFIG_RBD=n + ;; + --with-rdma) + CONFIG_RDMA=y + ;; + --without-rdma) + CONFIG_RDMA=n + ;; + --with-dpdk=*) + CONFIG_DPDK_DIR="${i#*=}" + ;; + --without-dpdk) + CONFIG_DPDK_DIR= + ;; + --with-fio=*) + FIO_SOURCE_DIR="${i#*=}" + CONFIG_FIO_PLUGIN=y + ;; + --without-fio) + FIO_SOURCE_DIR= + CONFIG_FIO_PLUGIN=n + ;; + --) + break + ;; + *) + echo "Unrecognized option $i" + usage + exit 1 + esac +done + +if [ -z "$CONFIG_ENV" ]; then + if [ -z "$CONFIG_DPDK_DIR" ]; then + echo "You must specify the path to dpdk using --with-dpdk=path." + exit 1 + fi +fi + +if [ "$CONFIG_FIO_PLUGIN" = "y" ]; then + if [ -z "$FIO_SOURCE_DIR" ]; then + echo "When fio is enabled, you must specify the fio directory using --with-fio=path" + exit 1 + fi +fi + +# Write the configuration file +rm -f CONFIG.local +if [ -n "$CONFIG_DEBUG" ]; then + echo "CONFIG_DEBUG?=$CONFIG_DEBUG" >> CONFIG.local +fi +if [ -n "$CONFIG_WERROR" ]; then + echo "CONFIG_WERROR?=$CONFIG_WERROR" >> CONFIG.local +fi +if [ -n "$CONFIG_COVERAGE" ]; then + echo "CONFIG_COVERAGE?=$CONFIG_COVERAGE" >> CONFIG.local +fi +if [ -n "$CONFIG_ASAN" ]; then + echo "CONFIG_ASAN?=$CONFIG_ASAN" >> CONFIG.local +fi +if [ -n "$CONFIG_UBSAN" ]; then + echo "CONFIG_UBSAN?=$CONFIG_UBSAN" >> CONFIG.local +fi +if [ -n "$CONFIG_ENV" ]; then + echo "CONFIG_ENV?=$CONFIG_ENV" >> CONFIG.local +fi +if [ -n "$CONFIG_DPDK_DIR" ]; then + echo "CONFIG_DPDK_DIR?=$CONFIG_DPDK_DIR" >> CONFIG.local +fi +if [ -n "$CONFIG_FIO_PLUGIN" ]; then + echo "CONFIG_FIO_PLUGIN?=$CONFIG_FIO_PLUGIN" >> CONFIG.local +fi +if [ -n "$FIO_SOURCE_DIR" ]; then + echo "FIO_SOURCE_DIR?=$FIO_SOURCE_DIR" >> CONFIG.local +fi +if [ -n "$CONFIG_RDMA" ]; then + echo "CONFIG_RDMA?=$CONFIG_RDMA" >> CONFIG.local +fi +if [ -n "$CONFIG_RBD" ]; then + echo "CONFIG_RBD?=$CONFIG_RBD" >> CONFIG.local +fi + +echo "Type make to build." + +exit 0 diff --git a/mk/spdk.common.mk b/mk/spdk.common.mk index a1e4ae1710..66c5249133 100644 --- a/mk/spdk.common.mk +++ b/mk/spdk.common.mk @@ -31,6 +31,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +-include $(SPDK_ROOT_DIR)/CONFIG.local include $(SPDK_ROOT_DIR)/CONFIG C_OPT ?= -fno-omit-frame-pointer diff --git a/scripts/autotest_common.sh b/scripts/autotest_common.sh index 8603c0494e..114388955d 100755 --- a/scripts/autotest_common.sh +++ b/scripts/autotest_common.sh @@ -3,7 +3,7 @@ ulimit -c unlimited export RUN_NIGHTLY=0 -MAKECONFIG='CONFIG_DEBUG=y CONFIG_WERROR=y' +config_params='--enable-debug --enable-werror' export UBSAN_OPTIONS='halt_on_error=1:print_stacktrace=1:abort_on_error=1' @@ -12,16 +12,16 @@ export NRHUGE=4096 case `uname` in FreeBSD) - DPDK_DIR=/usr/local/share/dpdk/x86_64-native-bsdapp-clang + config_params+=' --with-dpdk=/usr/local/share/dpdk/x86_64-native-bsdapp-clang' MAKE=gmake MAKEFLAGS=${MAKEFLAGS:--j$(sysctl -a | egrep -i 'hw.ncpu' | awk '{print $2}')} ;; Linux) - DPDK_DIR=/usr/local/share/dpdk/x86_64-native-linuxapp-gcc + config_params+=' --with-dpdk=/usr/local/share/dpdk/x86_64-native-linuxapp-gcc' MAKE=make MAKEFLAGS=${MAKEFLAGS:--j$(nproc)} - MAKECONFIG="$MAKECONFIG CONFIG_COVERAGE=y" - MAKECONFIG="$MAKECONFIG CONFIG_UBSAN=y" + config_params+=' --enable-coverage' + config_params+=' --enable-ubsan' ;; *) echo "Unknown OS in $0" @@ -30,9 +30,19 @@ case `uname` in esac if [ -f /usr/include/infiniband/verbs.h ]; then - MAKECONFIG="$MAKECONFIG CONFIG_RDMA=y" + config_params+=' --with-rdma' fi +if [ -d /usr/src/fio ]; then + config_params+=' --with-fio=/usr/src/fio' +fi + +if [ -d /usr/include/rbd ] && [ -d /usr/include/rados ]; then + config_params+=' --with-rbd' +fi + +export config_params + if [ -z "$output_dir" ]; then if [ -z "$rootdir" ] || [ ! -d "$rootdir/../output" ]; then output_dir=. diff --git a/scripts/genconfig.py b/scripts/genconfig.py index 02f4da94b0..54501f6c89 100755 --- a/scripts/genconfig.py +++ b/scripts/genconfig.py @@ -19,22 +19,33 @@ for arg in sys.argv: if 'DPDK_DIR' in args and 'CONFIG_DPDK_DIR' not in args: args['CONFIG_DPDK_DIR'] = args['DPDK_DIR'] -with open('CONFIG') as f: - for line in f: - line = line.strip() - if not comment.match(line): - m = assign.match(line) - if m: - var = m.group(1).strip() - default = m.group(3).strip() - val = default - if var in args: - val = args[var] - if default.lower() == 'y' or default.lower() == 'n': - if val.lower() == 'y': - print "#define SPDK_{0} 1".format(var) - else: - print "#undef SPDK_{0}".format(var) - else: - strval = val.replace('"', '\"') - print "#define SPDK_{0} \"{1}\"".format(var, strval) +defs = {} +for config in ('CONFIG', 'CONFIG.local'): + try: + with open(config) as f: + for line in f: + line = line.strip() + if not comment.match(line): + m = assign.match(line) + if m: + var = m.group(1).strip() + default = m.group(3).strip() + val = default + if var in args: + val = args[var] + if default.lower() == 'y' or default.lower() == 'n': + if val.lower() == 'y': + defs["SPDK_{}".format(var)] = 1 + else: + defs["SPDK_{}".format(var)] = 0 + else: + strval = val.replace('"', '\"') + defs["SPDK_{}".format(var)] = strval + except IOError: + continue + +for key, value in defs.items(): + if value == 0: + print "#undef {}".format(key) + else: + print "#define {} {}".format(key, value)