r-wasm / webr

The statistical language R compiled to WebAssembly via Emscripten, for use in web browsers and Node.
https://docs.r-wasm.org/webr/latest/
Other
804 stars 54 forks source link

Creating a library from webr packages #433

Closed stobor827 closed 3 weeks ago

stobor827 commented 3 weeks ago

I am attempting what was discussed in #260 for NodeJS but do not see how to download the packages in order to build them into a library. It is also hinted at in step one of this reply for a in-browser implementation: https://github.com/r-wasm/webr/issues/428#issuecomment-2134723022

I was hoping to be able to mount a NODEFS library, setup my .libpaths() to use it, then just installPackages() into it, but this crashes. Is there a simple method I am missing? I made sure that the "./extra" dir was writeable, not sure if there is other setup I need to perform.

import  WebR from "webr";

globalThis.webR = new WebR.WebR();
await globalThis.webR.init();
console.log( "webr init");
await globalThis.webR.FS.mkdir('/library')
await globalThis.webR.FS.mount('NODEFS', { root: './extra'  }, '/library');

await globalThis.webR.evalR(".libPaths(\"/library\")");
await globalThis.webR.installPackages(["cli"]);
node:internal/modules/run_main:115
    triggerUncaughtException(
    ^

Error: Error in `mount(mountpoint, data_url)`: Cannot set properties of undefined (setting 'DESCRIPTION')
    at captureR (/app/server/node_modules/webr/dist/webr-worker.js:4945:15)
    at evalR (/app/server/node_modules/webr/dist/webr-worker.js:4982:19)
    at SharedBufferChannelWorker.dispatch (/app/server/node_modules/webr/dist/webr-worker.js:4689:13)
    at SharedBufferChannelWorker.inputOrDispatch (/app/server/node_modules/webr/dist/webr-worker.js:2627:37)
    at Object.readConsole (/app/server/node_modules/webr/dist/webr-worker.js:5067:19)
    at 1107491 (/app/server/node_modules/webr/dist/R.bin.js:1861:34298)
    at runEmAsmFunction (/app/server/node_modules/webr/dist/R.bin.js:1861:316875)
    at _emscripten_asm_const_int (/app/server/node_modules/webr/dist/R.bin.js:1861:316945)
    at wasm://wasm/016b7cfa:wasm-function[2968]:0x2206de
    at wasm://wasm/016b7cfa:wasm-function[2998]:0x221efc {
  name: 'Ie'
}
georgestagg commented 3 weeks ago

WebR has been configured to download R packages as VFS MEMFS images by default. With this, VFS images are mounted in place rather than written to the NODEFS mounted filesystem as individual files.

So, rather than using install.packages(), tell webR to install R packages without mounting a MEMFS VFS image using the mount argument of webr::install(). With that, the package contents should be written to the NODEFS mount as expected:

await globalThis.webR.FS.mkdir('/library')
await globalThis.webR.FS.mount('NODEFS', { root: './extra' }, '/library');
await globalThis.webR.evalR(".libPaths(\"/library\")");
await globalThis.webR.evalR("webr::install(\"cli\", mount = FALSE)");
$ node packages.mjs
webr init
Downloading webR package: cli
^C
$ ls extra
cli
$ ls extra/cli
DESCRIPTION INDEX       LICENSE    [...]
stobor827 commented 3 weeks ago

This worked great, thank you.