[Nix-dev] influence of cpu/kernel version on builds

Mathijs Kwik mathijs at bluescreen303.nl
Wed Mar 7 09:13:45 CET 2012


Hi all,

I recently ran into a package (nss) which failed to compile on my
laptop, but succeeded on my desktop.

Now, you would think this must be because some dependency/setting is
different on these machines, meaning the nix-store hash of the result
would end up differently, but this was not the case.

I used nix-copy-closure to copy the result from my desktop to my laptop.
I tried to rebuild again, and it accepted the result that was in store,
and continued building.

Then I saw this commit come along [1].
Indeed the only difference I can think of between these machines are the
kernel version and the hardware itself.

As nss doesn't depend on the kernel, its store path ends up the same,
but during compilation, different choices are made.

Probably other differences can occur as well. Let's assume some package
checks for availability of SSE4 instructions on the cpu at compile-time
to decide optimizations to use. Then we end up with a store path which
isn't portable, but no way to detect this. 

This is very impure!
I think I've seen tricks used by CLFS (cross linux from scratch) or
gentoo some years back, which had some system call (or even the proc
filesystem) respond with custom answers like a hard-coded kernel
version, or cpu type. Of course packages can still make stupid
compile-time choices by inspecting other things (leave out functionality
if disk space is low, or even more contrived examples), but I don't
think they occur much. 

I also can't think of a package that makes
compile-time choices for cpu, but at least for the kernel version some
examples reveal themselves. (like nss, but python as well, try to build
kdeadmin on a machine running kernel 3.2 which built its own python, it
will fail to find pykde4 because of choices made by python)

Now, of course we can try to fix every package that doesn't understand
linux3's version numbering yet, but that leaves the problem that
packages _do_ contain internal differences we cannot detect (by looking
at the store path) depending on what machine built them.

I think there are 2 solutions:
- record some kernel version number in the store hash.
  Of course we don't want the full version number, as that would lead to
  rebuilding your entire system if you upgrade kernels. There are no
  real differences between 3.0 and 3.2 (not like 2.4 and 2.6 differed),
  so I don't know what number to look for.
- trick builders to think they execute on a specific kernel version,
  probably the version of kernel headers used for glibc.
  Maybe by just faking 'uname', or some underlying system call that gets
  used.

Maybe it's not that big a problem, but it's clear that purity is affected.
What do you all think? 

Mathijs

[1] https://nixos.org/repos/nix/nixpkgs/trunk@32834


More information about the nix-dev mailing list