Quick reference for common development tasks. See CLAUDE.md for complete build system documentation.

🔗Prerequisites

  • Rust toolchain (stable)
  • R 4.2+ with development headers
  • just command runner (optional if using the CLI)
  • autoconf (for regenerating configure from configure.ac)

Tip: The miniextendr CLI (miniextendr-cli/) can replace most just recipes. Install with just cli-install or cargo install --path miniextendr-cli --features dev. See the CLI README for full usage.

🔗One-shot dev bootstrap

just dev-tools-install

Installs the helpers expected by the other recipes:

  • cargo-revendor from the in-tree cargo-revendor/ (required by just vendor and the release builds that run it; neither configure nor bootstrap.R vendors).
  • cargo-limit, which provides the cargo lcheck / lclippy / ltest / lbuild aliases that truncate output to the first few errors, recommended for interactive iteration. CI and just recipes keep plain cargo so -D warnings output stays complete.

🔗Quick Start

just configure          # Generate build config (REQUIRED first step)
just rcmdinstall        # Build and install the example R package (`rpkg/`)
just devtools-test      # Run R tests

🔗Common Workflows

🔗Rust-only development (fastest iteration)

just check              # Type-check all crates
just check-features     # Verify feature combinations compile
just test               # Run Rust unit tests
just clippy             # Lint
just fmt                # Format

🔗R package development

just configure          # 1. Generate Makevars, config files
just rcmdinstall        # 2. Compile Rust + install R package
just devtools-test      # 3. Run R tests

🔗Browsing the R reference manual

just doc-r              # → rpkg/rust-target/doc/r/miniextendr.html
just doc-all            # nightly: rustdoc + crate index + the R manual → site/public/rustdoc/

Renders every man/*.Rd into one HTML page with tools::pkg2HTML() (base R 4.4+, a few seconds, nothing installed or loaded) after tools::checkRd() has passed over the sources — a finding aborts the build (MINIEXTENDR_HTML_STRICT=0 renders anyway). Run just devtools-document first when man/ may be stale. just doc-all needs a nightly toolchain: it documents the workspace crates and the rpkg bridge crate into one tree with rustdoc’s crate index page (--enable-index-page), copies it to the site output, and registers the R manual on that index. zola build starts site/public/ afresh, so run it after just site-build; publishing the tree from the Pages workflow is tracked in #1573. Scaffolded packages carry the same script as tools/build-html-reference.R, callable from R through minirextendr::miniextendr_html_reference().

🔗After changing proc macros or #[miniextendr] attributes

just configure && just rcmdinstall && just devtools-document

rcmdinstall regenerates R/miniextendr-wrappers.R from the new macro output; just devtools-document then runs roxygen2 over it to regenerate NAMESPACE and man/. For pure R/roxygen changes, just devtools-document alone is enough.

🔗Adding a new #[miniextendr] function

  1. Add #[miniextendr] to your pub function in a .rs file
  2. Run the macro-change workflow above

Registration is automatic via #[miniextendr] – no manual module declarations needed.

🔗Running R CMD check

just configure          # 1. Configure
just r-cmd-build        # 2. Build tarball
just r-cmd-check        # 3. Check the tarball

🔗Cross-package tests

just cross-install      # Build and install producer.pkg + consumer.pkg
just cross-test         # Run cross-package trait ABI tests

Both packages install into tests/cross-package/.r-lib/, a gitignored library inside the checkout that the cross-package recipes put first on .libPaths() (inside each R session, which they start in the repo root so that rv supplies the dependencies). Each checkout and worktree has its own copy, so parallel checkouts never overwrite each other’s installs in the user library.

🔗CRAN release prep

just vendor             # Regen Cargo.lock in tarball-shape, vendor deps,
                        # compress to inst/vendor.tar.xz.
just r-cmd-build        # Build tarball (depends on `just vendor`).
just r-cmd-check        # Check tarball (always check the tarball, not source dir).

The single signal [ -f inst/vendor.tar.xz ] triggers tarball-mode install automatically; no env var to set. See docs/CRAN_COMPATIBILITY.md.

🔗Troubleshooting

🔗“configure: command not found”

Always invoke configure with bash:

cd rpkg && bash ./configure     # Correct
cd rpkg && ./configure          # May fail on some systems

Or regenerate from configure.ac:

cd rpkg && autoconf && bash ./configure

🔗“Could not find tools necessary to compile a package”

If running in a sandboxed environment, compilation commands need the sandbox disabled.

🔗R tests fail with “could not find function”

The function exists in Rust but isn’t callable from R. Check:

  1. Function is pub
  2. Function has the #[miniextendr] attribute
  3. Run just devtools-document to regenerate NAMESPACE

Quick fix:

just configure && just rcmdinstall && just devtools-document

🔗Stale R wrappers after macro changes

Same fix:

just configure && just rcmdinstall && just devtools-document

🔗Permission errors during install

Use a local library path:

R_LIBS=/tmp/R_lib just rcmdinstall

🔗Lint warnings

Run just lint to check source-level attributes for consistency. See MACRO_ERRORS.md for interpreting lint output.

🔗Transient test failures in parallel runs

Running all test suites in parallel can cause races. Re-run failed suites individually:

just test               # If this fails, run specific crate tests
just clippy             # May fail during parallel configure

🔗Install modes

ModeWhenBehavior
Sourceinst/vendor.tar.xz absentCargo resolves through [patch."git+url"] to monorepo siblings, or fetches the git URL when no siblings are detected.
Tarballinst/vendor.tar.xz presentConfigure unpacks the tarball, writes [source] replacement to vendored-sources, build runs --offline.

See docs/CRAN_COMPATIBILITY.md for the full table.

🔗Sync Checks

just vendor-sync-check  # Verify vendored crates match workspace
just templates-check    # Verify templates haven't drifted from rpkg
just templates-approve  # Accept current template delta (after intentional changes)