numtide / devshell

Per project developer environments
https://numtide.github.io/devshell/
MIT License
1.25k stars 89 forks source link

Using a custom Node.js version #212

Closed zaiste closed 2 years ago

zaiste commented 2 years ago

I'm trying to build a custom Node.js version for a JS project initated with devshell using Flakes.

Here's my current flake.nix:

{
  description = "virtual environments";

  inputs.devshell.url = "github:numtide/devshell";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, flake-utils, devshell, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      devShell =
        let 
          pkgs = import nixpkgs {
            inherit system;

            overlays = [ devshell.overlay ];
          };

          buildInputs = with pkgs; [ python39 ];

          buildNodejs = pkgs.callPackage <nixpkgs/pkgs/development/web/nodejs/nodejs.nix> {};

          nodejs-8 = buildNodejs {
            enableNpm = true;  
            version = "17.3.1";
            sha256 = "cf088f7854aa78d5aef7f9bc58bdb8d7342a0197ba24af62afd2fc3233f21d1c";
          };
        in
        pkgs.devshell.mkShell {
          imports = [ (pkgs.devshell.importTOML ./devshell.toml) ];
          devshell.packages = [ nodejs-8 ];
        };
    });
}

When run as nix develop --impure the correct Node.js version is fetched, but the command returns the following error:

error: builder for '/nix/store/g7y5d0g6rnvnxknrg2i81rfw49rci88h-nodejs-17.3.1.drv' failed with exit code 1;
       last 10 log lines:
       > ./deps/npm/lib/utils/completion.sh: interpreter directive changed from "#!/bin/bash" to "/nix/store/b5wy2gwvqpgc9iwqhnbrw6xmm7i1zz4q-bash-5.1-p16/bin/bash"
       > updateAutotoolsGnuConfigScriptsPhase
       > Updating Autotools / GNU config script to a newer upstream version: ./deps/cares/config.sub
       > Updating Autotools / GNU config script to a newer upstream version: ./deps/cares/config.guess
       > configuring
       > fixing libtool script ./deps/cares/ltmain.sh
       > ./deps/cares/configure
       > configure flags: --prefix=/nix/store/25kdyyl9dh8xs2mvaj2plfrkvdk2qhvl-nodejs-17.3.1 --shared-libuv --shared-libuv-libpath=/nix/store/pp6zi7ssxvqbk3fdkcx830bjdr55v20q-libuv-1.44.1/lib --shared-openssl --shared-openssl-libpath=/nix/store/1yhkn4rmhxpxdpvf10m10x5z60sxwhkr-openssl-1.1.1q/lib --shared-zlib --shared-zlib-libpath=/nix/store/lkgrb3lfingdcxr9fzc847c5wihk1w73-zlib-1.2.12/lib --with-intl=system-icu --without-dtrace
       > Node.js configure: Found Python 2.7.18...
       > Please use python3.10 or python3.9 or python3.8 or python3.7 or python3.6.
       For full logs, run 'nix log /nix/store/g7y5d0g6rnvnxknrg2i81rfw49rci88h-nodejs-17.3.1.drv'.
error: 1 dependencies of derivation '/nix/store/9620nfi2k1vw84r2byd6a00a510n7qk6-devshell-dir.drv' failed to build
error: 1 dependencies of derivation '/nix/store/8m5w6hs4m997k9d1p7pn4fcxn2r3sqhi-devshell-env.drv' failed to build

I've added the buildInputs with the correct Python version, but it doesn't seem to be taken into account.

Is it possible to solve this use case with devshell? Is it possible to skip the --impure flag?

srounce commented 2 years ago

The issue you are having (as you correctly pointed out) is due to a valid version of Python not being supplied to the nodejs package's nativeBuildInputs when it is built. To fix it there is a small change to make: Currently you have specified a let binding called buildInputs but this doesn't seem to be evaluated anywhere and isn't doing anything. Instead, a fix is to set a python attribute referring to a valid Python version in the callPackage invocation (see diff).

To avoid --impure you can specify nixpkgs as a flake input, and then when creating the path to nodejs.nix reference the input rather than using the NIX_PATH notation <nixpkgs>.

Please see the diff below:

{
  description = "virtual environments";

+ inputs.nixpkgs.url = "github:nixos/nixpkgs";
  inputs.devshell.url = "github:numtide/devshell";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, flake-utils, devshell, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      devShell =
        let 
          pkgs = import nixpkgs {
            inherit system;

            overlays = [ devshell.overlay ];
          };

-         buildInputs = with pkgs; [ python39 ];
-
-         buildNodejs = pkgs.callPackage <nixpkgs/pkgs/development/web/nodejs/nodejs.nix> {};
+         buildNodejs = pkgs.callPackage "${nixpkgs}/pkgs/development/web/nodejs/nodejs.nix" {
+           python = pkgs.python39;
+         };

          nodejs-8 = buildNodejs {
            enableNpm = true;  
            version = "17.3.1";
            sha256 = "cf088f7854aa78d5aef7f9bc58bdb8d7342a0197ba24af62afd2fc3233f21d1c";
          };
        in
        pkgs.devshell.mkShell {
          imports = [ (pkgs.devshell.importTOML ./devshell.toml) ];
          devshell.packages = [ nodejs-8 ];
        };
    });
}
zaiste commented 2 years ago

Thank you! It works. I'm still new to Nix, but I (slowly) start to understand how all the pieces fit together.

Is there perhaps a way to extract the function (?) signature (i.e. in this case python) to know what could be overridden, or simply it's a matter of getting familiar with the built-in .nix files by reading the source code?