#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# This is not an autoconf generated configure
#

# Output file which is input to Makefile
CONFIG_FINAL=config.mk
CONFIG=".${CONFIG}.tmp"

# Make a temp directory in build tree.
TMPDIR=$(mktemp -d config.XXXXXX)
trap 'status=$?; rm -rf $TMPDIR; rm -f $CONFIG; exit $status' EXIT HUP INT QUIT TERM

check_opts()
{
    : ${PRODUCTION:=0}
    : ${DYNAMIC_LIBXDP:=0}
    : ${MAX_DISPATCHER_ACTIONS:=10}
    echo "PRODUCTION:=${PRODUCTION}" >>$CONFIG
    echo "DYNAMIC_LIBXDP:=${DYNAMIC_LIBXDP}" >>$CONFIG
    echo "MAX_DISPATCHER_ACTIONS:=${MAX_DISPATCHER_ACTIONS}" >>$CONFIG
}

check_toolchain()
{
    local emacs_version

    : ${PKG_CONFIG:=pkg-config}
    : ${CC=gcc}
    : ${CLANG=clang}
    : ${LLC=llc}
    : ${M4=m4}
    : ${EMACS=emacs}

    for TOOL in $PKG_CONFIG $CC $CLANG $LLC $M4; do
        if [ ! $(command -v ${TOOL} 2>/dev/null) ]; then
            echo "*** ERROR: Cannot find tool ${TOOL}" ;
            exit 1;
        fi;
    done

    if ! command -v $EMACS >/dev/null 2>&1; then
        EMACS=""
    else
        emacs_version=$($EMACS --version 2>/dev/null | head -n 1)
        if echo $emacs_version | grep -Eq 'GNU Emacs 2[67]'; then
            echo "using emacs: $emacs_version"
        else
            echo "not using emacs: $emacs_version"
            EMACS=""
        fi
    fi

    if [ -z "$EMACS" ] && [ "${FORCE_EMACS:-0}" -eq "1" ]; then
        echo "FORCE_EMACS is set, but no usable emacs found on system"
        rm -f "$CONFIG"
        exit 1
    fi

    echo "PKG_CONFIG:=${PKG_CONFIG}" >>$CONFIG
    echo "CC:=${CC}" >>$CONFIG
    echo "CLANG:=${CLANG}" >>$CONFIG
    echo "LLC:=${LLC}" >>$CONFIG
    echo "M4:=${M4}" >>$CONFIG
    echo "EMACS:=${EMACS}" >>$CONFIG
}

check_elf()
{
    if ${PKG_CONFIG} libelf --exists; then
        echo "HAVE_ELF:=y" >>$CONFIG
        echo "yes"

        echo 'CFLAGS += -DHAVE_ELF' `${PKG_CONFIG} libelf --cflags` >> $CONFIG
        echo 'LDLIBS += ' `${PKG_CONFIG} libelf --libs` >>$CONFIG
    else
        echo "missing - this is required"
        return 1
    fi
}

check_pcap()
{
    local libpcap_err

    if ${PKG_CONFIG} libpcap --exists; then
        LIBPCAP_CFLAGS=$(${PKG_CONFIG} libpcap --cflags)
        LIBPCAP_LDLIBS=$(${PKG_CONFIG} libpcap --libs)
    else
        LIBPCAP_CFLAGS=""
        LIBPCAP_LDLIBS="-lpcap"
    fi

    cat >$TMPDIR/libpcaptest.c <<EOF
#define PCAP_DONT_INCLUDE_PCAP_BPF_H
#include <pcap/dlt.h>
#include <pcap/pcap.h>
int main(int argc, char **argv) {
    pcap_t *pcap = pcap_open_live("ifname", 100, 1, 1000, NULL);
    return 0;
}
EOF
    libpcap_err=$($CC -o $TMPDIR/libpcaptest $TMPDIR/libpcaptest.c  $LIBPCAP_CFLAGS $LIBPCAP_LDLIBS 2>&1)
    if [ "$?" -eq "0" ]; then
        echo "HAVE_PCAP:=y" >>$CONFIG
        [ -n "$LIBPCAP_CFLAGS" ] && echo 'CFLAGS += ' $LIBPCAP_CFLAGS >> $CONFIG
        echo "yes"
    else
        echo "missing - this is required"
        echo "error: $libpcap_err"
        return 1
    fi
}

check_zlib()
{
    if ${PKG_CONFIG} zlib --exists; then
        echo "HAVE_ZLIB:=y" >>$CONFIG
        echo "yes"

        echo 'CFLAGS += -DHAVE_ZLIB' `${PKG_CONFIG} zlib --cflags` >> $CONFIG
        echo 'LDLIBS += ' `${PKG_CONFIG} zlib --libs` >>$CONFIG
    else
        echo "missing - this is required"
        return 1
    fi
}

check_perf_consume()
{
    cat >$TMPDIR/libbpftest.c <<EOF
#include <bpf/libbpf.h>
int main(int argc, char **argv) {
    perf_buffer__consume(NULL);
    return 0;
}
EOF
    libbpf_err=$($CC -o $TMPDIR/libbpftest $TMPDIR/libbpftest.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS 2>&1)
    if [ "$?" -eq "0" ]; then
        echo "HAVE_LIBBPF_PERF_BUFFER__CONSUME:=y" >>"$CONFIG"
        echo "yes"
    else
        echo "HAVE_LIBBPF_PERF_BUFFER__CONSUME:=n" >>"$CONFIG"
        echo "no"
    fi
}

