First off, I know what I’m doing is very outside the norm. I’m doing a global stdenv changing overlay, but for a few packages I’d like to still use the original derivation so I don’t get a cache miss and need to recompile large programs (electron) or deal with some build / test problems. My approach is as follows:
nixpkgs.overlays = let
nixpkgs-unoptimized = import inputs.nixpkgs {
inherit (pkgs) system;
};
in [
(self: super: {
stdenv = (super.addAttrsToDerivation {} super.stdenv).override (old: {
# Disclaimer: This is very simplified from my actual code to avoid too much confusion on the problem.
mkDerivationFromStdenv = extendMkDerivationArgs old (args:
let
updateMarch = super.stdenv.system == "x86_64-linux";
updateFunction = flags: flags + " -O3 " + (if updateMarch then " -march=znver4 -mtune=znver4 " else "");
in
if (lib.strings.hasInfix "bootstrap" old.name) then {} else
(lib.attrsets.optionalAttrs (args ? "NIX_CFLAGS_COMPILE") {
NIX_CFLAGS_COMPILE = updateFunction (toString(args.NIX_CFLAGS_COMPILE));
}) // (lib.attrsets.optionalAttrs (!(args ? "NIX_CFLAGS_COMPILE") || ((args.env or {}) ? "NIX_CFLAGS_LINK")) {
env = (args.env or {}) // lib.attrsets.optionalAttrs (!(args ? "NIX_CFLAGS_COMPILE")) {
NIX_CFLAGS_COMPILE = updateFunction (toString(args.env.NIX_CFLAGS_COMPILE or ""));
};
}));
});
electron = nixpkgs-unoptimized.pkgs.electron;
# There are a bunch more packages I do the override this way here too
libavif = nixpkgs-unoptimized.pkgs.libavif;
})
];
After making that override, if I open up nix repl I get the following response:
> :lf .
> nixosConfigurations.framework.pkgs.pkgsi686Linux.libavif.system
"x86_64-linux"
This should be “i686-linux” like all other packages in pkgsi686Linux. This isn’t really a problem for electron, but I have a few libraries that are used by 32-bit programs that are overridden in this way and those programs fail to build due to the dependency actually being a 64-bit library and not a 32-bit one.
I got further, but it looks like the inputs for the builds are coming from the normal pkgs set instead of the i686 set.
useUnoptimized = super: pkgs: lib.lists.foldr (a: b: (lib.attrsets.setAttrByPath [a] (lib.attrsets.getAttrFromPath [a] nixpkgs-unoptimized.pkgs)) // b) { } pkgs
// {
pkgsi686Linux = super.pkgsi686Linux // lib.lists.foldr (a: b: (lib.attrsets.setAttrByPath [a] (lib.attrsets.getAttrFromPath [a] nixpkgs-unoptimized.pkgs.pkgsi686Linux)) // b) { } pkgs;
};
And then I use it as an overlay:
(final: super: (useUnoptimized super [ "nodejs" "electron" "firefox" "firefox-bin" "webkitgtk" "dav1d"]))
I can see this problem in nix repl:
> lf .
> nixosConfigurations.framework.pkgs.pkgsi686Linux.libavif.system
"i686-linux"
> nixosConfigurations.framework.pkgs.pkgsi686Linux.libavif.buildInputs
[ ... /nix/store/apbdpiqvazqp96s2a6d6qch9z4zg19aj-dav1d-1.4.1.drv ... ]
> nixosConfigurations.framework.pkgs.dav1d
«derivation /nix/store/apbdpiqvazqp96s2a6d6qch9z4zg19aj-dav1d-1.4.1.drv»
> nixosConfigurations.framework.pkgs.pkgsi686Linux.dav1d
«derivation /nix/store/2pbjzrhjpylysqjhiqcxhpnjc8ghvz92-dav1d-1.4.1.drv»
So the system is set correctly, but the inputs are coming from the wrong package set
I’ve come up with a fully working solution, albeit a bit hacky.
nixpkgs.overlays = let
useUnoptimized-x64 = super: pkgs: lib.lists.foldr (a: b: (lib.attrsets.setAttrByPath [a] (lib.attrsets.getAttrFromPath [a] nixpkgs-unoptimized.pkgs)) // b) { } pkgs;
useUnoptimized-i686 = super: pkgs: lib.lists.foldr (a: b: (lib.attrsets.setAttrByPath [a] (lib.attrsets.getAttrFromPath [a] nixpkgs-unoptimized-i686.pkgs)) // b) { } pkgs;
useUnoptimized = super: pkgs: if (super.stdenv.system == "x86_64-linux") then (useUnoptimized-x64 super pkgs) else (useUnoptimized-i686 super pkgs);
useUnoptimizedHaskell-x64 = super: pkgs: lib.lists.foldr (a: b: (lib.attrsets.setAttrByPath [a] (lib.attrsets.getAttrFromPath [a] nixpkgs-unoptimized.pkgs.haskellPackages)) // b) { } pkgs;
useUnoptimizedHaskell-i686 = super: pkgs: lib.lists.foldr (a: b: (lib.attrsets.setAttrByPath [a] (lib.attrsets.getAttrFromPath [a] nixpkgs-unoptimized-i686.pkgs.haskellPackages)) // b) { } pkgs;
useUnoptimizedHaskell = super: pkgs: {
haskellPackages = super.haskellPackages.override{
overrides = (new: old: (if (super.stdenv.system == "x86_64-linux") then (useUnoptimizedHaskell-x64 super pkgs) else (useUnoptimizedHaskell-i686 super pkgs)));
};
};
in [
<other overlays>
(final: super: (useUnoptimized super [
# These are here because they can be very slow to build
"nodejs"
"electron"
"electron_29"
"firefox"
"firefox-bin"
"webkitgtk"
"webkitgtk_4_1"
"webkitgtk_5_0"
"webkitgtk_6_0"
# Build failure - 5/8/2024
"dav1d"
# Test failure if too many builds are happening at once
"fprintd"]))
(final: super: (useUnoptimizedHaskell super [
# Test failure - 5/8/2024
"crypton"
# Test failure - 5/8/2024
"cryptonite"]))
];
I had to do some other hacks for Haskell packages that failed
1 Like