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 = 1

Note 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.win

Learn 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.rs
  • src/entrypoint.c
  • src/Makevars.in or src/Makevars.win.in
  • src/<pkg>-win.def
  • configure or configure.win
  • tools/msrv.R
  • tools/config.R
  • cleanup or cleanup.win