Are there rules to order of entries in PATH?

Are there any concrete rules in what order things appear in PATH when provided in buildInputs or other arguments that modify PATH?

I made this simple derivation to test this:

{ pkgs ? import <nixpkgs> { } }:

pkgs.stdenv.mkDerivation {
  name = "nix-path-test";

  buildInputs = with pkgs; [ vim go ];

  phases = [ "buildPhase" ];
  buildPhase = ''
    echo $PATH | tr ':' '\n'

And the result I get is:


Which shows that both vim and go appear in the order they were specified in buildInputs, but they also appear in the middle of PATH, rather than in the beginning or at the end.

I assume the order of entries in PATH has to be deterministic, but what are some other rules that decide the order of things?

I won’t claim to have looked closely enough to know, but in case no one else turns up with a definitive answer, in most cases this is governed by the implementation in nixpkgs/ at 6bae92a3eea8c56999d9c76417809a81e0fedfa6 · NixOS/nixpkgs · GitHub

1 Like

Thanks. That makes sense.

So I can see PATH being set from _PATH:

Which appears to be configured here via addToSearchPath from within activatePackage:

Which is used here from _activatePkgs:

And packages seem to be coming from pkgAccumVarVars which is defined here:

But then the trail gets very confusing due to some high level Bash magic, but I can see that the variables like buildInputs appear to be collected via findInputs:

Which in turn is another function full of Bash dark magic:

Quite the rabbit hole…

1 Like

it’s a bit of a rabbit hole to support cross compilation, in which only packages which can be executed by the host should be available on the PATH.

Is there something you are trying to solve by ordering the PATH? Generally in nixpkgs, you just need one occurrence of a package.

1 Like

Not really, I’m just trying to understand how things work under the hood. Thanks for explaining.