Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: System checks on SystemRequirements (cargo, rustc, msrv) #379

Merged
merged 10 commits into from
Sep 7, 2024
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: rextendr
Title: Call Rust Code from R using the 'extendr' Crate
Version: 0.3.1.9000
albersonmiranda marked this conversation as resolved.
Show resolved Hide resolved
Version: 0.3.1.9001
Authors@R:
c(person(given = "Claus O.",
family = "Wilke",
Expand Down Expand Up @@ -69,6 +69,6 @@ Config/testthat/edition: 3
Config/testthat/parallel: true
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
RoxygenNote: 7.3.2
SystemRequirements: Rust 'cargo'; the crate 'libR-sys' must compile
without error
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export(rust_sitrep)
export(rust_source)
export(to_toml)
export(use_cran_defaults)
export(use_crate)
export(use_extendr)
export(vendor_pkgs)
export(write_license_note)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Removed `use_try_from` as an option in `rust_function`, and added `use_rng` (#354)
* Added `use_crate()` function to make adding dependencies to Cargo.toml easier within R, similar to `usethis::use_package()` (#361)
* Fixed an issue in `rust_source()` family of functions that prevented usage of `r#` escape sequences in Rust function names (#374)
* `use_cran_defaults()` now checks the `SystemRequirements` field in the `DESCRIPTION` file for cargo and rustc. It will display installation instructions if either is missing or provide the minimum required version if the installed version is outdated.

# rextend 0.3.1

Expand Down
15 changes: 14 additions & 1 deletion R/cran-compliance.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#' @details
#'
#' `use_cran_defaults()` modifies an existing package to provide CRAN complaint
#' settings and files. It creates `configure` and `configure.win` files as well as
#' settings and files. It creates `tools/msrv.R`, `configure` and `configure.win` files as well as
#' modifies `Makevars` and `Makevars.win` to use required CRAN settings.
#'
#' `vendor_pkgs()` is used to package the dependencies as required by CRAN.
Expand Down Expand Up @@ -52,6 +52,19 @@ use_cran_defaults <- function(path = ".", quiet = FALSE, overwrite = NULL, lib_n
)
}

# create tools directory if it does not exist
if (!dir.exists("tools")) {
dir.create("tools")
}

# add msrv.R template
use_rextendr_template(
"cran/msrv.R",
save_as = file.path("tools", "msrv.R"),
quiet = quiet,
overwrite = overwrite
)

# add configure and configure.win templates
use_rextendr_template(
"cran/configure",
Expand Down
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ reference:
- title: Package development
contents:
- use_extendr
- use_crate
- document
- register_extendr
- write_license_note
Expand Down
22 changes: 2 additions & 20 deletions inst/templates/cran/configure
Original file line number Diff line number Diff line change
@@ -1,21 +1,3 @@
#!/usr/bin/env sh

# https://github.com/eitsupi/prqlr/blob/main/configure
export PATH="$PATH:$HOME/.cargo/bin"

if [ ! "$(command -v cargo)" ]; then
echo "----------------------- [RUST NOT FOUND]---------------------------"
echo "The 'cargo' command was not found on the PATH. Please install rustc"
echo "from: https://www.rust-lang.org/tools/install"
echo ""
echo "Alternatively, you may install cargo from your OS package manager:"
echo " - Debian/Ubuntu: apt-get install cargo"
echo " - Fedora/CentOS: dnf install cargo"
echo " - macOS: brew install rustc"
echo "-------------------------------------------------------------------"
echo ""
exit 1
fi

exit 0

: "${R_HOME=`R RHOME`}"
"${R_HOME}/bin/Rscript" tools/msrv.R
17 changes: 2 additions & 15 deletions inst/templates/cran/configure.win
Original file line number Diff line number Diff line change
@@ -1,15 +1,2 @@
#!/bin/sh

# https://github.com/eitsupi/prqlr/blob/main/configure.win
export PATH="$PATH:$HOME/.cargo/bin"

if [ ! "$(command -v cargo)" ]; then
echo "----------------------- [RUST NOT FOUND]---------------------------"
echo "The 'cargo' command was not found on the PATH. Please install rustc"
echo "from: https://www.rust-lang.org/tools/install"
echo "-------------------------------------------------------------------"
echo ""
exit 1
fi

exit 0
#!/usr/bin/env sh
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/msrv.R
116 changes: 116 additions & 0 deletions inst/templates/cran/msrv.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# read the DESCRIPTION file
desc <- read.dcf("DESCRIPTION")

if (!"SystemRequirements" %in% colnames(desc)) {
fmt <- c(
"`SystemRequirements` not found in `DESCRIPTION`.",
"Please specify `SystemRequirements: Cargo (Rust's package manager), rustc`"
)
stop(paste(fmt, collapse = "\n"))
}

# extract system requirements
sysreqs <- desc[, "SystemRequirements"]

# check that cargo and rustc is found
if (!grepl("cargo", sysreqs, ignore.case = TRUE)) {
stop("You must specify `Cargo (Rust's package manager)` in your `SystemRequirements`")
}

if (!grepl("rustc", sysreqs, ignore.case = TRUE)) {
stop("You must specify `Cargo (Rust's package manager), rustc` in your `SystemRequirements`")
}

# split into parts
parts <- strsplit(sysreqs, ", ")[[1]]

# identify which is the rustc
rustc_ver <- parts[grepl("rustc", parts)]

# perform checks for the presence of rustc and cargo on the OS
no_cargo_msg <- c(
"----------------------- [CARGO NOT FOUND]--------------------------",
"The 'cargo' command was not found on the PATH. Please install Cargo",
"from: https://www.rust-lang.org/tools/install",
"",
"Alternatively, you may install Cargo from your OS package manager:",
" - Debian/Ubuntu: apt-get install cargo",
" - Fedora/CentOS: dnf install cargo",
" - macOS: brew install rustc",
"-------------------------------------------------------------------"
JosiahParry marked this conversation as resolved.
Show resolved Hide resolved
)

no_rustc_msg <- c(
"----------------------- [RUST NOT FOUND]---------------------------",
"The 'rustc' compiler was not found on the PATH. Please install",
paste(rustc_ver, "or higher from:"),
"https://www.rust-lang.org/tools/install",
"",
"Alternatively, you may install Rust from your OS package manager:",
" - Debian/Ubuntu: apt-get install rustc",
" - Fedora/CentOS: dnf install rustc",
" - macOS: brew install rustc",
"-------------------------------------------------------------------"
)

# Add {user}/.cargo/bin to path before checking
new_path <- paste0(
Sys.getenv("PATH"),
":",
paste0(Sys.getenv("HOME"), "/.cargo/bin")
)

# set the path with the new path
Sys.setenv("PATH" = new_path)
JosiahParry marked this conversation as resolved.
Show resolved Hide resolved

# check for rustc installation
rustc_version <- tryCatch(
system("rustc --version", intern = TRUE),
error = function(e) {
stop(paste(no_rustc_msg, collapse = "\n"))
}
)

# check for cargo installation
cargo_version <- tryCatch(
system("cargo --version", intern = TRUE),
error = function(e) {
stop(paste(no_cargo_msg, collapse = "\n"))
}
)

# helper function to extract versions
extract_semver <- function(ver) {
if (grepl("\\d+\\.\\d+(\\.\\d+)?", ver)) {
sub(".*?(\\d+\\.\\d+(\\.\\d+)?).*", "\\1", ver)
} else {
NA
}
}

# get the MSRV
msrv <- extract_semver(rustc_ver)

# extract current version
current_rust_version <- extract_semver(rustc_version)

# perform check
if (!is.na(msrv)) {
# -1 when current version is later
# 0 when they are the same
# 1 when MSRV is newer than current
is_msrv <- utils::compareVersion(msrv, current_rust_version)
if (is_msrv == 1) {
fmt <- paste0(
"\n------------------ [UNSUPPORTED RUST VERSION]------------------\n",
"- Minimum supported Rust version is %s.\n",
"- Installed Rust version is %s.\n",
"---------------------------------------------------------------"
)
stop(sprintf(fmt, msrv, current_rust_version))
}
}

# print the versions
versions_fmt <- "Using %s\nUsing %s"
message(sprintf(versions_fmt, cargo_version, rustc_version))
2 changes: 1 addition & 1 deletion man/cran.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/rust_source.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions man/use_crate.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/write_license_note.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading