Merge pull request #3586 from klauskiwi/scripts_cleanup_stage_3

ci: Rework SDK build steps
diff --git a/ci/build-all-defconfigs.sh b/ci/build-all-defconfigs.sh
index 0ad613e..30703f2 100755
--- a/ci/build-all-defconfigs.sh
+++ b/ci/build-all-defconfigs.sh
@@ -4,14 +4,14 @@
 set -eo pipefail
 
 BUILD_INFO=0
+SDK_ONLY=0
 CONFIGTAG="_defconfig"
-
 DEFCONFIGS=();
-
+CCACHE_DIR=""
 SDK_DIR=""
 
-opt=$(getopt -o 'o:s:p:r' -- "$@")
-if [ $? != 0 ] ; then
+opt=$(getopt -o 'o:Ss:p:r' -- "$@")
+if [ $? -ne 0 ] ; then
 	echo "Invalid arguments"
 	exit 1
 fi
@@ -26,10 +26,14 @@
       echo "Output directory: $1"
       OUTDIR="$1"
       ;;
+    '-S')
+      echo "Build SDK Only"
+      SDK_ONLY=1
+      ;;
     '-s')
       shift
-      echo "SDK is in: $1"
-      SDK_DIR=$1
+      echo "SDK cache dir is in: $1"
+      SDK_CACHE=$1
       ;;
     '-p')
       shift
@@ -52,12 +56,142 @@
   shift
 done
 
-function get_kernel_release
+function get_major_minor_release
 {
 	IFS=. read major minor macro <<<"$1"
 	echo -n "${major}_${minor}"
 }
 
