# Anticonf (tm) script by Jeroen Ooms (2021)
# Package requires either libv8 6 and up, or legacy branch (3.14 / 3.15).
# If your libv8 is installed in a custom location you need to set
# INCLUDE_DIR and LIB_DIR manually via e.g:
# R CMD INSTALL --configure-vars='INCLUDE_DIR=/.../include LIB_DIR=/.../lib'
PKG_DEB_NAME="libv8-dev or libnode-dev"
PKG_RPM_NAME="v8-devel"
PKG_CSW_NAME="libv8_dev"
PKG_BREW_NAME="v8"
PKG_TEST_HEADER="<v8.h>"
PKG_LIBS="-lv8 -lv8_libplatform"
PKG_CFLAGS="-I/usr/include/v8 -I/usr/include/v8-3.14"

# Allow users to override PKG_LIBS and PKG_CFLAGS
if [ "$V8_PKG_LIBS" ]; then
PKG_LIBS="$V8_PKG_LIBS"
PKG_CFLAGS="$V8_PKG_CFLAGS"
DISABLE_STATIC_LIBV8=1
fi

UNAME=`uname`
UARCH=`uname -m`

# Test common production platforms
if test -f "/etc/redhat-release" && ! grep -Fq Fedora "/etc/redhat-release"; then
IS_RHEL=1
fi
if test -f "/etc/os-release" && grep -Fq Ubuntu "/etc/os-release"; then
IS_UBUNTU=1
fi
if [ "$UNAME" = "Darwin" ]; then
IS_MACOS=1
fi

# Default to static V8 on supported production platforms
if [ -z "$DISABLE_STATIC_LIBV8" ]; then
if [ "$IS_MACOS" ] || [ "$IS_UBUNTU" ] || [ "$IS_RHEL" ] || [ "$CI" ] || [ -f "/usr/lib/libv8.so.3.14.5" ]; then
if [ "$UARCH" = "x86_64" ] || [ "$UARCH" = "arm64" ] || [ "$UARCH" = "aarch64" ]; then
DOWNLOAD_STATIC_LIBV8=1
fi
fi
fi

# Use CXX17 when available, required as of libv8 version 10.2
CXX17=`${R_HOME}/bin/R CMD config CXX17` || unset CXX17

# Otherwise use CXX14 when available, required as of libv8 version 8.7.80
CXX14=`${R_HOME}/bin/R CMD config CXX14` || unset CXX14

if [ "$CXX17" ]; then
echo "Found C++17 compiler: $CXX17"
CXX_STD=CXX17
CXX="$CXX17 `${R_HOME}/bin/R CMD config CXX17STD`"
CXXFLAGS=`${R_HOME}/bin/R CMD config CXX17FLAGS`
elif [ "$CXX14" ]; then
echo "Found C++14 compiler: $CXX14"
CXX_STD=CXX14
CXX="$CXX14 `${R_HOME}/bin/R CMD config CXX14STD`"
CXXFLAGS=`${R_HOME}/bin/R CMD config CXX14FLAGS`
else
echo "Using default C++11 compiler: $CXX14"
CXX_STD=CXX11
CXX=`${R_HOME}/bin/R CMD config CXX`
CXXFLAGS=`${R_HOME}/bin/R CMD config CXXFLAGS`
fi

# Find compiler
CPPFLAGS=`${R_HOME}/bin/R CMD config CPPFLAGS`
LDFLAGS=`${R_HOME}/bin/R CMD config LDFLAGS`
CXXCPP="$CXX -E"

# Check for custom locations
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 [ "$IS_MACOS" ]; then
  if [ `command -v brew` ] && [ -z "$DOWNLOAD_STATIC_LIBV8" ]; then
    BREWDIR=`brew --prefix`
    V8HOME="$BREWDIR/opt/$PKG_BREW_NAME"
    PKG_CFLAGS="-I${V8HOME}/include -I${V8HOME}/libexec/include"
    PKG_LIBS="-L${V8HOME}/libexec $PKG_LIBS"
  else
    curl -sfL "https://autobrew.github.io/scripts/$PKG_BREW_NAME" > autobrew
    . ./autobrew
  fi
