# -*- Autoconf -*-
#
# Copyright (C) 2019-2021 ABINIT Group (Yann Pouillon)
#
# This file is part of the ABINIT software package. For license information,
# please see the COPYING file in the top-level directory of the ABINIT source
# distribution.
#

# ---------------------------------------------------------------------------- #

#
# IMPORTANT NOTE
#
# Please DO NOT EDIT this file unless you REALLY know what you are doing.
# Everything is important, in particular the order of the various commands
# executed here. YOU HAVE BEEN WARNED !
#

# ---------------------------------------------------------------------------- #

#
# Autoconf & Automake startup
#

# Initialize Autoconf
AC_PREREQ(2.59)
AC_INIT([ABINIT Common],[8.11.11],
  [https://bugs.launchpad.net/abinit/],
  [abinit-common])
AC_REVISION([Autotools support for ABINIT Common])
AC_CONFIG_AUX_DIR([config/gnu])
AC_CONFIG_MACRO_DIR([config/m4])
AC_CONFIG_SRCDIR([src/10_defs/defs_basis.F90])
AC_CONFIG_HEADERS([config.h])

# Initial setup
AC_CANONICAL_TARGET

# Disable pax to initialize Automake because it causes 'make dist' to fail
alias pax='/bin/false'
AM_INIT_AUTOMAKE([1.10 tar-ustar])
unalias pax

# Early ABINIT Common setup - the order is important!
ABI_INIT_DIRS
ABI_INIT_VERSION
ABI_INIT_CPU_INFO
ABI_INIT_OS_INFO
ABI_INIT_HEADER
ABI_INIT_ARCH

# Check for common programs
AC_PROG_MAKE_SET
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_SED
AC_PROG_AWK
AC_PROG_GREP
AC_PATH_PROG(BOURNE_SHELL, sh, /bin/sh)
AC_PATH_PROG(MV, mv, /bin/false)
AC_PATH_PROG(PERL, perl, /bin/false)
AC_PATH_PROG(RM, rm, /bin/false)
AC_CHECK_PROGS(TAR, [tar gtar star])

# Workaround for the wrong path to install-sh on Mac systems
ABI_PROG_MKDIR_P

# Look for a command that provide absolute paths
AC_CHECK_PROGS(REALPATH, [realpath readlink], [/bin/true])
test "${REALPATH}" = "readlink" && REALPATH="${REALPATH} -f"

# We might need a Python interpreter early on
ABI_PROG_PYTHON

# Define command-line arguments
ABI_OPTIONS_DEFINE

# Read config file and ensure that priorities are respected
ABI_ENV_BACKUP
ABI_OPTIONS_BACKUP
ABI_LOAD_OPTIONS
ABI_OPTIONS_CFG_TRANSFER
ABI_OPTIONS_RECALL
ABI_ENV_RECALL

# Set still undefined options
ABI_OPTIONS_SETUP

# Initialize environment, taking options into account
ABI_ENV_INIT

AC_SUBST(CC_LDFLAGS)
AC_SUBST(CC_LIBS)
AC_SUBST(CXX_LDFLAGS)
AC_SUBST(CXX_LIBS)
AC_SUBST(FC_LDFLAGS)
AC_SUBST(FC_LIBS)

# Initialize install dirs (requires version and config options to be set)
ABI_INIT_INSTALL_DIRS

# Disable wrapping of Fortran compiler by default
abi_fc_wrap="no"

# Save user-defined CPP
abi_cpp_user="${CPP}"

# Set-up required information for core libraries
ABI_CORELIBS_INIT

# Init Steredeg core features
SD_CORE_INIT

# Prepare MPI support
ABI_MPI_INIT

# GPU support requires MPI
if test "${abi_gpu_enable}" = "yes" -a "${abi_mpi_enable}" != "yes"; then
  AC_MSG_ERROR([GPU support requires MPI])
fi

# Prepare GPU support
# Note: must be done after MPI
ABI_GPU_INIT

# Set basic ABINIT Common C parameters
# Note: advanced fetaures are set later on
ABI_PROG_CC

# Set basic ABINIT Common C++ parameters
# Note: advanced fetaures are set later on
ABI_PROG_CXX

# Set basic ABINIT Common Fortran parameters
# Note: advanced fetaures are set later on
ABI_PROG_FC

# Set default file extensions
ABI_FC_EXTENSIONS

# Get module file case
ABI_FC_MOD_CASE

# Determine Fortran-C name mangling scheme
AC_FC_WRAPPERS

# The IBM Fortran compiler crashes if the mpi module is included
# more than once
if test "${abi_fc_vendor}" = "ibm" -a "${abi_mpi_enable}" = "yes"; then
  AC_MSG_NOTICE([activating MPI workaround for the IBM Fortran compiler])
  AC_DEFINE([HAVE_MPI_INCLUDED_ONCE], 1,
    [Define to 1 if you are using XLF.])
fi

# Wrap Fortran compiler calls if needed or requested
# Note: must be the last step of basic Fortran configuration
if test "${abi_fc_wrapper_enable}" = "yes"; then
  abi_fc_wrap="yes"
fi

# FIXME: obsolete mechanism
AC_SUBST(fc_mod_fcflags)

# Look for a true C preprocessor
if test "${TRUE_CPP}" = ""; then
  AC_CHECK_PROGS([TRUE_CPP],[cpp])
fi
if test "${TRUE_CPP}" = ""; then
  AC_PATH_PROG([TRUE_CPP],[cpp])
fi
if test "${TRUE_CPP}" = ""; then
  if test -x "/lib/cpp"; then
    TRUE_CPP="/lib/cpp"
  fi
fi
AC_MSG_CHECKING([for a true C preprocessor])
if test "${TRUE_CPP}" = ""; then
  AC_MSG_RESULT([none])
else
  AC_MSG_RESULT([${TRUE_CPP}])
fi

# Set Fortran preprocessor when needed
if test "${abi_fc_wrap}" = "yes"; then
  AC_MSG_CHECKING([for a Fortran-compatible C preprocessor])
  if test "${FPP}" = ""; then
    if test "${abi_cpp_user}" != ""; then
      FPP="${abi_cpp_user}"
    else
      if test "${TRUE_CPP}" != ""; then
        FPP="${TRUE_CPP}"
      else
        FPP="${CPP}"
      fi
    fi
  fi
  AC_MSG_RESULT([${FPP}])
fi

# FIXME: set CPP vendor
case "${target_os}" in
  aix*)
    abi_cpp_vendor="ibm"
    abi_xpp_vendor="ibm"
    abi_fpp_vendor="ibm"
    ;;
  *)
    abi_cpp_vendor="default"
    abi_xpp_vendor="default"
    abi_fpp_vendor="default"
    ;;
