Skip to content

Commit 35f9521

Browse files
authored
Merge pull request #113 from t-kalinowski/windows-runtime-dll-preload
Preload Windows runtime DLL dependencies
2 parents 86beab3 + cf11ebb commit 35f9521

2 files changed

Lines changed: 76 additions & 1 deletion

File tree

R/quick.R

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ compile <- function(fsub, build_dir = tempfile(paste0(fsub@name, "-build-"))) {
296296
stop("Compilation Error", call. = FALSE)
297297
}
298298

299-
quickr_windows_add_dll_paths(link_flags)
299+
dll_dirs <- quickr_windows_add_dll_paths(link_flags)
300+
quickr_windows_load_dll_dependencies(dll_dirs)
300301

301302
# tryCatch(dyn.unload(dll_path), error = identity)
302303
dll <- tryCatch(
@@ -439,6 +440,44 @@ quickr_windows_add_dll_paths <- function(
439440
}
440441

441442

443+
quickr_windows_load_dll_dependencies <- function(
444+
dirs,
445+
os_type = .Platform$OS.type,
446+
dyn_load = base::dyn.load
447+
) {
448+
if (!identical(os_type, "windows")) {
449+
return(invisible(character()))
450+
}
451+
stopifnot(is.character(dirs), is.function(dyn_load))
452+
453+
patterns <- c(
454+
"libgcc_s*.dll",
455+
"libwinpthread*.dll",
456+
"libquadmath*.dll",
457+
"libgfortran*.dll",
458+
"libopenblas*.dll",
459+
"Rblas.dll",
460+
"Rlapack.dll"
461+
)
462+
dlls <- unlist(
463+
lapply(patterns, \(pattern) Sys.glob(file.path(dirs, pattern))),
464+
use.names = FALSE
465+
)
466+
dlls <- dlls[file.exists(dlls)]
467+
if (!length(dlls)) {
468+
return(invisible(character()))
469+
}
470+
471+
dlls <- normalizePath(dlls, winslash = "\\", mustWork = FALSE)
472+
dlls <- dlls[!duplicated(tolower(basename(dlls)))]
473+
for (dll in dlls) {
474+
dyn_load(dll)
475+
}
476+
477+
invisible(dlls)
478+
}
479+
480+
442481
create_quick_closure <- function(
443482
name,
444483
closure,

tests/testthat/test-quick-windows-paths.R

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,39 @@ test_that("quickr_windows_add_dll_paths leaves PATH unchanged when complete", {
346346
expect_type(res, "character")
347347
expect_identical(Sys.getenv("PATH"), base_path)
348348
})
349+
350+
test_that("quickr_windows_load_dll_dependencies preloads known runtime DLLs", {
351+
temp <- withr::local_tempdir()
352+
lib_dir <- file.path(temp, "lib")
353+
bin_dir <- file.path(temp, "bin")
354+
dir.create(lib_dir)
355+
dir.create(bin_dir)
356+
file.create(
357+
file.path(lib_dir, "libgfortran-5.dll"),
358+
file.path(bin_dir, "libgfortran-5.dll"),
359+
file.path(bin_dir, "libquadmath-0.dll"),
360+
file.path(lib_dir, "Rlapack.dll")
361+
)
362+
363+
loaded <- character()
364+
res <- quickr_windows_load_dll_dependencies(
365+
c(lib_dir, bin_dir),
366+
os_type = "windows",
367+
dyn_load = function(path) {
368+
loaded <<- c(loaded, path)
369+
structure(list(), class = "DLLInfo")
370+
}
371+
)
372+
373+
expected <- normalizePath(
374+
c(
375+
file.path(bin_dir, "libquadmath-0.dll"),
376+
file.path(lib_dir, "libgfortran-5.dll"),
377+
file.path(lib_dir, "Rlapack.dll")
378+
),
379+
winslash = "\\",
380+
mustWork = FALSE
381+
)
382+
expect_identical(res, expected)
383+
expect_identical(loaded, expected)
384+
})

0 commit comments

Comments
 (0)