There is always going to be a degree of un-reproducibility just due to the nature of math. If you don't have the same system, same compiler version (down to the minor or patch level), same dependency versions, same build flags, filesystem ordering, OS handling etc. . .you're going to get differences.
The RB project has readily disclosed that there is a degree of "significantly reproducible" sussing that each end user is going to have to do. The fact that the Debian maintainers chose not to display the degree of reproducibility is probably because showing low reproducibility scores undermines the efforts to evangelize the movement.
I think that's understandable, but also is a bit of a two edged sword. If we don't disclose scores, we allow for the misrepresentation that "this is safe because it has the word reproducible in it". If we disclose scores, we get articles like this saying "wow, thats a really low score, wtf" and short lived paranoia gives way to ambivalence about the whole thing.
It's difficult to capture the nuance in this in pithy tidbits, hence blog post on HN with me explaining this :).
> There is always going to be a degree of un-reproducibility just due to the nature of math.
Fundamentally the math is deterministic (reproducible): if you do the same sequence of mathematical operations you get the same result. I gather you're getting at the non-associativity of floating point (eg additions), which is a fair point, but if you arrange to do your floating point operations in the same sequence then it will be reproducible.
This requires engineering on the part of compiler writers, but ultimately is solvable, given enough funding.
(About the compiler writers part: I'm thinking about GHC Haskell and the like... the Clangs/GCCs of the world will have no problems because of Translation Units. Things may change when Modules are a practical choice.)
Sitting in the middle results with additional downsides from modifying pipeline without core upsides of reproducible builds.
Clang works fine as a compiler for this--there is nothing in it that normally produces different results due to timing or whatever. When something does leak in, we fix it upstream. You do have to ensure that no one uses __DATE__ or similar macros, or that you redefine them to a known value on the command line.
You know what would be awesome? If someone could start from, let's say, live-bootstrap[1] and build towards matching the checksums for some distro kernel+toolchain.
It sounds like the same kind of problem, it all comes down to knowing what build conditions affect the resulting binaries, so I think you nailed the problem description on this and yes, it all feels very orthogonal from that perspective!
Thanks for writing this blog entry!
Since we already have "deterministic build" and "reproducible build" for this, there's no need to overload "idempotent" (which already causes confusion).
An idempotent build is when you type "make" twice and the second one doesn't do anything.
This stuff matters. You can't trust open source supply chains any more. There have been too many incidents of someone inserting a security hole.
For a software build it sounds like running `make` multiple times. But those builds will be idempotent even without reproducibility/determinism as they happen on the same system.
"Multiple runs of the same compiler on the same code produced the same output"
No more revolutionary a concept than a hash function. Valuable like a hash function, but not revolutionary.
When a more systems-inclined person in computer science uses the word idempotent they very often mean something like “repeatable” or “deterministic”.
AFIAK this usage first gained traction in the theory of distributed systems, in which it (roughly) means that one application of an operation might change the state of the system, but subsequent applications will not change it further. Set union is sort of the canonical example.
For example, let’s consider a function that accepts a string as an argument and then writes that string to disk. We can consider the disk state as a side effect of the function.
The function itself is perfectly deterministic (output string is a predictable and consistent function of input string), but depending on the implementation of side effects it may not be idempotent. If, for example, this function room simply added the output to a file “output.txt”, this file would grow with every incantation, which is not idempotent. If instead we overwrote the output file so that it reflects only the singular output of the previous run, then the side effects would also be deterministic, that would be idempotent.
At a pedantic level you could redefine your scope of deterministic to not just include outputs, but also include the external state and side effects, but for practical purposes the above distinction is generally how deterministic and idempotent would be applied in practice in computing. I cannot speak to the math-centric view, if there is a different definition there.
This is deterministic (doesn't change randomly), but not idempotent.
The reason they don't like Nix should be obvious; it blatantly and vocally doesn't even try to do the thing the authors want. It'd be just as relevant to bring up Gentoo or something -- another fine project, like Nix, but not especially helpful for the stated problem, and so obviously so that it shouldn't be worth paying lip service to in the article.
"When compiling from the same source on independent infrastructure yields bit-by-bit identical results, this gives confidence that the build infrastructure was not compromised and the artifact really does correspond to the source." - https://reproducible.nixos.org/
@Foxboron wrote a compelling if clickbaity post a few months back to poke at the bit-for-bit interpretation of what reproducibility means in nixland: https://linderud.dev/blog/nixos-is-not-reproducible/
It didn't get much traction here (https://news.ycombinator.com/from?site=linderud.dev) but there was more lively discussion on lobsters: https://lobste.rs/s/jpoy4q/nixos_is_not_reproducible
(That said, the nix ecosystem does have levers and practices for working to weed out common sources of build reproducibility problems and the community is reasonably interested/active here. But there isn't any magic in it that fixes all bit-for-bit issues. People still have to catch, tag, and fix them.)
Not going to lie, I either don't understand what you're saying, or don't understand the shade you're trying to throw.
Nix is going to do as good, or better a job, than any other solution other there. Probably with a lot less duck-tape.
Not to mention that much of Nix packages are reliably bit-for-bit reproducible.
Not to not to mention that bit-for-bit reproducability is really only beneficial for "trust", not reliability or re-playability.
And no, comparing Nix to Gentoo in this case only very much confirms you don't understand Nix. Maybe you should check out the talk from a past NixCon where the speaker rebuilds Firefox from 10 years ago and boots up Flash swfs.
This goes quite far along the path, building all the build tools and toolchain to the same version before building the packages.
Deterministic builds aren't always that straightforward
So I'm reasonably sure it does produce bit-identical results.