esac
case "${abi_fc_vendor}" in
  ibm)
    abi_fpp_vendor="ibm"
    ;;
esac
AC_MSG_NOTICE([setting C preprocessor vendor to '${abi_cpp_vendor}'])
AC_MSG_NOTICE([setting C++ preprocessor vendor to '${abi_xpp_vendor}'])
AC_MSG_NOTICE([setting Fortran preprocessor vendor to '${abi_fpp_vendor}'])

# Preset flags to have the source building properly
if test "${abi_hints_enable}" = "yes"; then

  # C support
  ABI_CPP_HINTS
  ABI_CC_HINTS

  # C++ support
  ABI_XPP_HINTS
  ABI_CXX_HINTS

  # Fortran support
  ABI_FPP_HINTS
  ABI_FC_HINTS

  # Library archiver support
  #ABI_AR_HINTS

fi

# Adjust OpenMP flags if not used
if test "${abi_openmp_enable}" != "yes"; then
  FCFLAGS_OPENMP=""
fi

# Set Fortran preprocessing flags
if test "${abi_fc_wrap}" = "yes"; then
  test "${FPPFLAGS}" = "" && FPPFLAGS="${FPPFLAGS_HINTS_EXT}"
fi

# Display Fortran preprocessing parameters
AC_MSG_CHECKING([which Fortran preprocessor to use])
if test "${FPP}" = ""; then
  AC_MSG_RESULT([none])
else
  AC_MSG_RESULT([${FPP}])
fi
AC_MSG_CHECKING([which Fortran preprocessor flags to apply])
if test "${FPPFLAGS}" = ""; then
  AC_MSG_RESULT([none])
