From c0616f10171cc83e7c69697ec275b112b7ab1184 Mon Sep 17 00:00:00 2001 From: Cosmin Truta Date: Mon, 3 Jul 2023 22:59:24 +0300 Subject: [PATCH] ci: Add ci.lib.ch; update ci_verify_*.sh accordingly Move the common declarations and initializations from ci_verify_*.sh to ci.lib.sh, and update them as follows: * Simplify the ci_ function names. * Refactor the CI_ variable names: - Add the new variable CI_TOPLEVEL_DIR. - Rename the variables CI_SCRIPTNAME, CI_SCRIPTDIR, etc., to CI_SCRIPT_NAME, CI_SCRIPT_DIR, etc. - Rename the variables CI_SRCDIR_FROM_BUILDDIR, etc., to CI_BUILD_TO_SRC_RELDIR, etc. * Add new functions inside ci.lib.sh: - Replace ci_err with ci_err_usage, ci_err_fatal, ci_err_internal. - Add the new functions ci_warn and ci_assert. * Simplify the ci_ function names inside ci_verify_*.sh. --- ci/ci_verify_cmake.sh | 88 ++++++++++++++++----------------------- ci/ci_verify_configure.sh | 72 +++++++++++++------------------- ci/ci_verify_makefiles.sh | 57 ++++++++++--------------- ci/lib/ci.lib.sh | 69 ++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 130 deletions(-) create mode 100644 ci/lib/ci.lib.sh diff --git a/ci/ci_verify_cmake.sh b/ci/ci_verify_cmake.sh index f2ecc50c2..9fdd03147 100755 --- a/ci/ci_verify_cmake.sh +++ b/ci/ci_verify_cmake.sh @@ -10,37 +10,20 @@ set -e # # SPDX-License-Identifier: BSL-1.0 -CI_SCRIPTNAME="$(basename "$0")" -CI_SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)" -CI_SRCDIR="$(dirname "$CI_SCRIPTDIR")" -CI_BUILDDIR="$CI_SRCDIR/out/ci_verify_cmake.build" -CI_INSTALLDIR="$CI_SRCDIR/out/ci_verify_cmake.install" +source "$(dirname "$0")/lib/ci.lib.sh" +cd "$CI_TOPLEVEL_DIR" + +CI_SRC_DIR="$CI_TOPLEVEL_DIR" +CI_BUILD_DIR="$CI_TOPLEVEL_DIR/out/ci_verify_cmake.build" +CI_INSTALL_DIR="$CI_TOPLEVEL_DIR/out/ci_verify_cmake.install" # Keep the following relative paths in sync with the absolute paths. # We use them for the benefit of native Windows tools that might be # otherwise confused by the path encoding used by Bash-on-Windows. -CI_SRCDIR_FROM_BUILDDIR="../.." -CI_INSTALLDIR_FROM_BUILDDIR="../ci_verify_cmake.install" +CI_BUILD_TO_SRC_RELDIR="../.." +CI_BUILD_TO_INSTALL_RELDIR="../ci_verify_cmake.install" -function ci_info { - printf >&2 "%s: %s\\n" "$CI_SCRIPTNAME" "$*" -} - -function ci_err { - printf >&2 "%s: error: %s\\n" "$CI_SCRIPTNAME" "$*" - exit 2 -} - -function ci_spawn { - printf >&2 "%s: executing:" "$CI_SCRIPTNAME" - printf >&2 " %q" "$@" - printf >&2 "\\n" - "$@" -} - -function ci_init_cmake_build { - CI_SYSTEM_NAME="$(uname -s)" - CI_MACHINE_NAME="$(uname -m)" +function ci_init_build { CI_CMAKE="${CI_CMAKE:-cmake}" CI_CTEST="${CI_CTEST:-ctest}" CI_CMAKE_BUILD_TYPE="${CI_CMAKE_BUILD_TYPE:-Release}" @@ -58,13 +41,13 @@ function ci_init_cmake_build { fi } -function ci_trace_cmake_build { +function ci_trace_build { ci_info "## START OF CONFIGURATION ##" ci_info "system name: $CI_SYSTEM_NAME" ci_info "machine hardware name: $CI_MACHINE_NAME" - ci_info "source directory: $CI_SRCDIR" - ci_info "build directory: $CI_BUILDDIR" - ci_info "install directory: $CI_INSTALLDIR" + ci_info "source directory: $CI_SRC_DIR" + ci_info "build directory: $CI_BUILD_DIR" + ci_info "install directory: $CI_INSTALL_DIR" ci_info "environment option: \$CI_CMAKE: '$CI_CMAKE'" ci_info "environment option: \$CI_CMAKE_GENERATOR: '$CI_CMAKE_GENERATOR'" ci_info "environment option: \$CI_CMAKE_GENERATOR_PLATFORM: '$CI_CMAKE_GENERATOR_PLATFORM'" @@ -93,14 +76,17 @@ function ci_trace_cmake_build { ci_info "## END OF CONFIGURATION ##" } -function ci_cleanup_old_cmake_build { - [[ ! -e $CI_BUILDDIR ]] || - ci_spawn rm -fr "$CI_BUILDDIR" - [[ ! -e $CI_INSTALLDIR ]] || - ci_spawn rm -fr "$CI_INSTALLDIR" +function ci_cleanup_old_build { + if [[ -e $CI_BUILD_DIR || -e $CI_INSTALL_DIR ]] + then + ci_info "## START OF PRE-BUILD CLEANUP ##" + ci_spawn rm -fr "$CI_BUILD_DIR" + ci_spawn rm -fr "$CI_INSTALL_DIR" + ci_info "## END OF PRE-BUILD CLEANUP ##" + fi } -function ci_build_cmake { +function ci_build { ci_info "## START OF BUILD ##" ci_spawn "$(command -v "$CI_CMAKE")" --version ci_spawn "$(command -v "$CI_CTEST")" --version @@ -135,18 +121,16 @@ function ci_build_cmake { [[ $CI_CMAKE_GENERATOR_PLATFORM ]] && ci_spawn export CMAKE_GENERATOR_PLATFORM="$CI_CMAKE_GENERATOR_PLATFORM" # Build and install. - # Use $CI_SRCDIR_FROM_BUILDDIR and $CI_INSTALLDIR_FROM_BUILDDIR - # instead of $CI_SRCDIR and $CI_INSTALLDIR from this point onwards. - ci_spawn mkdir -p "$CI_BUILDDIR" - ci_spawn cd "$CI_BUILDDIR" - [[ $CI_SRCDIR -ef $CI_SRCDIR_FROM_BUILDDIR ]] || - ci_err "assertion failed: testing: '$CI_SRCDIR' -ef '$CI_SRCDIR_FROM_BUILDDIR'" - ci_spawn mkdir -p "$CI_INSTALLDIR" - [[ $CI_INSTALLDIR -ef $CI_INSTALLDIR_FROM_BUILDDIR ]] || - ci_err "assertion failed: testing: '$CI_INSTALLDIR' -ef '$CI_INSTALLDIR_FROM_BUILDDIR'" - ci_spawn "$CI_CMAKE" -DCMAKE_INSTALL_PREFIX="$CI_INSTALLDIR_FROM_BUILDDIR" \ + # Use $CI_BUILD_TO_SRC_RELDIR and $CI_BUILD_TO_INSTALL_RELDIR + # instead of $CI_SRC_DIR and $CI_INSTALL_DIR from this point onwards. + ci_spawn mkdir -p "$CI_BUILD_DIR" + ci_spawn cd "$CI_BUILD_DIR" + ci_assert "$CI_SRC_DIR" -ef "$CI_BUILD_TO_SRC_RELDIR" + ci_spawn mkdir -p "$CI_INSTALL_DIR" + ci_assert "$CI_INSTALL_DIR" -ef "$CI_BUILD_TO_INSTALL_RELDIR" + ci_spawn "$CI_CMAKE" -DCMAKE_INSTALL_PREFIX="$CI_BUILD_TO_INSTALL_RELDIR" \ "${ALL_CMAKE_VARS[@]}" \ - "$CI_SRCDIR_FROM_BUILDDIR" + "$CI_BUILD_TO_SRC_RELDIR" ci_spawn "$CI_CMAKE" --build . \ --config "$CI_CMAKE_BUILD_TYPE" \ "${ALL_CMAKE_BUILD_FLAGS[@]}" @@ -169,12 +153,12 @@ function ci_build_cmake { function main { [[ $# -eq 0 ]] || { ci_info "note: this program accepts environment options only" - ci_err "unexpected command arguments: '$*'" + ci_err "unsupported command argument: '$1'" } - ci_init_cmake_build - ci_trace_cmake_build - ci_cleanup_old_cmake_build - ci_build_cmake + ci_init_build + ci_trace_build + ci_cleanup_old_build + ci_build } main "$@" diff --git a/ci/ci_verify_configure.sh b/ci/ci_verify_configure.sh index 74e5f93f6..96ada92ea 100755 --- a/ci/ci_verify_configure.sh +++ b/ci/ci_verify_configure.sh @@ -10,47 +10,30 @@ set -e # # SPDX-License-Identifier: BSL-1.0 -CI_SCRIPTNAME="$(basename "$0")" -CI_SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)" -CI_SRCDIR="$(dirname "$CI_SCRIPTDIR")" -CI_BUILDDIR="$CI_SRCDIR/out/ci_verify_configure.build" -CI_INSTALLDIR="$CI_SRCDIR/out/ci_verify_configure.install" +source "$(dirname "$0")/lib/ci.lib.sh" +cd "$CI_TOPLEVEL_DIR" -function ci_info { - printf >&2 "%s: %s\\n" "$CI_SCRIPTNAME" "$*" -} +CI_SRC_DIR="$CI_TOPLEVEL_DIR" +CI_BUILD_DIR="$CI_TOPLEVEL_DIR/out/ci_verify_configure.build" +CI_INSTALL_DIR="$CI_TOPLEVEL_DIR/out/ci_verify_configure.install" -function ci_err { - printf >&2 "%s: error: %s\\n" "$CI_SCRIPTNAME" "$*" - exit 2 -} - -function ci_spawn { - printf >&2 "%s: executing:" "$CI_SCRIPTNAME" - printf >&2 " %q" "$@" - printf >&2 "\\n" - "$@" -} - -function ci_init_configure_build { - CI_SYSTEM_NAME="$(uname -s)" - CI_MACHINE_NAME="$(uname -m)" +function ci_init_build { CI_MAKE="${CI_MAKE:-make}" # Set CI_CC to cc by default, if the cc command is available. # The configure script defaults CC to gcc, which is not always a good idea. [[ -x $(command -v cc) ]] && CI_CC="${CI_CC:-cc}" # Ensure that the CI_ variables that cannot be customized reliably are not initialized. - [[ ! $CI_CONFIGURE_VARS ]] || ci_err "unexpected: \$CI_CONFIGURE_VARS='$CI_CONFIGURE_VARS'" - [[ ! $CI_MAKE_VARS ]] || ci_err "unexpected: \$CI_MAKE_VARS='$CI_MAKE_VARS'" + [[ ! $CI_CONFIGURE_VARS ]] || ci_err "unsupported: \$CI_CONFIGURE_VARS='$CI_CONFIGURE_VARS'" + [[ ! $CI_MAKE_VARS ]] || ci_err "unsupported: \$CI_MAKE_VARS='$CI_MAKE_VARS'" } -function ci_trace_configure_build { +function ci_trace_build { ci_info "## START OF CONFIGURATION ##" ci_info "system name: $CI_SYSTEM_NAME" ci_info "machine hardware name: $CI_MACHINE_NAME" - ci_info "source directory: $CI_SRCDIR" - ci_info "build directory: $CI_BUILDDIR" - ci_info "install directory: $CI_INSTALLDIR" + ci_info "source directory: $CI_SRC_DIR" + ci_info "build directory: $CI_BUILD_DIR" + ci_info "install directory: $CI_INSTALL_DIR" ci_info "environment option: \$CI_CONFIGURE_FLAGS: '$CI_CONFIGURE_FLAGS'" ci_info "environment option: \$CI_MAKE: '$CI_MAKE'" ci_info "environment option: \$CI_MAKE_FLAGS: '$CI_MAKE_FLAGS'" @@ -80,14 +63,17 @@ function ci_trace_configure_build { ci_info "## END OF CONFIGURATION ##" } -function ci_cleanup_old_configure_build { - [[ ! -e $CI_BUILDDIR ]] || - ci_spawn rm -fr "$CI_BUILDDIR" - [[ ! -e $CI_INSTALLDIR ]] || - ci_spawn rm -fr "$CI_INSTALLDIR" +function ci_cleanup_old_build { + if [[ -e $CI_BUILD_DIR || -e $CI_INSTALL_DIR ]] + then + ci_info "## START OF PRE-BUILD CLEANUP ##" + ci_spawn rm -fr "$CI_BUILD_DIR" + ci_spawn rm -fr "$CI_INSTALL_DIR" + ci_info "## END OF PRE-BUILD CLEANUP ##" + fi } -function ci_build_configure { +function ci_build { ci_info "## START OF BUILD ##" # Export the configure build environment. [[ $CI_CC ]] && ci_spawn export CC="$CI_CC" @@ -103,9 +89,9 @@ function ci_build_configure { ci_spawn export LDFLAGS="-fsanitize=$CI_SANITIZERS $LDFLAGS" } # Build and install. - ci_spawn mkdir -p "$CI_BUILDDIR" - ci_spawn cd "$CI_BUILDDIR" - ci_spawn "$CI_SRCDIR/configure" --prefix="$CI_INSTALLDIR" $CI_CONFIGURE_FLAGS + ci_spawn mkdir -p "$CI_BUILD_DIR" + ci_spawn cd "$CI_BUILD_DIR" + ci_spawn "$CI_SRC_DIR/configure" --prefix="$CI_INSTALL_DIR" $CI_CONFIGURE_FLAGS ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS [[ $CI_NO_TEST ]] || ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS test [[ $CI_NO_INSTALL ]] || ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS install @@ -117,12 +103,12 @@ function ci_build_configure { function main { [[ $# -eq 0 ]] || { ci_info "note: this program accepts environment options only" - ci_err "unexpected command arguments: '$*'" + ci_err "unsupported command argument: '$1'" } - ci_init_configure_build - ci_trace_configure_build - ci_cleanup_old_configure_build - ci_build_configure + ci_init_build + ci_trace_build + ci_cleanup_old_build + ci_build } main "$@" diff --git a/ci/ci_verify_makefiles.sh b/ci/ci_verify_makefiles.sh index 554df989b..fc05d27f7 100755 --- a/ci/ci_verify_makefiles.sh +++ b/ci/ci_verify_makefiles.sh @@ -10,29 +10,12 @@ set -e # # SPDX-License-Identifier: BSL-1.0 -CI_SCRIPTNAME="$(basename "$0")" -CI_SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)" -CI_SRCDIR="$(dirname "$CI_SCRIPTDIR")" +source "$(dirname "$0")/lib/ci.lib.sh" +cd "$CI_TOPLEVEL_DIR" -function ci_info { - printf >&2 "%s: %s\\n" "$CI_SCRIPTNAME" "$*" -} +CI_SRC_DIR="$CI_TOPLEVEL_DIR" -function ci_err { - printf >&2 "%s: error: %s\\n" "$CI_SCRIPTNAME" "$*" - exit 2 -} - -function ci_spawn { - printf >&2 "%s: executing:" "$CI_SCRIPTNAME" - printf >&2 " %q" "$@" - printf >&2 "\\n" - "$@" -} - -function ci_init_makefiles_build { - CI_SYSTEM_NAME="$(uname -s)" - CI_MACHINE_NAME="$(uname -m)" +function ci_init_build { CI_MAKE="${CI_MAKE:-make}" case "$CI_CC" in ( *clang* ) @@ -44,11 +27,11 @@ function ci_init_makefiles_build { esac } -function ci_trace_makefiles_build { +function ci_trace_build { ci_info "## START OF CONFIGURATION ##" ci_info "system name: $CI_SYSTEM_NAME" ci_info "machine hardware name: $CI_MACHINE_NAME" - ci_info "source directory: $CI_SRCDIR" + ci_info "source directory: $CI_SRC_DIR" ci_info "environment option: \$CI_MAKEFILES: '$CI_MAKEFILES'" ci_info "environment option: \$CI_MAKE: '$CI_MAKE'" ci_info "environment option: \$CI_MAKE_FLAGS: '$CI_MAKE_FLAGS'" @@ -79,20 +62,24 @@ function ci_trace_makefiles_build { ci_info "## END OF CONFIGURATION ##" } -function ci_cleanup_old_makefiles_build { +function ci_cleanup_old_build { # Any old makefile-based build will most likely leave a mess # of object files behind if interrupted, e.g., via Ctrl+C. # There may be other files behind, depending on what makefile # had been used. We cannot easily enumerate all of those. # Fortunately, for a clean makefiles-based build, it should be # sufficient to remove the old object files only. - [[ -z $(find "$CI_SRCDIR" -maxdepth 1 -name "*.o") ]] || - ci_spawn rm -f "$CI_SRCDIR"/*.o - [[ -z $(find "$CI_SRCDIR" -maxdepth 1 -name "*.obj") ]] || - ci_spawn rm -f "$CI_SRCDIR"/*.obj + ci_info "## START OF PRE-BUILD CLEANUP ##" + local MY_FILE + find "$CI_SRC_DIR" -maxdepth 1 \( -iname "*.o" -o -iname "*.obj" \) | + while IFS="" read -r MY_FILE + do + ci_spawn rm -fr "$MY_FILE" + done + ci_info "## END OF PRE-BUILD CLEANUP ##" } -function ci_build_makefiles { +function ci_build { ci_info "## START OF BUILD ##" # Initialize ALL_CC_FLAGS and ALL_LD_FLAGS as strings. local ALL_CC_FLAGS="$CI_CC_FLAGS" @@ -118,7 +105,7 @@ function ci_build_makefiles { [[ $CI_LIBS ]] && ALL_MAKE_VARS+=(LIBS="$CI_LIBS") ALL_MAKE_VARS+=($CI_MAKE_VARS) # Build! - cd "$CI_SRCDIR" + ci_assert "$CI_SRC_DIR" -ef . local MY_MAKEFILE for MY_MAKEFILE in $CI_MAKEFILES do @@ -143,12 +130,12 @@ function ci_build_makefiles { function main { [[ $# -eq 0 ]] || { ci_info "note: this program accepts environment options only" - ci_err "unexpected command arguments: '$*'" + ci_err "unsupported command argument: '$1'" } - ci_init_makefiles_build - ci_trace_makefiles_build - ci_cleanup_old_makefiles_build - ci_build_makefiles + ci_init_build + ci_trace_build + ci_cleanup_old_build + ci_build } main "$@" diff --git a/ci/lib/ci.lib.sh b/ci/lib/ci.lib.sh new file mode 100644 index 000000000..e1586d1d9 --- /dev/null +++ b/ci/lib/ci.lib.sh @@ -0,0 +1,69 @@ +# Copyright (c) 2019-2023 Cosmin Truta. +# +# Use, modification and distribution are subject +# to the Boost Software License, Version 1.0. +# See the accompanying file LICENSE_BSL_1_0.txt +# or visit http://www.boost.org/LICENSE_1_0.txt +# +# SPDX-License-Identifier: BSL-1.0 + +test -f "$BASH_SOURCE" || + echo >&2 "warning: this module requires Bash version 3 or newer" +test "${#BASH_SOURCE[@]}" -gt 1 || + echo >&2 "warning: this module should be sourced from a Bash script" + +# Reset the locale to avoid surprises from locale-dependent commands. +export LC_ALL=C +export LANG=C +export LANGUAGE=C + +# Reset CDPATH to avoid surprises from the "cd" command. +export CDPATH="" + +# Initialize the global constants CI_SCRIPT_{NAME,DIR} and CI_TOPLEVEL_DIR. +CI_SCRIPT_NAME="$(basename -- "$0")" +CI_SCRIPT_DIR="$(cd "$(dirname -- "$0")" && pwd)" +CI_TOPLEVEL_DIR="$(cd "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)" + +# Initialize the global constants CI_{HOST,TARGET}_{SYSTEM,MACHINE}. +CI_SYSTEM_NAME="${CI_SYSTEM_NAME:-"$(uname -s)"}" +CI_MACHINE_NAME="${CI_MACHINE_NAME:-"$(uname -m)"}" + +function ci_info { + printf >&2 "%s: %s\\n" "$CI_SCRIPT_NAME" "$*" +} + +function ci_warn { + printf >&2 "%s: warning: %s\\n" "$CI_SCRIPT_NAME" "$*" +} + +function ci_err { + printf >&2 "%s: error: %s\\n" "$CI_SCRIPT_NAME" "$*" + exit 2 +} + +function ci_err_internal { + printf >&2 "%s: internal error: %s\\n" "$CI_SCRIPT_NAME" "$*" + printf >&2 "ABORTED\\n" + # Exit with the conventional SIGABRT code. + exit 134 +} + +function ci_assert { + # Use the "test" built-in command instead of the "[[ ]]" syntax, + # to ensure the a-priori expansion of all assertion arguments. + # (Consistently, both "ci_assert" and "test" have a command-like behavior.) + test "$@" || ci_err_internal "failed:" test "$@" +} + +function ci_spawn { + printf >&2 "%s: executing:" "$CI_SCRIPT_NAME" + printf >&2 " %q" "$@" + printf >&2 "\\n" + "$@" +} + +# Ensure that the initialization is correct. +ci_assert "$CI_TOPLEVEL_DIR/ci/lib/ci.lib.sh" -ef "${BASH_SOURCE[0]}" +ci_assert "$CI_SCRIPT_DIR/$CI_SCRIPT_NAME" -ef "$0" +ci_assert -n "$CI_SYSTEM_NAME" -a -n "$CI_MACHINE_NAME"