Fri, 23 May 2025 12:44:24 +0200
make test-compile depend on both static and shared
the shared lib is not needed for the tests,
but when run with coverage, gcov will be confused
when outdated line information is available from
a previous shared build
#!/bin/sh # some utility functions isplatform() { for p in $PLATFORM do if [ "$p" = "$1" ]; then return 0 fi done return 1 } notisplatform() { for p in $PLATFORM do if [ "$p" = "$1" ]; then return 1 fi done return 0 } istoolchain() { for t in $TOOLCHAIN do if [ "$t" = "$1" ]; then return 0 fi done return 1 } notistoolchain() { for t in $TOOLCHAIN do if [ "$t" = "$1" ]; then return 1 fi done return 0 } # clean abort abort_configure() { rm -Rf "$TEMP_DIR" exit 1 } # Test for availability of pkg-config PKG_CONFIG=`command -v pkg-config` : ${PKG_CONFIG:="false"} # Simple uname based platform detection # $PLATFORM is used for platform dependent dependency selection OS=`uname -s` OS_VERSION=`uname -r` printf "detect platform... " if [ "$OS" = "SunOS" ]; then PLATFORM="solaris sunos unix svr4" elif [ "$OS" = "Linux" ]; then PLATFORM="linux unix" elif [ "$OS" = "FreeBSD" ]; then PLATFORM="freebsd bsd unix" elif [ "$OS" = "OpenBSD" ]; then PLATFORM="openbsd bsd unix" elif [ "$OS" = "NetBSD" ]; then PLATFORM="netbsd bsd unix" elif [ "$OS" = "Darwin" ]; then PLATFORM="macos osx bsd unix" elif echo "$OS" | grep -i "MINGW" > /dev/null; then PLATFORM="windows mingw" fi : ${PLATFORM:="unix"} PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -` echo "$PLATFORM_NAME" # help text printhelp() { echo "Usage: $0 [OPTIONS]..." cat << __EOF__ Installation directories: --prefix=PREFIX path prefix for architecture-independent files [$prefix] --exec-prefix=EPREFIX path prefix for architecture-dependent files [PREFIX] --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR system configuration files [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR run-time variable data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --mandir=DIR man documentation [DATAROOTDIR/man] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] Build Types: --debug add extra compile flags for debug builds --release add extra compile flags for release builds Optional Features: --enable-api-docs run Doxygen during build --enable-coverage test coverage with gcov --enable-asan address sanitizer --disable-cxx-tests the check-cxx makefile target --disable-szmul-builtin use custom implementation, instead __EOF__ } # create temporary directory TEMP_DIR=".tmp-`uname -n`" rm -Rf "$TEMP_DIR" if mkdir -p "$TEMP_DIR"; then : else echo "Cannot create tmp dir $TEMP_DIR" echo "Abort" exit 1 fi touch "$TEMP_DIR/options" touch "$TEMP_DIR/features" # define standard variables # also define standard prefix (this is where we will search for config.site) prefix=/usr exec_prefix= bindir= sbindir= libdir= libexecdir= datarootdir= datadir= sysconfdir= sharedstatedir= localstatedir= runstatedir= includedir= infodir= localedir= mandir= # custom variables if true \ ; then root_dir=`pwd` DOXYGEN=`command -v doxygen` fi # features FEATURE_CXX_TESTS=auto FEATURE_SZMUL_BUILTIN=auto # # parse arguments # BUILD_TYPE="default" for ARG in "$@" do case "$ARG" in "--prefix="*) prefix=${ARG#--prefix=} ;; "--exec-prefix="*) exec_prefix=${ARG#--exec-prefix=} ;; "--bindir="*) bindir=${ARG#----bindir=} ;; "--sbindir="*) sbindir=${ARG#--sbindir=} ;; "--libdir="*) libdir=${ARG#--libdir=} ;; "--libexecdir="*) libexecdir=${ARG#--libexecdir=} ;; "--datarootdir="*) datarootdir=${ARG#--datarootdir=} ;; "--datadir="*) datadir=${ARG#--datadir=} ;; "--sysconfdir="*) sysconfdir=${ARG#--sysconfdir=} ;; "--sharedstatedir="*) sharedstatedir=${ARG#--sharedstatedir=} ;; "--localstatedir="*) localstatedir=${ARG#--localstatedir=} ;; "--includedir="*) includedir=${ARG#--includedir=} ;; "--infodir="*) infodir=${ARG#--infodir=} ;; "--mandir"*) mandir=${ARG#--mandir} ;; "--localedir"*) localedir=${ARG#--localedir} ;; "--help"*) printhelp; abort_configure ;; "--debug") BUILD_TYPE="debug" ;; "--release") BUILD_TYPE="release" ;; "--enable-api-docs") FEATURE_API_DOCS=on ;; "--disable-api-docs") unset FEATURE_API_DOCS ;; "--enable-coverage") FEATURE_COVERAGE=on ;; "--disable-coverage") unset FEATURE_COVERAGE ;; "--enable-asan") FEATURE_ASAN=on ;; "--disable-asan") unset FEATURE_ASAN ;; "--enable-cxx-tests") FEATURE_CXX_TESTS=on ;; "--disable-cxx-tests") unset FEATURE_CXX_TESTS ;; "--enable-szmul-builtin") FEATURE_SZMUL_BUILTIN=on ;; "--disable-szmul-builtin") unset FEATURE_SZMUL_BUILTIN ;; "-"*) echo "unknown option: $ARG"; abort_configure ;; esac done # set defaults for dir variables : ${exec_prefix:="$prefix"} : ${bindir:='${exec_prefix}/bin'} : ${sbindir:='${exec_prefix}/sbin'} : ${libdir:='${exec_prefix}/lib'} : ${libexecdir:='${exec_prefix}/libexec'} : ${datarootdir:='${prefix}/share'} : ${datadir:='${datarootdir}'} : ${sysconfdir:='${prefix}/etc'} : ${sharedstatedir:='${prefix}/com'} : ${localstatedir:='${prefix}/var'} : ${runstatedir:='${localstatedir}/run'} : ${includedir:='${prefix}/include'} : ${infodir:='${datarootdir}/info'} : ${mandir:='${datarootdir}/man'} : ${localedir:='${datarootdir}/locale'} # remember the above values and compare them later orig_bindir="$bindir" orig_sbindir="$sbindir" orig_libdir="$libdir" orig_libexecdir="$libexecdir" orig_datarootdir="$datarootdir" orig_datadir="$datadir" orig_sysconfdir="$sysconfdir" orig_sharedstatedir="$sharedstatedir" orig_localstatedir="$localstatedir" orig_runstatedir="$runstatedir" orig_includedir="$includedir" orig_infodir="$infodir" orig_mandir="$mandir" orig_localedir="$localedir" # check if a config.site exists and load it if [ -n "$CONFIG_SITE" ]; then # CONFIG_SITE may contain space separated file names for cs in $CONFIG_SITE; do printf "loading defaults from $cs... " . "$cs" echo ok done elif [ -f "$prefix/share/config.site" ]; then printf "loading site defaults... " . "$prefix/share/config.site" echo ok elif [ -f "$prefix/etc/config.site" ]; then printf "loading site defaults... " . "$prefix/etc/config.site" echo ok fi # generate vars.mk cat > "$TEMP_DIR/vars.mk" << __EOF__ prefix=$prefix exec_prefix=$exec_prefix bindir=$bindir sbindir=$sbindir libdir=$libdir libexecdir=$libexecdir datarootdir=$datarootdir datadir=$datadir sysconfdir=$sysconfdir sharedstatedir=$sharedstatedir localstatedir=$localstatedir runstatedir=$runstatedir includedir=$includedir infodir=$infodir mandir=$mandir localedir=$localedir __EOF__ # toolchain detection utilities . make/toolchain.sh # # DEPENDENCIES # # check languages lang_c= lang_cpp= if detect_cpp_compiler ; then lang_cpp=1 fi if detect_c_compiler ; then lang_c=1 fi # create buffer for make variables required by dependencies echo > "$TEMP_DIR/make.mk" test_pkg_config() { if "$PKG_CONFIG" --exists "$1" ; then : else return 1 ; fi if [ -z "$2" ] || "$PKG_CONFIG" --atleast-version="$2" "$1" ; then : else return 1 ; fi if [ -z "$3" ] || "$PKG_CONFIG" --exact-version="$3" "$1" ; then : else return 1 ; fi if [ -z "$4" ] || "$PKG_CONFIG" --max-version="$4" "$1" ; then : else return 1 ; fi return 0 } print_check_msg() { if [ -z "$1" ]; then shift printf "$@" fi } dependency_error_coverage() { print_check_msg "$dep_checked_coverage" "checking for coverage... " # dependency coverage toolchain="gcc" while true do if notistoolchain "gcc"; then break fi if command -v gcovr > /dev/null ; then : else break fi TEMP_CFLAGS="$TEMP_CFLAGS \${COVERAGE_CFLAGS}" TEMP_LDFLAGS="$TEMP_LDFLAGS \${COVERAGE_LDFLAGS}" print_check_msg "$dep_checked_coverage" "yes\n" dep_checked_coverage=1 return 1 done print_check_msg "$dep_checked_coverage" "no\n" dep_checked_coverage=1 return 0 } dependency_error_asan() { print_check_msg "$dep_checked_asan" "checking for asan... " # dependency asan toolchain="gnuc" while true do if notistoolchain "gnuc"; then break fi TEMP_CFLAGS="$TEMP_CFLAGS -fsanitize=address" TEMP_LDFLAGS="$TEMP_LDFLAGS -fsanitize=address" print_check_msg "$dep_checked_asan" "yes\n" dep_checked_asan=1 return 1 done print_check_msg "$dep_checked_asan" "no\n" dep_checked_asan=1 return 0 } dependency_error_cxx() { print_check_msg "$dep_checked_cxx" "checking for cxx... " # dependency cxx while true do if [ -z "$lang_cpp" ] ; then break fi print_check_msg "$dep_checked_cxx" "yes\n" dep_checked_cxx=1 return 1 done print_check_msg "$dep_checked_cxx" "no\n" dep_checked_cxx=1 return 0 } dependency_error_c() { print_check_msg "$dep_checked_c" "checking for c... " # dependency c platform="mingw" while true do if notisplatform "mingw"; then break fi if [ -z "$lang_c" ] ; then break fi cat >> $TEMP_DIR/make.mk << __EOF__ # Dependency: c AR=ar ARFLAGS=r STLIB_EXT=.lib SHLIB_EXT=.dll __EOF__ print_check_msg "$dep_checked_c" "yes\n" dep_checked_c=1 return 1 done # dependency c platform="macos" while true do if notisplatform "macos"; then break fi if [ -z "$lang_c" ] ; then break fi cat >> $TEMP_DIR/make.mk << __EOF__ # Dependency: c AR=ar ARFLAGS=r STLIB_EXT=.a SHLIB_EXT=.dylib __EOF__ print_check_msg "$dep_checked_c" "yes\n" dep_checked_c=1 return 1 done # dependency c platform="unix" while true do if notisplatform "unix"; then break fi if [ -z "$lang_c" ] ; then break fi cat >> $TEMP_DIR/make.mk << __EOF__ # Dependency: c AR=ar ARFLAGS=cr STLIB_EXT=.a SHLIB_EXT=.so __EOF__ print_check_msg "$dep_checked_c" "yes\n" dep_checked_c=1 return 1 done print_check_msg "$dep_checked_c" "no\n" dep_checked_c=1 return 0 } dependency_error_file_tools() { print_check_msg "$dep_checked_file_tools" "checking for file_tools... " # dependency file-tools while true do cat >> $TEMP_DIR/make.mk << __EOF__ # Dependency: file_tools MKDIR=/bin/mkdir -p RMFILE=/bin/rm -f RMDIR=/bin/rm -f -R COPYFILE=/bin/cp -f COPYALL=/bin/cp -f -R SYMLINK=/bin/ln -s __EOF__ print_check_msg "$dep_checked_file_tools" "yes\n" dep_checked_file_tools=1 return 1 done print_check_msg "$dep_checked_file_tools" "no\n" dep_checked_file_tools=1 return 0 } dependency_error_doxygen() { print_check_msg "$dep_checked_doxygen" "checking for doxygen... " # dependency doxygen while true do if test -n "$DOXYGEN" > /dev/null ; then : else break fi cat >> $TEMP_DIR/make.mk << __EOF__ # Dependency: doxygen DOXYGEN=$DOXYGEN __EOF__ print_check_msg "$dep_checked_doxygen" "yes\n" dep_checked_doxygen=1 return 1 done print_check_msg "$dep_checked_doxygen" "no\n" dep_checked_doxygen=1 return 0 } dependency_error_no_coverage() { print_check_msg "$dep_checked_no_coverage" "checking for no_coverage... " # dependency no_coverage while true do if test -z "$FEATURE_COVERAGE" > /dev/null ; then : else break fi print_check_msg "$dep_checked_no_coverage" "yes\n" dep_checked_no_coverage=1 return 1 done print_check_msg "$dep_checked_no_coverage" "no\n" dep_checked_no_coverage=1 return 0 } # start collecting dependency information echo > "$TEMP_DIR/flags.mk" DEPENDENCIES_FAILED= ERROR=0 # unnamed dependencies TEMP_CFLAGS="$CFLAGS" TEMP_CXXFLAGS="$CXXFLAGS" TEMP_LDFLAGS="$LDFLAGS" while true do while true do cat >> "$TEMP_DIR/make.mk" << __EOF__ # library version VERSION=3.2.0 LIBVERSION=5.1.0 LIBVERSION_MAJOR=5 # build directory structure !! do not change or override !! root_dir=${root_dir} build_dir=${root_dir}/build docs_dir=${root_dir}/build/docs dist_dir=${root_dir}/dist __EOF__ break done break done while true do if notisplatform "solaris"; then break fi while true do TEMP_LDFLAGS="$TEMP_LDFLAGS -lm" break done break done # build type if [ "$BUILD_TYPE" = "debug" ]; then TEMP_CFLAGS="\${DEBUG_CFLAGS}$TEMP_CFLAGS" TEMP_CXXFLAGS="\${DEBUG_CXXFLAGS}$TEMP_CXXFLAGS" fi if [ "$BUILD_TYPE" = "release" ]; then TEMP_CFLAGS="\${RELEASE_CFLAGS}$TEMP_CFLAGS" TEMP_CXXFLAGS="\${RELEASE_CXXFLAGS}$TEMP_CXXFLAGS" fi # add general dependency flags to flags.mk echo "# general flags" >> "$TEMP_DIR/flags.mk" if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" fi if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then echo "CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" fi if [ -n "${TEMP_LDFLAGS}" ]; then echo "LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" fi # # OPTION VALUES # # # TARGETS # echo >> "$TEMP_DIR/flags.mk" echo "configuring global target" echo "# flags for unnamed target" >> "$TEMP_DIR/flags.mk" TEMP_CFLAGS= TEMP_CXXFLAGS= TEMP_LDFLAGS= if dependency_error_c; then DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED c " ERROR=1 fi if dependency_error_file_tools; then DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED file_tools " ERROR=1 fi # Features if [ -n "$FEATURE_API_DOCS" ]; then # check dependency if dependency_error_doxygen ; then # "auto" features can fail and are just disabled in this case if [ "$FEATURE_API_DOCS" = "auto" ]; then DISABLE_FEATURE_API_DOCS=1 else DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED doxygen " ERROR=1 fi fi if [ -n "$DISABLE_FEATURE_API_DOCS" ]; then unset FEATURE_API_DOCS fi fi if [ -n "$FEATURE_API_DOCS" ]; then : cat >> "$TEMP_DIR/make.mk" << __EOF__ # Documentation WITH_API_DOCS=yes __EOF__ else : fi if [ -n "$FEATURE_COVERAGE" ]; then # check dependency if dependency_error_coverage ; then # "auto" features can fail and are just disabled in this case if [ "$FEATURE_COVERAGE" = "auto" ]; then DISABLE_FEATURE_COVERAGE=1 else DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED coverage " ERROR=1 fi fi if [ -n "$DISABLE_FEATURE_COVERAGE" ]; then unset FEATURE_COVERAGE fi fi if [ -n "$FEATURE_COVERAGE" ]; then : else : fi if [ -n "$FEATURE_ASAN" ]; then # check dependency if dependency_error_asan ; then # "auto" features can fail and are just disabled in this case if [ "$FEATURE_ASAN" = "auto" ]; then DISABLE_FEATURE_ASAN=1 else DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED asan " ERROR=1 fi fi if [ -n "$DISABLE_FEATURE_ASAN" ]; then unset FEATURE_ASAN fi fi if [ -n "$FEATURE_ASAN" ]; then : else : fi if [ -n "$FEATURE_CXX_TESTS" ]; then # check dependency if dependency_error_cxx ; then # "auto" features can fail and are just disabled in this case if [ "$FEATURE_CXX_TESTS" = "auto" ]; then DISABLE_FEATURE_CXX_TESTS=1 else DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED cxx " ERROR=1 fi fi if [ -n "$DISABLE_FEATURE_CXX_TESTS" ]; then unset FEATURE_CXX_TESTS fi fi if [ -n "$FEATURE_CXX_TESTS" ]; then : cat >> "$TEMP_DIR/make.mk" << __EOF__ # Enable the check-cxx target WITH_CXX_TEST=yes __EOF__ else : fi if [ -n "$FEATURE_SZMUL_BUILTIN" ]; then # check dependency if dependency_error_no_coverage ; then # "auto" features can fail and are just disabled in this case if [ "$FEATURE_SZMUL_BUILTIN" = "auto" ]; then DISABLE_FEATURE_SZMUL_BUILTIN=1 else DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED no_coverage " ERROR=1 fi fi if [ -n "$DISABLE_FEATURE_SZMUL_BUILTIN" ]; then unset FEATURE_SZMUL_BUILTIN fi fi if [ -n "$FEATURE_SZMUL_BUILTIN" ]; then : else : TEMP_CFLAGS="$TEMP_CFLAGS -DCX_NO_SZMUL_BUILTIN" TEMP_CXXFLAGS="$TEMP_CXXFLAGS -DCX_NO_SZMUL_BUILTIN" fi if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" fi if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then echo "CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" fi if [ -n "${TEMP_LDFLAGS}" ]; then echo "LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" fi # final result if [ $ERROR -ne 0 ]; then echo echo "Error: Unresolved dependencies" echo "$DEPENDENCIES_FAILED" abort_configure fi echo "configure finished" echo echo "Toolchain" echo " name: $TOOLCHAIN_NAME" if [ -n "$TOOLCHAIN_CC" ]; then echo " cc: $TOOLCHAIN_CC" fi if [ -n "$TOOLCHAIN_CXX" ]; then echo " cxx: $TOOLCHAIN_CXX" fi if [ -n "$TOOLCHAIN_WSIZE" ]; then echo " word size: $TOOLCHAIN_WSIZE bit" fi if [ -n "$TOOLCHAIN_CSTD" ]; then echo " default C std: $TOOLCHAIN_CSTD" fi echo echo "Build Config:" echo " prefix: $prefix" echo " exec_prefix: $exec_prefix" if [ "$orig_bindir" != "$bindir" ]; then echo " bindir: $bindir" fi if [ "$orig_sbindir" != "$sbindir" ]; then echo " sbindir: $sbindir" fi if [ "$orig_libdir" != "$libdir" ]; then echo " libdir: $libdir" fi if [ "$orig_libexecdir" != "$libexecdir" ]; then echo " libexecdir: $libexecdir" fi if [ "$orig_datarootdir" != "$datarootdir" ]; then echo " datarootdir: $datarootdir" fi if [ "$orig_datadir" != "$datadir" ]; then echo " datadir: $datadir" fi if [ "$orig_sysconfdir" != "$sysconfdir" ]; then echo " sysconfdir: $sysconfdir" fi if [ "$orig_sharedstatedir" != "$sharedstatedir" ]; then echo " sharedstatedir: $sharedstatedir" fi if [ "$orig_localstatedir" != "$localstatedir" ]; then echo " localstatedir: $localstatedir" fi if [ "$orig_runstatedir" != "$runstatedir" ]; then echo " runstatedir: $runstatedir" fi if [ "$orig_includedir" != "$includedir" ]; then echo " includedir: $includedir" fi if [ "$orig_infodir" != "$infodir" ]; then echo " infodir: $infodir" fi if [ "$orig_mandir" != "$mandir" ]; then echo " mandir: $mandir" fi if [ "$orig_localedir" != "$localedir" ]; then echo " localedir: $localedir" fi echo echo "Features:" if [ -n "$FEATURE_API_DOCS" ]; then echo " api-docs: on" else echo " api-docs: off" fi if [ -n "$FEATURE_COVERAGE" ]; then echo " coverage: on" else echo " coverage: off" fi if [ -n "$FEATURE_ASAN" ]; then echo " asan: on" else echo " asan: off" fi if [ -n "$FEATURE_CXX_TESTS" ]; then echo " cxx-tests: on" else echo " cxx-tests: off" fi if [ -n "$FEATURE_SZMUL_BUILTIN" ]; then echo " szmul-builtin: on" else echo " szmul-builtin: off" fi echo # generate the config.mk file pwd=`pwd` cat > "$TEMP_DIR/config.mk" << __EOF__ # # config.mk generated by: # pwd: $pwd # $0 $@ # __EOF__ write_toolchain_defaults "$TEMP_DIR/toolchain.mk" cat "$TEMP_DIR/config.mk" "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk rm -Rf "$TEMP_DIR"