else
  AC_MSG_RESULT([${FPPFLAGS}])
fi

# Display Fortran compiler wrapper status
AC_MSG_CHECKING([whether to wrap Fortran compiler calls])
AC_MSG_RESULT([${abi_fc_wrap}])

# Export true CPPFLAGS (required by LibXC)
AC_SUBST(CPPFLAGS_HINTS_EXT)

# Init debug flags
ABI_DEBUG_INIT([${abi_debug_flavor}])

# Activate "design-by-contract" debugging tests when paranoid
AC_MSG_CHECKING([whether to activate design-by-contract debugging])
if test "${abi_debug_flavor}" = "paranoid"; then
  AC_DEFINE([DEBUG_CONTRACT], 1,
    [Define to 1 if you want to activate design-by-contract debugging tests.])
  AC_MSG_RESULT([yes])
else
  AC_MSG_RESULT([no])
fi
AM_CONDITIONAL(DO_BUILD_32_CONTRACT,
  [test "${abi_debug_flavor}" = "paranoid"])

# Disable optimizations if debug mode is activated in source files
if test "${abi_debug_source}" = "yes"; then
  if test "${abi_optim_flavor}" != "none"; then
    AC_MSG_WARN([disabling optimizations])
  fi
  abi_optim_flavor="none"
fi

# Init optimization flags
# Note: must be done only once debugging is configured
ABI_OPTIM_INIT([${abi_optim_flavor}])

# FIXME: 20_datashare does not support optimizations
if test "${abi_optim_flavor}" != "none"; then
  AC_MSG_NOTICE([disabling optimizations for src/20_datashare/])
  fcflags_opt_20_datashare="-O0"
  AC_MSG_NOTICE([disabling optimizations for src/43_ptgroups/])
  fcflags_opt_43_ptgroups="-O0"
fi

# Set per-directory Fortran optimizations
# Note: must be done only once FCFLAGS_OPTIM is set
ABI_OPTFLAGS_DIRS([${FCFLAGS_OPTIM}])

# ---------------------------------------------------------------------------- #

# Set-up target and binary package names
# Note: requires knowledge of Fortran compiler
ABI_INIT_TARGET
ABINIT_BINARY_PACKAGE="${PACKAGE}-${VERSION}_${ABINIT_TARGET}"
AC_SUBST(ABINIT_BINARY_PACKAGE)

# Preserve environment
ABI_ENV_BACKUP

# Look for archiver
if test "${AR}" = ""; then
  AC_CHECK_PROGS(AR,[ar xiar])
fi

# Set archiver command flag
test "${ARFLAGS_CMD}" = "" && ARFLAGS_CMD="rc"
AC_SUBST(ARFLAGS_CMD)

# Look for ranlib
AC_PROG_RANLIB

# Restore back compile flags
CFLAGS="${abi_env_CFLAGS}"
CXXFLAGS="${abi_env_CXXFLAGS}"
FCFLAGS="${abi_env_FCFLAGS}"

# We want to be able access the archiver from anywhere
AC_SUBST(AR)
AC_SUBST(ARFLAGS)

# Report the use of libtool-related options
AC_SUBST(enable_shared)
AC_SUBST(enable_static)
AC_SUBST(with_gnu_ld)

# Final adjustments for library archiver
test "${ARFLAGS}" = "" && \
  ARFLAGS="${ARFLAGS_DEBUG} ${ARFLAGS_OPTIM} ${ARFLAGS_HINTS} ${ARFLAGS_EXTRA} ${ARFLAGS_CMD}"

# Final adjustments for C
test "${CFLAGS}" = "" && \
  CFLAGS="${CFLAGS_DEBUG} ${CFLAGS_OPTIM} ${CFLAGS_HINTS} ${CFLAGS_EXTRA}"
test "${CC_LDFLAGS}" = "" && \
  CC_LDFLAGS="${CC_LDFLAGS_DEBUG} ${CC_LDFLAGS_OPTIM} ${CC_LDFLAGS_HINTS} ${CC_LDFLAGS_EXTRA}"
test "${CC_LIBS}" = "" && \
  CC_LIBS="${CC_LIBS_DEBUG} ${CC_LIBS_OPTIM} ${CC_LIBS_HINTS} ${CC_LIBS_EXTRA}"

