Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/run_preflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Set up R
uses: r-lib/actions/setup-r@v2

- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
Expand All @@ -24,6 +27,9 @@ jobs:
working-directory: rust
run: rustup component add clippy rustfmt

- name: Set R_HOME env var
run: echo "R_HOME=$(R RHOME)" >> $GITHUB_ENV

- name: Format check
working-directory: rust
run: cargo fmt --all -- --check
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/run_rust_unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up R
uses: r-lib/actions/setup-r@v2

- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
Expand All @@ -27,7 +30,9 @@ jobs:
run: sudo apt-get update && sudo apt-get install -y libssl-dev pkg-config

- name: Run tests
working-directory: rust
run: cargo test
run: |
export LD_LIBRARY_PATH=$(R RHOME)/lib:$LD_LIBRARY_PATH
cargo test



15 changes: 14 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,17 @@ venv/
.codegpt

# prettier node
node_modules/
node_modules/

# R specific
.Rhistory
.RData
bindings/r/src/rust/vendor
bindings/r/src/Makevars
bindings/r/src/Makevars.win
*.o
*.so
*.dll
target
.cargo
.Rproj.user
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
members = [
"rust/codelist-rs",
"rust/codelist-validator-rs",
"bindings/python"
"bindings/python",
"bindings/r/src/rust"
]
8 changes: 8 additions & 0 deletions bindings/r/.Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
^\.vscode$
^src/\.cargo$
^src/rust/vendor$
^src/rust/target$
^src/Makevars$
^src/Makevars\.win$
^.*\.Rproj$
^\.Rproj\.user$
13 changes: 0 additions & 13 deletions bindings/r/Cargo.toml

This file was deleted.

5 changes: 4 additions & 1 deletion bindings/r/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Imports:
rextendr
Config/rextendr/version: 0.3.1
Config/rextendr/version: 0.4.0.9000
SystemRequirements: Cargo (Rust's package manager), rustc
Depends:
R (>= 4.2)
5 changes: 4 additions & 1 deletion bindings/r/NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Generated by roxygen2: do not edit by hand

S3method("$",Codelist)
S3method("[[",Codelist)
useDynLib(codelist, .registration = TRUE)
export(hello)
14 changes: 14 additions & 0 deletions bindings/r/R/extendr-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,19 @@ NULL

hello <- function() .Call(wrap__hello)

Codelist <- new.env(parent = emptyenv())

Codelist$new <- function(name) .Call(wrap__Codelist__new, name)

Codelist$set_name <- function(new_name) .Call(wrap__Codelist__set_name, self, new_name)

Codelist$get_entries <- function() .Call(wrap__Codelist__get_entries, self)

#' @export
`$.Codelist` <- function (self, name) { func <- Codelist[[name]]; environment(func) <- environment(); func }

#' @export
`[[.Codelist` <- `$.Codelist`


# nolint end
44 changes: 20 additions & 24 deletions bindings/r/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# R Bindings

This package demonstrates how to call Rust functions from R using extendr. I
(@CarolineMorton) have not yet implemented this with our Codelist library but
rather with a simple "hello world" function.
This package demonstrates how to call Rust functions from R using extendr.

## Prerequisites

Expand Down Expand Up @@ -35,19 +33,15 @@ which i said no to.

## Building and Installing

1. First build the Rust library:
1. First go into R folder and build the package.

```bash
cd r
cargo build --release
cd bindings/r
```

This will create a shared library in `target/release/libcodelist.dylib` (macOS)
or `target/release/libcodelist.so` (Linux).

2. Open R with the terminal command `R` and install required packages. If you
get an error message when running this, you may also need to install package
dependencies for `devtools` first if not already installed:
You will need to go into R at this point and install required packages of
`rextendr`. If you get an error message when running this, you may also need to
install package dependencies for `devtools` first if not already installed:

```r
install.packages("devtools")
Expand All @@ -60,8 +54,6 @@ I picked `64` as the mirror I wanted to use.

```r
rextendr::document()
devtools::document()
devtools::load_all()
```

4. Test that it works:
Expand All @@ -70,18 +62,22 @@ devtools::load_all()
hello()
```

## Installing Permanently

To install the package permanently:
Everytime you make changes to the Rust code, you will need to run the following
commands in R:

```r
devtools::build()
devtools::install()
rextendr::document()
library(codelist)
```

After installation, you can use it like any other R package:
The `library(codelist)` command loads the package, so you can use the functions
and structs within in so it is important to run this after you have made changes
to the Rust code.

```r
library(codelist)
hello()
```
#### Tips for non-R users

- You can create R scripts by making a file that ends with `.R` and then running
it in R. It is probably easier at this point to opne in RStudio and run in the
console or by clicking at the script. Remember to save.
- Exit the R console with `q()` and then type `n` to not save the workspace
image.
3 changes: 3 additions & 0 deletions bindings/r/configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env sh
: "${R_HOME=`R RHOME`}"
"${R_HOME}/bin/Rscript" tools/config.R
2 changes: 2 additions & 0 deletions bindings/r/configure.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env sh
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" tools/config.R
17 changes: 17 additions & 0 deletions bindings/r/r.Rproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX

BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
8 changes: 8 additions & 0 deletions bindings/r/scripts/scratch.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
library(codelist)

c <- Codelist$new('test')
c$set_name('new_test')
e <- c$get_entries()

first <- e[[1]]$code

39 changes: 34 additions & 5 deletions bindings/r/src/Makevars
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
LIBDIR = ../target/release
TARGET_DIR = ./rust/target
LIBDIR = $(TARGET_DIR)/debug
STATLIB = $(LIBDIR)/libcodelist.a
PKG_LIBS = -L$(LIBDIR) -lcodelist

all: C_clean
all: $(SHLIB) rust_clean

.PHONY: $(STATLIB)

$(SHLIB): $(STATLIB)

CARGOTMP = $(CURDIR)/.cargo
VENDOR_DIR = $(CURDIR)/vendor


# RUSTFLAGS appends --print=native-static-libs to ensure that
# the correct linkers are used. Use this for debugging if need.
#
# CRAN note: Cargo and Rustc versions are reported during
# configure via tools/msrv.R.
#
# vendor.tar.xz, if present, is unzipped and used for offline compilation.
$(STATLIB):
cargo build --lib --release

C_clean:
rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS)
if [ -f ./rust/vendor.tar.xz ]; then \
tar xf rust/vendor.tar.xz && \
mkdir -p $(CARGOTMP) && \
cp rust/vendor-config.toml $(CARGOTMP)/config.toml; \
fi

