#!/bin/bash
# configure script adapter for Meson
# Based on build-api: https://github.com/cgwalters/build-api
# Copyright 2010, 2011, 2013 Colin Walters <walters@verbum.org>
# Copyright 2016 Emmanuele Bassi
# Copyright 2017 Niels De Graef
# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php)

# Build API variables:
# buildapi-variable-require-builddir

shopt -s extglob

# Configurable Options (for more info, run 'meson configure')
# ====================
DIRECTORY_OPTIONS='--@(prefix|bindir|sbindir|libexecdir|datadir|sysconfdir|libdir|mandir|includedir)'
# Keep this in sync with meson_options.txt
PROJECT_OPTIONS='--@(pgp-support|check-compatible-gpg|pkcs11-support|keyservers-support|hkp-support|ldap-support|key-sharing)'

# The configurable option values
declare -A option_values

# Little helper function for reading args from the commandline.
# it automatically handles -a b and -a=b variants, and returns 1 if
# we need to shift $3.
read_arg() {
    # $1 = arg name
    # $2 = arg value
    # $3 = arg parameter
    local rematch='^[^=]*=(.*)$'
    if [[ $2 =~ $rematch ]]; then
      option_values["$1"]="${BASH_REMATCH[1]}"
    else
      option_values["$1"]="$3"
      # There is no way to shift our callers args, so
      # return 1 to indicate they should do it instead.
      return 1
    fi
}

options2list() {
    local pattern="$1"
    local pattern="${pattern#--@(}"
    local pattern="${pattern%)}"
    IFS=\| read -a "$2" <<<"${pattern#--@(}"
}

sanitycheck() {
    # $1 = arg name
    # $1 = arg command
    # $2 = arg alternates
    local cmd=$( which $2 2>/dev/null )

    if [ -x "$cmd" ]; then
        read "$1" <<< "$cmd"
        return 0
    fi

    test -z $3 || {
        for alt in $3; do
            cmd=$( which $alt 2>/dev/null )

            if [ -x "$cmd" ]; then
                read "$1" <<< "$cmd"
                return 0
            fi
        done
    }

    echo -e "\e[1;31mERROR\e[0m: Command '$2' not found"
    exit 1
}

# First check if our build system is installed
sanitycheck MESON 'meson'
sanitycheck NINJA 'ninja' 'ninja-build'

# convert the patterns into actual lists
options2list "${DIRECTORY_OPTIONS}" 'dir_list'
options2list "${PROJECT_OPTIONS}" 'project_option_list'

# Parse the options
while (($# > 0)); do
    option="${1%%=*}"
    option_name=${option#--}

    case "${option}" in
      --prefix) read_arg "${option_name}" "$@" || shift;;
      ${DIRECTORY_OPTIONS}) read_arg "${option_name}" "$@" || shift;;
      ${PROJECT_OPTIONS}) read_arg "${option_name}" "$@" || shift;;
      # Special case for datarootdir: not understood by meson
      --datarootdir) read_arg "datadir" "$@" || shift;;
      *) echo -e "\e[1;33mINFO\e[0m: Ignoring unknown option '$1'";;
    esac
    shift
done

# Deduce directories
prefix="${option_values['prefix']:-/usr/local}"
option_values['prefix']="${prefix}"
option_values['bindir']="${option_values['bindir']:-${prefix}/bin}"
option_values['sbindir']="${option_values['sbindir']:-${prefix}/sbin}"
option_values['libexecdir']="${option_values['libexecdir']:-${prefix}/bin}"
option_values['datarootdir']="${option_values['datarootdir']:-${prefix}/share}"
option_values['datadir']="${option_values['datarootdir']}"
option_values['sysconfdir']="${option_values['sysconfdir']:-${prefix}/etc}"
option_values['libdir']="${option_values['libdir']:-${prefix}/lib}"
option_values['mandir']="${option_values['mandir']:-${prefix}/share/man}"
option_values['includedir']="${option_values['includedir']:-${prefix}/include}"

# The source directory is the location of this file
srcdir="$(dirname $0)"

# The bild directory is the current directory
builddir="$(pwd)"

# Wrapper Makefile for Ninja
cat > Makefile <<END
# Generated by configure; do not edit

all:
	CC="\$(CC)" CXX="\$(CXX)" ${NINJA}

install:
	DESTDIR="\$(DESTDIR)" ${NINJA} install
END


# Summary
column_width=16

echo "Summary:"
echo "    meson:........... ${MESON}"
echo "    ninja:........... ${NINJA}"
echo "Directories:"
for dir in "${dir_list[@]}";do
  padding_len=$(( ${column_width} - ${#dir} ))
  padding="$(printf '.%.0s' $(seq 1 ${padding_len}))"
  value=${option_values[${dir}]}
  echo "    ${dir}:${padding} ${value}"
done
echo "Project options:"
for opt in "${project_option_list[@]}";do
  padding_len=$(( $column_width - ${#opt} ))
  padding="$(printf '.%.0s' $(seq 1 $padding_len))"
  value=${option_values[$opt]:-<use_default>}
  echo "    ${opt}:${padding} ${value}"
done

# Add arguments to meson
meson_args=()
# Directories
for dir in "${dir_list[@]}";do
  value="${option_values[$dir]}"
  meson_args+=(--${dir}="${value}")
done
# Project options (only add if set)
for opt in "${project_option_list[@]}";do
  value="${option_values[$opt]}"
  [[ -n "${value}" ]] && meson_args+=(-D${opt}="${value}")
done


set -x
${MESON} "${meson_args[@]}" "${srcdir}" "${builddir}"
