extendr / rextendr

An R package that helps scaffolding extendr-enabled packages or compiling Rust code dynamically
https://extendr.github.io/rextendr/
Other
197 stars 27 forks source link

Using a local rust crate with extendr #398

Open sanghoonio opened 6 days ago

sanghoonio commented 6 days ago

I am working on a Rust tool with this directory structure:

image

I want to add R bindings in bindings/r using rextendr that can call functions from my main Rust crate.

The specific issue I'm running into is with Cargo being unable to find the main crate during package installation. While an absolute path in bindings/r/src/rust/Cargo.toml works:

[dependencies]
gtars = { path = "/Users/sam/Documents/Work/gtars/gtars" }

This obviously isn't suitable for distribution. Using a relative path fails during R package installation:

[dependencies]
gtars = { path = "../../../../gtars" }

Error during installation:

error: failed to get `gtars` as a dependency of package `gtars-r v0.1.0`
Caused by:
  failed to load source for dependency `gtars`

How can I properly set up R bindings that:

  1. Can access my main Rust crate
  2. Works with relative paths
  3. Can be distributed to other users

I've tried:

Any guidance on the correct way to address this would be appreciated.

JosiahParry commented 6 days ago

Thanks for the issue! Do you have a repo available that we can look at?

thanks!

nleroy917 commented 6 days ago

Hey @JosiahParry! I'm not @sanghoonio but I work on the project too. Here is a link to the repo: https://github.com/databio/gtars

The branch is r_bindings

JosiahParry commented 6 days ago

Thanks @nleroy917, I'm playing with this now. I've got something working but it isn't ideal.

Out of curiosity where would you like to publish your R package? BioConductor?

For context, the challenge is that gtars is 2 levels up from the R package source meaning that the R package source is not portable.

The entirety of an R package's source should be contained within it. When using this approach that is not the case. What we need to do is vendor the package that is being used which isn't ideal because then you lose the nice developer experience of a change in one place is reflected elsewhere.

I can get the package to install by using

fs::dir_copy("../../gtars", "src/rust")
devtools::install()

and modifying the Cargo.toml to be

[dependencies]
extendr-api = "*"
gtars = { path = "gtars" }

again, this is undesirable.

@CGMossa do you have thoughts on how we can improve this? I personally would like to figure this out for rnetmatch rust crate. Robin Lovelace is interested in this pattern too.

I'm trying to think through how we can include the relative directory in the vendor.tar.gz but cargo vendor doesn't support using crates like this.

I also wonder if a workspace would be able to help here

nleroy917 commented 4 days ago

@JosiahParry thank you for this thorough response! This is super awesome. I am wondering if it would be easier to just create a new repo for this? It just nice to have it all in one place

JosiahParry commented 4 days ago

@nleroy917 technically, yes it may be easier, but it is still something I'd like to have work nicely. One alternative is to use

gtars = { git = "https://...." }

in the R package this would be a close alternative but would require pushing commits to have them reflected in your R bindings package.