#!/bin/sh
# Convenience wrapper for easily viewing/setting options that
# the project's CMake scripts will recognize
set -e

trap '[ $? -eq 0 ] && exit 0 ||
echo "Also, before re-running configure, consider cleaning the cache \
(removing the build directory) via \`make distclean\`"' EXIT

command="$0 $*"

usage="\
Usage: $0 [OPTION]... [VAR=VALUE]...

  Build Options:
    --cmake=PATH                custom path to a CMake binary
    --builddir=DIR              place build files in directory [build]
    --build-dir=DIR             alias for --builddir
    --build-type=TYPE           set CMake build type [RelWithDebInfo]:
                                  - Debug: optimizations off, debug symbols + flags
                                  - MinSizeRel: size optimizations, debugging off
                                  - Release: optimizations on, debugging off
                                  - RelWithDebInfo: optimizations on,
                                        debug symbols on, debug flags off
    --generator=GENERATOR       CMake generator to use (see cmake --help)
    --ccache                    use ccache to speed up recompilation (requires
                                ccache installation and CMake 3.10+)
    --toolchain=PATH            path to a CMAKE_TOOLCHAIN_FILE
                                (useful for cross-compiling)
    --sanitizers=LIST           comma-separated list of sanitizer names to enable
    --include-plugins=PATHS     paths containing plugins to build directly into Zeek
                                (semicolon delimited and quoted when multiple)

  Installation Directories:
    --prefix=PREFIX        installation directory [/usr/local/zeek]
    --scriptdir=PATH       root installation directory for Zeek scripts
                           [PREFIX/share/zeek]
    --localstatedir=PATH   when using ZeekControl, path to store log files
                           and run-time data (within log/ and spool/ subdirs)
                           [PREFIX]
    --spooldir=PATH        directory for in-progress logs [PREFIX/spool]
    --statedir=PATH        directory for variable state [PREFIX/var/lib]
    --logdir=PATH          directory for finalized logs [PREFIX/logs]
    --libdir=PATH          installation directory for library files [PREFIX/lib]
    --plugindir=PATH       installation directory for plugins [LIBDIR/zeek/plugin]
    --conf-files-dir=PATH  installation directory for config files [PREFIX/etc]
    --mandir=PATH          installation path for man pages [PREFIX/share/man]
    --python-dir=PATH      explicit installation directory for Python modules
    --python-prefix=PATH   versioned installation directory for Python modules,
                           like setup.py install --prefix
                           [PATH/lib/python<Python Version>/site-packages]
    --python-home=PATH     installation path for Python modules, like setup.py's
                           install --home [PATH/lib/python]

  Optional Features:
    --enable-coverage      compile with code coverage support (implies debugging mode)
    --enable-debug         compile in debugging mode (like --build-type=Debug)
    --enable-fuzzers       build fuzzer targets
    --enable-jemalloc      link against jemalloc
    --enable-mobile-ipv6   analyze mobile IPv6 features defined by RFC 6275
    --enable-perftools     enable use of Google perftools (use tcmalloc)
    --enable-perftools-debug use Google's perftools for debugging
    --enable-static-binpac build binpac statically (ignored if --with-binpac is specified)
    --enable-static-broker build Broker statically (ignored if --with-broker is specified)
    --disable-archiver     don't build or install zeek-archiver tool
    --disable-auxtools     don't build or install auxiliary tools
    --disable-broker-tests don't try to build Broker unit tests
    --disable-btest        don't install BTest
    --disable-btest-pcaps  don't install Zeek's BTest input pcaps
    --disable-cpp-tests    don't build Zeek's C++ unit tests
    --disable-python       don't try to build python bindings for Broker
    --disable-spicy        don't include Spicy
    --disable-zeek-client  don't install Zeek cluster management client
    --disable-zeekctl      don't install ZeekControl
    --disable-zkg          don't install zkg

  Required Packages in Non-Standard Locations:
    --with-bifcl=PATH      path to Zeek BIF compiler executable
                           (useful for cross-compiling)
    --with-bind=PATH       path to BIND install root
    --with-binpac=PATH     path to BinPAC executable
                           (useful for cross-compiling)
    --with-bison=PATH      path to bison executable
    --with-broker=PATH     path to Broker install root
                           (Zeek uses an embedded version by default)
    --with-caf=PATH        path to C++ Actor Framework install root
                           (a Broker dependency that is embedded by default)
    --with-gen-zam=PATH    path to Gen-ZAM code generator
                           (Zeek uses an embedded version by default)
    --with-flex=PATH       path to flex executable
    --with-libkqueue=PATH  path to libkqueue install root
                           (Zeek uses an embedded version by default)
    --with-openssl=PATH    path to OpenSSL install root
    --with-pcap=PATH       path to libpcap install root
    --with-python=PATH     path to Python executable

  Optional Packages in Non-Standard Locations:
    --with-geoip=PATH      path to the libmaxminddb install root
    --with-jemalloc=PATH   path to jemalloc install root
    --with-krb5=PATH       path to krb5 install root
    --with-perftools=PATH  path to Google Perftools install root
    --with-python-inc=PATH path to Python headers
    --with-python-lib=PATH path to libpython
    --with-spicy=PATH      path to Spicy install root
    --with-spicy-plugin=PATH path to Spicy plugin source tree
    --with-swig=PATH       path to SWIG executable

  Packaging Options (for developers):
    --binary-package       toggle special logic for binary packaging
    --ignore-dirs=PATHS    paths to ignore when creating source package
                           (semicolon delimited and quoted when multiple)
    --pkg-name-prefix=NAME use the given name as the package prefix instead
                           of the default CMake project name
    --osx-sysroot=PATH     path to the OS X SDK to compile against
    --osx-min-version=VER  minimum OS X version (the deployment target)

  Influential Environment Variables (only on first invocation
  per build directory):
    CC                     C compiler command
    CFLAGS                 C compiler flags
    CXX                    C++ compiler command
    CXXFLAGS               C++ compiler flags
