#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

die() {
    echo "$@" 1>&2 ; exit 1
}

arg ()
{
    echo "$1" | sed "s/^${2-[^=]*=}//"
}

# Detect directory information.
source_dir=`cd "\`dirname \"$0\"\`";pwd`
binary_dir=`pwd`

# Choose the default install prefix.
default_prefix="/opt/dependency/package"

# Display bootstrap usage
usage() {
echo '
Usage: '"$0"' [<options>]
Options: [defaults in brackets after descriptions]
Configuration:
    --help                          print this message
    --prefix=PREFIX                 install files in tree rooted at PREFIX
                                    ['"${default_prefix}"']
    --enable-coverage               enable code coverage, must be used together with --enable-debug
    --enable-debug                  enable debug build
    --enable-avx                    enable avx for vector instruction optimization
'
    exit 10
}

# Parse arguments
prefix_dir="${default_prefix}"
build_type="Release"
enable_coverage="OFF"
enable_avx="ON"
while test $# != 0; do
    case "$1" in
    --prefix=*) dir=`arg "$1"`
                prefix_dir="$dir";;
	--enable-coverage) enable_coverage="ON"
                       build_type="Debug";;
    --enable-debug) build_type="Debug";;
    --enable-avx=*) avx=`arg "$1"`
                    enable_avx="$avx";;
    --help) usage ;;
    *) die "Unknown option: $1" ;;
    esac
    shift
done

if [ ${source_dir} = ${binary_dir} ]; then
	die "cannot build the project in the source directory! Out-of-source build is enforced!"
fi

enable_avx_upper=`echo "${enable_avx}" | tr [a-z] [A-Z]`
if [ ${enable_avx_upper} != "ON" ] && [ ${enable_avx_upper} != "OFF" ]; then
    die "unknown value for option enable-avx: ${enable_avx}, valid options are: on and off"
fi

# Check clang compiler
if [[ x"${CC}" = x"" ]]; then
    CC=gcc
fi

if [[ x"${CXX}" = x"" ]]; then
    CXX=g++
fi

c_compiler=`which ${CC}`
cxx_compiler=`which ${CXX}`
cmake=`which cmake`

if [ ! -x ${c_compiler} ]; then
    die "cannot found c compiler"
fi

if [ ! -x ${cxx_compiler} ]; then
    die "cannot found c++ compiler"
fi

if [ ! -x ${cmake} ]; then
    die "cannot found cmake"
fi

# Configure 
${cmake} -DCMAKE_BUILD_TYPE=${build_type} -DCMAKE_INSTALL_PREFIX=${prefix_dir} -DCMAKE_C_COMPILER=${c_compiler} -DCMAKE_CXX_COMPILER=${cxx_compiler} -DENABLE_COVERAGE=${enable_coverage} -DENABLE_AVX=${enable_avx_upper} ${source_dir} || die "failed to configure the project"

echo 'bootstrap success. Run "make" to build.'