# Final adjustments for C++
test "${CXXFLAGS}" = "" && \
  CXXFLAGS="${CXXFLAGS_DEBUG} ${CXXFLAGS_OPTIM} ${CXXFLAGS_HINTS} ${CXXFLAGS_EXTRA}"
test "${CXX_LDFLAGS}" = "" && \
  CXX_LDFLAGS="${CXX_LDFLAGS_DEBUG} ${CXX_LDFLAGS_OPTIM} ${CXX_LDFLAGS_HINTS} ${CXX_LDFLAGS_EXTRA}"
test "${CXX_LIBS}" = "" && \
  CXX_LIBS="${CXX_LIBS_DEBUG} ${CXX_LIBS_OPTIM} ${CXX_LIBS_HINTS} ${CXX_LIBS_EXTRA}"

# Final adjustments for Fortran
# Note: FCFLAGS_OPTIM must not be included (per-directory optimizations)
test "${FCFLAGS}" = "" && \
  FCFLAGS="${FCFLAGS_DEBUG} ${FCFLAGS_HINTS} ${FCFLAGS_EXTRA} ${FCFLAGS_OPENMP}"
test "${FC_LDFLAGS}" = "" && \
  FC_LDFLAGS="${FC_LDFLAGS_DEBUG} ${FC_LDFLAGS_OPTIM} ${FC_LDFLAGS_HINTS} ${FC_LDFLAGS_EXTRA}"
test "${FC_LIBS}" = "" && \
  FC_LIBS="${FC_LIBS_DEBUG} ${FC_LIBS_OPTIM} ${FC_LIBS_HINTS} ${FC_LIBS_EXTRA}"

# Final adjustments for preprocessors
test "${CPPFLAGS}" = "" && \
  CPPFLAGS="${CPPFLAGS_DEBUG} ${CPPFLAGS_OPTIM} ${CPPFLAGS_HINTS} ${CPPFLAGS_EXTRA}"
test "${XPPFLAGS}" = "" && \
  XPPFLAGS="${XPPFLAGS_DEBUG} ${XPPFLAGS_OPTIM} ${XPPFLAGS_HINTS} ${XPPFLAGS_EXTRA}"
test "${FPPFLAGS}" = "" -a "${abi_fc_wrap}" = "no" && \
  FPPFLAGS="${FPPFLAGS_DEBUG} ${FPPFLAGS_OPTIM} ${FPPFLAGS_HINTS} ${FPPFLAGS_EXTRA}"

# FIXME: temporary workaround for Macs
if test "${abi_cpu_platform}" = "apple"; then
  AC_MSG_WARN([${abi_cpu_platform} is not able to handle full link information])
  AC_MSG_WARN([static builds will fail])
else
  AC_MSG_NOTICE([static builds may be performed])
  FC_LIBS="${FC_LIBS} ${FCLIBS}"
fi

# ---------------------------------------------------------------------------- #

# Look for desired C features
ABI_CC_FEATURES

# Look for desired Fortran features
ABI_FC_FEATURES

# Look for desired Python features
ABI_PY_FEATURES

# Platform-specific libraries
AC_MSG_CHECKING([which operating system we have])
AC_MSG_RESULT([${target_os}])

# Basic mathematical functions
AC_LANG_PUSH([C])
AC_SEARCH_LIBS([expl], [m ml],
  [abi_math_expl_ok="yes"], [abi_math_expl_ok="no"])
AC_SEARCH_LIBS([logl], [m ml],
  [abi_math_logl_ok="yes"], [abi_math_logl_ok="no"])
AC_LANG_POP([C])

# OpenMP support
AC_MSG_CHECKING([whether to enable OpenMP support])
AC_MSG_RESULT([${abi_openmp_enable}])
if test "${abi_openmp_enable}" = "yes"; then
  AC_MSG_CHECKING([Fortran flags for OpenMP])
  AC_MSG_RESULT([${FCFLAGS_OPENMP}])
  ABI_OMP_CHECK_COLLAPSE
  AC_MSG_NOTICE([OpenMP support is enabled in Fortran source code only])
fi

# MPI support
ABI_MPI_DETECT
if test "${abi_mpi_enable}" = "yes"; then
  ABI_MPI_DUMP
