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

2

5

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?

Fairfield answered 26/10, 2020 at 14:26 Comment(0)
C
2

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
}
Clarabelle answered 26/10, 2020 at 15:55 Comment(0)
A
5

Another way of doing it is by exporting the specific paths during the phases of the derivation - although I am unsure if this is the correct way.

So say you need a package cowsay to be in your path when you are building something then you can make it available via adding it:

# ... 
<nixpkgs>.stdenv.mkDerivation{
# ...
  buildPhase = '' 
    export PATH="${<nixpkgs>.cowsay}/bin:$PATH"
  '';
# ... 
}

This will make the builder execute that command during buildPhase and also build the package and add it to your path for the build phase. You can do the same with a mkDerivation for shell by using shellHook

# ... 
<nixpkgs>.stdenv.mkDerivation{
# ...
  shellHook = '' 
    export PATH="${<nixpkgs>.cowsay}/bin:$PATH"
  '';
# ... 
}

Then the path will be available in your shell environment.

It is worth noting that by default, if a derivation is built (in buildInputs or anywhere else, if it has a ./bin/ directory, it is made available to the environment.

Apothecary answered 17/5, 2021 at 12:36 Comment(0)
C
2

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
}
Clarabelle answered 26/10, 2020 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.