elif [ "$DOWNLOAD_STATIC_LIBV8" ]; then
  ${R_HOME}/bin/R -s -e 'curl::curl_download("http://jeroen.github.io/V8/get-v8-linux.sh","get-v8-linux.sh")' && . ./get-v8-linux.sh || true
fi

# For debugging
echo "Using CXXCPP=$CXXCPP"
echo "Using PKG_CFLAGS=$PKG_CFLAGS"
echo "Using PKG_LIBS=$PKG_LIBS"

# Test for libv8
echo "#include $PKG_TEST_HEADER" | ${CXXCPP} ${PKG_CFLAGS} ${CPPFLAGS} ${CXXFLAGS} -xc++ - >/dev/null 2>configure.log
if [ $? -ne 0 ]; then
  echo "-----------------------------[ ANTICONF ]-------------------------------"
  echo "Configuration failed to find the libv8 engine library. Try installing:"
  echo " * deb: $PKG_DEB_NAME (Debian / Ubuntu)"
  echo " * rpm: $PKG_RPM_NAME (Fedora, EPEL)"
  echo " * brew: $PKG_BREW_NAME (OSX)"
  echo " * csw: $PKG_CSW_NAME (Solaris)"
  echo "Alternatively, on Linux (x86_64) or MacOS you can set environment variable:"
  echo "    DOWNLOAD_STATIC_LIBV8=1"
  echo "to automatically download a static version of libv8."
  echo "To use a custom libv8, 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

# Test for legacy libv8 version
${CXXCPP} ${PKG_CFLAGS} ${CPPFLAGS} ${CXXFLAGS} src/legacy/test.cpp >/dev/null 2>&1
if [ $? -eq 0 ]; then
  echo "Found legacy version of libv8"
  PKG_LIBS=`echo "$PKG_LIBS" | sed -e "s/-lv8_libplatform//"`
  sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" src/legacy/Makevars.in > src/Makevars
  exit 0
fi

# Test if we need to enable pointer compression (Usually V8 8.4 and up, except for NodeJS)
echo "Running feature test for pointer compression..."
${CXX} ${PKG_CFLAGS} ${CPPFLAGS} ${CXXFLAGS} -DV8_ENABLE_CHECKS tools/test.cpp -o pctest1 ${PKG_LIBS} ${LDFLAGS} -ldl -pthread
{ ./pctest1; } 2>> configure.log
if [ $? -eq 0 ]; then
  echo "Pointer compression not needed"
  PKG_CFLAGS="$PKG_CFLAGS -DV8_ENABLE_CHECKS"
else
  echo "Enabling pointer compression"
  PKG_CFLAGS="$PKG_CFLAGS -DV8_COMPRESS_POINTERS"

  echo "Running feature test for sandbox..."
  ${CXX} ${CPPFLAGS} ${PKG_CFLAGS} ${CXXFLAGS} tools/test.cpp -o pctest2 ${LDFLAGS} ${PKG_LIBS} -ldl -pthread
  { ./pctest2; } 2> configure.log
  if [ $? -ne 0 ]; then
    if grep -Fq "sandbox" "configure.log"; then
      echo "Enabling sandbox"
      PKG_CFLAGS="$PKG_CFLAGS -DV8_ENABLE_SANDBOX"
    else
      grep 'mismatch' configure.log && exit 1
    fi
  else
    echo "Sandbox not enabled"
  fi
fi

rm -Rf pctest*

# Test the runtime V8 version is nodejs
${CXX} ${PKG_CFLAGS} ${CPPFLAGS} ${CXXFLAGS} tools/version.cpp -o v8version ${PKG_LIBS} ${LDFLAGS} -ldl -pthread || true
V8VERSION=$(./v8version) || true
case $V8VERSION in
  *"node"*)
    PKG_CFLAGS="$PKG_CFLAGS -DISNODEJS=$V8VERSION"
esac
rm -Rf v8version*

# Assume a modern V8 API
sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" -e "s|CXX11|${CXX_STD}|" src/Makevars.in > src/Makevars
exit 0