+function get_major_release
+{
+	IFS=. read major minor macro <<<"$1"
+	echo -n "${major}"
+}
+
+function build_sdk
+{
+# $1 is the defconfig
+# $2 is the SDK output directory
+# writes the output SDK pathname in global $SDK_DIR
+# also considers global var $CCACHE_DIR
+	SDK_BUILD_DIR=`mktemp -d`
+	op-build O=$SDK_BUILD_DIR $1
+
+	# Accumulate the SDK properties we want to hash to make it unique, but
+	# just so. Start with the buildroot version and machine/OS
+	HASH_PROPERTIES="$(git submodule) $(uname -mo)"
+
+	# Even if they should be interchangeable, we want to force the sdk
+	# build on every supported OS variations
+	HASH_PROPERTIES="$(HASH PROPERTIES) $(lsb_release -as | tr -d '/n[:space:]')"
+
+	# Disable things not necessary for the sdk
+	# (Buildroot manual section 6.1.3 plus a few more things)
+	buildroot/utils/config --file $SDK_BUILD_DIR/.config --disable INIT_BUSYBOX \
+		--enable INIT_NONE \
+		--disable SYSTEM_BIN_SH_BUSYBOX \
+		--disable TARGET_ROOTFS_TAR \
+		--disable SYSTEM_BIN_SH_DASH \
+		--enable SYSTEM_BIN_SH_NONE
+
+	# We don't need the Linux Kernel or eudev (they'll be rebuilt anyway), but we need
+	# to preserve the custom kernel version (if defined) for headers consistency, and
+	# since we're at it,  enabling CPP won't hurt and will make the SDK more general
+	buildroot/utils/config --file $SDK_BUILD_DIR/.config --disable LINUX_KERNEL \
+		--disable ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV \
+		--enable INSTALL_LIBSTDCPP
+
+	# As we are disabling BR2_LINUX_KERNEL, capture Kernel version if any
+	# to prevent it from defaulting to the last on olddefconfig
+	KERNEL_VER=$(buildroot/utils/config --file $SDK_BUILD_DIR/.config --state LINUX_KERNEL_CUSTOM_VERSION_VALUE)
+	if [ "$KERNEL_VER" != "undef" ]; then
+		KERNEL="KERNEL_HEADERS_$(get_major_minor_release $KERNEL_VER)"
+		buildroot/utils/config --file $SDK_BUILD_DIR/.config --enable "$KERNEL"
+	fi
+
+	# Disable packages we won't pull into the SDK to speed it's build
+	buildroot/utils/config --file $SDK_BUILD_DIR/.config --package \
+		--disable BUSYBOX \
+		--disable KEXEC_LITE \
+		--disable LINUX_FIRMWARE \
+		--disable CRYPTSETUP \
+		--disable IPMITOOL \
+		--disable LVM2 \
+		--disable MDADM \
+		--disable NVME \
+		--disable PCIUTILS \
+		--disable ZLIB \
+		--disable LIBZLIB \
+		--disable DTC \
+		--disable LIBAIO \
+		--disable JSON_C \
+		--disable ELFUTILS \
+		--disable NCURSES \
+		--disable POPT \
+		--disable DROPBEAR --disable DROPBEAR_CLIENT \
+		--disable ETHTOOL \
+		--disable IFUPDOWN_SCRIPTS \
+		--disable LRZSZ \
+		--disable NETCAT \
+		--disable RSYNC \
+		--disable SUDO \
+		--disable KMOD \
+		--disable POWERPC_UTILS \
+		--disable UTIL_LINUX \
+		--disable IPRUTILS
+
+	# Additionally, disable ROOTFS stuff that we won't need
+	# Including the OpenPower Packages
+	buildroot/utils/config --file $SDK_BUILD_DIR/.config --undefine ROOTFS_USERS_TABLES \
+		--undefine ROOTFS_OVERLAY \
+		--undefine ROOTFS_POST_BUILD_SCRIPT \
+		--undefine ROOTFS_POST_FAKEROOT_SCRIPT \
+		--undefine ROOTFS_POST_IMAGE_SCRIPT \
+		--undefine ROOTFS_POST_SCRIPT_ARGS \
+		--undefine OPENPOWER_PLATFORM \
+		--undefine BR2_OPENPOWER_POWER8 \
+		--undefine BR2_OPENPOWER_POWER9
+
+	# Enable CCACHE
+	buildroot/utils/config --file $SDK_BUILD_DIR/.config --enable CCACHE \
+		--set-str CCACHE_DIR $CCACHE_DIR
+
+	op-build O=$SDK_BUILD_DIR olddefconfig
+
+	# Ideally this woulnd't matter, but to be safe, include Kernel
+	# Headers and GCC version as part of the SDK Hash, so that we
+	# don't have Full builds and SDK builds potentially diverging
+	# on the headers/compiler versions each uses
+	KERNEL_VER=$(buildroot/utils/config --file $SDK_BUILD_DIR/.config --state DEFAULT_KERNEL_HEADERS)
+	HASH_PROPERTIES="$HASH_PROPERTIES $KERNEL_VER"
+	echo "SDK KERNEL Version: $KERNEL_VER"
+	GCC_VER=$(buildroot/utils/config --file $SDK_BUILD_DIR/.config --state GCC_VERSION)
+	echo "SDK GCC Version: $GCC_VER"
+	HASH_PROPERTIES="$HASH_PROPERTIES $GCC_VER"
+
+	# sha1sum our properties and check if a matching sdk exists
+	# A potential caveat he is if op-build is patching any of the
+	# HASH_PROPERTIES content at build time
+	HASH_VAL=$(echo -n "$HASH_PROPERTIES" | sha1sum | sed -e 's/ .*//')
+
+	SDK_DIR="$2/toolchain-${HASH_VAL}"
+
+	if [ -e "$SDK_DIR" ]; then
+		echo "Acceptable SDK for $i exists in $SDK_DIR - skipping build"
+	else
+		op-build O=$SDK_BUILD_DIR sdk
+		if [ $? -ne 0 ]; then
+			rm -rf $SDK_DIR
+			return 1
+		fi
+
+		# Move sdk to resting location and adjust paths
+		mv $SDK_BUILD_DIR $SDK_DIR
+		$SDK_DIR/host/relocate-sdk.sh
+	fi
+	export SDK_DIR
+}
+
 if [ -z "${PLATFORM_LIST}" ]; then
         echo "Using all the defconfigs for all the platforms"
         DEFCONFIGS=`(cd openpower/configs; ls -1 *_defconfig)`
@@ -90,26 +224,50 @@
 for i in ${DEFCONFIGS[@]}; do
 	export O=${OUTDIR}/$i
 	rm -rf $O
