Low-level R library bindings
The recommended way to build this library is to use precompiled bindings, which are available for Linux
, macOS
, and Windows
.
Alternatively, the library can be built from source, in which case it invokes bindgen
crate, which has extra platform-specific dependencies (including msys2
for Windows
).
libR-sys
recognizes the following environment variables:
LIBRSYS_R_VERSION
If set, it is used to determine the version of R, for which bindings should be generated. LIBRSYS_R_VERSION
should be set to one of the supported values, e.g. 4.2.0
or 4.3.0-devel
(the pattern is major.minor.patch[-devel]
). Malformed LIBRSYS_R_VERSION
results in compilation error. If LIBRSYS_R_VERSION
is unset, R
is invoked and its R.version
is used.Two components are required to build the library:
R
: It needs to be installed and available in the search path.Rust
: It is recommended to install Rust
using rustup
; search path should include Rust
binaries.Note: On Windows, R < 4.2 requires a more complex setup in order to support the 32-bit version. Please refer to README-old-windows.md for more details.
Once R
and Rust
are configured, the library can be easily built:
```bash
cargo build
cargo build --target x86_64-pc-windows-gnu ```
To test the build, run cargo test
.
```bash
cargo test
cargo test --target x86_64-pc-windows-gnu ```
Note: On Windows, R < 4.2 requires a more complex setup in order to support the 32-bit version. Please refer to README-old-windows.md for more details.
The bindings can be generated using bindgen
, special Rust
crate.
bindgen
usage is enabled via use-bindgen
feature flag.
bindgen
requires libclang
, which should be installed first.
This library relies on LIBCLANG_PATH
environment variable to determine path to the appropriate version of libclang
.
The output folder for bindings can be configured using LIBRSYS_BINDINGS_OUTPUT_PATH
environment variable, thus make sure it is set to e.g bindings
.
Linux
Set LIBCLANG_PATH
to the lib
directory of your llvm
installation, e.g.,
LIBCLANG_PATH=/usr/lib/llvm-3.9/lib
. Build & test using
shell
cargo build --features use-bindgen
cargo test --features use-bindgen
macOS
Install llvm-config
via homebrew with:
bash
brew install llvm
Add it to your search path via:
bash
echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.bash_profile
If you want to compile libR-sys
from within RStudio, you may also have to add the following line to your .Renviron
file:
bash
PATH=/usr/local/opt/llvm/bin:$PATH
Build & test using
shell
cargo build --features use-bindgen
cargo test --features use-bindgen
Windows
Binding generation on Windows happens with the help of MSYS2
.
Make sure the environment variable MSYS_ROOT
points to MSYS2
root, e.g., C:\tools\msys64
.
Installing and configuring
MSYS2
Install MSYS2
. Here is an example using chocolatey
:
shell
choco install msys2 -y
Set up MSYS_ROOT
environment variable.
Install clang
and mingw
-toolchains (assuming PowerShell
syntax)
pwsh
&"$env:MSYS_ROOT\usr\bin\bash" -l -c "pacman -S --noconfirm mingw-w64-x86_64-clang mingw-w64-x86_64-toolchain"
Add the following to the PATH
(using PowerShell
syntax).
```pwsh
$rtools_home = "C:\rtools42"
$env:PATH = "${env:RHOME}\bin\x64;${rtoolshome}\usr\bin;${rtoolshome}\x8664-w64-mingw32.static.posix\bin;${env:MSYS_ROOT}mingw64\bin;${env:PATH}" ```
then build & test with
pwsh
cargo build --target x86_64-pc-windows-gnu --features use-bindgen
The setup is tricky because the Rtools' toolchain is a bit different from the assumption of Rust.
Both the default MSVC toolchain and the GNU toolchain should work fine with libR-sys, but we recommend the MSVC toolchain because we mainly use it.
With either toolchain, since the R itself is built with the GNU toolchain, the target must be GNU. So, the GNU target needs to be installed.
shell
rustup target add x86_64-pc-windows-gnu
Rtools42 can be downloaded from here. For R >= 4.3, download
Rtools43 from here. Alternatively, Rtools
will eventually
be available on chocolatey
.
```shell
```
R_HOME
and PATH
Environment VariablesFirst, ensure that R_HOME
points to R
home, e.g. C:\Program Files\R\R-4.2.0
(in an R session, this should be automatically set by R).
Second, ensure that PATH
is properly configured that the following executables
are available:
R
binary to build againstRtools
Typically, the following paths need to be added to the head of PATH
(using
PowerShell
syntax).
```pwsh
$rtools_home = "C:\rtools42"
$env:PATH = "${env:RHOME}\bin\x64;${rtoolshome}\usr\bin;${rtoolshome}\x8664-w64-mingw32.static.posix\bin;${env:PATH}" ```
Note that the above prepends, rather than appends, because otherwise the wrong
toolchain might be accidentally chosen if the PATH
already contains another
version of R
or compiler toolchain.
As noted above, since the Rtools' toolchain is a bit different from the assumption of Rust, we need the following tweaks:
x86_64-w64-mingw32.static.posix-gcc.exe
.libgcc_s.a
and libgcc_eh.a
, and add them to the compiler's
library search paths via LIBRARY_PATH
environment variables.The first tweak is needed because Rtools42 and Rtools43 don't contain
x86_64-w64-mingw32-gcc
, which rustc
uses as the default linker for the
x86_64-pc-windows-gnu
target. This can be done by adding .cargo/config.toml
with the following lines on the root directory of the project:
toml
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32.static.posix-gcc.exe"
Alternatively, you can inject this configuration via the corresponding
environmental variable, CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER
. See [the
Cargo Book] about how this works.
The second tweak is also required. rustc
adds -lgcc_eh
and -lgcc_s
flags
to the compiler, but Rtools' GCC doesn't have libgcc_eh
or libgcc_s
due to
the compilation settings. So, in order to please the compiler, we need to add
empty libgcc_eh
or libgcc_s
to the library search paths. For more details,
please refer to [r-windows/rtools-packages].
First, create a directory that contains empty libgcc_eh
or libgcc_s
.
``` ps1
New-Item -Path libgcc_mock -Type Directory
New-Item -Path libgccmocklibgcceh.a -Type File New-Item -Path libgccmocklibgccs.a -Type File ```
Then, add the directory to LIBRARY_PATH
environment variables. For example, this can be done
by adding the following lines to .cargo/config.toml
:
toml
[env]
LIBRARY_PATH = "path/to/libgcc_mock"
Rust-analyzer might need some settings. For example, if you are using VS Code, you probably need to add the following options to .vscode/settings.json
.
json
{
// The target needs to be GNU
"rust-analyzer.cargo.target": "x86_64-pc-windows-gnu",
// Specify "use-bindgen" for developing R-devel.
"rust-analyzer.cargo.features": [],
"terminal.integrated.env.windows": {
"R_HOME": "C:/Program Files/R/R-4.2.2",
"PATH": "${env:R_HOME}/bin/x64;C:/rtools42/x86_64-w64-mingw32.static.posix/bin;C:/rtools42/usr/bin;${env:PATH}"
}
}