FOD's `$out/bin/<binary>` is not available in `$PATH`. Is this expected?

If I add the FOD options outputHashMode, outputHashAlgo and outputHash, the binary test-fod stops becoming available in $PATH.

If I comment it out it appears in $PATH.

Is this expected?

Context: I’m adding this to home.packages of Home Manager using callPackage.
Home Manager config is a flake.

{ stdenv }:
stdenv.mkDerivation rec {
  pname = "test-fod";
  version = "0.1.1";

  outputHashMode = "recursive";
  outputHashAlgo = "sha256";
  outputHash = "sha256-FhrJ5xru61YD92b5WCM9l1J9ttMU40cdS3TL0OLab1Q=";

  dontUnpack = true;

  installPhase = ''
    mkdir -p $out/bin
    echo "#!/bin/bash" >> $out/bin/test-fod
    echo "echo Hello" >> $out/bin/test-fod
    chmod +x $out/bin/test-fod
  '';
}

Just trying this out in the nix repl (with a different hash, sha256-sCB418okyRpBoangSckLe5psFmvvcs7XsNFGveE0C7c=. Not sure why your hash didn’t work. EDIT: Oh, of course, it’s the storepath of bash being different.), I noticed something odd:

This derivation produced the following outputs:
  out -> /nix/store/580kw5dz53x59in19ml4lmk2g8x66kad-test-fod-0.1.1

yet the actual store object that was created is named /nix/store/5npnpc3z35vzbc651rwgiphkzy4y3a6b-test-fod-0.1.1.

Make sure you’re not using an old outputHash. If you don’t update that after changing your derivation, Nix will just assume the derivation has the same output and yield that.

1 Like

This is a new derivation I created for demonstrating this effect that I observed in another derivation.

Strangely, if I comment out the FOD related options and home-manager switch, without changing the hash, the binary becomes available in the $PATH.

/nix/store paths are not allowed in fixed output derivations.

Excuse me for this noobish question but are we using nix store paths here? :sweat_smile:

There is a hook “repairing” your “broken” shebang to point at bash in the store, that’s why each of us gets different hashes.

Exactly, there is a fixupPhase that “repairs” your #!/bin/bash
line. You can opt-out with dontFixup = true; option.

If you see majority of fetchers in nixpkgs repo dont use the standard
build phases. They have a custom builder script. That’s because
standard build phases preassume you are building a normal derivation
not a fixed output one.

1 Like

Ooh so the issue here is that my FOD generates a file that has a nix store item in it’s shebang.
And that’s somehow forbidden?

  1. Why is this forbidden? What could go wrong if my shebang points to a nix store bash?
  2. So the algorithm here is that if a file has a reference to /nix/store and it belongs to an FOD, don’t put it in $PATH?

FOD is like content-addressed derivation and seems like a nix store item
make $out not-predictable.

I’m not sure if this a feature or maybe a bug. I face with this problem
only recently, but have found some related issues:

I link them here before:

  1. FODs are fundamentally only supposed to be used for things that are very resistant to changes in dependencies or environment, like using curl to download a file from a URL. It isn’t supposed to matter which curl you use or whether some database of package dependencies changed something and a dependency resolution algorithm made a subtly difference choice. If you’re doing real computation or accessing complex databases inside a FOD, you’re probably doing it wrong. At least for the reason that those output hashes will break way too often. Including a nix store path in the output of a FOD is kind of the epitome of this problem, since they tend to change constantly, and is disallowed I think at least in part just to give people a push not to try to do this kind of thing.

  2. I’m not sure of the exact reason you’re seeing this precise failure mode. Based on my observation, there might be some bug causing a miscalculation of the store path, so the derivation that gathers all the links together sees a non-existent store path. However, I do know that using FODs this way is discouraged, for good reason. FODs themselves might have been a bad idea, and we should have instead stuck with only a select set of builtin fetchers, but what is, is at this point.

1 Like