-        op-build O=$O $i
-	./buildroot/utils/config --file $O/.config --enable CCACHE \
-		--set-str CCACHE_DIR $CCACHE_DIR
-	if [ -d "$SDK_DIR" ]; then
-	    ./buildroot/utils/config --file $O/.config --enable TOOLCHAIN_EXTERNAL \
-		    --set-str TOOLCHAIN_EXTERNAL_PATH $SDK_DIR \
-		    --enable TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC \
-		    --enable TOOLCHAIN_EXTERNAL_CXX
-	    # FIXME: How do we work this out programatically?
-	    ./buildroot/utils/config --file $O/.config --enable BR2_TOOLCHAIN_EXTERNAL_GCC_6
 
-	    KERNEL_VER=$(./buildroot/utils/config --file $O/.config --state BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE)
-	    echo "KERNEL_VER " $KERNEL_VER
-	    HEADERS=BR2_TOOLCHAIN_EXTERNAL_HEADERS_$(get_kernel_release $KERNEL_VER)
-	    ./buildroot/utils/config --file $O/.config --set-val $HEADERS y
+	SDK_DIR=""
+	build_sdk $i $SDK_CACHE
+	if [ $? -ne 0 ]; then
+		echo "Error building SDK"
+		exit 1
 	fi
+
+	if [ $SDK_ONLY -ne 0 ]; then
+		continue
+	fi
+
+        op-build O=$O $i
+	buildroot/utils/config --file $O/.config --enable CCACHE \
+		--set-str CCACHE_DIR $CCACHE_DIR
+	buildroot/utils/config --file $O/.config --enable TOOLCHAIN_EXTERNAL \
+		--set-str TOOLCHAIN_EXTERNAL_PATH $SDK_DIR/host \
+		--enable TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC
+
+	# Our SDK will always have CPP enabled, but avoid potentially
+	# diverging with the Full build by only enabling it
+	# conditionally
+	CPP_REQUIRED=$(buildroot/utils/config --file $O/.config --state INSTALL_LIBSTDCPP)
+	if [ "$CPP_REQUIRED" = "y" ]; then
+		buildroot/utils/config --file $O/.config --enable TOOLCHAIN_EXTERNAL_CXX
+	fi
+
+	# The Kernel Headers requested MUST be the same as the one
+	# provided by the SDK (i.e., it's part of the hash)
+	HEADERS_VER=$(buildroot/utils/config --file $O/.config --state TOOLCHAIN_HEADERS_AT_LEAST)
+	echo "Toolchain Headers Version Requested: $HEADERS_VER"
+	HEADERS="TOOLCHAIN_EXTERNAL_HEADERS_$(get_major_minor_release $HEADERS_VER)"
+	buildroot/utils/config --file $O/.config --enable "$HEADERS"
+
+	# Same for the GCC version
+	EXTERNAL_GCC_VER=$(buildroot/utils/config --file $O/.config --state GCC_VERSION)
+	echo "GCC Version Requested: $EXTERNAL_GCC_VER"
+	EXTERNAL_GCC="TOOLCHAIN_EXTERNAL_GCC_$(get_major_release $EXTERNAL_GCC_VER)"
+	buildroot/utils/config --file $O/.config --enable "$EXTERNAL_GCC"
+
         op-build O=$O olddefconfig
         op-build O=$O
         r=$?
-	if [ ${BUILD_INFO} = 1 ] && [ $r = 0 ]; then
+	if [ ${BUILD_INFO} -eq 1 ] && [ $r -eq 0 ]; then
 	    op-build O=$O legal-info
 	    op-build O=$O graph-build
 	    op-build O=$O graph-size
