Install R with packages

I want to install R with the RPostgreSQL CRAN package, which also needs the
postgresql package installed to provide the library libpq.

I found a way to do it that works, but it with incosistencies.

mkdir R_with_packages
cd R_with_packages
cat > default.nix <<hereDoc
with import <nixpkgs> {}; # adapted from https://nixos.org/manual/nixpkgs/stable/#installation
{
  myProject = stdenv.mkDerivation {
    name = "myProject";
    version = "1";
    src = if lib.inNixShell then null else nix; # i am not sure what this line does

    buildInputs =  [
      postgresql
      R
      rPackages.RPostgreSQL
    ];
  };
}
hereDoc

nix-shell .

this works on macos on apple silicon.
but when I try it on linux on x86_64,
it gets an error like this:

[nix-shell:~/foo]$ R

R version 4.2.2 (2022-10-31) -- "Innocent and Trusting"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> library(RPostgreSQL)
Loading required package: DBI
Error: package or namespace load failed for ‘RPostgreSQL’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/home/jeg/R/x86_64-pc-linux-gnu-library/4.2/RPostgreSQL/libs/RPostgreSQL.so':
  libpq.so.5: cannot open shared object file: No such file or directory
>

I did find a workaround, if I start R like this, it works:

LD_LIBRARY_PATH=$(dirname $(ldd $(which psql) | awk '/libpq.so.5/{print $3}')) R

note that this kludge does not work on macos, because it macos does not have the ldd command, but it is not needed there becasue it just works there anyway.

Hey thanks for the report and +1 for diving into writing some nix derivations!

You encountered a somewhat obnoxious quirk in how nixpkgs organizes “sub-parts” of a package ( “outputs” ), but the good news is I’ve got a fix for you. I’ll circle back to show you how to debug this in the future.

Give this modified derivation a try:

{ pkgs        ? import <nixpkgs> {}
, stdenv      ? pkgs.stdenv
, postgresql  ? pkgs.postgresql
, R           ? pkgs.R
, rPackages   ? pkgs.rPackages
, RPostgreSQL ? rPackages.RPostgreSQL
}: {
  myProject = stdenv.mkDerivation {
    name        = "myProject";
    version     = "1";
    src         = builtins.path { path = ./.; };
    buildInputs = [postgresql.lib R RPostgreSQL];
  };
}

Here’s the output of using the shell and loading that lib:

$ nix-shell .

[nix-shell:/tmp/example]$ R

R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> library(RPostgreSQL)
Loading required package: DBI
> q()
Save workspace image? [y/n/c]: n

The “key” part that fixed the library loading was using postgresql.lib instead of postgresql ( which only contains binaries ). In nixpkgs many packages have “multiple outputs”, which are similar to “sub-packages” with a tool like apt ( ex: glib and glib-dev with apt, is like glib and glib.dev in nixpkgs ).

Common outputs are:

  • <NAME>.out : the default, which is always defined. Conventionally contains executables and resources required to run them.
  • <NAME>.dev : conventionally contains headers and usually pkg-config files.
  • <NAME>.lib : conventionally contains lib and sometimes pkg-config files.
  • <NAME>.{man,info,doc} : provides manpages, infopages, and any other doc formats.

Personally I’d prefer that these were all just merged together, but this is a convention that nixpkgs uses to optimize builds. The good news is it’s easy to check to see if a package has multiple outputs, you can run the following to see the list for a given package:

$ nix eval 'nixpkgs#postgresql.outputs'
[ "out" "lib" "doc" "man" "debug" ]

This is what I used to check for postgresql libs with your example.

Next I’ll briefly cover the remaining modifications I made to the file:

  • Added arguments to the top of the file to align with nix and nixpkgs conventions.
    • This allows helpers such as nixpkgs#pkgs.callPackage to work with this derivation.
    • You could use this to create multiple “instances” of this package with different inputs.
  • Set src to the directory containing default.nix.
    • I wasn’t 100% sure that this is what you wanted, but the snippet you had previously would have copied the installed form of nix into your working directory which didn’t seem desirable. I suspect that you don’t really need src here.

Hopefully this helps. Let me know if you have any follow up questions.

Could you let me know if this helped resolve your issue?

Thanks! I confirm that your version works both on my macos aarch64 and Ubuntu X86_64.

It is great to have a clear working example to modify.

1 Like