"

sourcedir="$(cd "$(dirname "$0")" && pwd)"

if [ ! -e "$sourcedir/cmake/COPYING" ] && [ -d "$sourcedir/.git" ]; then
    echo "\
You seem to be missing the content of the cmake directory.

This typically means that you performed a non-recursive git clone of
Zeek. To check out the required subdirectories, please execute:

  ( cd $sourcedir && git submodule update --recursive --init )
" >&2
    exit 1
fi

# Function to append a CMake cache entry definition to the
# CMakeCacheEntries variable.
#   $1 is the cache entry variable name
#   $2 is the cache entry variable type
#   $3 is the cache entry variable value
append_cache_entry() {
    CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3"
}

# Function to remove a CMake cache entry definition from the
# CMakeCacheEntries variable
#   $1 is the cache entry variable name
remove_cache_entry() {
    CMakeCacheEntries="$CMakeCacheEntries -U $1"

    # Even with -U, cmake still warns by default if
    # added previously with -D.
    CMakeCacheEntries="$CMakeCacheEntries --no-warn-unused-cli"
}

# set defaults
builddir=build
prefix=/usr/local/zeek
CMakeCacheEntries=""
append_cache_entry CMAKE_INSTALL_PREFIX PATH $prefix
append_cache_entry ZEEK_ROOT_DIR PATH $prefix
append_cache_entry ZEEK_SCRIPT_INSTALL_PATH STRING $prefix/share/zeek
append_cache_entry ZEEK_ETC_INSTALL_DIR PATH $prefix/etc
append_cache_entry ENABLE_DEBUG BOOL false
append_cache_entry ENABLE_PERFTOOLS BOOL false
append_cache_entry ENABLE_JEMALLOC BOOL false
append_cache_entry ENABLE_ZEEK_UNIT_TESTS BOOL true
append_cache_entry BUILD_SHARED_LIBS BOOL true
append_cache_entry INSTALL_AUX_TOOLS BOOL true
append_cache_entry INSTALL_BTEST BOOL true
append_cache_entry INSTALL_BTEST_PCAPS BOOL true
append_cache_entry INSTALL_ZEEK_ARCHIVER BOOL true
append_cache_entry INSTALL_ZEEK_CLIENT BOOL true
append_cache_entry INSTALL_ZEEKCTL BOOL true
append_cache_entry INSTALL_ZKG BOOL true
append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING
append_cache_entry ZEEK_SANITIZERS STRING ""
append_cache_entry ZEEK_INCLUDE_PLUGINS STRING ""

has_enable_mobile_ipv6=0