diff --git a/ci/build-sdk.sh b/ci/build-sdk.sh
deleted file mode 100755
index f2a312a..0000000
--- a/ci/build-sdk.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-
-set -ex
-set -eo pipefail
-
-if [ -z "$1" ]; then
-	echo "No build distro specified"
-	exit 1;
-fi
-
-if [ -z "$2" ]; then
-	echo "No defconfig to build SDK from specified"
-	exit 1;
-fi
-
-if [ -z "$CCACHE_DIR" ]; then
-	CCACHE_DIR=`pwd`/.op-build_ccache
-fi
-
-shopt -s expand_aliases
-source op-build-env
-
-if [ -n "$DL_DIR" ]; then
-	unset BR2_DL_DIR
-	export BR2_DL_DIR=${DL_DIR}
-fi
-
-export O=`pwd`/output-$1-$2/
-op-build O=$O $2
-./buildroot/utils/config --file $O/.config --enable CCACHE
-./buildroot/utils/config --file $O/.config --set-str CCACHE_DIR $CCACHE_DIR
-
-# Disable things not necessary for the sdk
-# (Buildroot manual section 6.1.3)
-./buildroot/utils/config --file $O/.config --disable INIT_BUSYBOX \
-	--enable INIT_NONE \
-	--disable SYSTEM_BIN_SH_BUSYBOX \
-	--disable TARGET_ROOTFS_TAR
-
-# Additionally, disable OpenPower packages and
-# ROOTFS stuff that we won't need
-./buildroot/utils/config --file $O/.config --disable OPENPOWER_PLATFORM \
-	--undefine ROOTFS_USERS_TABLES \
-	--undefine ROOTFS_OVERLAY \
-	--undefine ROOTFS_POST_BUILD_SCRIPT \
-	--undefine ROOTFS_POST_FAKEROOT_SCRIPT \
-	--undefine ROOTFS_POST_IMAGE_SCRIPT \
-	--undefine ROOTFS_POST_SCRIPT_ARGS
-
-op-build O=$O olddefconfig
-
-if [ -f "$(ldconfig -p | grep libeatmydata.so | tr ' ' '\n' | grep /|head -n1)" ]; then
-    export LD_PRELOAD=${LD_PRELOAD:+"$LD_PRELOAD "}libeatmydata.so
-elif [ -f "/usr/lib64/nosync/nosync.so" ]; then
-    export LD_PRELOAD=${LD_PRELOAD:+"$LD_PRELOAD "}/usr/lib64/nosync/nosync.so
-fi
-
-op-build O=$O sdk
diff --git a/ci/build.sh b/ci/build.sh
index a0430df..e0acc1a 100755
--- a/ci/build.sh
+++ b/ci/build.sh
@@ -7,7 +7,7 @@
 SDK_ONLY=0
 
 opt=$(getopt -o 's:Sab:p:c:hr' -- "$@")
-if [ $? != 0 ] ; then
+if [ $? -ne 0 ] ; then
 	echo "Invalid arguments"
 	exit 1
 fi
@@ -96,10 +96,6 @@
          -t $1 $2
 }
 
-function toolchain_hash
-{
-    echo -n 'toolchain-'$((git submodule ; cd openpower/configs/; cat `ls -1 |grep '_defconfig$'|sort`)|sha1sum |sed -e 's/ .*//')
-}
 
 env
 
@@ -144,15 +140,6 @@
 EOF
 		  )
 	$DOCKER_PREFIX docker build --network=host -t openpower/op-build-$distro - <<< "${Dockerfile}"
-	SDK_DIR=$SDK_CACHE/$(toolchain_hash)-$distro
-	if [ ! -d "$SDK_DIR" ]; then
-	    chmod +x ci/build-sdk.sh
-	    run_docker openpower/op-build-$distro "./ci/build-sdk.sh $distro witherspoon_defconfig"
-	    mv output-$distro-witherspoon_defconfig $SDK_DIR
-	    $SDK_DIR/host/relocate-sdk.sh
-	fi
-
-	sdk_args="-s $SDK_DIR/host"
 
 	if [ -n "$PLATFORMS" ]; then
 	    platform_args="-p $PLATFORMS"
@@ -160,11 +147,15 @@
 	    platform_args=""
 	fi
 
-	if [ $SDK_ONLY == 0 ]; then
-	    run_docker openpower/op-build-$distro "./ci/build-all-defconfigs.sh -o `pwd`/output-$distro ${platform_args} ${release_args} ${sdk_args}"
+	if [ $SDK_ONLY -ne 0 ]; then
+	    sdk_args="-S"
+	else
+	    sdk_args=""
 	fi
 
-	if [ $? != 0 ]; then
+	run_docker openpower/op-build-$distro "./ci/build-all-defconfigs.sh -o `pwd`/output-$distro ${platform_args} ${release_args} ${sdk_args} -s $SDK_CACHE"
+
+	if [ $? -ne 0 ]; then
 		exit $?;
 	fi
 done;