xgboost/cmake/modules/FindLibR.cmake
2020-07-22 02:56:49 +08:00

194 lines
6.2 KiB
CMake

# CMake module for R
# Borrows ideas from RStudio's FindLibR.cmake
#
# Defines the following:
# LIBR_FOUND
# LIBR_HOME
# LIBR_EXECUTABLE
# LIBR_INCLUDE_DIRS
# LIBR_LIB_DIR
# LIBR_CORE_LIBRARY
# and a cmake function to create R.lib for MSVC
#
# The following could be provided by user through cmake's -D options:
# LIBR_EXECUTABLE (for unix and win)
# R_VERSION (for win)
# R_ARCH (for win 64 when want 32 bit build)
#
# TODO:
# - someone to verify OSX detection,
# - possibly, add OSX detection based on current R in PATH or LIBR_EXECUTABLE
# - improve registry-based R_HOME detection in Windows (from a set of R_VERSION's)
# Windows users might want to change this to their R version:
if(NOT R_VERSION)
set(R_VERSION "4.0.0")
endif()
if(NOT R_ARCH)
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
set(R_ARCH "i386")
else()
set(R_ARCH "x64")
endif()
endif()
# Creates R.lib and R.def in the build directory for linking with MSVC
function(create_rlib_for_msvc)
# various checks and warnings
if(NOT WIN32 OR (NOT MSVC AND NOT MINGW))
message(FATAL_ERROR "create_rlib_for_msvc() can only be used with MSVC or MINGW")
endif()
if(NOT EXISTS "${LIBR_LIB_DIR}")
message(FATAL_ERROR "LIBR_LIB_DIR was not set!")
endif()
find_program(DLLTOOL_EXE dlltool)
if(NOT DLLTOOL_EXE)
message(FATAL_ERROR "\ndlltool.exe not found!\
\nDo you have Rtools installed with its MinGW's bin/ in PATH?")
endif()
# extract symbols from R.dll into R.def and R.lib import library
get_filename_component(
LIBR_RSCRIPT_EXECUTABLE_DIR
${LIBR_EXECUTABLE}
DIRECTORY
)
set(LIBR_RSCRIPT_EXECUTABLE "${LIBR_RSCRIPT_EXECUTABLE_DIR}/Rscript")
execute_process(
COMMAND ${LIBR_RSCRIPT_EXECUTABLE}
"${CMAKE_CURRENT_BINARY_DIR}/../../R-package/inst/make-r-def.R"
"${LIBR_LIB_DIR}/R.dll" "${CMAKE_CURRENT_BINARY_DIR}/R.def"
)
execute_process(COMMAND ${DLLTOOL_EXE}
"--input-def" "${CMAKE_CURRENT_BINARY_DIR}/R.def"
"--output-lib" "${CMAKE_CURRENT_BINARY_DIR}/R.lib")
endfunction(create_rlib_for_msvc)
# detection for OSX
if(APPLE)
find_library(LIBR_LIBRARIES R)
if(LIBR_LIBRARIES MATCHES ".*\\.framework")
set(LIBR_HOME "${LIBR_LIBRARIES}/Resources" CACHE PATH "R home directory")
set(LIBR_INCLUDE_DIRS "${LIBR_HOME}/include" CACHE PATH "R include directory")
set(LIBR_EXECUTABLE "${LIBR_HOME}/R" CACHE PATH "R executable")
set(LIBR_LIB_DIR "${LIBR_HOME}/lib" CACHE PATH "R lib directory")
else()
get_filename_component(_LIBR_LIBRARIES "${LIBR_LIBRARIES}" REALPATH)
get_filename_component(_LIBR_LIBRARIES_DIR "${_LIBR_LIBRARIES}" DIRECTORY)
set(LIBR_EXECUTABLE "${_LIBR_LIBRARIES_DIR}/../bin/R")
execute_process(
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(R.home())"
OUTPUT_VARIABLE LIBR_HOME)
set(LIBR_HOME ${LIBR_HOME} CACHE PATH "R home directory")
set(LIBR_INCLUDE_DIRS "${LIBR_HOME}/include" CACHE PATH "R include directory")
set(LIBR_LIB_DIR "${LIBR_HOME}/lib" CACHE PATH "R lib directory")
endif()
# detection for UNIX & Win32
else()
# attempt to find R executable
if(NOT LIBR_EXECUTABLE)
find_program(LIBR_EXECUTABLE NAMES R R.exe)
endif()
if(UNIX)
if(NOT LIBR_EXECUTABLE)
message(FATAL_ERROR "Unable to locate R executable.\
\nEither add its location to PATH or provide it through the LIBR_EXECUTABLE cmake variable")
endif()
# ask R for the home path
execute_process(
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(R.home())"
OUTPUT_VARIABLE LIBR_HOME
)
# ask R for the include dir
execute_process(
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(R.home('include'))"
OUTPUT_VARIABLE LIBR_INCLUDE_DIRS
)
# ask R for the lib dir
execute_process(
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(R.home('lib'))"
OUTPUT_VARIABLE LIBR_LIB_DIR
)
# Windows
else()
# ask R for R_HOME
if(LIBR_EXECUTABLE)
execute_process(
COMMAND ${LIBR_EXECUTABLE} "--slave" "--no-save" "-e" "cat(normalizePath(R.home(),winslash='/'))"
OUTPUT_VARIABLE LIBR_HOME)
endif()
# if R executable not available, query R_HOME path from registry
if(NOT LIBR_HOME)
get_filename_component(LIBR_HOME
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\R-core\\R\\${R_VERSION};InstallPath]"
ABSOLUTE)
if(NOT LIBR_HOME)
message(FATAL_ERROR "\nUnable to locate R executable.\
\nEither add its location to PATH or provide it through the LIBR_EXECUTABLE cmake variable")
endif()
endif()
# set exe location based on R_ARCH
if(NOT LIBR_EXECUTABLE)
set(LIBR_EXECUTABLE "${LIBR_HOME}/bin/${R_ARCH}/R.exe")
endif()
# set other R paths based on home path
set(LIBR_INCLUDE_DIRS "${LIBR_HOME}/include")
set(LIBR_LIB_DIR "${LIBR_HOME}/bin/${R_ARCH}")
message(STATUS "LIBR_HOME [${LIBR_HOME}]")
message(STATUS "LIBR_EXECUTABLE [${LIBR_EXECUTABLE}]")
message(STATUS "LIBR_INCLUDE_DIRS [${LIBR_INCLUDE_DIRS}]")
message(STATUS "LIBR_LIB_DIR [${LIBR_LIB_DIR}]")
message(STATUS "LIBR_CORE_LIBRARY [${LIBR_CORE_LIBRARY}]")
endif()
endif()
if((WIN32 AND MSVC) OR (WIN32 AND MINGW))
# create a local R.lib import library for R.dll if it doesn't exist
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/R.lib")
create_rlib_for_msvc()
endif()
endif()
# look for the core R library
find_library(LIBR_CORE_LIBRARY NAMES R
HINTS "${CMAKE_CURRENT_BINARY_DIR}" "${LIBR_LIB_DIR}" "${LIBR_HOME}/bin" "${LIBR_LIBRARIES}")
if(LIBR_CORE_LIBRARY-NOTFOUND)
message(STATUS "Could not find R core shared library.")
endif()
set(LIBR_HOME ${LIBR_HOME} CACHE PATH "R home directory")
set(LIBR_EXECUTABLE ${LIBR_EXECUTABLE} CACHE PATH "R executable")
set(LIBR_INCLUDE_DIRS ${LIBR_INCLUDE_DIRS} CACHE PATH "R include directory")
set(LIBR_LIB_DIR ${LIBR_LIB_DIR} CACHE PATH "R shared libraries directory")
set(LIBR_CORE_LIBRARY ${LIBR_CORE_LIBRARY} CACHE PATH "R core shared library")
# define find requirements
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibR DEFAULT_MSG
LIBR_HOME
LIBR_EXECUTABLE
LIBR_INCLUDE_DIRS
LIBR_LIB_DIR
LIBR_CORE_LIBRARY
)
if(LIBR_FOUND)
message(STATUS "Found R: ${LIBR_EXECUTABLE}")
endif()