export CARGO_HOME=$(CARGOTMP) && \
export PATH="$(PATH):$(HOME)/.cargo/bin" && \
RUSTFLAGS="$(RUSTFLAGS) --print=native-static-libs" cargo build --lib --manifest-path=./rust/Cargo.toml --target-dir $(TARGET_DIR)

# Always clean up CARGOTMP
rm -Rf $(CARGOTMP);

rust_clean: $(SHLIB)
rm -Rf $(CARGOTMP) $(VENDOR_DIR)

clean:
rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) $(TARGET_DIR) $(VENDOR_DIR)
42 changes: 42 additions & 0 deletions bindings/r/src/Makevars.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
TARGET_DIR = ./rust/target
LIBDIR = $(TARGET_DIR)/@LIBDIR@
STATLIB = $(LIBDIR)/libcodelist.a
PKG_LIBS = -L$(LIBDIR) -lcodelist

all: $(SHLIB) rust_clean

.PHONY: $(STATLIB)

$(SHLIB): $(STATLIB)

CARGOTMP = $(CURDIR)/.cargo
VENDOR_DIR = $(CURDIR)/vendor


# RUSTFLAGS appends --print=native-static-libs to ensure that
# the correct linkers are used. Use this for debugging if need.
#
# CRAN note: Cargo and Rustc versions are reported during
# configure via tools/msrv.R.
#
# vendor.tar.xz, if present, is unzipped and used for offline compilation.
$(STATLIB):

if [ -f ./rust/vendor.tar.xz ]; then \
tar xf rust/vendor.tar.xz && \
mkdir -p $(CARGOTMP) && \
cp rust/vendor-config.toml $(CARGOTMP)/config.toml; \
fi

export CARGO_HOME=$(CARGOTMP) && \
export PATH="$(PATH):$(HOME)/.cargo/bin" && \
RUSTFLAGS="$(RUSTFLAGS) --print=native-static-libs" cargo build @CRAN_FLAGS@ --lib @PROFILE@ --manifest-path=./rust/Cargo.toml --target-dir $(TARGET_DIR) @TARGET@

# Always clean up CARGOTMP
rm -Rf $(CARGOTMP);

rust_clean: $(SHLIB)
rm -Rf $(CARGOTMP) $(VENDOR_DIR) @CLEAN_TARGET@

clean:
rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) $(TARGET_DIR) $(VENDOR_DIR)
39 changes: 39 additions & 0 deletions bindings/r/src/Makevars.win.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
TARGET = $(subst 64,x86_64,$(subst 32,i686,$(WIN)))-pc-windows-gnu

TARGET_DIR = ./rust/target
LIBDIR = $(TARGET_DIR)/$(TARGET)/@LIBDIR@
STATLIB = $(LIBDIR)/libcodelist.a
PKG_LIBS = -L$(LIBDIR) -lcodelist -lws2_32 -ladvapi32 -luserenv -lbcrypt -lntdll

all: $(SHLIB) rust_clean

.PHONY: $(STATLIB)

$(SHLIB): $(STATLIB)

CARGOTMP = $(CURDIR)/.cargo
VENDOR_DIR = vendor

$(STATLIB):
mkdir -p $(TARGET_DIR)/libgcc_mock
touch $(TARGET_DIR)/libgcc_mock/libgcc_eh.a

if [ -f ./rust/vendor.tar.xz ]; then \
tar xf rust/vendor.tar.xz && \
mkdir -p $(CARGOTMP) && \
cp rust/vendor-config.toml $(CARGOTMP)/config.toml; \
fi

# Build the project using Cargo with additional flags
export CARGO_HOME=$(CARGOTMP) && \
export LIBRARY_PATH="$(LIBRARY_PATH);$(CURDIR)/$(TARGET_DIR)/libgcc_mock" && \
RUSTFLAGS="$(RUSTFLAGS) --print=native-static-libs" cargo build @CRAN_FLAGS@ --target=$(TARGET) --lib @PROFILE@ --manifest-path=rust/Cargo.toml --target-dir=$(TARGET_DIR)

# Always clean up CARGOTMP
rm -Rf $(CARGOTMP);

rust_clean: $(SHLIB)
rm -Rf $(CARGOTMP) $(VENDOR_DIR) @CLEAN_TARGET@

clean:
rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS) $(TARGET_DIR) $(VENDOR_DIR)
Empty file added bindings/r/src/codelist-win.def
Empty file.
Loading
Loading