| Title: | Build 'Rust' Powered 'R' Packages |
| Version: | 0.5.0 |
| Description: | Provides a framework for creating high-performance 'R' packages powered by the 'Rust' programming language using the 'extendr' Rust crate. It offers 'usethis'-like functions to scaffold and develop 'Rust' powered 'R' packages, including utilities for publishing to CRAN, managing dependencies, configuring development environments, and rendering 'Rust' code in 'knitr' documents. Additionally, it provides functions to compile and evaluate 'Rust' code directly from 'R' for interactive development. |
| License: | MIT + file LICENSE |
| URL: | https://extendr.rs/rextendr/, https://github.com/extendr/rextendr |
| BugReports: | https://github.com/extendr/rextendr/issues |
| Depends: | R (≥ 4.2) |
| Imports: | brio, cli, desc, dplyr, glue (≥ 1.7.0), jsonlite, lifecycle, pkgbuild (≥ 1.4.0), processx, rlang (≥ 1.0.5), rprojroot, stringi, vctrs, withr |
| Suggests: | devtools, knitr, lintr, rcmdcheck, rmarkdown, testthat (≥ 3.1.7), usethis |
| VignetteBuilder: | knitr |
| Config/testthat/edition: | 3 |
| Config/testthat/parallel: | true |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.3 |
| SystemRequirements: | Rust 'cargo'; the crate 'libR-sys' must compile without error |
| NeedsCompilation: | no |
| Packaged: | 2026-04-16 18:36:45 UTC; josiahparry |
| Author: | Claus O. Wilke |
| Maintainer: | Kenneth Vernon <kenneth.b.vernon@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-04-18 16:40:02 UTC |
Call Rust code from R using the 'extendr' Crate
Description
The rextendr package implements functions to interface with Rust code from R.
See rust_source() for details.
Author(s)
Maintainer: Ilia Kosenkov ilia.kosenkov@outlook.com (ORCID)
Authors:
Claus O. Wilke wilke@austin.utexas.edu (ORCID)
Andy Thomason andy@andythomason.com
Mossa M. Reimert mossa@sund.ku.dk
Malcolm Barrett malcolmbarrett@gmail.com (ORCID)
Other contributors:
Josiah Parry josiah.parry@gmail.con (ORCID) [contributor]
Kenneth Vernon kenneth.b.vernon@gmail.com (ORCID) [contributor]
Alberson Miranda albersonmiranda@hotmail.com (ORCID) [contributor]
See Also
Useful links:
Report bugs at https://github.com/extendr/rextendr/issues
Clean Rust binaries and package cache.
Description
Removes Rust binaries (such as .dll/.so libraries), C wrapper object files,
invokes cargo clean to reset cargo target directory
(found by default at pkg_root/src/rust/target/).
Useful when Rust code should be recompiled from scratch.
Usage
clean(path = ".", echo = TRUE)
Arguments
path |
character scalar, path to R package root. |
echo |
logical scalar, should cargo command and outputs be printed to
console (default is |
Value
character vector with names of all deleted files (invisibly).
Examples
## Not run:
clean()
## End(Not run)
CRAN compliant extendr packages
Description
R packages developed using extendr are not immediately ready to be published to CRAN. The extendr package template ensures that CRAN publication is (farily) painless.
CRAN requirements
In order to publish a Rust based package on CRAN it must meet certain requirements. These are:
Rust dependencies are vendored
The package is compiled offline
the
DESCRIPTIONfile'sSystemRequirementsfield containsCargo (Rust's package manager), rustc
The extendr templates handle all of this except vendoring dependencies.
This must be done prior to publication using vendor_crates().
In addition, it is important to make sure that CRAN maintainers
are aware that the package they are checking contains Rust code.
Depending on which and how many crates are used as a dependencies
the vendor.tar.xz will be larger than a few megabytes. If a
built package is larger than 5mbs CRAN may reject the submission.
To prevent rejection make a note in your cran-comments.md file
(create one using usethis::use_cran_comments()) along the lines of
"The package tarball is 6mb because Rust dependencies are vendored within src/rust/vendor.tar.xz which is 5.9mb."
Compile Rust code and generate package documentation.
Description
As of rextendr 0.4.0, this function is no longer strictly necessary.
Packages created with use_extendr() now include a document binary that
generates R/extendr-wrappers.R as part of the normal cargo build step,
so devtools::document() works directly without any rextendr-specific
pre-processing. rextendr::document() is retained for backwards
compatibility.
rextendr::document() updates the package documentation for an R package
that uses extendr code. It is a wrapper for devtools::document().
Usage
document(pkg = ".", quiet = FALSE, roclets = NULL)
Arguments
pkg |
The package to use, can be a file path to the package or a
package object. See |
quiet |
if |
roclets |
Character vector of roclet names to use with package.
The default, |
Value
No return value, called for side effects.
Knitr engines
Description
Two knitr engines that enable code chunks of type extendr (individual Rust
statements to be evaluated via rust_eval()) and extendrsrc (Rust functions
or classes that will be exported to R via rust_source()).
Usage
eng_extendr(options)
eng_extendrsrc(options)
Arguments
options |
A list of chunk options. |
Value
A character string representing the engine output.
Inform the user that a development version of extendr is being used.
Description
This function returns a string that should be used inside of a cli function.
See validate_extendr_features() for an example.
Usage
inf_dev_extendr_used()
Silence {cli} output
Description
Use for functions that use cli output that should optionally be suppressed.
Usage
local_quiet_cli(quiet, env = rlang::caller_env())
Examples
if (interactive()) {
hello_rust <- function(..., quiet = FALSE) {
local_quiet_cli(quiet)
cli::cli_alert_info("This should be silenced when {.code quiet = TRUE}")
}
hello_rust()
hello_rust(quiet = TRUE)
}
Generate extendr module macro for Rust source
Description
Read some Rust source code, find functions or implementations with the
#[extendr] attribute, and generate an extendr_module! macro statement.
Usage
make_module_macro(code, module_name = "rextendr")
Arguments
code |
Character vector containing Rust code. |
module_name |
Module name |
Details
This function uses simple regular expressions to do the Rust parsing and can get confused by valid Rust code. It is only meant as a convenience for simple use cases. In particular, it cannot currently handle implementations for generics.
Value
Character vector holding the contents of the generated macro statement.
Retrieve metadata for packages and workspaces
Description
Retrieve metadata for packages and workspaces
Usage
read_cargo_metadata(path = ".", dependencies = FALSE, echo = FALSE)
Arguments
path |
character scalar, the R package directory |
dependencies |
Default |
echo |
Default |
Details
For more details, see
Cargo docs
for cargo-metadata. See especially "JSON Format" to get a sense of what you
can expect to find in the returned list.
Value
A list including the following elements:
-
packages -
workspace_members -
workspace_default_members -
resolve -
target_directory -
version -
workspace_root -
metadata
Examples
## Not run:
read_cargo_metadata()
## End(Not run)
Register the extendr module of a package with R
Description
This function is deprecated because we now rely on a small Rust binary to generate wrappers, which is called during the package build process.
Usage
register_extendr(path = ".", quiet = FALSE, force = FALSE, compile = NA)
Arguments
path |
Path from which package root is looked up. |
quiet |
Logical indicating whether any progress messages should be generated or not. |
force |
Logical indicating whether to force regenerating
|
compile |
Logical indicating whether to recompile DLLs:
|
Value
(Invisibly) Path to the file containing generated wrappers.
See Also
Evaluate Rust code
Description
Compile and evaluate one or more Rust expressions. If the last
expression in the Rust code returns a value (i.e., does not end with
;), then this value is returned to R. The value returned does not need
to be of type Robj, as long as it can be cast into this type with
.into(). This conversion is done automatically, so you don't have to
worry about it in your code.
Usage
rust_eval(code, env = parent.frame(), ...)
Arguments
code |
Input rust code. |
env |
The R environment in which the Rust code will be evaluated. |
... |
Other parameters handed off to |
Value
The return value generated by the Rust code.
Examples
## Not run:
# Rust code without return value, called only for its side effects
rust_eval(
code = 'rprintln!("hello from Rust!");'
)
# Rust code with return value
rust_eval(
code = "
let x = 5;
let y = 7;
let z = x * y;
z // return to R; rust_eval() takes care of type conversion code
"
)
## End(Not run)
Report on Rust infrastructure
Description
Prints out a detailed report on the state of Rust infrastructure on the host machine.
Usage
rust_sitrep()
Value
Nothing
Compile Rust code and call from R
Description
rust_source() compiles and loads a single Rust file for use in R.
rust_function() compiles and loads a single Rust function for use in R.
extendr_options() is a helper function to make it easier to pass additional
options when sourcing Rust code. It also proivdes defaults for each option
and does additional type checking.
Usage
rust_source(
file = NULL,
code = NULL,
env = parent.frame(),
echo = FALSE,
quiet = FALSE,
opts = NULL,
...
)
rust_function(
code,
extendr_fn_options = NULL,
env = parent.frame(),
echo = FALSE,
quiet = FALSE,
opts = NULL,
...
)
extendr_options(
cache_build = TRUE,
dependencies = NULL,
extendr_deps = NULL,
features = NULL,
generate_module_macro = TRUE,
module_name = "rextendr",
patch.crates_io = getOption("rextendr.patch.crates_io"),
profile = c("dev", "release", "perf"),
toolchain = getOption("rextendr.toolchain"),
use_dev_extendr = FALSE,
use_extendr_api = TRUE,
use_rtools = TRUE
)
## S3 method for class 'extendr_opts'
print(x, ...)
Arguments
file |
character scalar, input rust file to source. |
code |
character scalar, input rust code to be used instead of |
env |
environment, the R environment in which the wrapping functions
will be defined. Default is |
echo |
logical scalar, whether to print standard output and errors of
|
quiet |
logical scalar, whether to print |
opts |
|
... |
user supplied extendr options to be injected into the
|
extendr_fn_options |
A list of extendr function options that are
inserted into the |
cache_build |
logical scalar, whether builds should be cached between
calls to |
dependencies |
character vector, dependencies to be added to |
extendr_deps |
named list, versions of |
features |
character vector, |
generate_module_macro |
logical scalar, whether the Rust module
macro should be automatically generated from the code. Default is |
module_name |
character scalar, name of the module defined in the Rust source via
|
patch.crates_io |
character vector, patch statements for crates.io to
be added to |
profile |
character scalar, Rust profile. Can be either |
toolchain |
character scalar, Rust toolchain. The default, |
use_dev_extendr |
logical scalar, whether to use development version of
|
use_extendr_api |
logical scalar, whether |
use_rtools |
logical scalar, whether to append the path to Rtools to the
|
x |
an |
Value
For rust_source() and rust_function(), the result from
dyn.load(), which is an object of class DLLInfo. See getLoadedDLLs()
for more details. For extendr_options(), an extendr_opts list.
Examples
## Not run:
# creating a single rust function
rust_function("fn add(a:f64, b:f64) -> f64 { a + b }")
add(2.5, 4.7)
# creating multiple rust functions at once
code <- r"(
#[extendr]
fn hello() -> &'static str {
"Hello, world!"
}
#[extendr]
fn test( a: &str, b: i64) {
rprintln!("Data sent to Rust: {}, {}", a, b);
}
)"
rust_source(code = code)
hello()
test("a string", 42)
# use case with an external dependency: a function that converts
# markdown text to html, using the `pulldown_cmark` crate.
code <- r"(
use pulldown_cmark::{Parser, Options, html};
#[extendr]
fn md_to_html(input: &str) -> String {
let mut options = Options::empty();
options.insert(Options::ENABLE_TABLES);
let parser = Parser::new_ext(input, options);
let mut output = String::new();
html::push_html(&mut output, parser);
output
}
)"
rust_source(
code = code,
opts = extendr_options(
dependencies = list(`pulldown-cmark` = "0.8")
)
)
md_text <- "# The story of the fox
The quick brown fox **jumps over** the lazy dog.
The quick *brown fox* jumps over the lazy dog."
md_to_html(md_text)
# see default options
extendr_options()
## End(Not run)
Convert R list() into toml-compatible format.
Description
to_toml() can be used to build Cargo.toml.
The cargo manifest can be represented in terms of
R objects, allowing limited validation and syntax verification.
This function converts manifests written using R objects into
toml representation, applying basic formatting,
which is ideal for generating cargo
manifests at runtime.
Usage
to_toml(..., .str_as_literal = TRUE, .format_int = "%d", .format_dbl = "%g")
Arguments
... |
A list from which toml is constructed. Supports nesting and tidy evaluation. |
.str_as_literal |
Logical indicating whether to treat
strings as literal (single quotes no escapes) or
basic (escaping some sequences) ones. Default is |
.format_int, .format_dbl |
Character scalar describing
number formatting. Compatible with |
Value
A character vector, each element corresponds to one line of the resulting output.
Examples
# Produces [workspace] with no children
to_toml(workspace = NULL)
to_toml(patch.crates_io = list(`extendr-api` = list(git = "git-ref")))
# Single-element arrays are distinguished from scalars
# using explicitly set `dim`
to_toml(lib = list(`crate-type` = array("cdylib", 1)))
Update extendr scaffolding
Description
When a new version of extendr or rextendr is released, this function updates relevant scaffolding files to the new specification.
Usage
update_scaffold(path = ".", crate_name = NULL, lib_name = NULL, quiet = FALSE)
Arguments
path |
File path to the package for which to generate wrapper code. |
crate_name |
String that is used as the name of the Rust crate,
specifically |
lib_name |
String that is used as the name of the Rust library,
specifically |
quiet |
Logical indicating whether any progress messages should be generated or not. |
Details
This function does not touch any build artifacts or files or folders generated when vendoring cargo. Cargo.lock and Cargo.toml are also left unchanged. Only the following files are re-written:
-
src/entrypoint.c -
src/Makevars.in -
src/Makevars.win.in -
cleanup -
cleanup.win -
src/rust/document.rs -
tools/msrv.R -
tools/config.R -
configure -
configure.win
After updating these files, update_scaffold() will print a message that
explains what to do next to get your package up-to-date with the latest
versions of extendr and rextendr (provided quiet = FALSE, anyway). That
will typically include handling dependency resolution, updating Cargo.toml
and Cargo.lock, and vendoring crates for CRAN compliance. Usually, this
will be accompanied by a more detailed blog post explaining the update
process.
Value
a logical scalar indicating whether scaffold updating was successful
Add dependencies to a Cargo.toml manifest file
Description
Analogous to usethis::use_package() but for crate dependencies.
Usage
use_crate(
crate,
features = NULL,
git = NULL,
version = NULL,
optional = FALSE,
path = ".",
echo = TRUE
)
Arguments
crate |
character scalar, the name of the crate to add |
features |
character vector, a list of features to include from the crate |
git |
character scalar, the full URL of the remote Git repository |
version |
character scalar, the version of the crate to add |
optional |
boolean scalar, whether to mark the dependency as optional (FALSE by default) |
path |
character scalar, the package directory |
echo |
logical scalar, should cargo command and outputs be printed to console (default is TRUE) |
Details
For more details regarding these and other options, see the
Cargo docs
for cargo-add.
Value
NULL (invisibly)
Examples
## Not run:
# add to [dependencies]
use_crate("serde")
# add to [dependencies] and [features]
use_crate("serde", features = "derive")
# add to [dependencies] using github repository as source
use_crate("serde", git = "https://github.com/serde-rs/serde")
# add to [dependencies] with specific version
use_crate("serde", version = "1.0.1")
# add to [dependencies] with optional compilation
use_crate("serde", optional = TRUE)
## End(Not run)
Set up a package for use with Rust extendr code
Description
Create the scaffolding needed to add Rust extendr code to an R package.
use_extendr() adds a small Rust library with a single Rust function that
returns the string "Hello world!". It also adds wrapper code so this Rust
function can be called from R with hello_world().
Usage
use_extendr(
path = ".",
crate_name = NULL,
lib_name = NULL,
quiet = FALSE,
overwrite = NULL,
edition = c("2021", "2018")
)
Arguments
path |
File path to the package for which to generate wrapper code. |
crate_name |
String that is used as the name of the Rust crate,
specifically |
lib_name |
String that is used as the name of the Rust library,
specifically |
quiet |
Logical indicating whether any progress messages should be generated or not. |
overwrite |
Logical scalar or |
edition |
String indicating which Rust edition is used; Default |
Details
Generated files
-
R/extendr-wrappers.R: auto-generated R wrappers. Do not edit by hand. -
src/entrypoint.c: C entry point forwarding R's routine registration to the Rust library. -
src/Makevars.in/src/Makevars.win.in: Makefile templates compiled and employed at package build time. -
src/<pkg>-win.def: Windows DLL export definitions. -
src/.gitignore: Ignores compiled artifacts, Cargo directories, and generatedMakevarsfiles. -
src/rust/Cargo.toml: Rust package manifest with crate name, edition,extendr-apidependency, and release profile settings. -
src/rust/src/lib.rs: Main Rust library with an examplehello_world()function and theextendr_module!macro. -
src/rust/document.rs: Rust binary that writesR/extendr-wrappers.Rby introspecting exported function metadata at build time. -
tools/msrv.R: Verifies the installed Rust toolchain meets the MSRV inDESCRIPTION. -
tools/config.R: Readstools/msrv.R, checksDEBUG/NOT_CRANenv vars, and writes the finalMakevarsfile from the.intemplate. -
configure/configure.win: Shell scripts run before compilation that invoketools/config.RviaRscript. -
cleanup/cleanup.win: Shell scripts that removesrc/Makevarson package uninstall.
Value
A logical value (invisible) indicating whether any package files were generated or not.
extendr README badge
Description
Add the version of extendr being used by an R package to its README.
Usage
use_extendr_badge(path = ".")
Arguments
path |
File path to the package for which to generate wrapper code. |
Details
Requires usethis to be available.
Examples
## Not run:
use_extendr_badge()
## End(Not run)
Set the minimum supported rust version (MSRV)
Description
use_msrv() sets the minimum supported rust version for your R package.
Usage
use_msrv(version, path = ".", overwrite = FALSE)
Arguments
version |
character scalar, the minimum supported Rust version. |
path |
character scalar, path to folder containing DESCRIPTION file. |
overwrite |
default |
Details
The minimum supported rust version (MSRV) is determined by the
SystemRequirements field in a package's DESCRIPTION file. For example, to
set the MSRV to 1.67.0, the SystemRequirements must have
rustc >= 1.67.0.
By default, there is no MSRV set. However, some crates have features that depend on a minimum version of Rust. As of this writing the version of Rust on CRAN's Fedora machine's is 1.69. If you require a version of Rust that is greater than that, you must set it in your DESCRIPTION file.
It is also important to note that if CRAN's machines do not meet the specified MSRV, they will not be able to build a binary of your package. As a consequence, if users try to install the package they will be required to have Rust installed as well.
To determine the MSRV of your R package, we recommend installing the
cargo-msrv cli. You can do so by running cargo install cargo-msrv. To
determine your MSRV, set your working directory to src/rust then run
cargo msrv. Note that this may take a while.
For more details, please see cargo-msrv.
Value
version
Examples
## Not run:
use_msrv("1.67.1")
## End(Not run)
Set up VS Code configuration for an rextendr project
Description
This creates a .vscode folder (if needed) and populates it with a
settings.json template. If already exists, it will be updated to include
the rust-analyzer.linkedProjects setting.
Usage
use_vscode(quiet = FALSE, overwrite = NULL)
use_positron(quiet = FALSE, overwrite = NULL)
Arguments
quiet |
If |
overwrite |
If |
Details
Rust-Analyzer VSCode extension looks for a Cargo.toml file in the
workspace root by default. This function creates a .vscode folder and
populates it with a settings.json file that sets the workspace root to
the src directory of the package. This allows you to open the package
directory in VSCode and have the Rust-Analyzer extension work correctly.
Value
TRUE (invisibly) if the settings file was created or updated.
Vendor Rust dependencies
Description
vendor_crates() is used to package the dependencies as required by CRAN.
It executes cargo vendor on your behalf creating a vendor/ directory and a
compressed vendor.tar.xz which will be shipped with package itself.
If you have modified your dependencies, you will need need to repackage
the vendored dependencies using vendor_crates().
vendor_pkgs() was renamed to vendor_crates().
Usage
vendor_crates(path = ".", quiet = FALSE, overwrite = NULL, clean = FALSE)
vendor_pkgs(path = ".", quiet = FALSE, overwrite = NULL, clean = FALSE)
Arguments
path |
File path to the package for which to generate wrapper code. |
quiet |
Logical indicating whether any progress messages should be generated or not. |
overwrite |
Logical scalar or |
clean |
|
Value
-
vendor_crates()returns a data.frame with two columnscrateandversion
Examples
## Not run:
vendor_crates()
## End(Not run)
Generate LICENSE.note file.
Description
Usage
write_license_note(path = ".", quiet = FALSE, force = TRUE)
Arguments
path |
character scalar, the R package directory |
quiet |
logical scalar, whether to signal successful writing of
LICENSE.note (default is |
force |
logical scalar, whether to regenerate LICENSE.note if
LICENSE.note already exists (default is |
Details
LICENSE.note generated by this function contains information about all recursive dependencies in Rust crate.
The authors field in Cargo metadata is deprecated upstream
(see https://github.com/rust-lang/cargo/issues/16458). This function
relies on that field and may produce incomplete or missing author
information as crates stop populating or removes the field entirely.
Value
text printed to LICENSE.note (invisibly).
Examples
## Not run:
write_license_note()
## End(Not run)