core-lightning/configure
Matt Morehouse 968d6d6d24 configure: abort on UBSan failure
By default, UBSan reports runtime errors but does not stop execution.
We already abort in debug builds, and this commit makes us also abort in
regular builds when UBSan is enabled. Arguably, this is what users
expect when they enable UBSan, so it is a good default.

I know I've missed some UBSan bugs in the past because of this issue,
and dergoegge mentioned that this also happened to him.
2024-02-01 14:52:39 +10:30

546 lines
15 KiB
Bash
Executable File

#! /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; then
echo 'found'
return 0
fi
echo 'not found'
return 1
}
default_valgrind_setting()
{
# Valgrind must accept all these options (might exit with error 7 though
# if /bin/true leaks mem on your system!)
if valgrind -q --error-exitcode=7 --track-origins=yes --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all /bin/true >/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-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
# 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 [ "$ASAN" = "1" ]; then
if [ "$VALGRIND" = "1" ]; then
echo "Address sanitizer (ASAN) and valgrind cannot be enabled at the same time"
exit 1
fi
fi
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 <<EOF
var=HAVE_GOOD_LIBSODIUM
desc=libsodium with IETF chacha20 variants
style=DEFINES_EVERYTHING|EXECUTE|MAY_NOT_COMPILE
link=-lsodium
code=
#include <sodium.h>
#include <stdio.h>
#include <string.h>
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 <sqlite3.h>
#include <stdio.h>
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 <sqlite3.h>
#include <stdio.h>
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 <libpq-fe.h>
#include <stdio.h>
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 <sys/sdt.h>
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 <sys/uio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
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
# 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