1#!/usr/bin/env bash 2set -o errexit -o pipefail -o posix 3 4# Copyright (c) 2019-2024 Cosmin Truta. 5# 6# Use, modification and distribution are subject to the MIT License. 7# Please see the accompanying file LICENSE_MIT.txt 8# 9# SPDX-License-Identifier: MIT 10 11# shellcheck source=ci/lib/ci.lib.sh 12source "$(dirname "$0")/lib/ci.lib.sh" 13cd "$CI_TOPLEVEL_DIR" 14 15CI_SRC_DIR="$CI_TOPLEVEL_DIR" 16CI_OUT_DIR="$CI_TOPLEVEL_DIR/out" 17CI_BUILD_DIR="$CI_OUT_DIR/ci_verify_configure.$CI_TARGET_SYSTEM.$CI_TARGET_ARCH.build" 18CI_INSTALL_DIR="$CI_OUT_DIR/ci_verify_configure.$CI_TARGET_SYSTEM.$CI_TARGET_ARCH.install" 19 20function ci_init_build { 21 # Ensure that the mandatory variables are initialized. 22 CI_MAKE="${CI_MAKE:-make}" 23 [[ "$CI_TARGET_SYSTEM.$CI_TARGET_ARCH" != "$CI_BUILD_SYSTEM.$CI_BUILD_ARCH" ]] || { 24 # For native builds, set CI_CC to "cc" by default if the cc command is available. 25 # The configure script defaults CC to "gcc", which is not always a good idea. 26 [[ -x $(command -v cc) ]] && CI_CC="${CI_CC:-cc}" 27 } 28 # Ensure that the CI_ variables that cannot be customized reliably are not initialized. 29 [[ ! $CI_CONFIGURE_VARS ]] || { 30 ci_err "unsupported: \$CI_CONFIGURE_VARS='$CI_CONFIGURE_VARS'" 31 } 32 [[ ! $CI_MAKE_VARS ]] || { 33 ci_err "unsupported: \$CI_MAKE_VARS='$CI_MAKE_VARS'" 34 } 35} 36 37function ci_trace_build { 38 ci_info "## START OF CONFIGURATION ##" 39 ci_info "build arch: $CI_BUILD_ARCH" 40 ci_info "build system: $CI_BUILD_SYSTEM" 41 [[ "$CI_TARGET_SYSTEM.$CI_TARGET_ARCH" != "$CI_BUILD_SYSTEM.$CI_BUILD_ARCH" ]] && { 42 ci_info "target arch: $CI_TARGET_ARCH" 43 ci_info "target system: $CI_TARGET_SYSTEM" 44 } 45 ci_info "source directory: $CI_SRC_DIR" 46 ci_info "build directory: $CI_BUILD_DIR" 47 ci_info "install directory: $CI_INSTALL_DIR" 48 ci_info "environment option: \$CI_CONFIGURE_FLAGS: '$CI_CONFIGURE_FLAGS'" 49 ci_info "environment option: \$CI_MAKE: '$CI_MAKE'" 50 ci_info "environment option: \$CI_MAKE_FLAGS: '$CI_MAKE_FLAGS'" 51 ci_info "environment option: \$CI_CC: '$CI_CC'" 52 ci_info "environment option: \$CI_CC_FLAGS: '$CI_CC_FLAGS'" 53 ci_info "environment option: \$CI_CPP: '$CI_CPP'" 54 ci_info "environment option: \$CI_CPP_FLAGS: '$CI_CPP_FLAGS'" 55 ci_info "environment option: \$CI_AR: '$CI_AR'" 56 ci_info "environment option: \$CI_RANLIB: '$CI_RANLIB'" 57 ci_info "environment option: \$CI_LD: '$CI_LD'" 58 ci_info "environment option: \$CI_LD_FLAGS: '$CI_LD_FLAGS'" 59 ci_info "environment option: \$CI_SANITIZERS: '$CI_SANITIZERS'" 60 ci_info "environment option: \$CI_FORCE: '$CI_FORCE'" 61 ci_info "environment option: \$CI_NO_TEST: '$CI_NO_TEST'" 62 ci_info "environment option: \$CI_NO_INSTALL: '$CI_NO_INSTALL'" 63 ci_info "environment option: \$CI_NO_CLEAN: '$CI_NO_CLEAN'" 64 ci_info "executable: \$CI_MAKE: $(command -V "$CI_MAKE")" 65 [[ $CI_CC ]] && { 66 ci_info "executable: \$CI_CC: $(command -V "$CI_CC")" 67 } 68 [[ $CI_CPP ]] && { 69 ci_info "executable: \$CI_CPP: $(command -V "$CI_CPP")" 70 } 71 [[ $CI_AR ]] && { 72 ci_info "executable: \$CI_AR: $(command -V "$CI_AR")" 73 } 74 [[ $CI_RANLIB ]] && { 75 ci_info "executable: \$CI_RANLIB: $(command -V "$CI_RANLIB")" 76 } 77 [[ $CI_LD ]] && { 78 ci_info "executable: \$CI_LD: $(command -V "$CI_LD")" 79 } 80 ci_info "## END OF CONFIGURATION ##" 81} 82 83function ci_cleanup_old_build { 84 ci_info "## START OF PRE-BUILD CLEANUP ##" 85 [[ ! -e $CI_BUILD_DIR && ! -e $CI_INSTALL_DIR ]] || { 86 ci_spawn rm -fr "$CI_BUILD_DIR" 87 ci_spawn rm -fr "$CI_INSTALL_DIR" 88 } 89 [[ ! -e "$CI_SRC_DIR/config.status" ]] || { 90 ci_warn "unexpected build configuration file: '$CI_SRC_DIR/config.status'" 91 if ci_expr $((CI_FORCE)) 92 then 93 # Delete the old config and (possibly) the old build. 94 ci_info "note: forcing an in-tree build cleanup" 95 if [[ -f $CI_SRC_DIR/Makefile ]] 96 then 97 ci_spawn make -C "$CI_SRC_DIR" distclean 98 else 99 ci_spawn rm -fr "$CI_SRC_DIR"/config.{log,status} 100 fi 101 else 102 # Alert the user, but do not delete their files. 103 ci_warn "the configure script might fail" 104 ci_info "hint: consider using the option \$CI_FORCE=1" 105 fi 106 } 107 ci_info "## END OF PRE-BUILD CLEANUP ##" 108} 109 110function ci_build { 111 ci_info "## START OF BUILD ##" 112 # Export the configure build environment. 113 [[ $CI_CC ]] && ci_spawn export CC="$CI_CC" 114 [[ $CI_CC_FLAGS ]] && ci_spawn export CFLAGS="$CI_CC_FLAGS" 115 [[ $CI_CPP ]] && ci_spawn export CPP="$CI_CPP" 116 [[ $CI_CPP_FLAGS ]] && ci_spawn export CPPFLAGS="$CI_CPP_FLAGS" 117 [[ $CI_AR ]] && ci_spawn export AR="$CI_AR" 118 [[ $CI_RANLIB ]] && ci_spawn export RANLIB="$CI_RANLIB" 119 [[ $CI_LD ]] && ci_spawn export LD="$CI_LD" 120 [[ $CI_LD_FLAGS ]] && ci_spawn export LDFLAGS="$CI_LD_FLAGS" 121 [[ $CI_SANITIZERS ]] && { 122 ci_spawn export CFLAGS="${CFLAGS:-"-O2"} -fsanitize=$CI_SANITIZERS" 123 ci_spawn export LDFLAGS="${LDFLAGS}${LDFLAGS:+" "}-fsanitize=$CI_SANITIZERS" 124 } 125 # And... build! 126 ci_spawn mkdir -p "$CI_BUILD_DIR" 127 ci_spawn cd "$CI_BUILD_DIR" 128 # Spawn "configure". 129 ci_spawn "$CI_SRC_DIR/configure" --prefix="$CI_INSTALL_DIR" $CI_CONFIGURE_FLAGS 130 # Spawn "make". 131 ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS 132 ci_expr $((CI_NO_TEST)) || { 133 # Spawn "make test" if testing is not disabled. 134 ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS test 135 } 136 ci_expr $((CI_NO_INSTALL)) || { 137 # Spawn "make install" if installation is not disabled. 138 ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS install 139 } 140 ci_expr $((CI_NO_CLEAN)) || { 141 # Spawn "make clean" and "make distclean" if cleaning is not disabled. 142 ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS clean 143 ci_spawn "$CI_MAKE" $CI_MAKE_FLAGS distclean 144 } 145 ci_info "## END OF BUILD ##" 146} 147 148function usage { 149 echo "usage: $CI_SCRIPT_NAME [<options>]" 150 echo "options: -?|-h|--help" 151 exit "${@:-0}" 152} 153 154function main { 155 local opt 156 while getopts ":" opt 157 do 158 # This ain't a while-loop. It only pretends to be. 159 [[ $1 == -[?h]* || $1 == --help || $1 == --help=* ]] && usage 0 160 ci_err "unknown option: '$1'" 161 done 162 shift $((OPTIND - 1)) 163 # And... go! 164 ci_init_build 165 ci_trace_build 166 [[ $# -eq 0 ]] || { 167 echo >&2 "error: unexpected argument: '$1'" 168 echo >&2 "note: this program accepts environment options only" 169 usage 2 170 } 171 ci_cleanup_old_build 172 ci_build 173} 174 175main "$@" 176