#! /bin/sh # Simple configure script for Core Lightning. set -e CONFIGURATOR=ccan/tools/configurator/configurator CONFIG_VAR_FILE=config.vars CONFIG_HEADER=ccan/config.h BASE_WARNFLAGS="-Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition -Werror" OS=$(uname -s) ARCH=$(uname -m) if [ "$OS-$ARCH" = "Darwin-arm64" ]; then CPATH=/opt/homebrew/include LIBRARY_PATH=/opt/homebrew/lib export PKG_CONFIG_PATH=/opt/homebrew/opt/sqlite/lib/pkgconfig else CPATH=/usr/local/lib LIBRARY_PATH=/usr/local/lib export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/opt/sqlite/lib/pkgconfig fi : ${PKG_CONFIG=pkg-config} # You can set PG_CONFIG in the environment to direct configure to call # a specific 'pg_config' binary. If you set it to an empty string, then # PostgreSQL support will be explicitly disabled, even if a 'pg_config' # binary exists in your PATH. If you leave it unset, then the following # line enables the automagic detection that most users want. : ${PG_CONFIG=pg_config} usage_with_default() { if [ $# = 4 ]; then if [ "$2" = 1 ]; then DEF=$3 else DEF=$4 fi else DEF=$2 fi echo " $1 (default $DEF)" } # Given DEBUGBUILD, what COPTFLAGS do we default to. default_coptflags() { if [ "$1" = 0 ]; then echo "-Og" fi } # Given COPTFLAGS, HAVE_GCC and HAVE_MODERN_GCC, what CWARNFLAGS to default to? default_cwarnflags() { F=$BASE_WARNFLAGS # Clang doesn't like -Wno-maybe-uninitialized, but doesn't seem # to give spurious warnings, either. if [ "$2" = 1 ]; then # With old gccs, or optimization != -O3, we need to suppress some warnings. if [ -n "${1##*-O3*}" ] || [ "$3" != "1" ]; then F="$F -Wno-maybe-uninitialized" fi # Recent clang understands that, but at least our MacOS CI doesn't, so keep # this gcc-only. F="$F -Wshadow=local" fi echo "$F" } default_python() { PYTHON_BINS="python3 python" for p in $PYTHON_BINS; do if [ "$(which $p)" != "" ] ; then if $p --version 2>&1 | grep -q "Python 3."; then echo "$p" return fi fi done } # Takes PYTHON var default_pytest() { # Since we just checked that we have python3 we give that one the # most priority and then fall back to some common aliases. PYTEST_BINS="$1 -m pytest,pytest,py.test,pytest3,pytest-3" IFS=',' for p in $PYTEST_BINS; do # If it is a combined command such as `python3 -m pytest` we # want to only call which on the executable exe=$(echo "$p" | awk '{print $1}') # shellcheck disable=SC2086 if [ "$(which $exe)" != "" ] ; then "$p" --version 2>&1 | grep -q "pytest" || continue echo "$p" return fi done if $1 -c "import pytest" 2>/dev/null; then echo "$1 -m pytest" return fi } check_command() { name="$1" shift 1 echo -n "checking for $name... " if "$@" >/dev/null 2>&1 /dev/null 2>&1 || [ $? = 7 ]; then echo 1 else echo 0 fi } default_rust_setting() { if cargo --version > /dev/null 2>&1 && rustfmt --version >/dev/null 2>&1; then echo 1 else echo 0 fi } set_defaults() { # Default values, loaded from environment or canned. # Note that ":-" means substitute if empty or unset, "-" means only if unset # which matters since you might explicitly set of these blank. PREFIX=${PREFIX:-/usr/local} CC=${CC:-cc} CDEBUGFLAGS=${CDEBUGFLAGS--std=gnu11 -g -fstack-protector-strong} DEBUGBUILD=${DEBUGBUILD:-0} COMPAT=${COMPAT:-1} STATIC=${STATIC:-0} CLANG_COVERAGE=${CLANG_COVERAGE:-0} ASAN=${ASAN:-0} UBSAN=${UBSAN:-0} FUZZING=${FUZZING:-0} FUZZFLAGS="" CSANFLAGS="" if [ "$ASAN" != 0 ]; then CSANFLAGS="$CSANFLAGS -fsanitize=address" if [ "$DEBUGBUILD" != 0 ]; then CSANFLAGS="$CSANFLAGS -fno-sanitize-recover=address" fi fi if [ "$UBSAN" != 0 ]; then CSANFLAGS="$CSANFLAGS -fsanitize=undefined -fno-sanitize=function -fno-sanitize-recover=undefined" fi if [ "$FUZZING" != 0 ]; then FUZZFLAGS="-fsanitize=fuzzer-no-link -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" CSANFLAGS="$CSANFLAGS $FUZZFLAGS" fi echo CSANFLAGS = $CSANFLAGS PYTHON=${PYTHON-$(default_python)} PYTEST=${PYTEST-$(default_pytest $PYTHON)} COPTFLAGS=${COPTFLAGS-$(default_coptflags "$DEBUGBUILD")} CONFIGURATOR_CC=${CONFIGURATOR_CC-$CC} VALGRIND=${VALGRIND:-$(default_valgrind_setting)} TEST_NETWORK=${TEST_NETWORK:-regtest} RUST=${RUST:-$(default_rust_setting)} } usage() { echo "Usage: ./configure [--reconfigure] [setting=value] [options]" echo "If --reconfigure is specified, $CONFIG_VAR_FILE will set defaults." echo "Default settings:" set_defaults DEFAULT_COPTFLAGS="$(default_coptflags $DEBUGBUILD)" # We assume we have a modern gcc. DEFAULT_CWARNFLAGS="$(default_cwarnflags ""$DEFAULT_COPTFLAGS"" 1 1)" usage_with_default "CC" "$CC" usage_with_default "CWARNFLAGS" "$DEFAULT_CWARNFLAGS" usage_with_default "COPTFLAGS" "$DEFAULT_COPTFLAGS" usage_with_default "CDEBUGFLAGS" "$CDEBUGFLAGS" usage_with_default "CONFIGURATOR_CC" "${CONFIGURATOR_CC:-$CC}" echo " To override compile line for configurator itself" usage_with_default "PYTEST" "$PYTEST" usage_with_default "VALGRIND" "$VALGRIND" echo "Options include:" usage_with_default "--prefix=" "$PREFIX" echo " Prefix for make install" usage_with_default "--enable/disable-debugbuild" "$DEBUGBUILD" "enable" "disable" echo " Extra debug checks in the build, good for testing" usage_with_default "--enable/disable-compat" "$COMPAT" "enable" "disable" echo " Compatibility mode, good to disable to see if your software breaks" usage_with_default "--enable/disable-valgrind" "(autodetect)" echo " Run tests with Valgrind" usage_with_default "--enable/disable-static" "$STATIC" "enable" "disable" echo " Static link sqlite3 and zlib libraries" usage_with_default "--enable/disable-coverage" "$CLANG_COVERAGE" "enable" "disable" echo " Compile with Clang coverage instrumentation" usage_with_default "--enable/disable-address-sanitizer" "$ASAN" "enable" "disable" echo " Compile with address-sanitizer" usage_with_default "--enable/disable-ub-sanitizer" "$UBSAN" "enable" "disable" echo " Compile with undefined behaviour sanitizer" usage_with_default "--enable/disable-fuzzing" "$FUZZING" "enable" "disable" echo " Compile with fuzzing" usage_with_default "--enable/disable-rust" "$RUST" "enable" "disable" echo " Compile with Rust support" exit 1 } add_var() { if [ -n "$2" ]; then echo "Setting $1... $2" else echo "$1 not found" fi echo "$1=$2" >> $CONFIG_VAR_FILE.$$ [ -z "$3" ] || echo "#define $1 $2" >> "$3" } for opt in "$@"; do case "$opt" in --reconfigure) # Figure out what defaulT COPTFLAGS was for this config.vars DEFAULT_COPTFLAGS= # Set from values if not already set. while IFS='=' read VAR VAL; do if eval [ -z \${$VAR+x} ]; then eval $VAR=\"$VAL\"; fi # If they had an old config, it might set DEVELOPER. if [ "$VAR" = DEVELOPER ]; then DEFAULT_COPTFLAGS=$(default_coptflags "$VAL") DEBUGBUILD="$VAL" VAR=DEBUGBUILD fi if [ "$VAR" = DEBUGBUILD ]; then DEFAULT_COPTFLAGS=$(default_coptflags "$VAL") fi done < $CONFIG_VAR_FILE # If we were those defaults, unset so we get new defaults in # case DEBUGBUILD has changed. if [ x"$COPTFLAGS" = x"$DEFAULT_COPTFLAGS" ]; then unset COPTFLAGS fi ;; CC=*) CC="${opt#CC=}";; CONFIGURATOR_CC=*) CONFIGURATOR_CC="${opt#CONFIGURATOR_CC=}";; CWARNFLAGS=*) CWARNFLAGS="${opt#CWARNFLAGS=}";; CDEBUGFLAGS=*) CDEBUGFLAGS="${opt#CDEBUGFLAGS=}";; COPTFLAGS=*) COPTFLAGS="${opt#COPTFLAGS=}";; PYTEST=*) PYTEST="${opt#PYTEST=}";; --prefix=*) PREFIX="${opt#--prefix=}";; --enable-debugbuild) DEBUGBUILD=1;; --disable-debugbuild) DEBUGBUILD=0;; --enable-compat) COMPAT=1;; --disable-compat) COMPAT=0;; --enable-valgrind) VALGRIND=1;; --disable-valgrind) VALGRIND=0;; --enable-static) STATIC=1;; --disable-static) STATIC=0;; --enable-coverage) CLANG_COVERAGE=1;; --disable-coverage) CLANG_COVERAGE=0;; --enable-address-sanitizer) ASAN=1;; --disable-address-sanitizer) ASAN=0;; --enable-ub-sanitizer) UBSAN=1;; --disable-ub-sanitizer|--disable-ub-sanitize) UBSAN=0;; --enable-fuzzing) FUZZING=1;; --disable-fuzzing) FUZZING=0;; --enable-rust) RUST=1;; --disable-rust) RUST=0;; --help|-h) usage;; *) echo "Unknown option '$opt'" >&2 usage ;; esac done # Now fill in any unset vars. set_defaults if [ "$ASAN" = "1" ]; then if [ "$VALGRIND" = "1" ]; then echo "Address sanitizer (ASAN) and valgrind cannot be enabled at the same time" exit 1 fi # Test for buggy clang https://github.com/llvm/llvm-project/issues/81470 cat > /tmp/asan-test.$$.c </dev/null; then echo "WARNING: ASAN compilatin bug detected: DISABLING" >&2 CSANFLAGS=$(echo "$CSANFLAGS" | sed 's/-fsanitize=address//') ASAN=0 break fi done fi # We assume warning flags don't affect congfigurator that much! echo -n "Compiling $CONFIGURATOR..." $CC ${CWARNFLAGS-$BASE_WARNFLAGS} $CDEBUGFLAGS $COPTFLAGS -o $CONFIGURATOR $CONFIGURATOR.c echo "done" if [ "$CLANG_COVERAGE" = "1" ]; then case "$CC" in (*"clang"*) ;; (*) echo "Clang coverage requires building with CC=clang." exit 1 ;; esac fi if [ "$FUZZING" = "1" ]; then case "$CC" in (*"clang"*) ;; (*) echo "Fuzzing is currently only supported with clang." exit 1 ;; esac fi SQLITE3_CFLAGS="" SQLITE3_LDLIBS="-lsqlite3" if command -v "${PKG_CONFIG}" >/dev/null; then SQLITE3_CFLAGS="$("${PKG_CONFIG}" --silence-errors --cflags sqlite3 || :)" SQLITE3_LDLIBS="$("${PKG_CONFIG}" --silence-errors --libs sqlite3 || :)" fi POSTGRES_INCLUDE="" POSTGRES_LDLIBS="" if command -v "${PG_CONFIG}" >/dev/null; then POSTGRES_INCLUDE="-I$("${PG_CONFIG}" --includedir)" POSTGRES_LDLIBS="-L$("${PG_CONFIG}" --libdir) -lpq" fi # Clean up on exit. trap "rm -f $CONFIG_VAR_FILE.$$" 0 $CONFIGURATOR --extra-tests --autotools-style --var-file=$CONFIG_VAR_FILE.$$ --header-file=$CONFIG_HEADER.$$ --configurator-cc="$CONFIGURATOR_CC" --wrapper="$CONFIGURATOR_WRAPPER" "$CC" ${CWARNFLAGS-$BASE_WARNFLAGS} $CDEBUGFLAGS $COPTFLAGS $CSANFLAGS -I$CPATH -L$LIBRARY_PATH $SQLITE3_CFLAGS $POSTGRES_INCLUDE < #include int main(void) { gzFile f = gzopen("/dev/null", "wb"); return f != NULL ? 0 : 1; } /*END*/ var=HAVE_GOOD_LIBSODIUM desc=libsodium with IETF chacha20 variants style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE link=-lsodium code= #include #include #include int main(void) { crypto_secretstream_xchacha20poly1305_state crypto_state; unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; unsigned char data[] = { 1, 2, 3 }; crypto_secretstream_xchacha20poly1305_init_push(&crypto_state, header, data); printf("%p\n", crypto_aead_chacha20poly1305_ietf_encrypt); printf("%d\n", crypto_aead_chacha20poly1305_ietf_NPUBBYTES); return 0; } /*END*/ var=HAVE_SQLITE3_EXPANDED_SQL desc=sqlite3_expanded_sql style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE link=$SQLITE3_LDLIBS code= #include #include int main(void) { printf("%p\n", sqlite3_expanded_sql); return 0; } /*END*/ var=HAVE_SQLITE3 desc=sqlite3 style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE link=$SQLITE3_LDLIBS code= #include #include int main(void) { printf("%p\n", sqlite3_prepare_v2); return 0; } /*END*/ var=HAVE_POSTGRES desc=postgres style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE link=$POSTGRES_LDLIBS code= #include #include int main(void) { printf("libpq version %d\n", PQlibVersion()); return 0; } /*END*/ var=HAVE_USDT desc=User Statically-Defined Tracing (USDT) style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE code= #include int main(void) { DTRACE_PROBE(lightningd, test_sdt); return 0; } /*END*/ var=HAVE_GCC desc=compiler is GCC style=OUTSIDE_MAIN code= #ifndef __GNUC__ #error "Not GCC" #endif #ifdef __clang__ #error "clang" #endif /*END*/ var=HAVE_MODERN_GCC desc=GCC version is 7 or above style=OUTSIDE_MAIN code= #if __GNUC__ < 7 #error "Not modern GCC" #endif /*END*/ var=HAVE_PWRITEV desc=pwritev() defined style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE code= #include #include #include #include int main(void) { struct iovec iov[2]; int fd = open("/dev/null", O_WRONLY); iov[0].iov_base = "hello"; iov[0].iov_len = 5; iov[1].iov_base = " world"; iov[1].iov_len = 6; if (pwritev(fd, iov, 2, 0) == 11) return 0; return 1; } /*END*/ EOF if check_command 'python3-mako' python3 -c 'import mako'; then HAVE_PYTHON3_MAKO=1 else HAVE_PYTHON3_MAKO=0 fi if check_command 'lowdown' lowdown; then HAVE_LOWDOWN=1 else HAVE_LOWDOWN=0 fi if echo | check_command sha256sum sha256sum; then SHA256SUM=sha256sum elif echo | check_command "shasum -a 256" shasum -a 256; then SHA256SUM="shasum -a 256" elif echo | check_command sha256 sha256; then SHA256SUM=sha256 else echo "*** We need sha256sum, shasum -a 256, or sha256!" >&2 exit 1 fi if ! check_command 'jq' jq; then echo "*** We need jq!" >&2 exit 1 fi # Now we can finally set our warning flags if [ -z ${CWARNFLAGS+x} ]; then CWARNFLAGS=$(default_cwarnflags "$COPTFLAGS" \ $(sed -n 's/^HAVE_GCC=//p' < $CONFIG_VAR_FILE.$$) \ $(sed -n 's/^HAVE_MODERN_GCC=//p' < $CONFIG_VAR_FILE.$$) ) fi add_var PREFIX "$PREFIX" add_var CC "$CC" add_var CONFIGURATOR_CC "$CONFIGURATOR_CC" add_var CWARNFLAGS "$CWARNFLAGS" add_var CDEBUGFLAGS "$CDEBUGFLAGS" add_var COPTFLAGS "$COPTFLAGS" add_var CSANFLAGS "$CSANFLAGS" add_var FUZZFLAGS "$FUZZFLAGS" add_var SQLITE3_CFLAGS "$SQLITE3_CFLAGS" add_var SQLITE3_LDLIBS "$SQLITE3_LDLIBS" add_var POSTGRES_INCLUDE "$POSTGRES_INCLUDE" add_var POSTGRES_LDLIBS "$POSTGRES_LDLIBS" add_var VALGRIND "$VALGRIND" add_var DEBUGBUILD "$DEBUGBUILD" add_var COMPAT "$COMPAT" $CONFIG_HEADER.$$ add_var PYTEST "$PYTEST" add_var STATIC "$STATIC" add_var CLANG_COVERAGE "$CLANG_COVERAGE" add_var ASAN "$ASAN" add_var UBSAN "$UBSAN" add_var TEST_NETWORK "$TEST_NETWORK" add_var HAVE_PYTHON3_MAKO "$HAVE_PYTHON3_MAKO" add_var HAVE_LOWDOWN "$HAVE_LOWDOWN" add_var SHA256SUM "$SHA256SUM" add_var FUZZING "$FUZZING" add_var RUST "$RUST" add_var PYTHON "$PYTHON" # Hack to avoid sha256 name clash with libwally: will be fixed when that # becomes a standalone shared lib. echo '#include "ccan_compat.h"' >> $CONFIG_HEADER.$$ # Now we set them all and check. while IFS='=' read VAR VAL; do eval $VAR=\"$VAL\" done < $CONFIG_VAR_FILE.$$ if [ "$HAVE_SQLITE3" = 0 -a "$HAVE_POSTGRES" = 0 ]; then # I have no database yet I must schema!) echo "*** We need a database, but neither sqlite3 nor postgres found" >&2 exit 1 fi mv $CONFIG_VAR_FILE.$$ $CONFIG_VAR_FILE mv $CONFIG_HEADER.$$ $CONFIG_HEADER