#!/bin/bash -eu

set -o pipefail

. "$AUTOBUILD_ROOT/lib/build.sh"

"${AUTOBUILD_ROOT}/detect_source_root"

if [ -L _codeql_detected_source_root ]; then
  cd "$(readlink _codeql_detected_source_root)"
fi

configure_prefix_opt=
if [ -f configure.ac ] || [ -f configure.in ]; then
  # If a project seems to be autoconf-based, add this option to configure. It
  # is required by glibc, and it should do no harm for other projects.
  configure_prefix_opt="--prefix=/usr"
fi

function try_configure() {
  build_dir=.
  root_dir=.
  if grep -q 'AC_MSG_.* configure in a separate.* directory' \
        configure.in configure.ac 2>/dev/null; then
    # Keeping build artifacts separate from the source is always good practice,
    # but it is likely to be the least tested mode for most projects, so we only
    # do it if the configure script seems to require or suggest it. It is
    # required by glibc.
    build_dir=_codeql_build_dir
    root_dir=..
    mkdir -p "$build_dir"
  fi

  # The name `configure.gnu` is mentioned as an alternative to `configure` in
  # the autoconf manual and is used by Perl 5.
  for configure in configure configure.gnu; do
    if [ -x $configure ]; then
      cd $build_dir
      "${AUTOBUILD_ROOT}/wrappers/configure-wrapper" \
        $root_dir/$configure $configure_prefix_opt  \
        && [ -f Makefile ] \
        && exit 0
      cd $root_dir
    fi
  done
  # In case configure failed, don't leave a broken _codeql_build_dir that will
  # get picked up by `do-build`.
  rm -rf _codeql_build_dir
}

if [ -f CMakeLists.txt ]; then
  CMAKE_OPTS=(
      -DCMAKE_VERBOSE_MAKEFILE=ON
      -DBUILD_DOCS=OFF
      -DCATKIN_ENABLE_TESTING=OFF
      -DBUILD_DOCUMENTATION=OFF
      -DCMAKE_BUILD_TYPE=Release
      -DCMAKE_CXX_FLAGS="${CXXFLAGS:-}"
      -DCMAKE_C_FLAGS="${CFLAGS:-}"
  )

  mkdir -p _codeql_build_dir
  cd _codeql_build_dir
  if [[ "${CODEQL_EXTRACTOR_CPP_AUTOINSTALL_DEPENDENCIES:-}" == "true" ]]; then
    # not calling wrapper directly to avoid the full path leaking into diagnostics
    PATH="${AUTOBUILD_ROOT}/wrappers:$PATH" try_running --name cmake cmake-wrapper "${CMAKE_OPTS[@]}" .. && exit 0
  else
    try_running cmake "${CMAKE_OPTS[@]}" .. && exit 0
  fi
  cd ..
  # In case CMake failed, don't leave a broken _codeql_build_dir that will
  # get picked up by `do-build`.
  rm -rf _codeql_build_dir
fi

if [ -f meson.build ]; then
  mkdir -p _codeql_build_dir
  cd _codeql_build_dir
  try_running meson .. && exit 0
  cd ..
  # In case meson failed, don't leave a broken _codeql_build_dir that will
  # get picked up by `do-build`.
  rm -rf _codeql_build_dir
fi

try_configure

# The script that invokes autotools is by convention most often called
# autogen.sh, but we also try a few other names. The following are the most
# popular names according to the build instructions in OS X Homebrew, found
# with:
# $ find /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula \
#     -name \*.rb | xargs cat \
#     | grep -o 'system .* if build.head' | sort | uniq -c | sort -n
for bootstrap in bootstrap.sh bootstrap autogen.sh; do
  if [ -x $bootstrap ]; then
    try_running ./$bootstrap && try_configure
    break
  elif [ -f $bootstrap ]; then
    try_running --name-from-full-cmd bash $bootstrap && try_configure
    break
  fi
done

# The Waf "meta build system"
if [ -f wscript ]; then
  # Projects using the Waf build system often have it embedded in the
  # repository. If not, we will copy it in.
  if ! [ -x waf ] && [ -x /opt/work/autobuild/waf ]; then
    cp /opt/work/autobuild/waf .
  fi

  if [ -x waf ]; then
    try_running --name-from-full-cmd ./waf configure && exit 0
  fi
fi

if [ -f Kbuild ] && [ -f Kconfig ]; then
  # This is some variation of the Linux kernel build system
  try_running --name-from-full-cmd make defconfig && exit 0
fi

# If we've fallen through to here then configure has failed. But if the project
# still seems to use autotools then we run autoreconf, which is a wrapper that
# runs autoconf, automake and releated tools.
if [ -f configure.ac ] || [ -f configure.in ]; then
  # configure refuses to run if this file does not exist. This is a lint check
  # to help the author, not something we should stop the build on.
  # See https://www.gnu.org/software/autoconf/manual/autoconf.html, in the
  # bullet labeled "Macro: AC_PROG_INSTALL".
  touch install-sh

  [[ -x $(which glibtoolize) ]] && try_running glibtoolize -ci # The name of libtoolize via macOS homebrew libtool.
  [[ -x $(which libtoolize) ]] && try_running libtoolize -ci   # Assumption: at most one of these is available.
  try_running autoreconf -i

  try_configure
fi

# If there is one or more *.pro files, it may be a Qt project. A successful
# run of QMake will overwrite `Makefile`, so we only try QMake if there is no
# `Makefile` already.
if [ "$(echo ./*.pro)" != "./*.pro" ] && ! [ -f Makefile ]; then
  if [[ "${CODEQL_EXTRACTOR_CPP_AUTOINSTALL_DEPENDENCIES:-}" == "true" ]]; then
    # not calling wrapper directly to avoid the full path leaking into diagnostics
    PATH="${AUTOBUILD_ROOT}/wrappers:$PATH" try_running --name qmake qmake-wrapper && exit 0
  else
    try_running qmake && exit 0
  fi

fi

# config.m4 files indicate a php extension, that require phpize
if [ -f config.m4 ] && which phpize 2> /dev/null; then
  try_running phpize && try_configure
fi

# Nothing worked. Hopefully that just means nothing had to be done.
exit 0
