It is mentioned in this article that an output can have a runtime dependency on itself. How can this make sense?
https://nixos.org/manual/nix/stable/language/advanced-attributes.html
I would assume that if you need an absolute path to a file in the derivation you are building, that this would be a reference to itself.
As a simple example:
with import <nixpkgs> {};
runCommand "self-ref" {} ''
echo "$out" > $out
''
But more practically, imagine any derivation whose output contains an executable linked against a library in the same output.
$ readlink -f $(which nix)
/nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/bin/nix
$ ldd $(readlink -f $(which nix)) | grep /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3
libnixexpr.so => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libnixexpr.so (0x00007fe630cdd000)
libnixmain.so => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libnixmain.so (0x00007fe630b56000)
libnixfetchers.so => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libnixfetchers.so (0x00007fe630ab7000)
libnixstore.so => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libnixstore.so (0x00007fe630847000)
libnixutil.so => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libnixutil.so (0x00007fe630762000)
libnixcmd.so => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libnixcmd.so (0x00007fe6306e6000)
libboost_context.so.1.79.0 => /nix/store/0sxbaj71c4c4n43qhdxm31f56gjalksw-nix-2.13.3/lib/libboost_context.so.1.79.0 (0x00007fe6301b6000)
In such a case, how is the hash determined? Will this cause infinite recursion?
Hashes are fundamentally based on the description of what build process to run, which also specifies what store objects need to be present first. The output(s) of the derivation itself don’t need to be listed there, so there’s no hash fixed-point problem, if that’s what you meant. (ca-derivations
complicates this, but I’m talking about normal derivations here)
All “run-time dependency” really means in the nix world is that a store object retains a reference to another store object somewhere in its files. Nix searches for and remembers these links and uses them in garbage collection, so “run-time dependencies” keep still-necessary store objects from being deleted.
To add to that, think of it this way. When a derivation is being built, the build process has to know what path to output its results to. If it knows this path, there’s no reason it can’t just write that path name as the contents of a file in that path (echo "$out" > "$out"
). Therefore, it must be true that that path (out
) is determined before the derivation is built, which is what @tejing is describing. The path is determined only by the inputs required to build the derivation, not by the contents it produces. (And again, ca-derivations
complicates this)
Fundamentally $out
is computed before the build is ran, based on the hash of the derivation.