check_libbpf()
{
    local libbpf_err

    if ${PKG_CONFIG} libbpf --exists || [ -n "$LIBBPF_DIR" ]; then

        if [ -n "$LIBBPF_DIR" ]; then
            LIBBPF_CFLAGS="-I${LIBBPF_DIR}/include -L${LIBBPF_DIR}/lib"
            LIBBPF_LDLIBS="-lbpf"
        else
            LIBBPF_CFLAGS=$(${PKG_CONFIG} libbpf --cflags)
            LIBBPF_LDLIBS=$(${PKG_CONFIG} libbpf --libs)
        fi

        cat >$TMPDIR/libbpftest.c <<EOF
#include <bpf/libbpf.h>
int main(int argc, char **argv) {
    void *ptr;
    DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts, .pin_root_path = "/path");
    DECLARE_LIBBPF_OPTS(bpf_xdp_set_link_opts, lopts, .old_fd = -1);
    (void) bpf_object__open_file("file", &opts);
    (void) bpf_program__name(ptr);
    (void) bpf_map__set_initial_value(ptr, ptr, 0);
    (void) bpf_set_link_xdp_fd_opts(0, 0, 0, &lopts);
    return 0;
}
EOF

        libbpf_err=$($CC -o $TMPDIR/libbpftest $TMPDIR/libbpftest.c  $LIBBPF_CFLAGS -lbpf 2>&1)
        if [ "$?" -eq "0" ]; then
            echo "SYSTEM_LIBBPF:=y" >>$CONFIG
            echo 'CFLAGS += ' $LIBBPF_CFLAGS >> $CONFIG
            echo 'LDLIBS += ' $LIBBPF_LDLIBS >>$CONFIG
            echo 'OBJECT_LIBBPF = ' >>$CONFIG
            echo system

            echo -n "perf_buffer__consume support: "
            check_perf_consume
            return 0
        fi
    else
        libbpf_err="${PKG_CONFIG} couldn't find libbpf"
    fi

    if [ "${FORCE_SYSTEM_LIBBPF:-0}" -eq "1" ]; then
        echo "FORCE_SYSTEM_LIBBPF is set, but no usable libbpf found on system"
        echo "error: $libbpf_err"
        rm -f "$CONFIG"
        exit 1
    fi

    echo submodule
    echo "SYSTEM_LIBBPF:=n" >> $CONFIG
    echo 'CFLAGS += -I$(LIB_DIR)/libbpf/src/root/usr/include' >>$CONFIG
    echo 'BPF_CFLAGS += -I$(LIB_DIR)/libbpf/src/root/usr/include' >>$CONFIG
    echo 'LDFLAGS += -L$(LIB_DIR)/libbpf/src' >>$CONFIG
    echo 'LDLIBS += -l:libbpf.a' >>$CONFIG
    echo 'OBJECT_LIBBPF = $(LIB_DIR)/libbpf/src/libbpf.a' >>$CONFIG
    if ! [ -d "lib/libbpf/src" ] && [ -f ".gitmodules" ] && [ -e ".git" ]; then
        git submodule init && git submodule update
    fi

    echo -n "ELF support: "
    check_elf || exit 1

    echo -n "pcap support: "
    check_pcap || exit 1

    echo -n "zlib support: "
    check_zlib || exit 1

    # For the build submodule library we know it does support this API, so we
    # hard code it. Also due to the fact it's hard to build a test app as
    # libbpf.a has not been build at configure time.
    echo "HAVE_LIBBPF_PERF_BUFFER__CONSUME:=y" >>"$CONFIG"
}

quiet_config()
{
    cat <<EOF
# user can control verbosity similar to kernel builds (e.g., V=1)
ifeq ("\$(origin V)", "command line")
  VERBOSE = \$(V)
endif
ifndef VERBOSE
  VERBOSE = 0
endif
ifeq (\$(VERBOSE),1)
  Q =
else
  Q = @
endif
ifeq (\$(VERBOSE),0)
MAKEFLAGS += --no-print-directory
endif


ifeq (\$(VERBOSE), 0)
    QUIET_CC       = @echo '    CC       '\$@;
    QUIET_CLANG    = @echo '    CLANG    '\$@;
    QUIET_LLC      = @echo '    LLC      '\$@;
    QUIET_LINK     = @echo '    LINK     '\$@;
    QUIET_INSTALL  = @echo '    INSTALL  '\$@;
    QUIET_M4       = @echo '    M4       '\$@;
    QUIET_GEN      = @echo '    GEN      '\$@;
endif
EOF
}

echo "# Generated config" >$CONFIG
quiet_config >> $CONFIG

check_opts
check_toolchain

echo -n "libbpf support: "
check_libbpf

if [ -n "$KERNEL_HEADERS" ]; then
    echo "kernel headers: $KERNEL_HEADERS"
    echo "CFLAGS += -I$KERNEL_HEADERS" >>$CONFIG
    echo "BPF_CFLAGS += -I$KERNEL_HEADERS" >>$CONFIG
fi

mv $CONFIG $CONFIG_FINAL