fi

# GPU support
ABI_GPU_DETECT

# Init FFTW3
SD_FFTW3_INIT([optional skip])

# Init Levmar
SD_LEVMAR_INIT([optional fail])

# Init LibPSML
SD_LIBPSML_INIT([optional fail])

# Init LibXC
SD_LIBXC_INIT([no-fortran optional fail])

# Init PAPI
SD_NETCDF_INIT([no-cxx optional fail])

# Init PAPI
SD_PAPI_INIT([optional fail])

# Init PFFT
SD_PFFT_INIT([optional skip])

# Init TRIQS
SD_TRIQS_INIT([optional fail])

# Init Wannier90
SD_WANNIER90_INIT([optional fail], [-lwannier90])

# Init XMLF90
SD_XMLF90_INIT([optional fail])

# Linear algebra support
SD_LINALG_INIT([required fail])
SD_LINALG_INIT_FLAVOR

SD_LINALG_DETECT

# Optimized FFT support (must be done after linear algebra is fully configured)
SD_FFT_INIT

SD_FFT_DETECT

                       # ------------------------------ #

# PAPI library support
SD_PAPI_DETECT
AC_MSG_CHECKING([whether to enable the internal ABINIT Common timer])
AC_MSG_RESULT([${abi_timer_enable}])
if test "${sd_papi_ok}" != "yes"; then
  if test "${abi_timer_enable}" = "yes"; then
    AC_DEFINE([HAVE_TIMER_ABINIT], 1,
      [Define to 1 if you want to use the ABINIT Common timer.])
  fi
fi

                       # ------------------------------ #

# NetCDF library support
SD_NETCDF_DETECT
# FIXME: quick workaround
if test "${sd_netcdf_ok}" = "yes"; then
  sd_netcdf_fcflags="${sd_netcdf_fcflags} ${sd_netcdf_cppflags}"
fi

# XMLF90 library support
SD_XMLF90_DETECT

# LibPSML library support
if test "${sd_xmlf90_ok}" = "yes"; then
  SD_LIBPSML_DETECT
else
  if test "${sd_libpsml_enable}" = "auto"; then
    sd_libpsml_enable="no"
  else
    if test "${sd_libpsml_enable}" != "no"; then
      AC_MSG_ERROR([LibPSML support has been requested but XMLF90 does not work
                  Please point the configuration to a working XMLF90
                  installation or disable LibPSML support])
    fi
  fi
fi
AM_CONDITIONAL([DO_BUILD_PSML],
  [test "${sd_libpsml_enable}" = "yes " -a "${sd_libpsml_ok}" = "yes"])

                       # ------------------------------ #

# Levmar library support
SD_LEVMAR_DETECT

                       # ------------------------------ #

# LibXC library support
#ABI_LIBXC_DETECT(2, 2)
SD_LIBXC_DETECT
AM_CONDITIONAL([DO_BUILD_01_LIBXC_EXT],
  [test "${sd_libxc_ok}" = "yes"])

# TRIQS support
SD_TRIQS_DETECT
AM_CONDITIONAL([DO_BUILD_67_TRIQS_EXT],
  [test "${sd_triqs_enable}" = "yes" -a "${sd_triqs_ok}" = "yes"])

# Wannier90 library support
SD_WANNIER90_DETECT

# Display summary table
ABI_TRIGGERS_SUMMARY

# Always generate a build script for required fallbacks
AC_OUTPUT([transient/build-abinit-fallbacks.sh])

# Check that we have all required fallbacks
ABI_FALLBACKS_VALIDATE([${abi_fbk_required}])

# Report situation
if test "${abi_fbk_required}" = ""; then
  AC_MSG_NOTICE([no fallback required - you may run production calculations])
else
  AC_MSG_NOTICE([fallbacks required - you should not run production calculations])
fi

