Skip to content
64 changes: 5 additions & 59 deletions R/source.R
Original file line number Diff line number Diff line change
Expand Up @@ -278,65 +278,7 @@ rust_source <- function(

# append rtools path to the end of PATH on Windows
if (opts[["use_rtools"]] && .Platform$OS.type == "windows") {
if (!suppressMessages(pkgbuild::has_rtools())) {
cli::cli_abort(
c(
"Unable to find Rtools that are needed for compilation.",
"i" = "Required version is {.emph {pkgbuild::rtools_needed()}}."
),
class = "rextendr_error"
)
}

if (identical(R.version$crt, "ucrt")) {
# TODO: update this when R 5.0 is released.
if (!identical(R.version$major, "4")) {
cli::cli_abort(
"rextendr currently supports R 4.2",
call = rlang::caller_call(),
class = "rextendr_error"
)
}

minor_patch <- package_version(R.version$minor)

if (minor_patch >= "5.0") {
rtools_version <- "45" # nolint: object_usage_linter
} else if (minor_patch >= "4.0") {
rtools_version <- "44" # nolint: object_usage_linter
} else if (minor_patch >= "3.0") {
rtools_version <- "43" # nolint: object_usage_linter
} else {
rtools_version <- "42" # nolint: object_usage_linter
}

rtools_home <- normalizePath(
Sys.getenv(
glue("RTOOLS{rtools_version}_HOME"),
glue("C:\\rtools{rtools_version}")
),
mustWork = TRUE
)

# c.f. https://github.com/wch/r-source/blob/f09d3d7fa4af446ad59a375d914a0daf3ffc4372/src/library/profile/Rprofile.windows#L70-L71 # nolint: line_length_linter
subdir <- c("x86_64-w64-mingw32.static.posix", "usr")
} else {
# rtools_path() returns path to the RTOOLS40_HOME\usr\bin,
# but we need RTOOLS40_HOME\mingw{arch}\bin, hence the "../.."
rtools_home <- normalizePath(
# `pkgbuild` may return two paths for R < 4.2 with Rtools40v2
file.path(pkgbuild::rtools_path()[1], "..", ".."),
winslash = "/",
mustWork = TRUE
)

subdir <- paste0("mingw", ifelse(R.version$arch == "i386", "32", "64"))
# if RTOOLS40_HOME is properly set, this will have no real effect
withr::local_envvar(RTOOLS40_HOME = rtools_home)
}

rtools_bin_path <- normalizePath(file.path(rtools_home, subdir, "bin"))
withr::local_path(rtools_bin_path, action = "suffix")
use_rtools()
}

# get target name, not null for Windows
Expand Down Expand Up @@ -804,6 +746,10 @@ get_specific_target_name <- function() {
return("i686-pc-windows-gnu")
}

if (R.version$arch == "aarch64") {
return(NULL)
}

cli::cli_abort(
"Unknown Windows architecture",
class = "rextendr_error"
Expand Down
112 changes: 112 additions & 0 deletions R/use_rtools.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
is_windows_arm <- function() {
proc_arch <- Sys.getenv("PROCESSOR_ARCHITECTURE")
r_arch <- R.version[["arch"]]

if (identical(proc_arch, "ARM64") && !identical(r_arch, "aarch64")) {
cli::cli_abort(
c(
"Architecture mismatch detected.",
"i" = "You are running the {.code {proc_arch}} version of Windows, but the {.code {r_arch}} version of R.",
"i" = "You can find ARM64 build of R at {.url https://www.r-project.org/nosvn/winutf8/aarch64}"
),
class = "rextendr_error"
)
}

identical(proc_arch, "ARM64") && identical(r_arch, "aarch64")
}

throw_if_no_rtools <- function() {
if (!suppressMessages(pkgbuild::has_rtools())) {
cli::cli_abort(
c(
"Unable to find Rtools that are needed for compilation.",
"i" = "Required version is {.emph {pkgbuild::rtools_needed()}}."
),
class = "rextendr_error"
)
}
}

throw_if_not_ucrt <- function() {
if (!identical(R.version$crt, "ucrt")) {
cli::cli_abort(
c(
"R must be built with UCRT to use rextendr.",
"i" = "Please install the UCRT version of R from {.url https://cran.r-project.org/}."
),
class = "rextendr_error"
)
}
}

get_rtools_version <- function() {
minor_patch <- package_version(R.version$minor)

if (minor_patch >= "5.0") {
"45"
} else if (minor_patch >= "4.0") {
"44"
} else if (minor_patch >= "3.0") {
"43"
} else {
"42"
}
}

get_path_to_cargo_folder_arm <- function(rtools_root) {
path_to_cargo_folder <- file.path(rtools_root, "clangarm64", "bin")
path_to_cargo <- file.path(path_to_cargo_folder, "cargo.exe")
if (!file.exists(path_to_cargo)) {
cli::cli_abort(
c(
"{.code rextendr} on ARM Windows requires an ARM-compatible Rust toolchain.",
"i" = "Check this instructions to set up {.code cargo} using ARM version of RTools: {.url https://github.com/r-rust/faq?tab=readme-ov-file#does-rust-support-windows-on-arm64-aarch64}." # nolint: line_length_linter
),
class = "rextendr_error"
)
}

normalizePath(path_to_cargo_folder, mustWork = TRUE)
}
Comment on lines +61 to +75
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add internal doc comments here? I don't necessarily follow what this function does 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this differ from rtools bin path funciton?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path to rtools cargo installation, different subfolder

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay! So rtools now distributes cargo??!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but you can install cargo msys2 style on Arm machine because the target we need is not yet supported (Tier 2).


use_rtools <- function(.local_envir = parent.frame()) {
throw_if_no_rtools()
throw_if_not_ucrt()

is_arm <- is_windows_arm()

rtools_version <- get_rtools_version()

env_var <- if (is_arm) {
sprintf("RTOOLS%s_AARCH64_HOME", rtools_version)
} else {
sprintf("RTOOLS%s_HOME", rtools_version)
}

default_path <- if (is_arm) {
sprintf("C:\\rtools%s-aarch64", rtools_version)
} else {
sprintf("C:\\rtools%s", rtools_version)
}

rtools_home <- normalizePath(
Sys.getenv(env_var, default_path),
mustWork = TRUE
)

# c.f. https://github.com/wch/r-source/blob/f09d3d7fa4af446ad59a375d914a0daf3ffc4372/src/library/profile/Rprofile.windows#L70-L71 # nolint: line_length_linter
subdir <- if (is_arm) {
c("aarch64-w64-mingw32.static.posix", "usr")
} else {
c("x86_64-w64-mingw32.static.posix", "usr")
}

rtools_bin_path <- normalizePath(file.path(rtools_home, subdir, "bin"))
withr::local_path(rtools_bin_path, action = "suffix", .local_envir = .local_envir)

if (is_arm) {
cargo_path <- get_path_to_cargo_folder_arm(rtools_home)
withr::local_path(cargo_path, .local_envir = .local_envir)
}
}
Loading