Search code examples
nixnix-shell

Nix: How a derivation sets up PATH in nix-shell without calling builder?


A derivation takes lots of arguments but only one of them, builder, is executable right?

And nix-shell doesn't really execute the builder, which means there's no way of running commands such as export PATH=....

But I found some other derivations provide their virtual shell environment in which PATH is arbitrarily set e.g .env attribute of haskell package derivations.

I also found that mkDerivation add buildInput packages' sub /bin directory to PATH if exists.

How do they do that? Is there some special argument to built-in derivation function that enables you to run custom commands when evaluating?


Solution

  • The last time I checked, nix-shell attempts to run this command when it starts up:

    source $stdenv/setup
    

    So when you call the derivation function, you should define an environment variable named $stdenv that points to a directory with a file named setup, and that file should be a valid Bash script. That script can then define shell functions and environment variables that you need.

    In my nixcrpkgs project, my setup script just has one line:

    export PATH=$_PATH
    

    So I pass _PATH as an argument to derivation, and my setup script copies it into the PATH environment variable.

    We can't just set PATH in our derivation because nix-shell will make the derivation's PATH override the system PATH, meaning we can't use utilities like "git" or "which" from the host system.

    Here's some pseudocode showing what you need to do:

    derivation {
      stdenv = ./my_pretened_stdenv;  # directory that has setup script in it
      _PATH = "/stuff/bin:/more_stuff/bin";
      # other attributes
    }