What you describe as a deal-killer is just purity and safety. Updating a build input gives no guarantee that the build output will be the same or even work. Sure, as smart humans we can say “I know this change does not impact X, so it’s fine”, but NixOS is based partly on the claim that we do not do that reliably or consistently, and tries to save us from ourselves. Yes, it means more rebuilding, but it also means less debugging, confusion, etc., when things do go awry.
It's not really "pure" since you are packaging software with side-effects to begin with. Even if you use the same text bit by bit it's also no guarantee that the output will be the same or that even it will work. You are still relying on some human claiming that it will do.
So the advantage is not really that big in practice, and the disadvantage means rebuilding the world on every low-level package change. Even Gentoo fares better in that regard.
And yes, I am aware that the deal-killer is at the core of these approaches, which is why I don't take them seriously.
Suppose I make an overlay of libc to add some functionality that I am debugging which changes the libc binary, albeit not the ABI. Can I still reuse the same packages? Can I still reuse someone else's binary cache ? Basically, can I do without having to rebuild the entire system (save for libc) ?
However, also remember that changing dynamic libraries behind executables back is a concept that only makes sense in the presence of ABI compatibility. This is predominantly a C concept (or at least popular in the C world), and much less so for other linked programming languages like C++, Haskell, Go, and so on. Thus Nix being a general-purpose build system takes the general route here, and builds can also use their dependencies during the build step (e.g. a packaged program's autoconf suite might check the version or a symbol provided by a library), which requires full rebuilds for reproducibility.
(Nix is working on content-addressed instead of input-hash-haddressed builds, which might open the door for avoiding many rebuilds that do not affect build _output_.)
That said, it might still be quite easy to achieve what you want:
* If you want to iterate on a C library that's early in the dependency graph, in am ABI-compatible fashion, you coul duse LD_LIBRARY_PATH or LD_PRELOAD on it.
* If you want to override libc in an ABI-compatible way, you can use `patchelf` with its `--set-interpreter` and `--set-rpath` flags to replace the libc an executable is linked against after the fact. For example, you can make an `.override` of a nix derivation that just `cp -r`'s the existing files, and then calls `patchelf` on them.
I have used both these methods to work around glibc bugs that I patched out, avoiding even to have to recompile my own software at the top of the build dependency tree.
Some more relevant links about replacing glibc specifically:
* https://github.com/NixOS/nixpkgs/issues/50329
* https://github.com/NixOS/nixpkgs/issues/129595
If you want to replace things system-wide instead of for your own software, the `system.replaceRuntimeDependencies` mentioned by a sibling comment might be a good choice.
[1] https://search.nixos.org/options?channel=21.11&show=system.r...
[2] https://github.com/NixOS/nixpkgs/blob/fad04722fc3d692e3511e5...
https://guix.gnu.org/en/blog/2020/grafts-continued/
We use that for security updates, but also in other situations where we know we can take advantage of it such as the new `--tune` package transformation option, which tunes a package for a specific CPU:
https://hpc.guix.info/blog/2022/01/tuning-packages-for-a-cpu...
Similarly, as a user, you can "graft" a replacement straight from the command line using `--with-graft`:
https://guix.gnu.org/manual/devel/en/html_node/Package-Trans...
It's one of the points where it differs from Nix.
Guix grafts are used to distribute updates, and they're quite easy to use, that's all I can say.
If I want to do that, then I have to rebuild the entire system so as to use my patched version. This is because the NixOS "dependencies" are basically expressed as hashes of binaries.
That is for me the single biggest deal-killer of NixOS, Guix, and while we're at it -- static linking.