Closed delroth closed 5 years ago
Ugh, I dug into this one and figured it out, it's a result of the definition of pkgsi686Linux
(and also at least pkgsMusl
) implicitly relying on nixpkgs being imported impurely (via pkgs/top-level/impure.nix
rather than pkgs/top-level/default.nix
). morph does import it impurely, but explicitly setting crossSystem
breaks a subtle assumption later in nixpkgs' eval machinery.
Details:
In the definition of pkgsi686Linux
, it uses a check on stdenv.hostPlatform
and stdenv.buildPlatform
being equivalent (which is typically the case), in order to determine whether to override localSystem
or crossSystem
in its call to nixpkgsFun
(which hackily re-evaluates nixpkgs).
https://github.com/NixOS/nixpkgs/blob/e82b8fa7f7890e819bb4de6ce1f8e20d5a5a4c53/pkgs/top-level/stage.nix#L183-L193
The issue here is that it leaves the other localSystem
/crossSystem
argument unset, and if you look at the definition of that here you can see that means it defaults to whatever arguments were given to nixpkgs originally and captured by the args
@-pattern.
Normally, crossSystem
is defaulted to null
when evaluating nixpkgs impurely, then that null
is passed on to the pure eval machinery, within which it is defaulted to localSystem
if it is null.
See the problem? If we let the impure null
crossSystem
default be passed on to the pure eval machinery, then nixpkgsFun
captures that null
, and i686PkgsLinux
later re-evaluates nixpkgs with a modifed localSystem
and a null
crossSystem
, which then results in crossSystem
within that re-eval being defaulted to the modified localSystem
.
If instead we explicitly pass crossSystem
originally, then crossSystem
within the i686PkgsLinux
re-eval is not defaulted to the i686 localSystem
, and cross-compiling occurs.
We could "fix" this in morph by changing the nixpkgs.pkgs
default to only set crossSystem
if localSystem != crossSystem
, and we probably should... but I also think this represents an upstream bug in nixpkgs. pkgsi686Linux
shouldn't be reliant on a detail of how the default impure nixpkgs eval expression functions =/.
Test case: have a morph deployment with
hardware.pulseaudio.support32Bit = true;
Current behavior:
morph build
cross-builds half of the world to build an i686 alsa-plugins package.Expected behavior:
morph build
does not do that, which is what happens with e.g. nixops or nixos-rebuild on the same config.Can be easily repro'd by trying to build anything from pkgsi686Linux:
cc @Shados