# parse arguments
while [ $# -ne 0 ]; do
    case "$1" in
        -*=*) optarg=$(echo "$1" | sed 's/[-_a-zA-Z0-9]*=//') ;;
        *) optarg= ;;
    esac

    case "$1" in
        --help | -h)
            echo "${usage}" 1>&2
            exit 1
            ;;
        --cmake=*)
            CMakeCommand=$optarg
            ;;
        --builddir=*)
            builddir=$optarg
            ;;
        --build-dir=*)
            builddir=$optarg
            ;;
        --build-type=*)
            append_cache_entry CMAKE_BUILD_TYPE STRING $optarg

            if [ $(echo "$optarg" | tr [:upper:] [:lower:]) = "debug" ]; then
                append_cache_entry ENABLE_DEBUG BOOL true
            fi
            ;;
        --generator=*)
            CMakeGenerator="$optarg"
            ;;
        --ccache)
            append_cache_entry ENABLE_CCACHE BOOL true
            ;;
        --toolchain=*)
            append_cache_entry CMAKE_TOOLCHAIN_FILE PATH $optarg
            ;;
        --include-plugins=*)
            append_cache_entry ZEEK_INCLUDE_PLUGINS STRING $optarg
            ;;
        --prefix=*)
            prefix=$optarg
            append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg
            append_cache_entry ZEEK_ROOT_DIR PATH $optarg
            ;;
        --libdir=*)
            append_cache_entry CMAKE_INSTALL_LIBDIR PATH $optarg
            ;;
        --plugindir=*)
            append_cache_entry ZEEK_PLUGIN_DIR PATH $optarg
            ;;
        --python-dir=*)
            append_cache_entry ZEEK_PYTHON_DIR PATH $optarg
            ;;
        --python-prefix=*)
            append_cache_entry ZEEK_PYTHON_PREFIX PATH $optarg
            ;;
        --python-home=*)
            append_cache_entry ZEEK_PYTHON_HOME PATH $optarg
            ;;
        --scriptdir=*)
            append_cache_entry ZEEK_SCRIPT_INSTALL_PATH STRING $optarg
            user_set_scriptdir="true"
            ;;
        --conf-files-dir=*)
            append_cache_entry ZEEK_ETC_INSTALL_DIR PATH $optarg
            user_set_conffilesdir="true"
            ;;
        --localstatedir=*)
            append_cache_entry ZEEK_LOCAL_STATE_DIR PATH $optarg
            ;;
        --spooldir=*)
            append_cache_entry ZEEK_SPOOL_DIR PATH $optarg
            ;;
        --statedir=*)
            append_cache_entry ZEEK_STATE_DIR PATH $optarg
            ;;
        --logdir=*)
            append_cache_entry ZEEK_LOG_DIR PATH $optarg
            ;;
        --mandir=*)
            append_cache_entry ZEEK_MAN_INSTALL_PATH PATH $optarg
            ;;
        --enable-coverage)
            append_cache_entry ENABLE_COVERAGE BOOL true
            append_cache_entry ENABLE_DEBUG BOOL true
            ;;
        --enable-debug)
            append_cache_entry ENABLE_DEBUG BOOL true
            ;;
        --enable-fuzzers)
            append_cache_entry ZEEK_ENABLE_FUZZERS BOOL true
            ;;
        --enable-jemalloc)
            append_cache_entry ENABLE_JEMALLOC BOOL true
            ;;
        --enable-mobile-ipv6)
            has_enable_mobile_ipv6=1
            ;;
        --enable-perftools)
            append_cache_entry ENABLE_PERFTOOLS BOOL true
            ;;
        --enable-perftools-debug)
            append_cache_entry ENABLE_PERFTOOLS BOOL true
            append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL true
            ;;
        --enable-static-binpac)
            append_cache_entry BUILD_STATIC_BINPAC BOOL true
            ;;
        --enable-static-broker)
            append_cache_entry BUILD_STATIC_BROKER BOOL true
            ;;
        --disable-archiver)
            append_cache_entry INSTALL_ZEEK_ARCHIVER BOOL false
            ;;
        --disable-auxtools)
            append_cache_entry INSTALL_AUX_TOOLS BOOL false
            ;;
        --disable-broker-tests)
            append_cache_entry BROKER_DISABLE_TESTS BOOL true
            append_cache_entry BROKER_DISABLE_DOC_EXAMPLES BOOL true
            ;;
        --disable-btest)
            append_cache_entry INSTALL_BTEST BOOL false
            ;;
        --disable-btest-pcaps)
            append_cache_entry INSTALL_BTEST_PCAPS BOOL false
            ;;
        --disable-cpp-tests)
            append_cache_entry ENABLE_ZEEK_UNIT_TESTS BOOL false
            ;;
        --disable-python)
            append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true
            ;;
        --disable-spicy)
            append_cache_entry DISABLE_SPICY BOOL true
            ;;
        --disable-zeek-client)
            append_cache_entry INSTALL_ZEEK_CLIENT BOOL false
            ;;
        --disable-zeekctl)
            append_cache_entry INSTALL_ZEEKCTL BOOL false
            ;;
        --disable-zkg)
            append_cache_entry INSTALL_ZKG BOOL false
            ;;
        --with-bifcl=*)
            append_cache_entry BIFCL_EXE_PATH PATH $optarg
            ;;
        --with-bind=*)
            append_cache_entry BIND_ROOT_DIR PATH $optarg
            ;;
        --with-binpac=*)
            append_cache_entry BINPAC_EXE_PATH PATH $optarg
            ;;
        --with-bison=*)
            append_cache_entry BISON_EXECUTABLE PATH $optarg
            ;;
        --with-broker=*)
            append_cache_entry BROKER_ROOT_DIR PATH $optarg
            ;;
        --with-caf=*)
            append_cache_entry CAF_ROOT PATH $optarg
            ;;
        --with-flex=*)
            append_cache_entry FLEX_EXECUTABLE PATH $optarg
            ;;
        --with-gen-zam=*)
            append_cache_entry GEN_ZAM_EXE_PATH PATH $optarg
            ;;
        --with-geoip=*)
            append_cache_entry LibMMDB_ROOT_DIR PATH $optarg
            ;;
        --with-jemalloc=*)
            append_cache_entry JEMALLOC_ROOT_DIR PATH $optarg
            append_cache_entry ENABLE_JEMALLOC BOOL true
            ;;
        --with-krb5=*)
            append_cache_entry LibKrb5_ROOT_DIR PATH $optarg
            ;;
        --with-libkqueue=*)
            append_cache_entry LIBKQUEUE_ROOT_DIR PATH $optarg
            ;;
        --with-pcap=*)
            append_cache_entry PCAP_ROOT_DIR PATH $optarg
            ;;
        --with-perftools=*)
            append_cache_entry GooglePerftools_ROOT_DIR PATH $optarg
            ;;
        --with-openssl=*)
            append_cache_entry OPENSSL_ROOT_DIR PATH $optarg
            ;;
        --with-python=*)
            append_cache_entry PYTHON_EXECUTABLE PATH $optarg
            ;;
        --with-python-inc=*)
            append_cache_entry PYTHON_INCLUDE_DIR PATH $optarg
            append_cache_entry PYTHON_INCLUDE_PATH PATH $optarg
            ;;
        --with-python-lib=*)
            append_cache_entry PYTHON_LIBRARY PATH $optarg
            ;;
        --with-spicy=*)
            append_cache_entry SPICY_ROOT_DIR PATH $optarg
            ;;
        --with-spicy-plugin=*)
            append_cache_entry SPICY_PLUGIN_PATH PATH $optarg
            ;;
        --with-swig=*)
            append_cache_entry SWIG_EXECUTABLE PATH $optarg
            ;;
        --sanitizers=*)
            append_cache_entry ZEEK_SANITIZERS STRING $optarg
            ;;
        --binary-package)
            append_cache_entry BINARY_PACKAGING_MODE BOOL true
            ;;
        --ignore-dirs=*)
            append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING $optarg
            ;;
        --pkg-name-prefix=*)
            append_cache_entry PACKAGE_NAME_PREFIX STRING $optarg
            ;;
        --osx-sysroot=*)
            append_cache_entry CMAKE_OSX_SYSROOT PATH $optarg
            ;;
        --osx-min-version=*)
            append_cache_entry CMAKE_OSX_DEPLOYMENT_TARGET STRING $optarg
            ;;
        *)
            echo "Invalid option '$1'.  Try $0 --help to see available options."
            exit 1
            ;;
    esac
    shift
done

if [ -z "$CMakeCommand" ]; then
    # prefer cmake3 over "regular" cmake (cmake == cmake2 on RHEL)
    if command -v cmake3 >/dev/null 2>&1; then
        CMakeCommand="cmake3"
    elif command -v cmake >/dev/null 2>&1; then
        CMakeCommand="cmake"
    else
        echo "This package requires CMake, please install it first."
        echo "Then you may use this script to configure the CMake build."
        echo "Note: pass --cmake=PATH to use cmake in non-standard locations."
        exit 1
    fi
fi

if [ "$user_set_scriptdir" != "true" ]; then
    append_cache_entry ZEEK_SCRIPT_INSTALL_PATH STRING $prefix/share/zeek
fi

if [ "$user_set_conffilesdir" != "true" ]; then
    append_cache_entry ZEEK_ETC_INSTALL_DIR PATH $prefix/etc
fi

if [ -d $builddir ]; then
    # If build directory exists, check if it has a CMake cache
    if [ -f $builddir/CMakeCache.txt ]; then
        # If the CMake cache exists, delete it so that this configuration
        # is not tainted by a previous one
        rm -f $builddir/CMakeCache.txt
    fi
else
    # Create build directory
    mkdir -p $builddir
fi

echo "Build Directory : $builddir"
echo "Source Directory: $sourcedir"
cd $builddir

echo "Using $(cmake --version | head -1)"
echo
if [ -n "$CMakeGenerator" ]; then
    "$CMakeCommand" -G "$CMakeGenerator" $CMakeCacheEntries $sourcedir
else
    "$CMakeCommand" $CMakeCacheEntries $sourcedir
fi

echo "# This is the command used to configure this build" >config.status
echo $command >>config.status
chmod u+x config.status

if [ $has_enable_mobile_ipv6 -eq 1 ]; then
    echo
    echo "NOTE: The --enable-mobile-ipv6 argument no longer has any effect and will be removed in v5.1."
fi
