From 1b8cf2d2dcb74c5dec84e8054710503f387f8920 Mon Sep 17 00:00:00 2001 From: James Lamb Date: Sun, 29 Nov 2020 15:29:20 +0000 Subject: [PATCH] [R-package] Use command-line args to customize CMake builds (fixes #2441) (#3574) * [R-package] Use command-line args to customize CMake builds (fixes #2441) * Apply suggestions from code review Co-authored-by: Nikita Titov Co-authored-by: Nikita Titov --- .ci/test_r_package_windows.ps1 | 30 +++++++++++-------------- R-package/README.md | 29 +++++++++++++++--------- build_r.R | 40 +++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/.ci/test_r_package_windows.ps1 b/.ci/test_r_package_windows.ps1 index c538242f0..6f60044da 100644 --- a/.ci/test_r_package_windows.ps1 +++ b/.ci/test_r_package_windows.ps1 @@ -71,22 +71,6 @@ cd $env:BUILD_SOURCESDIRECTORY tzutil /s "GMT Standard Time" [Void][System.IO.Directory]::CreateDirectory($env:R_LIB_PATH) -if ($env:R_BUILD_TYPE -eq "cmake") { - $install_libs = "$env:BUILD_SOURCESDIRECTORY/R-package/src/install.libs.R" - if ($env:TOOLCHAIN -eq "MINGW") { - Write-Output "Telling R to use MinGW" - ((Get-Content -Path $install_libs -Raw) -Replace 'use_mingw <- FALSE','use_mingw <- TRUE') | Set-Content -Path $install_libs - } elseif ($env:TOOLCHAIN -eq "MSYS") { - Write-Output "Telling R to use MSYS" - ((Get-Content -Path $install_libs -Raw) -Replace 'use_msys2 <- FALSE','use_msys2 <- TRUE') | Set-Content -Path $install_libs - } elseif ($env:TOOLCHAIN -eq "MSVC") { - # no customization for MSVC - } else { - Write-Output "[ERROR] Unrecognized toolchain: $env:TOOLCHAIN" - Check-Output $false - } -} - # download R and RTools Write-Output "Downloading R and Rtools" Download-File-With-Retries -url "https://cran.r-project.org/bin/windows/base/old/$env:R_WINDOWS_VERSION/R-$env:R_WINDOWS_VERSION-win.exe" -destfile "R-win.exe" @@ -131,7 +115,19 @@ if ($env:COMPILER -ne "MSVC") { $LOG_FILE_NAME = "lightgbm.Rcheck/00check.log" if ($env:R_BUILD_TYPE -eq "cmake") { - Run-R-Code-Redirect-Stderr "commandArgs <- function(...){'--skip-install'}; source('build_r.R')"; Check-Output $? + if ($env:TOOLCHAIN -eq "MINGW") { + Write-Output "Telling R to use MinGW" + $env:BUILD_R_FLAGS = "c('--skip-install', '--use-mingw')" + } elseif ($env:TOOLCHAIN -eq "MSYS") { + Write-Output "Telling R to use MSYS" + $env:BUILD_R_FLAGS = "c('--skip-install', '--use-msys2')" + } elseif ($env:TOOLCHAIN -eq "MSVC") { + $env:BUILD_R_FLAGS = "'--skip-install'" + } else { + Write-Output "[ERROR] Unrecognized toolchain: $env:TOOLCHAIN" + Check-Output $false + } + Run-R-Code-Redirect-Stderr "commandArgs <- function(...){$env:BUILD_R_FLAGS}; source('build_r.R')"; Check-Output $? } elseif ($env:R_BUILD_TYPE -eq "cran") { Run-R-Code-Redirect-Stderr "result <- processx::run(command = 'sh', args = 'build-cran-package.sh', echo = TRUE, windows_verbatim_args = FALSE, error_on_status = TRUE)" ; Check-Output $? # Test CRAN source .tar.gz in a directory that is not this repo or below it. diff --git a/R-package/README.md b/R-package/README.md index f237f1468..795f9e695 100644 --- a/R-package/README.md +++ b/R-package/README.md @@ -115,20 +115,20 @@ By default, the package will be built with [Visual Studio Build Tools](https://v If you are using R 3.x and installation fails with Visual Studio, `LightGBM` will fall back to using [MinGW](http://mingw-w64.org/doku.php) bundled with `Rtools`. -If you want to force `LightGBM` to use MinGW (for any R version), open `R-package/src/install.libs.R` and change `use_mingw`: +If you want to force `LightGBM` to use MinGW (for any R version), pass `--use-mingw` to the installation script. -```r -use_mingw <- TRUE +```shell +Rscript build_r.R --use-mingw ``` **MSYS2 (R 4.x)** If you are using R 4.x and installation fails with Visual Studio, `LightGBM` will fall back to using [MSYS2](https://www.msys2.org/). This should work with the tools already bundled in `Rtools` 4.0. -If you want to force `LightGBM` to use MSYS2 (for any R version), open `R-package/src/install.libs.R` and change `use_msys2`: +If you want to force `LightGBM` to use MSYS2 (for any R version), pass `--use-msys2` to the installation script. -```r -use_msys2 <- TRUE +```shell +Rscript build_r.R --use-msys2 ``` #### Mac OS Preparation @@ -150,15 +150,24 @@ cd LightGBM Rscript build_r.R ``` -The `build_r.R` script builds the package in a temporary directory called `lightgbm_r`. It will destroy and recreate that directory each time you run the script. +The `build_r.R` script builds the package in a temporary directory called `lightgbm_r`. It will destroy and recreate that directory each time you run the script. That script supports the following command-line options: -Note: for the build with Visual Studio/VS Build Tools in Windows, you should use the Windows CMD or Powershell. +- `--skip-install`: Build the package tarball, but do not install it. +- `--use-gpu`: Build a GPU-enabled versioon of the library +- `--use-mingw`: Force the use of MinGW toolchain, regardless of R version. +- `--use-msys2`: Force the use of MSYS2 toolchain, regardless of R version. + +Note: for the build with Visual Studio/VS Build Tools in Windows, you should use the Windows CMD or PowerShell. ### Installing a GPU-enabled Build -Set `use_gpu` to `TRUE` in `R-package/src/install.libs.R` to enable the build with GPU support. You will need to install Boost and OpenCL first: details for installation can be found in [Installation-Guide](https://github.com/microsoft/LightGBM/blob/master/docs/Installation-Guide.rst#build-gpu-version). +You will need to install Boost and OpenCL first: details for installation can be found in [Installation-Guide](https://github.com/microsoft/LightGBM/blob/master/docs/Installation-Guide.rst#build-gpu-version). -After installing these other libraries, follow the steps in ["Installing from Source with CMake"](#install). +After installing these other libraries, follow the steps in ["Installing from Source with CMake"](#install). When you reach the step that mentions `build_r.R`, pass the flag `--use-gpu`. + +```shell +Rscript build_r.R --use-gpu +``` ### Installing Precompiled Binaries diff --git a/build_r.R b/build_r.R index b3a98c45c..ec15fa241 100644 --- a/build_r.R +++ b/build_r.R @@ -10,10 +10,42 @@ INSTALL_AFTER_BUILD <- !("--skip-install" %in% args) TEMP_R_DIR <- file.path(getwd(), "lightgbm_r") TEMP_SOURCE_DIR <- file.path(TEMP_R_DIR, "src") +USING_GPU <- "--use-gpu" %in% args +USING_MINGW <- "--use-mingw" %in% args +USING_MSYS2 <- "--use-msys2" %in% args + +recognized_args <- c( + "--skip-install" + , "--use-gpu" + , "--use-mingw" + , "--use-msys2" +) +unrecognized_args <- setdiff(args, recognized_args) +if (length(unrecognized_args) > 0L) { + msg <- paste0( + "Unrecognized arguments: " + , paste0(unrecognized_args, collapse = ", ") + ) + stop(msg) +} + +# [description] Replace statements in install.libs.R code based on +# command-line flags +.replace_flag <- function(variable_name, value, content) { + out <- gsub( + pattern = paste0(variable_name, " <-.*") + , replacement = paste0(variable_name, " <- ", as.character(value)) + , x = content + ) + return(out) +} + install_libs_content <- readLines( file.path("R-package", "src", "install.libs.R") ) -USING_GPU <- any(grepl("use_gpu.*TRUE", install_libs_content)) +install_libs_content <- .replace_flag("use_gpu", USING_GPU, install_libs_content) +install_libs_content <- .replace_flag("use_mingw", USING_MINGW, install_libs_content) +install_libs_content <- .replace_flag("use_msys2", USING_MSYS2, install_libs_content) # R returns FALSE (not a non-zero exit code) if a file copy operation # breaks. Let's fix that @@ -75,6 +107,12 @@ result <- file.copy( ) .handle_result(result) +# overwrite src/install.libs.R with new content based on command-line flags +writeLines( + text = install_libs_content + , con = file.path(TEMP_SOURCE_DIR, "install.libs.R") +) + # Add blank Makevars files result <- file.copy( from = file.path(TEMP_R_DIR, "inst", "Makevars")