From 84bdf25798435b41d3639fadb55a18d19eefd80c Mon Sep 17 00:00:00 2001 From: James Lamb Date: Wed, 1 Apr 2020 17:18:52 +0100 Subject: [PATCH] [R-package] adding routine registration in R package (fixes #1910) (#2911) --- .ci/test_r_package.sh | 2 +- CMakeLists.txt | 11 +++++-- R-package/.Rbuildignore | 14 +++++---- R-package/src/install.libs.R | 19 ++++++++---- src/lightgbm_R.cpp | 53 ++++++++++++++++++++++++++++++++ windows/LightGBM.vcxproj | 3 -- windows/LightGBM.vcxproj.filters | 9 ------ 7 files changed, 84 insertions(+), 27 deletions(-) diff --git a/.ci/test_r_package.sh b/.ci/test_r_package.sh index 0e660ba8581b..30254f8ecf70 100755 --- a/.ci/test_r_package.sh +++ b/.ci/test_r_package.sh @@ -91,7 +91,7 @@ if grep -q -R "WARNING" "$LOG_FILE_NAME"; then exit -1 fi -ALLOWED_CHECK_NOTES=3 +ALLOWED_CHECK_NOTES=2 NUM_CHECK_NOTES=$( cat ${LOG_FILE_NAME} \ | grep -e '^Status: .* NOTE.*' \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 895f2dd26fce..e0734b0534ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,7 +235,15 @@ file(GLOB SOURCES ) add_executable(lightgbm src/main.cpp ${SOURCES}) -add_library(_lightgbm SHARED src/c_api.cpp src/lightgbm_R.cpp ${SOURCES}) +list(APPEND SOURCES "src/c_api.cpp") + +# Only build the R part of the library if building for +# use with the R package +if(BUILD_FOR_R) + list(APPEND SOURCES "src/lightgbm_R.cpp") +endif(BUILD_FOR_R) + +add_library(_lightgbm SHARED ${SOURCES}) if(MSVC) set_target_properties(_lightgbm PROPERTIES OUTPUT_NAME "lib_lightgbm") @@ -308,7 +316,6 @@ if(WIN32 AND (MINGW OR CYGWIN)) endif() if(BUILD_FOR_R) - TARGET_LINK_LIBRARIES(lightgbm ${LIBR_CORE_LIBRARY}) TARGET_LINK_LIBRARIES(_lightgbm ${LIBR_CORE_LIBRARY}) endif(BUILD_FOR_R) diff --git a/R-package/.Rbuildignore b/R-package/.Rbuildignore index 309a82858cbc..3a542101392a 100644 --- a/R-package/.Rbuildignore +++ b/R-package/.Rbuildignore @@ -4,20 +4,22 @@ ^pkgdown$ # Objects created by compilation -\.o$ -\.so$ -\.dll$ -\.out$ -\.bin$ +^.*\.o +^.*\.so +^.*\.dll +^.*\.out +^.*\.bin # Code copied in at build time ^src/CMakeLists.txt$ +^Makefile$ +^src/build/.*$ # unnecessary files from submodules ^src/compute/.appveyor.yml$ ^src/compute/.coveralls.yml$ ^src/compute/.travis.yml$ -^src/compute/test/$ +^src/compute/test/.*$ ^src/compute/index.html$ ^src/compute/.git$ ^src/compute/.gitignore$ diff --git a/R-package/src/install.libs.R b/R-package/src/install.libs.R index f6d2335b2cd8..a79c93d846b7 100644 --- a/R-package/src/install.libs.R +++ b/R-package/src/install.libs.R @@ -43,7 +43,7 @@ if (!use_precompile) { # Prepare installation steps cmake_cmd <- "cmake " build_cmd <- "make _lightgbm" - lib_folder <- file.path(R_PACKAGE_SOURCE, "src", fsep = "/") + lib_folder <- file.path(source_dir, fsep = "/") if (use_gpu) { cmake_cmd <- paste0(cmake_cmd, " -DUSE_GPU=ON ") @@ -98,7 +98,7 @@ if (!use_precompile) { } else { cmake_cmd <- paste0(cmake_cmd, local_vs_def) build_cmd <- "cmake --build . --target _lightgbm --config Release" - lib_folder <- file.path(R_PACKAGE_SOURCE, "src/Release", fsep = "/") + lib_folder <- file.path(source_dir, "Release", fsep = "/") } } } @@ -110,9 +110,7 @@ if (!use_precompile) { # Makefile. We don't need it here anyway since targets are built serially, so trying # to remove it with this hack generated_makefile <- file.path( - R_PACKAGE_SOURCE - , "src" - , "build" + build_dir , "Makefile" ) if (file.exists(generated_makefile)) { @@ -163,12 +161,21 @@ if (!use_precompile) { } } -# Check installation correctness +# Packages with install.libs.R need to copy some artifacts into the +# expected places in the package structure. +# see https://cran.r-project.org/doc/manuals/r-devel/R-exts.html#Package-subdirectories, +# especially the paragraph on install.libs.R dest <- file.path(R_PACKAGE_DIR, paste0("libs", R_ARCH), fsep = "/") dir.create(dest, recursive = TRUE, showWarnings = FALSE) if (file.exists(src)) { print(paste0("Found library file: ", src, " to move to ", dest)) file.copy(src, dest, overwrite = TRUE) + + symbols_file <- file.path(source_dir, "symbols.rds") + if (file.exists(symbols_file)) { + file.copy(symbols_file, dest, overwrite = TRUE) + } + } else { stop(paste0("Cannot find lib_lightgbm", SHLIB_EXT)) } diff --git a/src/lightgbm_R.cpp b/src/lightgbm_R.cpp index 1c8c52324661..7d3a8dcafe80 100644 --- a/src/lightgbm_R.cpp +++ b/src/lightgbm_R.cpp @@ -16,6 +16,8 @@ #include #include +#include + #define COL_MAJOR (0) #define R_API_BEGIN() \ @@ -656,3 +658,54 @@ LGBM_SE LGBM_BoosterDumpModel_R(LGBM_SE handle, EncodeChar(out_str, inner_char_buf.data(), buffer_len, actual_len, static_cast(out_len)); R_API_END(); } + +// .Call() calls +static const R_CallMethodDef CallEntries[] = { + {"LGBM_GetLastError_R" , (DL_FUNC) &LGBM_GetLastError_R , 3}, + {"LGBM_DatasetCreateFromFile_R" , (DL_FUNC) &LGBM_DatasetCreateFromFile_R , 5}, + {"LGBM_DatasetCreateFromCSC_R" , (DL_FUNC) &LGBM_DatasetCreateFromCSC_R , 10}, + {"LGBM_DatasetCreateFromMat_R" , (DL_FUNC) &LGBM_DatasetCreateFromMat_R , 7}, + {"LGBM_DatasetGetSubset_R" , (DL_FUNC) &LGBM_DatasetGetSubset_R , 6}, + {"LGBM_DatasetSetFeatureNames_R" , (DL_FUNC) &LGBM_DatasetSetFeatureNames_R , 3}, + {"LGBM_DatasetGetFeatureNames_R" , (DL_FUNC) &LGBM_DatasetGetFeatureNames_R , 5}, + {"LGBM_DatasetSaveBinary_R" , (DL_FUNC) &LGBM_DatasetSaveBinary_R , 3}, + {"LGBM_DatasetFree_R" , (DL_FUNC) &LGBM_DatasetFree_R , 2}, + {"LGBM_DatasetSetField_R" , (DL_FUNC) &LGBM_DatasetSetField_R , 5}, + {"LGBM_DatasetGetFieldSize_R" , (DL_FUNC) &LGBM_DatasetGetFieldSize_R , 4}, + {"LGBM_DatasetGetField_R" , (DL_FUNC) &LGBM_DatasetGetField_R , 4}, + {"LGBM_DatasetUpdateParamChecking_R", (DL_FUNC) &LGBM_DatasetUpdateParamChecking_R, 3}, + {"LGBM_DatasetGetNumData_R" , (DL_FUNC) &LGBM_DatasetGetNumData_R , 3}, + {"LGBM_DatasetGetNumFeature_R" , (DL_FUNC) &LGBM_DatasetGetNumFeature_R , 3}, + {"LGBM_BoosterCreate_R" , (DL_FUNC) &LGBM_BoosterCreate_R , 4}, + {"LGBM_BoosterFree_R" , (DL_FUNC) &LGBM_BoosterFree_R , 2}, + {"LGBM_BoosterCreateFromModelfile_R", (DL_FUNC) &LGBM_BoosterCreateFromModelfile_R, 3}, + {"LGBM_BoosterLoadModelFromString_R", (DL_FUNC) &LGBM_BoosterLoadModelFromString_R, 3}, + {"LGBM_BoosterMerge_R" , (DL_FUNC) &LGBM_BoosterMerge_R , 3}, + {"LGBM_BoosterAddValidData_R" , (DL_FUNC) &LGBM_BoosterAddValidData_R , 3}, + {"LGBM_BoosterResetTrainingData_R" , (DL_FUNC) &LGBM_BoosterResetTrainingData_R , 3}, + {"LGBM_BoosterResetParameter_R" , (DL_FUNC) &LGBM_BoosterResetParameter_R , 3}, + {"LGBM_BoosterGetNumClasses_R" , (DL_FUNC) &LGBM_BoosterGetNumClasses_R , 3}, + {"LGBM_BoosterUpdateOneIter_R" , (DL_FUNC) &LGBM_BoosterUpdateOneIter_R , 2}, + {"LGBM_BoosterUpdateOneIterCustom_R", (DL_FUNC) &LGBM_BoosterUpdateOneIterCustom_R, 5}, + {"LGBM_BoosterRollbackOneIter_R" , (DL_FUNC) &LGBM_BoosterRollbackOneIter_R , 2}, + {"LGBM_BoosterGetCurrentIteration_R", (DL_FUNC) &LGBM_BoosterGetCurrentIteration_R, 3}, + {"LGBM_BoosterGetUpperBoundValue_R" , (DL_FUNC) &LGBM_BoosterGetUpperBoundValue_R , 3}, + {"LGBM_BoosterGetLowerBoundValue_R" , (DL_FUNC) &LGBM_BoosterGetLowerBoundValue_R , 3}, + {"LGBM_BoosterGetEvalNames_R" , (DL_FUNC) &LGBM_BoosterGetEvalNames_R , 5}, + {"LGBM_BoosterGetEval_R" , (DL_FUNC) &LGBM_BoosterGetEval_R , 4}, + {"LGBM_BoosterGetNumPredict_R" , (DL_FUNC) &LGBM_BoosterGetNumPredict_R , 4}, + {"LGBM_BoosterGetPredict_R" , (DL_FUNC) &LGBM_BoosterGetPredict_R , 4}, + {"LGBM_BoosterPredictForFile_R" , (DL_FUNC) &LGBM_BoosterPredictForFile_R , 10}, + {"LGBM_BoosterCalcNumPredict_R" , (DL_FUNC) &LGBM_BoosterCalcNumPredict_R , 8}, + {"LGBM_BoosterPredictForCSC_R" , (DL_FUNC) &LGBM_BoosterPredictForCSC_R , 14}, + {"LGBM_BoosterPredictForMat_R" , (DL_FUNC) &LGBM_BoosterPredictForMat_R , 11}, + {"LGBM_BoosterSaveModel_R" , (DL_FUNC) &LGBM_BoosterSaveModel_R , 4}, + {"LGBM_BoosterSaveModelToString_R" , (DL_FUNC) &LGBM_BoosterSaveModelToString_R , 6}, + {"LGBM_BoosterDumpModel_R" , (DL_FUNC) &LGBM_BoosterDumpModel_R , 6}, + {NULL, NULL, 0} +}; + +void R_init_lightgbm(DllInfo *dll) { + R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); + R_useDynamicSymbols(dll, FALSE); +} diff --git a/windows/LightGBM.vcxproj b/windows/LightGBM.vcxproj index 6e15af50c5f6..0f814a341977 100644 --- a/windows/LightGBM.vcxproj +++ b/windows/LightGBM.vcxproj @@ -237,13 +237,11 @@ - - @@ -308,7 +306,6 @@ - diff --git a/windows/LightGBM.vcxproj.filters b/windows/LightGBM.vcxproj.filters index 11852bcb986d..f122c865afee 100644 --- a/windows/LightGBM.vcxproj.filters +++ b/windows/LightGBM.vcxproj.filters @@ -183,12 +183,6 @@ src\metric - - include\LightGBM - - - include\LightGBM - src\boosting @@ -296,9 +290,6 @@ src\boosting - - src - src\boosting