
# This configure script finds OpenSSL and Abseil, optionally building
# Abseil if not found.

# Anticonf (tm) script by Jeroen Ooms (2020) for finding OpenSSL
# This script will query 'pkg-config' for the required cflags and ldflags.
# If pkg-config is unavailable or does not find the library, try setting
# INCLUDE_DIR and LIB_DIR manually via e.g:
# R CMD INSTALL --configure-vars='INCLUDE_DIR=/.../include LIB_DIR=/.../lib'

# Library settings
PKG_CONFIG_NAME="openssl"
PKG_DEB_NAME="libssl-dev"
PKG_RPM_NAME="openssl-devel"
PKG_BREW_NAME="openssl"
PKG_LIBS="-lssl -lcrypto"
PKG_CFLAGS=""
PKG_CPPFLAGS=""

# Use pkg-config if available
pkg-config ${PKG_CONFIG_NAME} --atleast-version=1.0  2>/dev/null
if [ $? -eq 0 ]; then
  PKGCONFIG_CFLAGS=`pkg-config --cflags ${PKG_CONFIG_NAME}`
  PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME}`
fi

# Note that cflags may be empty in case of success
if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]; then
  echo "Found INCLUDE_DIR and/or LIB_DIR!"
  PKG_CFLAGS="-I$INCLUDE_DIR $PKG_CFLAGS"
  PKG_LIBS="-L$LIB_DIR $PKG_LIBS"
elif [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then
  echo "Found OpenSSL pkg-config cflags and libs!"
  PKG_CFLAGS=${PKGCONFIG_CFLAGS}
  PKG_LIBS=${PKGCONFIG_LIBS}
fi

# Find compiler
CC=`${R_HOME}/bin/R CMD config CC`
CFLAGS=`${R_HOME}/bin/R CMD config CFLAGS`
CPPFLAGS=`${R_HOME}/bin/R CMD config CPPFLAGS`

# For debugging
echo "Testing compiler OpenSSL configuration using PKG_CFLAGS=$PKG_CFLAGS"

# Test configuration
${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E tools/test_openssl.c >/dev/null 2>configure.log

# Customize the error
if [ $? -ne 0 ]; then
  echo "--------------------------- [ANTICONF] --------------------------------"
  echo "Configuration failed because $PKG_CONFIG_NAME was not found. Try installing:"
  echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)"
  echo " * rpm: $PKG_RPM_NAME (Fedora, CentOS, RHEL)"
  echo " * brew: $PKG_BREW_NAME (Mac OSX)"
  echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your"
  echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file. If pkg-config"
  echo "is unavailable you can set INCLUDE_DIR and LIB_DIR manually via:"
  echo "R CMD INSTALL --configure-vars='INCLUDE_DIR=... LIB_DIR=...'"
  echo "-------------------------- [ERROR MESSAGE] ---------------------------"
  cat configure.log
  echo "--------------------------------------------------------------------"
  exit 1
fi

# Check pkg-config for abseil-cpp, but fall back to a cmake build
# because a sufficient version of abseil-cpp is not available on
# all platforms (notably, Ubuntu 20.04 and Ubuntu 22.04).
export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:`pwd`/tools/pkgconfig"

echo "** Using PKG_CONFIG_PATH=${PKG_CONFIG_PATH}"

if [ -z "$S2_FORCE_BUNDLED_ABSEIL" ]; then
  if [ "`uname -s`" = "Linux" ]; then
    S2_FORCE_BUNDLED_ABSEIL=true
  else
    S2_FORCE_BUNDLED_ABSEIL=false
  fi
fi

if [ "$S2_FORCE_BUNDLED_ABSEIL" = "false" ] && pkg-config absl_s2 --libs >/dev/null 2>/dev/null; then
  echo "** Using abseil-cpp from pkg-config"

  PKGCONFIG_CFLAGS=`pkg-config --cflags-only-I absl_s2`
  PKGCONFIG_LIBS=`pkg-config --libs absl_s2`
  PKG_CFLAGS="${PKGCONFIG_CFLAGS} ${PKG_CFLAGS}"
  PKG_LIBS="${PKGCONFIG_LIBS} ${PKG_LIBS}"
  R_S2_ABSL_HOME=""
else
  echo "** Building abseil-cpp using cmake"

  # If the build has explicitly forced building bundled Abseil, we install to a temporary
  # directory so that R CMD check does not inspects its static libraries for disallowed
  # symbols. Otherwise, we install into the package source (more conventional).
  if [ "$S2_FORCE_BUNDLED_ABSEIL" != "false" ]; then
    CMAKE_INSTALL_PREFIX="${TMPDIR:-/tmp}/s2_absl_$$"
  else
    CMAKE_INSTALL_PREFIX="`pwd`/tools/dist"
  fi

  mkdir -p "${CMAKE_INSTALL_PREFIX}"
  if tools/build_absl.sh "${CMAKE_INSTALL_PREFIX}"; then
    echo "** Done!"
  else
    echo "** CMake build of Abseil failed"
    echo "** Abseil can be installed with:"
    echo "** - apt-get install libabsl-dev"
    echo "** - dnf install abseil-cpp-devel"
    echo "** - brew install abseil"
    echo "** If a system install of Abseil is not possible, cmake is required to build"
    echo "** the internal vendored copy."
    exit 1
  fi

  # Clean up build directory
  rm -rf tools/build

  # Depending on the cmake options this can end up in a subdirectory of lib
  ABSL_BASE_PC=`find "${CMAKE_INSTALL_PREFIX}" -name absl_base.pc`
  R_S2_PKG_CONFIG_PATH=`dirname "${ABSL_BASE_PC}"`
  R_S2_ABSL_HOME="${CMAKE_INSTALL_PREFIX}"
  export PKG_CONFIG_PATH="${R_S2_PKG_CONFIG_PATH}:${PKG_CONFIG_PATH}"
  echo "** Using PKG_CONFIG_PATH=${PKG_CONFIG_PATH}"

  # Resolve only against the pkg-config files for the copy we just built. The
  # absl_s2 file is maintained by this package; its dependencies are installed
  # alongside the vendored Abseil libraries.
  R_S2_BUNDLED_PKG_CONFIG_PATH="${R_S2_PKG_CONFIG_PATH}:`pwd`/tools/pkgconfig"
  PKGCONFIG_LIBS=`PKG_CONFIG_PATH="${R_S2_BUNDLED_PKG_CONFIG_PATH}" PKG_CONFIG_LIBDIR="${R_S2_BUNDLED_PKG_CONFIG_PATH}" pkg-config --libs absl_s2`
  if [ -z "${PKGCONFIG_LIBS}" ]; then
    echo "** Failed to resolve built vendored copy of Abseil using pkg-config"
    exit 1
  fi

  # The vendored build contains static libraries. Replace its -labsl_* flags
  # with exact archive paths so that the linker cannot select a system Abseil
  # ahead of the copy whose headers and pkg-config files are used here.
  R_S2_ABSL_LIBDIR=`PKG_CONFIG_PATH="${R_S2_BUNDLED_PKG_CONFIG_PATH}" PKG_CONFIG_LIBDIR="${R_S2_BUNDLED_PKG_CONFIG_PATH}" pkg-config --variable=libdir absl_base`
  R_S2_STATIC_LIBS=""
  for R_S2_LIB in ${PKGCONFIG_LIBS}; do
    case "${R_S2_LIB}" in
      -labsl*)
        R_S2_ARCHIVE="${R_S2_ABSL_LIBDIR}/lib${R_S2_LIB#-l}.a"
        if [ ! -f "${R_S2_ARCHIVE}" ]; then
          echo "** Failed to find vendored Abseil archive ${R_S2_ARCHIVE}"
          exit 1
        fi
        R_S2_STATIC_LIBS="${R_S2_STATIC_LIBS} ${R_S2_ARCHIVE}"
        ;;
      *)
        R_S2_STATIC_LIBS="${R_S2_STATIC_LIBS} ${R_S2_LIB}"
        ;;
    esac
  done
  PKGCONFIG_LIBS="${R_S2_STATIC_LIBS# }"

  PKG_CPPFLAGS="-I${R_S2_ABSL_HOME}/include"
  PKG_LIBS="${PKGCONFIG_LIBS} ${PKG_LIBS}"
fi

# Check compile of test file
CXX17="`${R_HOME}/bin/R CMD config CXX17`"
CXX17FLAGS=`"${R_HOME}"/bin/R CMD config CXX17FLAGS`
CXX17STD=`"${R_HOME}"/bin/R CMD config CXX17STD`

echo "Testing Abseil configuration using PKG_CPPFLAGS=${PKG_CPPFLAGS} PKG_CFLAGS=${PKG_CFLAGS}"

${CXX17} ${PKG_CPPFLAGS} ${CPPFLAGS} ${PKG_CFLAGS} ${CXX17FLAGS} ${CXX17STD} -E tools/test_absl.cc >/dev/null 2>>configure.log
if [ $? -ne 0 ]; then
  echo "Test compile failed!"
  echo "------- Error ---------"
  cat configure.log
  echo "-----------------------"
  exit 1
fi

# From apache/arrow/r/configure:
# If on Raspberry Pi, need to manually link against latomic
# See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81358 for similar example
if grep raspbian /etc/os-release >/dev/null 2>&1; then
  PKG_LIBS="-latomic $PKG_LIBS"
fi

echo "Using PKG_LIBS=$PKG_LIBS"
echo "Using PKG_CFLAGS=$PKG_CFLAGS"
echo "Using PKG_CPPFLAGS=$PKG_CPPFLAGS"

# Write to Makevars
sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@cppflags@|$PKG_CPPFLAGS|" -e "s|@libs@|$PKG_LIBS|" -e "s|@absl_home@|$R_S2_ABSL_HOME|" src/Makevars.in > src/Makevars

# Success
exit 0
