An open API service indexing awesome lists of open source software.

https://github.com/extendr/libR-sys

Low level R bindgen interface
https://github.com/extendr/libR-sys

Last synced: 3 months ago
JSON representation

Low level R bindgen interface

Awesome Lists containing this project

README

        

# libR-sys

Low-level R library bindings

[![Github Actions Build Status](https://github.com/extendr/libR-sys/workflows/Tests/badge.svg)](https://github.com/extendr/libR-sys/actions)
[![crates.io](https://img.shields.io/crates/v/libR-sys.svg)](https://crates.io/crates/libR-sys)
[![Documentation](https://docs.rs/libR-sys/badge.svg)](https://docs.rs/libR-sys)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Installation

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`).

## Configuration

`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.

## Using precompiled bindings (recommended)

Two components are required to build the library:

1. [`R`](https://cran.r-project.org/): It needs to be installed and available in the search path.
2. [`Rust`](https://www.rust-lang.org/learn/get-started): It is recommended to install `Rust` using `rustup`; search path should include `Rust` binaries.

**Note: On Windows, only R >= 4.2 is supported**

Once `R` and `Rust` are configured, the library can be easily built:

```bash
# macOS & Linux
cargo build

# Windows
cargo build --target x86_64-pc-windows-gnu
```

To test the build, run `cargo test`.

```bash
# macOS & Linux
cargo test

# Windows
cargo test --target x86_64-pc-windows-gnu
```

## Building bindings from source (advanced)

**Note: On Windows, only R >= 4.2 is supported**

The bindings can be generated using [`bindgen`](https://github.com/rust-lang/rust-bindgen), special `Rust` crate.
`bindgen` usage is enabled via `use-bindgen` feature flag.

`bindgen` requires [`libclang`](https://clang.llvm.org/docs/Tooling.html), 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](https://brew.sh/) 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**
On Windows, bindings can be generated using native `LLVM` installation and `Rtools` distribution.

Install LLVM:

```powershell
choco install llvm -y
```

`LLVM` can be also installed using `winget`, `scoop`, or manually.

To ensure LLVM is successfully installed and configured, run `clang --version`. If `clang` is not on the `PATH`, manually add path to `clang` installation to the `PATH` environement variable.

Install `Rtools` if it is misisng:

```powershell
choco install rtools -y
```

Installing `Rtools` this way automatically sets `RTOOLS42_HOME` (or `RTOOLS43_HOME`) environment variable.

Ensure that `R_HOME` environment variable is set to the `R` installation directory.

Finally, point `libR-sys` to the include directory of `Rtools`:

```powershell
$env:LIBRSYS_LIBCLANG_INCLUDE_PATH="$env:RTOOLS42_HOME\x86_64-w64-mingw32.static.posix\include"
```

Now, the bindings can be build using the following command:

```powershell
cargo build --target x86_64-pc-windows-gnu --features use-bindgen
```

## Running bindgen tests on Windows

Running bindgen tests on Windows requires a bit more setup.

First, add `Rtools` `bin` directory to the `PATH` (replace `RTOOLS42_HOME` with `RTOOLS43_HOME` if you are using `Rtools` 4.3):

```powershell
$env:PATH += ";$env:RTOOLS42_HOME\x86_64-w64-mingw32.static.posix\bin"
```

Second, patch `Rtools` version `4.2` and higher since there is a `gcc` static linking issue. `rustc` adds `-lgcc_eh` flag
to the compiler, but Rtools' GCC doesn't have `libgcc_eh` due to
the compilation settings. So, in order to please the compiler, `libgcc_eh` should be mocked and added to the library search paths. For more details, please refer to [r-windows/rtools-packages].

[r-windows/rtools-packages]: https://github.com/r-windows/rtools-packages/blob/2407b23f1e0925bbb20a4162c963600105236318/mingw-w64-gcc/PKGBUILD#L313-L316

Create a directory for missing library file and an empty file there:

``` powershell
# create a directory in an arbitrary location (e.g. libgcc_mock)
New-Item -Path libgcc_mock -Type Directory

# create empty libgcc_eh.a and libgcc_s.a
New-Item -Path libgcc_mock\libgcc_eh.a -Type File
```

Finally, configure `Rust` compiler and select appropriate linker (see [The Cargo Book]):

[The Cargo Book]: https://doc.rust-lang.org/cargo/reference/config.html#environment-variables

```powershell
$env:CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="x86_64-w64-mingw32.static.posix-gcc.exe"
$env:LIBRARY_PATH="libgcc_mock" # Replace it with the path to the directory created above
```

Alternatively, linker can be configured in `.cargo/config.toml`:

``` toml
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32.static.posix-gcc.exe"
```

Now, the tests can be run:

```powershell
cargo test --target x86_64-pc-windows-gnu --features use-bindgen
```

### Editor settings

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}"
}
}
```