# FIXME: copying linear algebra tarball for now,
#        ensuring ~/.abinit/tarballs/ exists
if test "${abi_fbk_linalg}" = "yes"; then
  tmp_abinit_tardir="${HOME}/.abinit/tarballs"
  tmp_linalg_tarball="lapack-abinit_6.10.tar.gz"
  if test ! -s "${tmp_abinit_tardir}/${tmp_linalg_tarball}"; then
    AC_MSG_NOTICE([using tarball repository ${tmp_abinit_tardir}])
    if test ! -e "${tmp_abinit_tardir}"; then
      AC_MSG_NOTICE([creating '${tmp_abinit_tardir}'])
      ${INSTALL} -d -m 755 "${tmp_abinit_tardir}"
    elif test ! -d "${tmp_abinit_tardir}"; then
      AC_MSG_ERROR(['${tmp_abinit_tardir}' is not a directory
        please move away the current file and reconfigure ABINIT Common])
    fi

    AC_MSG_NOTICE([installing linear algebra fallback tarball to '${tmp_abinit_tardir}'])
    ${INSTALL} -m 644 "${abinit_srcdir}/transient/${tmp_linalg_tarball}" \
      "${tmp_abinit_tardir}"
  fi
fi

# Check that all triggers or their fallbacks are working
# FIXME: triggers must not fall back if with_* options are provided
for pkg in ${abi_trig_packages}; do
  tmp_trig_errors=""
  eval tmp_pkg_ok=\"\$\{abi_${pkg}_ok\}\"
  eval tmp_fbk_ok=\"\$\{abi_fbk_${pkg}_ok\}\"
  if test "${tmp_pkg_ok}" = "no" -a "${tmp_fbk_ok}" != "yes"; then
    tmp_trig_errors="${tmp_trig_errors} ${pkg}"
  fi
done
if test "${tmp_trig_errors}" != ""; then
  for pkg in ${tmp_trig_errors}; do
    tmp_fbk_error=`echo "${abi_fbk_packages}" | grep "${pkg}"`
    AC_MSG_WARN([${pkg} support is unavailable or broken])
    if test "${tmp_fbk_error}" != ""; then
      AC_MSG_WARN([${pkg} fallback is unavailable])
    fi
  done
  AC_MSG_ERROR([some optional features were not found on this system
                  (see messages above)
                  Please correct the options of configure to match your
                  actual situation])
fi

# Defines and conditionals for CPP options
# (see config/specs/options.conf for details)
ABI_OPTIONS_CPP_DEFINES

# Wrap buggy Fortran compilers
FC_NOWRAP="${FC}"
if test "${abi_fc_wrap}" = "yes"; then
  FC="${abinit_builddir}/config/wrappers/wrap-fc"
fi
AC_SUBST(FC_NOWRAP)

# Force F77 and F90 environment variables (keep always last)
F77="${FC}"
FFLAGS="${FCFLAGS}"
F90="${FC}"
F90FLAGS="${FCFLAGS}"

# The following is required for oldish fixed-form Fortran libraries
AC_SUBST(F77)
AC_SUBST(FFLAGS)

# Void CPPFLAGS to allow for C/Fortran mixing
ABI_CPPFLAGS="${CPPFLAGS}"
CPPFLAGS=""

# FIXME: Temporary options to remove
case "${ABINIT_LEGACY_OPTION}" in
  mpi1)
    AC_DEFINE([HAVE_MPI1], 1,
      [Define to 1 if you have a MPI-1 implementation (obsolete, broken).])
    ;;
  wannier90_v1)
    AC_DEFINE([HAVE_WANNIER90_V1], 1,
      [Define to 1 if you want to use Wanner90 1.x (awfully obsolete).])
    ;;
esac

# FIXME: temporary translation of XML status
if test "${abi_libxml2_enable}" = "yes"; then
  AC_DEFINE([HAVE_XML], 1,
    [Define to 1 if you want to use LibXML2-based XML I/O.])
fi

# Output files
# Note: later, add tests/atconfig and tests/atlocal for test suite
ABI_OUTPUT

# The end
if test "${sd_linalg_flavor}" = "netlib-fallback"; then
  ABI_MSG_NOTICE([linalg-abinit],
    [Suboptimal linear algebra configuration])
fi
if test "${abi_gpu_enable}" = "yes" -a "${sd_linalg_chk_gpu}" != "magma"; then
  ABI_MSG_NOTICE([gpu-without-magma],
    [Suboptimal GPU configuration])
fi
ABI_MSG_FC_BUGGY(${abi_fc_vendor})
ABI_MSG_END
