#!/bin/sh

# Copyright © Tavian Barnes <tavianator@tavianator.com>
# SPDX-License-Identifier: 0BSD

# bfs build configuration script

set -eu

# Default to `make`
MAKE="${MAKE:-make}"

# Pass -j$(nproc) unless MAKEFLAGS is set
if [ "${MAKEFLAGS+y}" ]; then
    j=""
else
    j="-j$({ nproc || sysctl -n hw.ncpu || getconf _NPROCESSORS_ONLN || echo 1; } 2>/dev/null)"
fi

for arg; do
    case "$arg" in
        -h|--help)
            cat <<EOF
Usage:

  \$ $0 [--enable-*|--disable-*] [CC=...] [CFLAGS=...] [...]
  \$ $MAKE $j

Variables set in the environment or on the command line will be picked up:

  MAKE
      The make implementation to use
  CC
      The C compiler to use

  CPPFLAGS="-I... -D..."
  CFLAGS="-W... -f..."
  LDFLAGS="-L... -Wl,..."
      Preprocessor/compiler/linker flags

  LDLIBS="-l... -l..."
      Dynamic libraries to link

  EXTRA_{CPPFLAGS,CFLAGS,LDFLAGS,LDLIBS}
      Adds to the default flags, instead of replacing them

The default flags result in a plain debug build.  Other build profiles include:

  --enable-release
      Enable optimizations, disable assertions
  --enable-{asan,lsan,msan,tsan,ubsan}
      Enable sanitizers
  --enable-gcov
      Enable code coverage instrumentation

External dependencies are auto-detected by default, but you can --enable or
--disable them manually:

  --enable-libacl      --disable-libacl
  --enable-libcap      --disable-libcap
  --enable-libselinux  --disable-libselinux
  --enable-liburing    --disable-liburing
  --enable-oniguruma   --disable-oniguruma

Packaging:

  --prefix=/path
      Set the installation prefix (default: /usr)

This script is a thin wrapper around a makefile-based configuration system.
Any other arguments will be passed directly to the $MAKE invocation, e.g.

  \$ $0 $j V=1
EOF
            exit 0
            ;;

        --enable-*|--disable-*)
            case "$arg" in
                --enable-*) yn=y ;;
                --disable-*) yn=n ;;
            esac

            name="${arg#--*able-}"
            NAME=$(printf '%s' "$name" | tr 'a-z-' 'A-Z_')
            case "$name" in
                libacl|libcap|libselinux|liburing|oniguruma)
                    shift
                    set -- "$@" "USE_$NAME=$yn"
                    ;;
                release|asan|lsan|msan|tsan|ubsan|lint|gcov)
                    shift
                    set -- "$@" "$NAME=$yn"
                    ;;
                *)
                    printf 'error: Unrecognized option "%s"\n\n' "$arg" >&2
                    printf 'Run %s --help for more information.\n' "$0" >&2
                    exit 1
                    ;;
            esac
            ;;

        --prefix=*)
            shift
            set -- "$@" "PREFIX=${arg#*=}"
            ;;

        MAKE=*)
            MAKE="${arg#*=}"
            shift
            ;;

        # make flag (-j2) or variable (CC=clang)
        -*|*=*)
            continue
            ;;

        *)
            printf 'error: Unrecognized option "%s"\n\n' "$arg" >&2
            printf 'Run %s --help for more information.\n' "$0" >&2
            exit 1
            ;;
    esac
done

# Get the relative path to the source tree based on how the script was run
DIR=$(dirname -- "$0")

# Set up symbolic links for out-of-tree builds
for f in Makefile build completions docs src tests; do
    test -e "$f" || ln -s "$DIR/$f" "$f"
done

# Set MAKEFLAGS to -j$(nproc) if it's unset
export MAKEFLAGS="${MAKEFLAGS-$j}"

$MAKE -rf build/config.mk "$@"