Project Structure
When you run rextendr::use_extendr() for the first time, it will generate the
scaffolding needed to integrate Rust code into an R package. The result is a
directory structure that is fairly unique among R packages, so this page serves
to give a high level overview of the generated files, focusing on those that are
relevant to you as an R package developer. The package directory should have the
following structure:
.
├── R
│ └── extendr-wrappers.R
├── cleanup
├── cleanup.win
├── configure
├── configure.win
├── src
│ ├── .gitignore
│ ├── Makevars.in
│ ├── Makevars.win.in
│ ├── entrypoint.c
│ ├── <pkg>-win.def
│ └── rust
│ ├── Cargo.toml
| ├── document.rs
│ └── src
│ └── lib.rs
└── tools
├── config.R
└── msrv.R
As an R package developer, the file R/extendr-wrappers.R will perhaps look the
most familiar to you. This file contains auto-generated R wrapper functions that
call compiled Rust code via .Call(). The file is regenerated every time you
call devtools::document(). It should never be edited by hand. In fact, with
the exception of Cargo.toml and Rust scripts in rust/src/, none of the files
listed above should ever be edited by hand.
The Cargo manifest
The Cargo.toml file, also known as a manifest, defines the crate name,
edition, dependencies, and build profiles. By default, you should see this in
your manifest:
src/rust/Cargo.toml
[package]
name = 'hellorust'
publish = false
version = '0.1.0'
edition = '2021'
rust-version = '1.65'
[lib]
crate-type = ['rlib', 'staticlib']
name = 'hellorust'
[[bin]]
name = 'document'
path = 'document.rs'
[dependencies]
extendr-api = '*'
[profile.release]
lto = true
codegen-units = 1Note that the crate is built as both an rlib (used by the document binary to
introspect exports) and a staticlib (linked into the R package). The [[bin]]
entry registers document.rs as an executable used to generate R wrappers at
build time, the content of R/extendr-wrappers.R. You should never touch these
parts of your manifest, as they are critical to the build process. If there are
other crates you want to depend on, though, you will need to list them here
under [dependencies], similar to imports in DESCRIPTION. We provide a
small utility use_crate() for this purpose. You can also add them by hand or
call cargo add in the terminal if you prefer.
The crate library
While you can add Rust scripts to rust/src/ to organize your Rust code as you
see fit, by default, it will consist of a single Rust file, lib.rs. This is
the main Rust library file where you gather Rust code to be linked into R. The
scaffolded version will initially contain a simple hello_world() example:
src/rust/src/lib.rs
use extendr_api::prelude::*;
/// Return string `"Hello world!"` to R.
/// @export
#[extendr]
fn hello_world() -> &'static str {
"Hello world!"
}
// Macro to generate exports.
// This ensures exported functions are registered with R.
// See corresponding C code in `entrypoint.c`.
extendr_module! {
mod hellorust;
fn hello_world;
}The extendr_module! macro controls which functions, impl blocks, and
submodules are exposed to R. Every function you want available in R must be
listed in an extendr_module!.
Git ignore
One other file that you may on occasion find it helpful to edit is
src/.gitignore. This local .gitignore ignores artifacts of the build process
that should not be committed:
src/.gitignore
*.o
*.so
*.dll
target
.cargo
rust/vendor
Makevars
Makevars.winLearn more
On this page, we only describe the content of files if it is helpful to you as an R package developer. If you want to know more about how these files are generated and what they are for, you can have a look at the {rextendr} Internals page in the Contributing guide.
As a reminder, we emphasize that with the exception of Cargo.toml,
src/rust/src, and src/.gitignore, no scaffolding files should be edited by
the package developer. We repeat, DO NOTE EDIT THESE FILES:
R/extendr-wrappers.R~/document.rssrc/entrypoint.csrc/Makevars.inorsrc/Makevars.win.insrc/<pkg>-win.defconfigureorconfigure.wintools/msrv.Rtools/config.Rcleanuporcleanup.win