#!/bin/sh ### Automatic build configuration script for Dinit. ### This script generates an "mconfig" file suitable for building on the current system. ## Initial preparation set -eu cd "$(dirname "$0")" ## Helper functions # POSIX "echo" behaviour is unspecified behavior in some cases, for example # when the first argument is "-n" or backslash ("\"). # So, replace the shell built-in echo with a printf based function. # For more info see http://www.etalabs.net/sh_tricks.html echo() { IFS=" " printf %s\\n "$*" } info() { echo "$*" } sub_info() { echo " ... $*" } error() { >&2 echo "Error: $*" exit 1 } sub_error() { >&2 echo " ... Error: $*" exit 1 } # warning() have a built-in extra information feild which is optional # $1: Info, $2: Extra info (Optional) # NOTE: Always quote your warning() messages warning() { >&2 echo >&2 echo "Warning: $1" [ -n "${2:-}" ] && >&2 echo " ... $2" >&2 echo } cxx_works() { info Checking whether \""$1"\" is a working C++ compiler... if $CXX -o testfile.o testfile.cc; then rm -f testfile sub_info Yes. else rm -f testfile* sub_error It seems like \""$CXX"\" is not working a working C++ compiler. Please specify compiler. fi } # Test if the compiler accepts an argument (for compilation and link); if so add it to named variable. # $1 - the name of the variable to potentially add the argument to # $2 - the argument to add # CXX - the name of the compiler # CXXFLAGS, CXXFLAGS_EXTRA, LDFLAGS, LDFLAGS_EXTRA - any predetermined flags try_cxx_argument() { info Checking whether the compiler accepts "$2"... if $CXX $CXXFLAGS $2 $CXXFLAGS_EXTRA $LDFLAGS $LDFLAGS_EXTRA testfile.cc -o testfile > /dev/null 2>&1; then rm testfile sub_info Yes. eval "$1=\"\${$1} \$2\"" eval "$1=\${$1# }" return 0 else sub_info No. return 1 fi } try_ld_argument() { info Checking whether "$2" is accepted as a link-time option... if $CXX $CXXFLAGS $CXXFLAGS_EXTRA $LDFLAGS $LDFLAGS_EXTRA $2 testfile.cc -o testfile > /dev/null 2>&1; then sub_info Yes. eval "$1=\"\${$1} \$2\"" eval "$1=\${$1# }" else sub_info No. fi } try_both_argument() { info Checking whether the compiler/linker accepts "$3"... if $CXX $CXXFLAGS $CXXFLAGS_EXTRA $LDFLAGS $LDFLAGS_EXTRA $3 testfile.cc -o testfile > /dev/null 2>&1; then sub_info Yes. eval "$1=\"\${$1} \$3\"" eval "$1=\${$1# }" eval "$2=\"\${$2} \$3\"" eval "$2=\${$2# }" else sub_info No. fi } usage() { cat << _EOF Usage: $0 [OPTION]... Generates build configuration for Dinit. Defaults for the options are specified in brackets. -h, --help This help message. -q, --quiet Don't print normal messages, just errors. -c, --clear Clear mconfig and configure's temporary files. Target options: --platform=PLATFORM Set the platform manually (Just for cross-platform cross-compile!) [autodetected] Note: for all cross-compiles please specify correct CXX and CXX_FOR_BUILD! Installation directories: --prefix=PREFIX Main installation prefix [/usr] --exec-prefix=EPREFIX Main executables prefix [/] --sbindir=SBINDIR Dinit executables [EPREFIX/sbin] --mandir=MANDIR Dinit man-pages location [PREFIX/share/man] --syscontrolsocket=SOCKETPATH Dinitctl socket location [/run/dinitctl] on Linux systems [/var/run/dinitctl] on other systems Optional options: --enable-strip Strip debug information in installation process [Enabled] --disable-strip Don't strip debug information in installation process --shutdown-prefix=PREFIX Name prefix for shutdown, poweroff, reboot, halt programs [] --enable-shutdown Build shutdown, poweroff, reboot, halt programs [Enabled only on Linux systems] --disable-shutdown Don't build shutdown, poweroff, reboot, halt programs --enable-cgroups Enable Cgroups support [Enabled only on Linux based systems] --disable-cgroups Disable Cgroups support --enable-utmpx Enable manipulating the utmp/utmpx database via the related POSIX functions [guessed] --disable-utmpx Disable manipulating the utmp/utmpx database via the related POSIX functions --enable-initgroups Enable initialization of supplementary groups for run-as [Enabled] --disable-initgroups Disable initialization of supplementary groups for run-as --enable-auto-restart Enable auto-restart for services by default [Enabled] --disable-auto-restart Disable auto-restart for services by default --default-start-timeout=sec Default start-timeout for services [60] --default-stop-timeout=sec Default stop-timeout for services [10] Build variables: Note: build variables can be passed in the environment, or as $0 argument (as "var=VALUE"). Note: CXXFLAGS, TEST_CXXFLAGS, LDFLAGS and TEST_LDFLAGS by default will be set to options considered suitable for the platform, filtered to remove any options not supported by the compiler/linker. To disable this, specify the values explicitly (an empty string is accepted). To add options without removing the defaults, set the variable with _EXTRA appended to the name (eg CXXFLAGS_EXTRA). CXX C++ compiler CXX_FOR_BUILD C++ compiler generating code for the build system (for cross-compiles). CXXFLAGS_FOR_BUILD Flags to use when generating code for the build system. Defaults to the value of CXXFLAGS. CPPFLAGS_FOR_BUILD Preprocessor flags to use when generating code for the build system. Defaults to the value of CPPFLAGS. LDFLAGS_FOR_BUILD Link flags to use when generating code for the build system. Defaults to the value of LDFLAGS. CXXFLAGS Flags to use when compiling C++ code. CXXFLAGS_EXTRA Additional flags to use when compiling C++ code. TEST_CXXFLAGS Flags to use when compiling C++ code in tests. TEST_CXXFLAGS_EXTRA Additional flags to use when compiling C++ code in tests. CPPFLAGS Preprocessor flags to use when compiling C++ code. LDFLAGS Link flags. LDFLAGS_EXTRA Additional link flags. LDFLAGS_BASE Link flags to use in addition to any link-time optimisation (LTO)-related options. Set this to control link options without disabling LTO. Ignored if LDFLAGS is set. TEST_LDFLAGS Links flags when building test executables. TEST_LDFLAGS_EXTRA Additional link flags when building test executables. TEST_LDFLAGS_BASE Link flags to use when building test executables, in addition to LTO-releated options. Note: paths specified via --prefix/--exec-prefix/--sbindir/--mandir, and build variable values, must be escaped for use in a makefile and in shell commands. If there are spaces in paths it is recommended to prepend a backslash (\) to them. For example: ./configure --prefix="/home/my\ home" See BUILD file for more information. _EOF exit 0 } ## Don't take values from environment for these variables: for var in PREFIX \ EPREFIX \ SBINDIR \ MANDIR \ SHUTDOWN_PREFIX \ BUILD_SHUTDOWN \ SUPPORT_CGROUPS \ USE_UTMPX \ USE_INITGROUPS \ SYSCONTROLSOCKET \ STRIPOPTS do unset $var done ## Flag parser for arg in "$@"; do case "$arg" in -h|--help) usage ;; -q|--quiet) info() { true; } sub_info() { true; } warning() { true; } ;; -c|--clear) rm -f test* & rm -f mconfig && exit 0 ;; --platform=*) PLATFORM="${arg#*=}" && shift ;; --prefix=*) PREFIX="${arg#*=}" && shift ;; --exec-prefix=*) EPREFIX="${arg#*=}" && shift;; --sbindir=*) SBINDIR="${arg#*=}" && shift ;; --mandir=*) MANDIR="${arg#*=}" && shift ;; --default-start-timeout=*) DEFAULT_START_TIMEOUT="${arg#*=}" && shift ;; --default-stop-timeout=*) DEFAULT_STOP_TIMEOUT="${arg#*=}" && shift ;; --syscontrolsocket=*) SYSCONTROLSOCKET="${arg#*=}" && shift ;; --shutdown-prefix=*) SHUTDOWN_PREFIX="${arg#*=}" && shift ;; --enable-shutdown|--enable-shutdown=yes) BUILD_SHUTDOWN=yes ;; --disable-shutdown|--enable-shutdown=no) BUILD_SHUTDOWN=no ;; --enable-cgroups|--enable-cgroups=yes) SUPPORT_CGROUPS=1 ;; --disable-cgroups|--enable-cgroups=no) SUPPORT_CGROUPS=0 ;; --enable-utmpx|--enable-utmpx=yes) USE_UTMPX=1 ;; --disable-utmpx|--enable-utmpx=no) USE_UTMPX=0 ;; --enable-initgroups|--enable-initgroups=yes) USE_INITGROUPS=1 ;; --disable-initgroups|--enable-initgroups=no) USE_INITGROUPS=0 ;; --enable-auto-restart|--enable-auto-restart=yes) DEFAULT_AUTO_RESTART=true ;; --disable-auto-restart|--enable-auto-restart=no) DEFAULT_AUTO_RESTART=false ;; --enable-strip|--enable-strip=yes) STRIPOPTS="-s" ;; --disable-strip|--enable-strip=no) STRIPOPTS="" ;; CXX=*|CXX_FOR_BUILD=*|CXXFLAGS_FOR_BUILD=*|CPPFLAGS_FOR_BUILD=*\ |LDFLAGS_FOR_BUILD=*|CXXFLAGS=*|CXXFLAGS_EXTRA=*|TEST_CXXFLAGS=*\ |TEST_CXXFLAGS_EXTRA=*|LDFLAGS=*|LDFLAGS_EXTRA=*|TEST_LDFLAGS=*\ |TEST_LDFLAGS_EXTRA=*|CPPFLAGS=*|LDFLAGS_BASE=*|TEST_LDFLAGS_BASE=*) eval "${arg%%=*}=\${arg#*=}" ;; *=*) warning "Unknown variable: ${arg%%=*}" ;; *) warning "Unknown argument: $arg" ;; esac done ## Defaults for variables not specified by user : "${PLATFORM:=$(uname)}" : "${PREFIX:="/usr"}" : "${EPREFIX:="/"}" : "${SBINDIR:="${EPREFIX%%/}/sbin"}" : "${MANDIR:="${PREFIX%%/}/share/man"}" : "${SHUTDOWN_PREFIX:=""}" : "${CXXFLAGS_EXTRA:=""}" : "${TEST_CXXFLAGS_EXTRA:=""}" : "${CPPFLAGS:=""}" : "${LDFLAGS_EXTRA:=""}" : "${TEST_LDFLAGS_EXTRA:=""}" : "${DEFAULT_AUTO_RESTART:="true"}" : "${DEFAULT_START_TIMEOUT:="60"}" : "${DEFAULT_STOP_TIMEOUT:="10"}" : "${USE_INITGROUPS:="1"}" if [ "$PLATFORM" = "Linux" ]; then : "${BUILD_SHUTDOWN:="yes"}" : "${SUPPORT_CGROUPS:="1"}" : "${SYSCONTROLSOCKET:="/run/dinitctl"}" else : "${BUILD_SHUTDOWN:="no"}" : "${SUPPORT_CGROUPS:="0"}" : "${SYSCONTROLSOCKET:="/var/run/dinitctl"}" fi HAS_LTO="" ## Finalize $CXXFLAGS, $TEST_CXXFLAGS, $LDFLAGS, $TEST_LDFLAGS, $STRIPOPTS if [ -z "${CXXFLAGS+IS_SET}" ]; then CXXFLAGS="" AUTO_CXXFLAGS="true" else AUTO_CXXFLAGS="false" fi if [ -z "${TEST_CXXFLAGS+IS_SET}" ]; then TEST_CXXFLAGS="" AUTO_TEST_CXXFLAGS="true" else AUTO_TEST_CXXFLAGS="false" fi if [ -z "${LDFLAGS+IS_SET}" ]; then LDFLAGS="" AUTO_LDFLAGS="true" else AUTO_LDFLAGS="false" fi if [ -z "${TEST_LDFLAGS+IS_SET}" ]; then TEST_LDFLAGS="" AUTO_TEST_LDFLAGS="true" else AUTO_TEST_LDFLAGS="false" fi if [ -z "${LDFLAGS_BASE+IS_SET}" ]; then LDFLAGS_BASE="" AUTO_LDFLAGS_BASE="true" else AUTO_LDFLAGS=BASE="false" fi if [ -z "${TEST_LDFLAGS_BASE+IS_SET}" ]; then TEST_LDFLAGS_BASE="" AUTO_TEST_LDFLAGS_BASE="true" else AUTO_TEST_LDFLAGS=BASE="false" fi [ -z "${STRIPOPTS+IS_SET}" ] && STRIPOPTS="-s" ## Verify PLATFORM value if [ "$PLATFORM" != "Linux" ] && [ "$PLATFORM" != "FreeBSD" ] && \ [ "$PLATFORM" != "OpenBSD" ] && [ "$PLATFORM" != "Darwin" ]; then warning "$PLATFORM platform is unknown!" "Known Platforms are: Linux, FreeBSD, OpenBSD, Darwin" fi ## Create testfile.cc to test c++ compiler echo "int main(int argc, char **argv) { return 0; }" > testfile.cc || error Can\'t create temporary file ## Find and test C++ compiler if [ -z "${CXX:-}" ]; then info Checking C++ compiler... for guess in g++ clang++ c++; do if type "$guess" > /dev/null 2>&1; then CXX="$guess" sub_info "$CXX" break # Found fi done if [ -z "${CXX:-}" ]; then sub_error No C++ compiler found! # Not found fi fi cxx_works "$CXX" if [ -n "${CXX_FOR_BUILD:-}" ]; then cxx_works "$CXX_FOR_BUILD" fi ## Test compiler/linker supported arguments if [ "$AUTO_CXXFLAGS" = "true" ]; then if ! try_cxx_argument CXXFLAGS -std=c++11; then sub_error "The C++ compiler ($CXX) doesn't accept '-std=c++11' and may be too old." fi for argument in -Wall \ -Os \ -fno-plt do try_cxx_argument CXXFLAGS $argument || : done if [ "$PLATFORM" != "Darwin" ]; then try_cxx_argument CXXFLAGS -fno-rtti || : fi fi if [ "$AUTO_LDFLAGS" = "true" ] && [ "$AUTO_CXXFLAGS" = "true" ]; then if try_cxx_argument CXXFLAGS -flto; then HAS_LTO="true" else HAS_LTO="false" fi fi if [ "$AUTO_LDFLAGS_BASE" = true ] && [ "$PLATFORM" = FreeBSD ]; then try_ld_argument LDFLAGS_BASE -lrt fi if [ "$AUTO_TEST_LDFLAGS_BASE" = true ]; then TEST_LDFLAGS_BASE="\$(LDFLAGS_BASE)" established_TEST_LDFLAGS="$LDFLAGS_BASE" else established_TEST_LDFLAGS="$TEST_LDFLAGS_BASE" fi # Determine LDFLAGS/TEST_LDFLAGS. In the case of TEST_LDFLAGS we may still add sanitisation # options, shortly. if [ "$HAS_LTO" = true ]; then if [ "$AUTO_LDFLAGS" = true ]; then LDFLAGS="\$(LDFLAGS_BASE) \$(CXXFLAGS)" fi if [ "$AUTO_TEST_LDFLAGS" = true ]; then TEST_LDFLAGS="\$(TEST_LDFLAGS_BASE) \$(TEST_CXXFLAGS)" established_TEST_LDFLAGS="$established_TEST_LDFLAGS $TEST_CXXFLAGS" else established_TEST_LDFLAGS="$TEST_LDFLAGS" fi else # default LDFLAGS are just $(LDFLAGS_BASE) if [ "$AUTO_LDFLAGS" = true ]; then LDFLAGS="\$(LDFLAGS_BASE)" fi if [ "$AUTO_TEST_LDFLAGS" = true ]; then TEST_LDFLAGS="\$(TEST_LDFLAGS_BASE)" else established_TEST_LDFLAGS="$TEST_LDFLAGS" fi fi # Default for test flags (TEST_CXXFLAGS, TEST_LDFLAGS) is to use the build flags if [ "$AUTO_TEST_CXXFLAGS" = "true" ]; then TEST_CXXFLAGS="\$(CXXFLAGS)" established_TEST_CXXFLAGS="$CXXFLAGS" else established_TEST_CXXFLAGS="$TEST_CXXFLAGS" fi # Check whether sanitizers can be used for tests if [ "$AUTO_TEST_LDFLAGS" = "true" ] && [ "$AUTO_TEST_CXXFLAGS" = "true" ]; then if [ "$HAS_LTO" = true ]; then CXXFLAGS="$established_TEST_CXXFLAGS" CXXFLAGS_EXTRA="$TEST_CXXFLAGS_EXTRA" \ LDFLAGS="$established_TEST_LDFLAGS" LDFLAGS_EXTRA="$TEST_LDFLAGS_EXTRA" \ try_cxx_argument TEST_CXXFLAGS -fsanitize=address,undefined else CXXFLAGS="$established_TEST_CXXFLAGS" CXXFLAGS_EXTRA="$TEST_CXXFLAGS_EXTRA" \ LDFLAGS="$established_TEST_LDFLAGS" LDFLAGS_EXTRA="$TEST_LDFLAGS_EXTRA" \ try_both_argument TEST_CXXFLAGS TEST_LDFLAGS -fsanitize=address,undefined fi fi ## Create mconfig rm -f testfile* info Creating mconfig... cat << _EOF > mconfig ## Auto-generated by "$0" for "$PLATFORM" # All changes will be lost if "$0" is re-run. # See BUILD for help on all variables. # Installation path options. SBINDIR=$SBINDIR MANDIR=$MANDIR SYSCONTROLSOCKET=$SYSCONTROLSOCKET # General build options. CXX=$CXX CXXFLAGS=$CXXFLAGS CXXFLAGS_EXTRA=$CXXFLAGS_EXTRA TEST_CXXFLAGS=$TEST_CXXFLAGS TEST_CXXFLAGS_EXTRA=$TEST_CXXFLAGS_EXTRA CPPFLAGS=$CPPFLAGS LDFLAGS_BASE=$LDFLAGS_BASE LDFLAGS=$LDFLAGS LDFLAGS_EXTRA=$LDFLAGS_EXTRA TEST_LDFLAGS_BASE=$TEST_LDFLAGS_BASE TEST_LDFLAGS=$TEST_LDFLAGS TEST_LDFLAGS_EXTRA=$TEST_LDFLAGS_EXTRA BUILD_SHUTDOWN=$BUILD_SHUTDOWN STRIPOPTS=$STRIPOPTS # Feature settings SUPPORT_CGROUPS=$SUPPORT_CGROUPS USE_INITGROUPS=$USE_INITGROUPS # Optional settings SHUTDOWN_PREFIX=${SHUTDOWN_PREFIX:-} # Service defaults DEFAULT_AUTO_RESTART=$DEFAULT_AUTO_RESTART DEFAULT_START_TIMEOUT=$DEFAULT_START_TIMEOUT DEFAULT_STOP_TIMEOUT=$DEFAULT_STOP_TIMEOUT _EOF if [ -n "${USE_UTMPX:-}" ]; then echo "USE_UTMPX=$USE_UTMPX" >> mconfig fi if [ -n "${CXX_FOR_BUILD:-}" ]; then { echo "" echo "# For cross-compiling" echo "CXX_FOR_BUILD=$CXX_FOR_BUILD" } >> mconfig fi if [ -n "${CXXFLAGS_FOR_BUILD:-}" ]; then echo "CXXFLAGS_FOR_BUILD=$CXXFLAGS_FOR_BUILD" >> mconfig fi if [ -n "${CPPFLAGS_FOR_BUILD:-}" ]; then echo "CPPFLAGS_FOR_BUILD=$CPPFLAGS_FOR_BUILD" >> mconfig fi if [ -n "${LDFLAGS_FOR_BUILD:-}" ]; then echo "LDFLAGS_FOR_BUILD=$LDFLAGS_FOR_BUILD" >> mconfig fi sub_info done. info Done! exit 0