nixnix-shell

Using variable in NIX buildInputs?


I have a shell.nix configuration retrieving a pkgs from a variable like so:

{ pkgs ? import <nixpkgs> { } }:
with pkgs;
let
  nodeJs = "pkgs.nodejs_${builtins.getEnv "NODE_VERSION"}";
  terraform = pkgs.writers.writeBashBin "terraform" ''
    ${pkgs.terraform}/bin/terraform "$@"
  '';
in
pkgs.mkShell {
  buildInputs = [
    nodeJs 
    terraform
    pkgs.ngrok
  ];

}

But when I run nix shell I get:

build input pkgs.nodejs_20 does not exist

Yet, if I was to run it straight up (without variable) like so:

{ pkgs ? import <nixpkgs> { } }:
with pkgs;
pkgs.mkShell {
  buildInputs = [
    nodejs_20
    terraform
    pkgs.ngrok
  ];
}

This would work fine. I think it's being interpreted as a string. I cannot figure a way to write this variable as anything other than a string without throwing a syntax error.

How would I resolve this, Is this even possible to install a pkgs based off an environment variable?


Solution

  • "pkgs.nodejs_${builtins.getEnv "NODE_VERSION"}" is a string, and so doesn't refer to a package. To create a dynamic reference to a package, you need to instead construct a string and convert the whole thing to a reference via string interpolation (${}). That is, pkgs.${"nodejs_" + builtins.getEnv "NODE_VERSION"}:

    ❯ NODE_VERSION=20 nix repl --file '<nixpkgs/nixos>'
    Welcome to Nix 2.18.7. Type :? for help.
    
    Loading installable ''...
    Added 6 variables.
    nix-repl> pkgs.${"nodejs_" + builtins.getEnv "NODE_VERSION"}
    «derivation /nix/store/3hxn26fh3cpz4rnx3lcwm5cb0vg15rzk-nodejs-20.17.0.drv»