Skip to content

Commit

Permalink
[R-package] replaced gendef.exe with R code to create R.def (fixes mi…
Browse files Browse the repository at this point in the history
  • Loading branch information
jameslamb committed May 27, 2020
1 parent 8ead7cc commit 73cadba
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ R-package/src-i386
lightgbm_r/*
lightgbm*.tar.gz
lightgbm.Rcheck/
*.def

# Files created by R examples and tests
**/lgb-Dataset.data
Expand Down
16 changes: 11 additions & 5 deletions R-package/src/cmake/modules/FindLibR.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,26 @@ function(create_rlib_for_msvc)
message(FATAL_ERROR "LIBR_CORE_LIBRARY, '${LIBR_CORE_LIBRARY}', not found")
endif()

find_program(GENDEF_EXE gendef)
# find_program(GENDEF_EXE gendef)
find_program(DLLTOOL_EXE dlltool)

if(NOT GENDEF_EXE OR NOT DLLTOOL_EXE)
#if(NOT GENDEF_EXE OR NOT DLLTOOL_EXE)
if(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()

set(LIBR_MSVC_CORE_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/R.lib" CACHE PATH "R.lib filepath")

# extract symbols from R.dll into R.def and R.lib import library
execute_process(COMMAND ${GENDEF_EXE}
"-" "${LIBR_CORE_LIBRARY}"
OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/R.def"
#execute_process(COMMAND ${GENDEF_EXE}
# "-" "${LIBR_CORE_LIBRARY}"
# OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/R.def"
#)
execute_process(
COMMAND "${LIBR_HOME}/bin/Rscript"
"${CMAKE_CURRENT_BINARY_DIR}/make-r-def.R"
"${LIBR_CORE_LIBRARY}" "${CMAKE_CURRENT_BINARY_DIR}/R.def"
)
execute_process(COMMAND ${DLLTOOL_EXE}
"--input-def" "${CMAKE_CURRENT_BINARY_DIR}/R.def"
Expand Down
13 changes: 13 additions & 0 deletions R-package/src/install.libs.R
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ if (!use_precompile) {
, showWarnings = FALSE
)
setwd(build_dir)

# If using MSVC to build, pull in the file used
# to create R.def from R.dll
if (WINDOWS && !use_mingw){
write_succeeded <- file.copy(
"../../inst/bin/make-r-def.R"
, file.path(build_dir, "make-r-def.R")
, overwrite = TRUE
)
if (!write_succeeded) {
stop("Copying make-r-def.R failed")
}
}

# Prepare installation steps
cmake_args <- NULL
Expand Down
64 changes: 64 additions & 0 deletions R-package/src/make-r-def.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# [description]
# Create a definition file (.def) from a .dll file, using objdump.
#
# [usage]
#
# Rscript make-r-def.R something.dll something.def
#
# [references]
# * https://www.cs.colorado.edu/~main/cs1300/doc/mingwfaq.html

args <- commandArgs(trailingOnly = TRUE)

IN_DLL_FILE <- args[[1]]
OUT_DEF_FILE <- args[[2]]
print(sprintf("Creating '%s' from '%s'", IN_DLL_FILE, OUT_DEF_FILE))

# Creates a .def file from R.dll, using tools bundled with R4.0
#LIBR_CORE_LIBRARY <- "C:/Program Files/R/R-3.6.1/bin/x64/R.dll"

# use objdump to dump all the symbols
OBJDUMP_FILE <- "R.fil"
exit_code <- system2(
command = "objdump"
, args = c(
"-p"
, shQuote(IN_DLL_FILE)
)
, stdout = OBJDUMP_FILE
)

objdump_results <- readLines(OBJDUMP_FILE)
file.remove(OBJDUMP_FILE)

# Name Pointer table start
# https://www.cs.colorado.edu/~main/cs1300/doc/mingwfaq.html
start_index <- which(
grepl(
pattern = "[Ordinal/Name Pointer] Table"
, x = objdump_results
, fixed = TRUE
)
)
empty_lines <- which(objdump_results == "")
end_of_table <- empty_lines[empty_lines > start_index][1]

# Read the contents of the table
exported_symbols <- objdump_results[(start_index + 1):end_of_table]
exported_symbols <- gsub("\t", "", exported_symbols)
exported_symbols <- gsub(".*\\] ", "", exported_symbols)
exported_symbols <- gsub(" ", "", exported_symbols)

# Write R.def file
write_succeeded <- writeLines(
text = c(
paste0("LIBRARY ", '\"R.dll\"')
, "EXPORTS"
, exported_symbols
)
, con = OUT_DEF_FILE
, sep = "\n"
)
if (!isTRUE(write_succeeded)){
stop("Failed to create R.def")
}
7 changes: 7 additions & 0 deletions build_r.R
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ for (src_file in c("lightgbm_R.cpp", "lightgbm_R.h", "R_object_helper.h")) {
.handle_result(result)
}

result <- file.copy(
from = file.path("R-package", "src", "make-r-def.R")
, to = file.path("lightgbm_r", "inst", "bin/")
, overwrite = TRUE
)
.handle_result(result)

# NOTE: --keep-empty-dirs is necessary to keep the deep paths expected
# by CMake while also meeting the CRAN req to create object files
# on demand
Expand Down

0 comments on commit 73cadba

Please sign in to comment.