зеркало из https://github.com/microsoft/LightGBM.git
* [R-package] started cutting over from custom R-to-C interface to R.h * replaced LGBM_SE with SEXP * fixed error about ocnflicting definitions of length * got linking working * more stuff * eliminated R CMD CHECK note about printing * switched from hard-coded include dir to the one from FindLibR.cmake * cleaned up formatting in FindLibR.cmake * commented-out everything in CI that does not touch R * more changes * trying to get better logs * tried ignoring * added error message to confirm a suspicion * still trying to find R during R CMD CHECK * restore full CI * fixed comment * Update R-package/src/cmake/modules/FindLibR.cmake * changed strategy for finding LIBR_HOME on Windows * Removed 32-bit Windows stuff in FindLibR.cmake * Update R-package/src/cmake/modules/FindLibR.cmake * Update CMakeLists.txt Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update CMakeLists.txt Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * removed some duplication in cmake scripts * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * added LIBR_CORE_LIBRARY back * small fixes to CMakeLists * simplified FindLibR.cmake * some fixes for windows * Apply suggestions from code review Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * allowed for directly passing LIBR_EXECUTABLE to FindLibR.cmake * reorganized FindLibR.cmake to catch more cases * clean up inconsistencies in R calls in FindLibR.cmake * Update R-package/src/cmake/modules/FindLibR.cmake Co-Authored-By: Nikita Titov <nekit94-08@mail.ru> * removed unnecessary log messages * removed unnecessary unset() call Co-authored-by: Nikita Titov <nekit94-08@mail.ru>
This commit is contained in:
Родитель
a8c1e0a11a
Коммит
0341906c45
|
@ -72,6 +72,12 @@ if(USE_R35)
|
|||
endif(USE_R35)
|
||||
|
||||
if(BUILD_FOR_R)
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules")
|
||||
find_package(LibR REQUIRED)
|
||||
message(STATUS "LIBR_EXECUTABLE: ${LIBR_EXECUTABLE}")
|
||||
message(STATUS "LIBR_INCLUDE_DIRS: ${LIBR_INCLUDE_DIRS}")
|
||||
message(STATUS "LIBR_CORE_LIBRARY: ${LIBR_CORE_LIBRARY}")
|
||||
include_directories(${LIBR_INCLUDE_DIRS})
|
||||
ADD_DEFINITIONS(-DLGB_R_BUILD)
|
||||
endif(BUILD_FOR_R)
|
||||
|
||||
|
@ -301,6 +307,11 @@ if(WIN32 AND (MINGW OR CYGWIN))
|
|||
TARGET_LINK_LIBRARIES(_lightgbm IPHLPAPI)
|
||||
endif()
|
||||
|
||||
if(BUILD_FOR_R)
|
||||
TARGET_LINK_LIBRARIES(lightgbm ${LIBR_CORE_LIBRARY})
|
||||
TARGET_LINK_LIBRARIES(_lightgbm ${LIBR_CORE_LIBRARY})
|
||||
endif(BUILD_FOR_R)
|
||||
|
||||
install(TARGETS lightgbm _lightgbm
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
# CMake module used to find the location of R's
|
||||
# dll and header files.
|
||||
#
|
||||
# Borrows heavily from xgboost's R package:
|
||||
#
|
||||
# * https://github.com/dmlc/xgboost/blob/master/cmake/modules/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
|
||||
|
||||
if(NOT R_ARCH)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(R_ARCH "i386")
|
||||
else()
|
||||
set(R_ARCH "x64")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ("${R_ARCH}" STREQUAL "x64"))
|
||||
message(FATAL_ERROR "LightGBM's R package currently only supports 64-bit operating systems")
|
||||
endif()
|
||||
|
||||
# Creates R.lib and R.def in the build directory for linking with MSVC
|
||||
function(create_rlib_for_msvc)
|
||||
|
||||
message("Creating R.lib and R.def")
|
||||
|
||||
# various checks and warnings
|
||||
if(NOT WIN32 OR NOT MSVC)
|
||||
message(FATAL_ERROR "create_rlib_for_msvc() can only be used with MSVC")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${LIBR_LIB_DIR}")
|
||||
message(FATAL_ERROR "LIBR_LIB_DIR, '${LIBR_LIB_DIR}', not found")
|
||||
endif()
|
||||
|
||||
find_program(GENDEF_EXE gendef)
|
||||
find_program(DLLTOOL_EXE dlltool)
|
||||
|
||||
if(NOT GENDEF_EXE OR NOT DLLTOOL_EXE)
|
||||
message(FATAL_ERROR "Either gendef.exe or dlltool.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
|
||||
execute_process(COMMAND ${GENDEF_EXE}
|
||||
"-" "${LIBR_LIB_DIR}/R.dll"
|
||||
OUTPUT_FILE "${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)
|
||||
|
||||
# R version information is used to search for R's libraries in
|
||||
# the registry on Windows. Since this code is orchestrated by
|
||||
# an R script (src/install.libs.R), that script uses R's built-ins to
|
||||
# find the version of R and pass it through as a CMake variable
|
||||
if(CMAKE_R_VERSION)
|
||||
message("R version passed into FindLibR.cmake: ${CMAKE_R_VERSION}")
|
||||
elseif(WIN32)
|
||||
message(FATAL_ERROR "Expected CMAKE_R_VERSION to be passed in on Windows but none was provided. Check src/install.libs.R")
|
||||
endif()
|
||||
|
||||
|
||||
if (NOT LIBR_EXECUTABLE)
|
||||
find_program(
|
||||
LIBR_EXECUTABLE
|
||||
NAMES R R.exe
|
||||
)
|
||||
|
||||
# CRAN may run RD CMD CHECK instead of R CMD CHECK,
|
||||
# which can lead to this infamous error:
|
||||
# 'R' should not be used without a path -- see par. 1.6 of the manual
|
||||
if(LIBR_EXECUTABLE MATCHES ".*\\.Rcheck.*")
|
||||
unset(LIBR_EXECUTABLE CACHE)
|
||||
endif()
|
||||
|
||||
# ignore the R bundled with R.app on Mac, since that is GUI-only
|
||||
if(LIBR_EXECUTABLE MATCHES ".+R\\.app.*")
|
||||
unset(LIBR_EXECUTABLE CACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Find R executable unless it has been provided directly or already found
|
||||
if (NOT LIBR_EXECUTABLE)
|
||||
if(APPLE)
|
||||
|
||||
find_library(LIBR_LIBRARIES R)
|
||||
|
||||
if(LIBR_LIBRARIES MATCHES ".*\\.framework")
|
||||
set(LIBR_HOME "${LIBR_LIBRARIES}/Resources")
|
||||
set(LIBR_EXECUTABLE "${LIBR_HOME}/R")
|
||||
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")
|
||||
endif()
|
||||
|
||||
elseif(UNIX)
|
||||
|
||||
# attempt to find R executable
|
||||
if(NOT LIBR_EXECUTABLE)
|
||||
find_program(
|
||||
LIBR_EXECUTABLE
|
||||
NO_DEFAULT_PATH
|
||||
HINTS "${CMAKE_CURRENT_BINARY_DIR}" "/usr/bin" "/usr/lib/" "/usr/local/bin/"
|
||||
NAMES R
|
||||
)
|
||||
endif()
|
||||
|
||||
# Windows
|
||||
else()
|
||||
|
||||
# if R executable not available, query R_HOME path from registry
|
||||
if(NOT LIBR_HOME)
|
||||
|
||||
# Try to find R's location in the registry
|
||||
# ref: https://cran.r-project.org/bin/windows/base/rw-FAQ.html#Does-R-use-the-Registry_003f
|
||||
get_filename_component(
|
||||
LIBR_HOME
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\R-core\\R\\${CMAKE_R_VERSION};InstallPath]"
|
||||
ABSOLUTE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT LIBR_HOME)
|
||||
get_filename_component(
|
||||
LIBR_HOME
|
||||
"[HKEY_CURRENT_USER\\SOFTWARE\\R-core\\R\\${CMAKE_R_VERSION};InstallPath]"
|
||||
ABSOLUTE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT LIBR_HOME)
|
||||
message(FATAL_ERROR "Unable to locate R executable.\
|
||||
\nEither add its location to PATH or provide it through the LIBR_EXECUTABLE CMake variable")
|
||||
endif()
|
||||
|
||||
# set exe location based on R_ARCH
|
||||
set(LIBR_EXECUTABLE "${LIBR_HOME}/bin/${R_ARCH}/R.exe")
|
||||
|
||||
endif()
|
||||
|
||||
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()
|
||||
|
||||
endif()
|
||||
|
||||
# ask R for the home path
|
||||
execute_process(
|
||||
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(normalizePath(R.home(), winslash='/'))"
|
||||
OUTPUT_VARIABLE LIBR_HOME
|
||||
)
|
||||
|
||||
# ask R for the include dir
|
||||
execute_process(
|
||||
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(normalizePath(R.home('include'), winslash='/'))"
|
||||
OUTPUT_VARIABLE LIBR_INCLUDE_DIRS
|
||||
)
|
||||
|
||||
# ask R for the lib dir
|
||||
execute_process(
|
||||
COMMAND ${LIBR_EXECUTABLE} "--slave" "--vanilla" "-e" "cat(normalizePath(R.home('lib'), winslash='/'))"
|
||||
OUTPUT_VARIABLE LIBR_LIB_DIR
|
||||
)
|
||||
|
||||
# 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}"
|
||||
)
|
||||
|
||||
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")
|
||||
|
||||
if(WIN32 AND MSVC)
|
||||
|
||||
# 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()
|
||||
|
||||
# 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
|
||||
)
|
|
@ -53,6 +53,17 @@ if (!use_precompile) {
|
|||
}
|
||||
cmake_cmd <- paste0(cmake_cmd, " -DBUILD_FOR_R=ON ")
|
||||
|
||||
# Pass in R version, used to help find R executable for linking
|
||||
R_version_string <- paste(
|
||||
R.Version()[["major"]]
|
||||
, R.Version()[["minor"]]
|
||||
, sep = "."
|
||||
)
|
||||
cmake_cmd <- sprintf(
|
||||
paste0(cmake_cmd, " -DCMAKE_R_VERSION='%s' ")
|
||||
, R_version_string
|
||||
)
|
||||
|
||||
# Check if Windows installation (for gcc vs Visual Studio)
|
||||
if (WINDOWS) {
|
||||
if (use_mingw) {
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
|
||||
// 64bit pointer
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
typedef int64_t R_xlen_t;
|
||||
typedef int64_t xlen_t;
|
||||
#else
|
||||
typedef int R_xlen_t;
|
||||
typedef int xlen_t;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -58,7 +58,7 @@
|
|||
unsigned int gccls : 3;
|
||||
};
|
||||
|
||||
typedef int R_xlen_t;
|
||||
typedef int xlen_t;
|
||||
#endif // R_VER_ABOVE_35
|
||||
|
||||
struct lgbm_primsxp {
|
||||
|
@ -110,8 +110,8 @@ typedef struct LGBM_SER {
|
|||
} LGBM_SER, *LGBM_SE;
|
||||
|
||||
struct lgbm_vecsxp {
|
||||
R_xlen_t length;
|
||||
R_xlen_t truelength;
|
||||
xlen_t length;
|
||||
xlen_t truelength;
|
||||
};
|
||||
|
||||
typedef struct VECTOR_SER {
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef LGB_R_BUILD
|
||||
#define R_NO_REMAP
|
||||
#define R_USE_C99_IN_CXX
|
||||
#include <R_ext/Error.h>
|
||||
#include <R_ext/Print.h>
|
||||
#endif
|
||||
|
||||
namespace LightGBM {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
@ -57,7 +64,6 @@ namespace LightGBM {
|
|||
if ((pointer) == nullptr) LightGBM::Log::Fatal(#pointer " Can't be NULL at %s, line %d .\n", __FILE__, __LINE__);
|
||||
#endif
|
||||
|
||||
|
||||
enum class LogLevel: int {
|
||||
Fatal = -1,
|
||||
Warning = 0,
|
||||
|
@ -65,7 +71,6 @@ enum class LogLevel: int {
|
|||
Debug = 2,
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* \brief A static Log class
|
||||
*/
|
||||
|
@ -107,19 +112,33 @@ class Log {
|
|||
vsprintf(str_buf, format, val);
|
||||
#endif
|
||||
va_end(val);
|
||||
fprintf(stderr, "[LightGBM] [Fatal] %s\n", str_buf);
|
||||
fflush(stderr);
|
||||
throw std::runtime_error(std::string(str_buf));
|
||||
|
||||
// R code should write back to R's error stream,
|
||||
// otherwise to stderr
|
||||
#ifndef LGB_R_BUILD
|
||||
fprintf(stderr, "[LightGBM] [Fatal] %s\n", str_buf);
|
||||
fflush(stderr);
|
||||
throw std::runtime_error(std::string(str_buf));
|
||||
#else
|
||||
Rf_error("[LightGBM] [Fatal] %s\n", str_buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
static void Write(LogLevel level, const char* level_str, const char *format, va_list val) {
|
||||
if (level <= GetLevel()) { // omit the message with low level
|
||||
// write to STDOUT
|
||||
printf("[LightGBM] [%s] ", level_str);
|
||||
vprintf(format, val);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
// R code should write back to R's output stream,
|
||||
// otherwise to stdout
|
||||
#ifndef LGB_R_BUILD
|
||||
printf("[LightGBM] [%s] ", level_str);
|
||||
vprintf(format, val);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
#else
|
||||
Rprintf("[LightGBM] [%s] ", level_str);
|
||||
Rvprintf(format, val);
|
||||
Rprintf("\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче