b-rodrigues / rix

Reproducible development environments for R with Nix
https://b-rodrigues.github.io/rix/
GNU General Public License v3.0
102 stars 11 forks source link

What's wrong about trying rix from within nix? #133

Closed clemens-tolboom closed 4 months ago

clemens-tolboom commented 4 months ago

On MacOS having nix installed in multi user mode

nix-shell -p neovim R

cat rix_test.R 

having file rix_test.R

#!/usr/bin/env Rscript

install.packages("rix", repos = c("https://b-rodrigues.r-universe.dev",
  "https://cloud.r-project.org"))

library("rix")

and running

chmod u+x ./rix_test.R 
./rix_test.R 

it cannot install

During startup - Warning messages:
1: Setting LC_COLLATE failed, using "C" 
2: Setting LC_TIME failed, using "C" 
3: Setting LC_MESSAGES failed, using "C" 
4: Setting LC_MONETARY failed, using "C" 
Installing package into ‘/nix/store/f06jsm22ziz2rx4skprjsv0465jp2f20-apple-framework-CoreFoundation-11.0.0/Library’
(as ‘lib’ is unspecified)
Warning in install.packages("rix", repos = c("https://b-rodrigues.r-universe.dev",  :
  'lib = "/nix/store/f06jsm22ziz2rx4skprjsv0465jp2f20-apple-framework-CoreFoundation-11.0.0/Library"' is not writable
Error in install.packages("rix", repos = c("https://b-rodrigues.r-universe.dev",  : 
  unable to install packages
Execution halted
clemens-tolboom commented 4 months ago

I'm a noob regarding Nix ... thus made a mistake ... it is not a script ... use R to run interactive

trying to run from within the nix-shell then R shell

install.packages("rix", repos = c("https://b-rodrigues.r-universe.dev",
  "https://cloud.r-project.org"))

library("rix")

I kept adding packages to the shell and finally gave up :-/

nix-shell -p neovim R \
  rPackages.renv rPackages.curl rPackages.jsonlite \
  rPackages.httr rPackages.askpass rPackages.mime rPackages.sys

I was curious how to build on nix but guess have to start from the RStudio/non-nix side.

b-rodrigues commented 4 months ago

Hi Clemens

the way you are using nix-shell will only provide a temporary interactive shell. This is quite handy if you quickly want to test a package, but if you want to build a reproducible environment, it is much better to write a file called default.nix (or even shell.nix) that will contain a recipe to build this environment. You can list the version of R and which R packages and other tools you need for that particular environment in the Nix programming language. Because this language might be difficult to learn, we wrote this package, rix, which helps you generate such a default.nix file.

The first issue is getting R on your system. How did you install R? If you installed R through the usual means for your system, for example, using your linux distribution's package manager, or using the installer for windows or macOS, you can install rix from the r-universe. You can then use it to generate the correct expression. In your case, something like this ought to do:

library(rix)

rix(r_ver = "latest,
      r_pkgs = c("curl", "jsonlite", "httr", "askpass", "mime", "sys" ,
      system_pkgs = "neovim")

(you'll notice I didn't list "renv", this is because renv doesn't play well with Nix. If you have an old project that use renv, it is highly recommended to keep using renv for that project. Use Nix and rix, for new projects only).

This will create a file called default.nix in the current working directory. You can now build the environment defined by this expression using the command line tool nix-build (you can also try the nix_build() function from your current R session). Then, once the environment is done building, you can start using it by typing nix-shell from your command line. This will "activate" the environment. Start neovim by simply typing neovim in that terminal. You will have access to that version of R and R packages that you listed.

We wrote some articles explaining all this in greater detail, take some time to go through them in order: https://b-rodrigues.github.io/rix/articles/

and if you have any other issues, don't hesitate to open an issue again :smile:

clemens-tolboom commented 4 months ago

(I guess I am a bad reader)

At work I have an renv mini project https://github.com/molgenis/molgenis-service-armadillo/tree/master/scripts/rock/rockctl which I want to use as a demo/test/(google Friday) case getting it into nix. I'm learning nix quicker then our R scripts.

I expected rix would do something similar as renv.lock generating based on current project adding stuff to it's generated default.nix

tbc

b-rodrigues commented 4 months ago

Hi, no the logic is different: renv will generate a lock file from your environment, but with rix, you have to specify your environment in advance. This generates the default.nix file (essentially a lock file) which can then be built with Nix. We plan on provide an renv2nix() function at some point in the future, but we're now focused on stabilizing the basic features of rix and get it on CRAN.

philipp-baumann commented 4 months ago

@clemens-tolboom maybe along what Bruno just said. What could maybe be neat is to transfer the contents of renv.lock JSON's ((sources, hashes, version numbers of R packages) ) from renv projects into something that rix::rix() could further digest. You are very welcome to make a PR for this :-)! i had this idea some time ago but as we are busy polishing rix, help is always appreciated.

clemens-tolboom commented 4 months ago

I agree that using a renv.lock would make a better proposition using rix but am still learning nix having (different?!) troubles (🤢 ) on my 3 test home systems so cannot sell nix @ work getting time.

Where is version ie 1.1.3 for https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=rPackages.dplyr which only show 1.1.4

Can I convert any R environment into a nix file or only when using particular version/matching nix versions ... I skip rix for now and focus on learning nix @ home first :-/

b-rodrigues commented 4 months ago

You can use any revision of nixpkgs (which you can find here https://github.com/NixOS/nixpkgs/tree/nixpkgs-unstable) and this will build an environment with the packages available at that particular revision (or github commit). rix provides a way to get revisions with particular R versions (or the very latest ones) but not a way to find a particular package version. The idea is that, most of the time, exact package versions don't really matter: what matters is that you need a coherent set up R packages + R.

There is unfortunately no easy way to look for a particular package version on Nix (this is not just a rix issue). I also thought about providing a lookup table of package versions and nixpkgs revisions (so not just R versions), but this would be a major endeavour, and we would still have the issue that one particular nixpkgs revision might have dplyr 1.1.3, but not the version of another package that you might need. This is a bit of an issue with renv, it makes it possible to have very incoherent sets of R versions and R package versions (you can have a very old version of R, some old packages, some more recent etc... it is quite complex to recreate such environments).

Our advice if you want to reproduce an old study is to only match the versions of R and use whatever packages come bundled with it, and test if you get the same results. This should happen most of the time. If not, it is possible to install a particular version of packages from source, as discussed here: https://b-rodrigues.github.io/rix/articles/d1-installing-r-packages-in-a-nix-environment.html#installing-old-packages-archived-on-cran

but this is not something that we advise you should use systematically because in this case, packages get installed from source.