Reference page
Linking Strategy
This document explains how miniextendr links against R's shared library (libR) for both R packages and standalone Rust binaries.
This document explains how miniextendr links against Rโs shared library (libR)
for both R packages and standalone Rust binaries.
๐Two Linking Contexts
miniextendr supports two usage patterns with different linking requirements:
| Context | Crate | Linking | rpath |
|---|---|---|---|
| R package | miniextendr-api | R handles linking | N/A |
| Standalone binary | miniextendr-engine | build.rs | Yes |
๐R Packages (miniextendr-api)
When building an R package, Rโs build system handles all linking:
R CMD INSTALLcompiles the Rust code viacargo build- R links the resulting static library into the packageโs shared object
- The shared object is loaded by R at runtime via
dyn.load()
No rpath needed: R is already running, so libR is already loaded.
๐Build Configuration
The Makevars (generated from Makevars.in) tells R how to link:
PKG_LIBS = $(CARGO_LIBDIR)/lib$(CARGO_STATICLIB_NAME).a
This uses the full path to the static archive (not -L/-l flags) to ensure
the linker picks up the staticlib directly. On Windows, Makevars.win also
adds system libraries (-lws2_32, -lntdll, etc.).
๐Standalone Binaries (miniextendr-engine)
When embedding R in a Rust binary (benchmarks, tools, etc.), the binary must:
- Link against
libRat compile time - Find
libRat runtime
๐build.rs Strategy
The miniextendr-engine/build.rs handles this:
// 1. Find R_HOME
let r_home = env::var("R_HOME")
.unwrap_or_else(|_| run_r_rhome());
// 2. Add library search path
let r_libdir = format!("{}/lib", r_home);
println!("cargo:rustc-link-search=native={}", r_libdir);
println!("cargo:rustc-link-lib=R");
// 3. Add rpath for runtime (non-Windows)
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", r_libdir);๐R Discovery
Rโs location is discovered in order:
R_HOMEenvironment variable (if set)R RHOMEcommand output (requires R on PATH)
Set R_HOME explicitly for reproducible builds:
R_HOME=/usr/lib/R cargo build๐rpath Behavior
The build script mirrors R CMD LINK behavior:
| Platform | rpath Strategy |
|---|---|
| Linux/macOS | -Wl,-rpath,<R_HOME>/lib embedded in binary |
| Windows | No rpath; uses PATH at runtime |
When rpath is emitted: Only for executable targets (bin, test, bench, example). Library targets skip rpath since the final binary determines runtime paths.
Detection logic:
fn should_emit_rpath() -> bool {
env::var_os("CARGO_BIN_NAME").is_some()
|| env::var_os("CARGO_TEST_NAME").is_some()
|| env::var_os("CARGO_BENCH_NAME").is_some()
|| env::var_os("CARGO_EXAMPLE_NAME").is_some()
}๐Platform Notes
๐Linux
Standard R installations put libR.so in $R_HOME/lib/. The rpath ensures
the binary finds it at runtime without modifying LD_LIBRARY_PATH.
For system R installations (e.g., /usr/lib/R), libR.so may already be in
a standard library path and work without rpath.
๐macOS
Similar to Linux. R.framework installations use $R_HOME/lib/ for libR.dylib.
The rpath uses -Wl,-rpath,<path> which macOS linker accepts.
For Homebrew R: R_HOME=$(brew --prefix r)/lib/R
๐Windows
Windows doesnโt use rpath. Instead:
R.dllmust be on PATH at runtime- Typically handled by Rโs installer adding R to PATH
- Or set
PATH=%R_HOME%\bin\x64;%PATH%before running
The build script skips rpath emission on Windows.
๐Troubleshooting
๐โlibR.so: cannot open shared object fileโ
The binary canโt find libR at runtime. Solutions:
- Set
LD_LIBRARY_PATH=$R_HOME/lib(temporary) - Rebuild with correct
R_HOMEto embed proper rpath - Install R to a standard system location
๐โR RHOME failedโ
The build script couldnโt find R. Solutions:
- Install R and ensure itโs on PATH
- Set
R_HOMEexplicitly:R_HOME=/path/to/R cargo build
๐Wrong R version linked
If multiple R versions are installed:
- Set
R_HOMEto the desired version - Verify with:
R_HOME=/path/to/R R --version
๐Static vs Dynamic Linking
miniextendr always links dynamically to libR:
- R is designed for dynamic linking
- Static linking would require R source modifications
- Dynamic linking allows version flexibility
๐Environment Variables
| Variable | Purpose | Example |
|---|---|---|
R_HOME | R installation directory | /usr/lib/R |
R_ARCH | R architecture subdirectory | /x64 (Windows) |
LD_LIBRARY_PATH | Runtime library search (Linux) | $R_HOME/lib |
DYLD_LIBRARY_PATH | Runtime library search (macOS) | $R_HOME/lib |