#!/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]...

  -h, --help                    display this help and exit
  --show-config                 display the most relevant config parameters of an existing build

  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)
    --localversion=version      version contains an additional, custom version string
                                that is appended to the standard Zeek version string,
                                with a dash [-] separating the two.

  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-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)
    --enable-werror        build with -Werror
    --enable-ZAM-profiling build with ZAM profiling enabled (--enable-debug implies this)
    --enable-spicy-ssl     build with spicy SSL/TLS analyzer (conflicts with --disable-spicy)
    --enable-iwyu          build with include-what-you-use enabled for the main Zeek target.
                           Requires include-what-you-use binary to be in the PATH.
    --enable-clang-tidy    build with clang-tidy enabled for the main Zeek target.
                           Requires clang-tidy binary to be in the PATH.
    --disable-af-packet    don't include native AF_PACKET support (Linux only)
    --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-cluster-backend-zeromq don't build Zeek's ZeroMQ cluster backend
    --disable-cpp-tests    don't build Zeek's C++ unit tests
    --disable-javascript   don't build Zeek's JavaScript support
    --disable-port-prealloc disable pre-allocating the PortVal array in ValManager
    --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-bison=PATH      path to bison executable
    --with-broker=PATH     path to Broker install root
                           (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-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)

    --display-cmake        don't create build configuration, just output final CMake invocation

  Advanced Options (for developers):
    -D PARAM               passes a parameter directly to CMake

  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" ]; then
    if [ -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
    else
        echo "\
You seem to be missing the content of the cmake directory.

This typically means that you downloaded a non-release archive from github.
These archives do not contain all required files.

If you want to download the current release of Zeek, please download a full
archive using one of the links at https://zeek.org/get-zeek/.

If you want to get the current development version of Zeek, please use git to
clone our repository.

See https://docs.zeek.org/en/master/install.html#retrieving-the-sources for
instructions.
" >&2
    fi
    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"
}

# set defaults
builddir=build
CMakeCacheEntries=""
display_cmake=0
has_disable_archiver=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
            ;;
        --show-config)
            if [ ! -f "$builddir/CMakeCache.txt" ]; then
                echo "Error: no CMake build found under '$builddir'." 1>&2
                exit 1
            fi
            grep -E "^ENABLE_|^ZEEK_|^INSTALL_|^CMAKE_INSTALL_PRE|^CMAKE_C.*_FLAGS|^CMAKE_C.*_COMPILER|^CMAKE_.*_LINKER_FLAGS|^CMAKE_BUILD" "$builddir/CMakeCache.txt" | grep -v ':INTERNAL'
            exit 0
            ;;
        -D)
            shift
            if [ $# -eq 0 ]; then
                echo "Error: -D requires an argument."
                exit 1
            fi
            CMakeCacheEntries="$CMakeCacheEntries -D $1"
            ;;
        --cmake=*)
            CMakeCommand=$optarg
            ;;
        --builddir=*)
            builddir=$optarg
            ;;
        --build-dir=*)
            builddir=$optarg
            ;;
        --build-type=*)
            append_cache_entry CMAKE_BUILD_TYPE STRING $optarg
            ;;
        --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\"
            ;;
        --localversion=*)
            append_cache_entry ZEEK_VERSION_LOCAL STRING \"$optarg\"
            ;;
        --prefix=*)
            append_cache_entry CMAKE_INSTALL_PREFIX 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
            append_cache_entry ENABLE_ZAM_PROFILE BOOL true
            ;;
        --enable-debug)
            append_cache_entry ENABLE_DEBUG BOOL true
            append_cache_entry ENABLE_ZAM_PROFILE BOOL true
            ;;
        --enable-fuzzers)
            append_cache_entry ZEEK_ENABLE_FUZZERS BOOL true
            ;;
        --enable-jemalloc)
            append_cache_entry ENABLE_JEMALLOC BOOL true
            ;;
        --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
            ;;
        --enable-werror)
            append_cache_entry BUILD_WITH_WERROR BOOL true
            ;;
        --enable-ZAM-profiling)
            append_cache_entry ENABLE_ZAM_PROFILE BOOL true
            ;;
        --enable-spicy-ssl)
            append_cache_entry ENABLE_SPICY_SSL BOOL true
            ;;
        --enable-iwyu)
            append_cache_entry ENABLE_IWYU BOOL true
            ;;
        --enable-clang-tidy)
            append_cache_entry ENABLE_CLANG_TIDY BOOL true
            ;;
        --disable-af-packet)
            append_cache_entry DISABLE_AF_PACKET BOOL true
            ;;
        --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-cluster-backend-zeromq)
            append_cache_entry ENABLE_CLUSTER_BACKEND_ZEROMQ BOOL false
            ;;
        --disable-cpp-tests)
            append_cache_entry ENABLE_ZEEK_UNIT_TESTS BOOL false
            ;;
        --disable-javascript)
            append_cache_entry DISABLE_JAVASCRIPT BOOL true
            ;;
        --disable-port-prealloc)
            append_cache_entry PREALLOCATE_PORT_ARRAY 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-bind=*)
            append_cache_entry BIND_ROOT_DIR 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-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-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
            ;;
        --display-cmake)
            display_cmake=1
            ;;
        *)
            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

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

if [ "${display_cmake}" = 1 ]; then
    echo "${cmake}"
    exit 0
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

eval ${cmake} 2>&1

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