Skip to content

Commit

Permalink
feat: System checks on systemRequirements (#379)
Browse files Browse the repository at this point in the history
* feat: modifies `use_cran_defaults()` to perform system checks on cargo and rustc versions for CRAN compliance.

* docs: add missing `rust_source.Rd`, `use_crate.Rd` and `write_license_note.Rd`, and update NAMESPACE.

* chore: Bump dev version and update NEWS

* feat: Add tools directory and msrv.R template for CRAN compliance

* tests: Update snapshots for `use_cran_defaults()` and `use_extendr()`

* tests: update tests

* docs: Add `use_crate` to package development reference

* Update snapshots

* Update NEWS.md

---------

Co-authored-by: Josiah Parry <josiah.parry@gmail.com>
  • Loading branch information
albersonmiranda and JosiahParry authored Sep 7, 2024
1 parent 0359070 commit 52cd2e5
Show file tree
Hide file tree
Showing 15 changed files with 329 additions and 75 deletions.
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
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",
"-------------------------------------------------------------------"
)

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)

# 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

0 comments on commit 52cd2e5

Please sign in to comment.