From 51b61286d10e58eea47be83e88de31c696faea6c Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Thu, 11 Apr 2024 08:47:48 +0200 Subject: [PATCH 1/9] pkgs/top-level: rewrite some outdated comments This removes all specific references to pkgsCross or pkgsi686Linux, because they have become outdated with the addition of many more package sets. --- pkgs/top-level/default.nix | 16 ++++++---------- pkgs/top-level/stage.nix | 7 +------ 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index fd443ac773ffb..918a47639f3c6 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -122,22 +122,18 @@ in let config = lib.showWarnings configEval.config.warnings configEval.config; # A few packages make a new package set to draw their dependencies from. - # (Currently to get a cross tool chain, or forced-i686 package.) Rather than - # give `all-packages.nix` all the arguments to this function, even ones that - # don't concern it, we give it this function to "re-call" nixpkgs, inheriting - # whatever arguments it doesn't explicitly provide. This way, - # `all-packages.nix` doesn't know more than it needs too. + # Rather than give `all-packages.nix` all the arguments to this function, + # even ones that don't concern it, we give it this function to "re-call" + # nixpkgs, inheriting whatever arguments it doesn't explicitly provide. This + # way, `all-packages.nix` doesn't know more than it needs to. # # It's OK that `args` doesn't include default arguments from this file: # they'll be deterministically inferred. In fact we must *not* include them, # because it's important that if some parameter which affects the default is # substituted with a different argument, the default is re-inferred. # - # To put this in concrete terms, this function is basically just used today to - # use package for a different platform for the current platform (namely cross - # compiling toolchains and 32-bit packages on x86_64). In both those cases we - # want the provided non-native `localSystem` argument to affect the stdenv - # chosen. + # To put this in concrete terms, we want the provided non-native `localSystem` + # and `crossSystem` arguments to affect the stdenv chosen. # # NB!!! This thing gets its `config` argument from `args`, i.e. it's actually # `config0`. It is important to keep it to `config0` format (as opposed to the diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 1cedd8dd18458..ae2ed325e5be3 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -176,12 +176,7 @@ let ((config.packageOverrides or (super: {})) super); # Convenience attributes for instantitating package sets. Each of - # these will instantiate a new version of allPackages. Currently the - # following package sets are provided: - # - # - pkgsCross. where system is a member of lib.systems.examples - # - pkgsMusl - # - pkgsi686Linux + # these will instantiate a new version of allPackages. otherPackageSets = self: super: { # This maps each entry in lib.systems.examples to its own package # set. Each of these will contain all packages cross compiled for From 8fb07de40a74ea348c2f3a0b8b4b597ea8df031f Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sun, 26 May 2024 21:43:20 +0200 Subject: [PATCH 2/9] pkgs/top-level/stage: refactor moving more generic package sets to the bottom No change, just move appendOverlays and extend to the bottom, since they will be changed much less often. This makes it easier to compare the other package sets side-by-side. --- pkgs/top-level/stage.nix | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index ae2ed325e5be3..09c17beb310e2 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -281,23 +281,6 @@ let localSystem = lib.systems.elaborate "${stdenv.hostPlatform.parsed.cpu.name}-linux"; }; - # Extend the package set with zero or more overlays. This preserves - # preexisting overlays. Prefer to initialize with the right overlays - # in one go when calling Nixpkgs, for performance and simplicity. - appendOverlays = extraOverlays: - if extraOverlays == [] - then self - else nixpkgsFun { overlays = args.overlays ++ extraOverlays; }; - - # NOTE: each call to extend causes a full nixpkgs rebuild, adding ~130MB - # of allocations. DO NOT USE THIS IN NIXPKGS. - # - # Extend the package set with a single overlay. This preserves - # preexisting overlays. Prefer to initialize with the right overlays - # in one go when calling Nixpkgs, for performance and simplicity. - # Prefer appendOverlays if used repeatedly. - extend = f: self.appendOverlays [f]; - # Fully static packages. # Currently uses Musl on Linux (couldn’t get static glibc to work). pkgsStatic = nixpkgsFun ({ @@ -340,6 +323,23 @@ let }) ] ++ overlays; }; + + # Extend the package set with zero or more overlays. This preserves + # preexisting overlays. Prefer to initialize with the right overlays + # in one go when calling Nixpkgs, for performance and simplicity. + appendOverlays = extraOverlays: + if extraOverlays == [] + then self + else nixpkgsFun { overlays = args.overlays ++ extraOverlays; }; + + # NOTE: each call to extend causes a full nixpkgs rebuild, adding ~130MB + # of allocations. DO NOT USE THIS IN NIXPKGS. + # + # Extend the package set with a single overlay. This preserves + # preexisting overlays. Prefer to initialize with the right overlays + # in one go when calling Nixpkgs, for performance and simplicity. + # Prefer appendOverlays if used repeatedly. + extend = f: self.appendOverlays [f]; }; # The complete chain of package set builders, applied from top to bottom. From 6e6388530cc9842a6dcab261328d580dff366faa Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sun, 15 Dec 2024 15:05:05 +0100 Subject: [PATCH 3/9] pkgs/top-level: refactor mkPkgs Sharing a first piece of common code between all package sets makes it easier to maintain and less likely to introduce a new package set without this. --- pkgs/top-level/stage.nix | 61 +++++++++++++--------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 09c17beb310e2..cb5e44ae0602a 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -177,7 +177,15 @@ let # Convenience attributes for instantitating package sets. Each of # these will instantiate a new version of allPackages. - otherPackageSets = self: super: { + otherPackageSets = let + mkPkgs = name: nixpkgsArgs: nixpkgsFun (nixpkgsArgs // { + overlays = [ + (self': super': { + "${name}" = super'; + }) + ] ++ nixpkgsArgs.overlays or [] ++ overlays; + }); + in self: super: { # This maps each entry in lib.systems.examples to its own package # set. Each of these will contain all packages cross compiled for # that target system. For instance, pkgsCross.raspberryPi.hello, @@ -187,12 +195,7 @@ let nixpkgsFun { inherit crossSystem; }) lib.systems.examples; - pkgsLLVM = nixpkgsFun { - overlays = [ - (self': super': { - pkgsLLVM = super'; - }) - ] ++ overlays; + pkgsLLVM = mkPkgs "pkgsLLVM" { # Bootstrap a cross stdenv using the LLVM toolchain. # This is currently not possible when compiling natively, # so we don't need to check hostPlatform != buildPlatform. @@ -202,12 +205,7 @@ let }; }; - pkgsArocc = nixpkgsFun { - overlays = [ - (self': super': { - pkgsArocc = super'; - }) - ] ++ overlays; + pkgsArocc = mkPkgs "pkgsArocc" { # Bootstrap a cross stdenv using the Aro C compiler. # This is currently not possible when compiling natively, # so we don't need to check hostPlatform != buildPlatform. @@ -217,12 +215,7 @@ let }; }; - pkgsZig = nixpkgsFun { - overlays = [ - (self': super': { - pkgsZig = super'; - }) - ] ++ overlays; + pkgsZig = mkPkgs "pkgsZig" { # Bootstrap a cross stdenv using the Zig toolchain. # This is currently not possible when compiling natively, # so we don't need to check hostPlatform != buildPlatform. @@ -235,10 +228,7 @@ let # All packages built with the Musl libc. This will override the # default GNU libc on Linux systems. Non-Linux systems are not # supported. 32-bit is also not supported. - pkgsMusl = if stdenv.hostPlatform.isLinux && stdenv.buildPlatform.is64bit then nixpkgsFun { - overlays = [ (self': super': { - pkgsMusl = super'; - })] ++ overlays; + pkgsMusl = if stdenv.hostPlatform.isLinux && stdenv.buildPlatform.is64bit then mkPkgs "pkgsMusl" { ${if stdenv.hostPlatform == stdenv.buildPlatform then "localSystem" else "crossSystem"} = { config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); @@ -247,10 +237,7 @@ let # All packages built for i686 Linux. # Used by wine, firefox with debugging version of Flash, ... - pkgsi686Linux = if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86 then nixpkgsFun { - overlays = [ (self': super': { - pkgsi686Linux = super'; - })] ++ overlays; + pkgsi686Linux = if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86 then mkPkgs "pkgsi686Linux" { ${if stdenv.hostPlatform == stdenv.buildPlatform then "localSystem" else "crossSystem"} = { config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { @@ -260,10 +247,7 @@ let } else throw "i686 Linux package set can only be used with the x86 family."; # x86_64-darwin packages for aarch64-darwin users to use with Rosetta for incompatible packages - pkgsx86_64Darwin = if stdenv.hostPlatform.isDarwin then nixpkgsFun { - overlays = [ (self': super': { - pkgsx86_64Darwin = super'; - })] ++ overlays; + pkgsx86_64Darwin = if stdenv.hostPlatform.isDarwin then mkPkgs "pkgsx86_64Darwin" { localSystem = { config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { cpu = lib.systems.parse.cpuTypes.x86_64; @@ -273,20 +257,16 @@ let # If already linux: the same package set unaltered # Otherwise, return a natively built linux package set for the current cpu architecture string. - # (ABI and other details will be set to the default for the cpu/os pair) pkgsLinux = if stdenv.hostPlatform.isLinux then self - else nixpkgsFun { + else mkPkgs "pkgsLinux" { localSystem = lib.systems.elaborate "${stdenv.hostPlatform.parsed.cpu.name}-linux"; }; # Fully static packages. # Currently uses Musl on Linux (couldn’t get static glibc to work). - pkgsStatic = nixpkgsFun ({ - overlays = [ (self': super': { - pkgsStatic = super'; - })] ++ overlays; + pkgsStatic = mkPkgs "pkgsStatic" { crossSystem = { isStatic = true; config = lib.systems.parse.tripleFromSystem ( @@ -297,12 +277,11 @@ let gcc = lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { abi = "elfv2"; } // stdenv.hostPlatform.gcc or {}; }; - }); + }; - pkgsExtraHardening = nixpkgsFun { + pkgsExtraHardening = mkPkgs "pkgsExtraHardening" { overlays = [ (self': super': { - pkgsExtraHardening = super'; stdenv = super'.withDefaultHardeningFlags ( super'.stdenv.cc.defaultHardeningFlags ++ [ "shadowstack" @@ -321,7 +300,7 @@ let pcre-cpp = super'.pcre-cpp.override { enableJit = false; }; pcre16 = super'.pcre16.override { enableJit = false; }; }) - ] ++ overlays; + ]; }; # Extend the package set with zero or more overlays. This preserves From 593e29b0a78ad85b1b8a01c1f60e135b2b50505c Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Wed, 10 Apr 2024 22:18:25 +0200 Subject: [PATCH 4/9] pkgs/test/top-level: add tests for package set composability This adds some basic tests to compose package sets. The cases that are currently broken are commented out, they include things like: - pkgsStatic.pkgsMusl losing the isStatic flag - pkgsCross.ppc64-musl.pkgsMusl losing the gcc.abi setting - pkgsCross.mingwW64.pkgsStatic losing the config string - pkgsLLVM.pkgsMusl losing the useLLVM flag - pkgsLLVM.pkgsStatic losing the useLLVM flag - pkgsLLVM.pkgsi686Linux losing the useLLVM flag And probably more. --- pkgs/test/top-level/stage.nix | 104 ++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 pkgs/test/top-level/stage.nix diff --git a/pkgs/test/top-level/stage.nix b/pkgs/test/top-level/stage.nix new file mode 100644 index 0000000000000..7c53289a960a3 --- /dev/null +++ b/pkgs/test/top-level/stage.nix @@ -0,0 +1,104 @@ +# run like this: +# nix-build pkgs/test/top-level/stage.nix +{ + localSystem ? { + system = builtins.currentSystem; + }, +}: + +with import ../../top-level { inherit localSystem; }; + +let + # To silence platform specific evaluation errors + discardEvaluationErrors = e: (builtins.tryEval e).success -> e; + + # Basic test for idempotency of the package set, i.e: + # Applying the same package set twice should work and + # not change anything. + isIdempotent = set: discardEvaluationErrors (pkgs.${set}.stdenv == pkgs.${set}.${set}.stdenv); + + # Some package sets should be noops in certain circumstances. + # This is very similar to the idempotency test, but not going + # via the super' overlay. + isNoop = + parent: child: + discardEvaluationErrors ( + (lib.getAttrFromPath parent pkgs).stdenv == (lib.getAttrFromPath parent pkgs).${child}.stdenv + ); + + allMuslExamples = builtins.attrNames ( + lib.filterAttrs (_: system: lib.hasSuffix "-musl" system.config) lib.systems.examples + ); + + allLLVMExamples = builtins.attrNames ( + lib.filterAttrs (_: system: system.useLLVM or false) lib.systems.examples + ); + + # A package set should only change specific configuration, but needs + # to keep all other configuration from previous layers in place. + # Each package set has one or more key characteristics for which we + # test here. Those should be kept, even when applying the "set" package + # set. + isComposable = + set: + discardEvaluationErrors ( + pkgsCross.mingwW64.${set}.stdenv.hostPlatform.config == "x86_64-w64-mingw32" + ) + && discardEvaluationErrors (pkgsCross.mingwW64.${set}.stdenv.hostPlatform.libc == "msvcrt") + && discardEvaluationErrors (pkgsCross.ppc64-musl.${set}.stdenv.hostPlatform.gcc.abi == "elfv2") + && discardEvaluationErrors ( + builtins.elem "trivialautovarinit" pkgs.pkgsExtraHardening.${set}.stdenv.cc.defaultHardeningFlags + ) + && discardEvaluationErrors (pkgs.pkgsLLVM.${set}.stdenv.hostPlatform.useLLVM) + && discardEvaluationErrors (pkgs.pkgsArocc.${set}.stdenv.hostPlatform.useArocc) + && discardEvaluationErrors (pkgs.pkgsZig.${set}.stdenv.hostPlatform.useZig) + && discardEvaluationErrors (pkgs.pkgsLinux.${set}.stdenv.buildPlatform.isLinux) + && discardEvaluationErrors (pkgs.pkgsMusl.${set}.stdenv.hostPlatform.isMusl) + && discardEvaluationErrors (pkgs.pkgsStatic.${set}.stdenv.hostPlatform.isStatic) + && discardEvaluationErrors (pkgs.pkgsi686Linux.${set}.stdenv.hostPlatform.isx86_32) + && discardEvaluationErrors (pkgs.pkgsx86_64Darwin.${set}.stdenv.hostPlatform.isx86_64); +in + +# Appends same defaultHardeningFlags again on each .pkgsExtraHardening - thus not idempotent. +# assert isIdempotent "pkgsExtraHardening"; +# TODO: Remove the isDarwin condition, which currently results in infinite recursion. +# Also see https://github.com/NixOS/nixpkgs/pull/330567#discussion_r1894653309 +assert (stdenv.hostPlatform.isDarwin || isIdempotent "pkgsLLVM"); +assert isIdempotent "pkgsArocc"; +assert isIdempotent "pkgsZig"; +assert isIdempotent "pkgsLinux"; +assert isIdempotent "pkgsMusl"; +assert isIdempotent "pkgsStatic"; +assert isIdempotent "pkgsi686Linux"; +assert isIdempotent "pkgsx86_64Darwin"; + +# TODO: fails +# assert isNoop [ "pkgsStatic" ] "pkgsMusl"; +# TODO: fails because of ppc64-musl +# assert lib.all (sys: isNoop [ "pkgsCross" sys ] "pkgsMusl") allMuslExamples; +assert lib.all (sys: isNoop [ "pkgsCross" sys ] "pkgsLLVM") allLLVMExamples; + +assert isComposable "pkgsExtraHardening"; +assert isComposable "pkgsLLVM"; +assert isComposable "pkgsArocc"; +# TODO: unexpected argument 'bintools' - uncomment once https://github.com/NixOS/nixpkgs/pull/331011 is done +# assert isComposable "pkgsZig"; +# TODO: attribute 'abi' missing +# assert isComposable "pkgsMusl"; +# TODO: fails +# assert isComposable "pkgsStatic"; +# assert isComposable "pkgsi686Linux"; + +# Special cases regarding buildPlatform vs hostPlatform +# TODO: fails +# assert discardEvaluationErrors (pkgsCross.gnu64.pkgsMusl.stdenv.hostPlatform.isMusl); +# assert discardEvaluationErrors (pkgsCross.gnu64.pkgsi686Linux.stdenv.hostPlatform.isx86_32); +# assert discardEvaluationErrors (pkgsCross.mingwW64.pkgsLinux.stdenv.hostPlatform.isLinux); +# assert discardEvaluationErrors (pkgsCross.aarch64-darwin.pkgsx86_64Darwin.stdenv.hostPlatform.isx86_64); + +# pkgsCross should keep upper cross settings +# TODO: fails +# assert discardEvaluationErrors (with pkgsStatic.pkgsCross.gnu64.stdenv.hostPlatform; isGnu && isStatic); +# assert discardEvaluationErrors (with pkgsLLVM.pkgsCross.musl64.stdenv.hostPlatform; isMusl && useLLVM); + +emptyFile From df621d8989d5afeec92f7eb48e1147bf2ff8d2a5 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 11 Jan 2025 11:24:30 +0100 Subject: [PATCH 5/9] nixos/nixpkgs: pass original system args instead of elaborated Passing the elaborated system defeats what pkgs/top-level/default.nix tries to do: Pass only the original args and let defaults be inferred. The underlying problem is that lib.systems.elaborate can not deal with arbitrary overrides, but will often return an inconsistent system description when partially overriding some values. This becomes most prominent if trying to override an already elaborated system. --- lib/modules.nix | 2 ++ nixos/modules/misc/nixpkgs.nix | 15 ++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/modules.nix b/lib/modules.nix index f5b8af0e9858b..f9441684cf15a 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -844,6 +844,8 @@ let in warnDeprecation opt // { value = addErrorContext "while evaluating the option `${showOption loc}':" value; + # raw value before "apply" above + rawValue = addErrorContext "while evaluating the option `${showOption loc}':" res.mergedValue; inherit (res.defsFinal') highestPrio; definitions = map (def: def.value) res.defsFinal; files = map (def: def.file) res.defsFinal; diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix index e1c705eef3b5a..f99f75af7659b 100644 --- a/nixos/modules/misc/nixpkgs.nix +++ b/nixos/modules/misc/nixpkgs.nix @@ -70,19 +70,24 @@ let ++ lib.optional (opt.localSystem.highestPrio < (lib.mkOptionDefault { }).priority) opt.localSystem ++ lib.optional (opt.crossSystem.highestPrio < (lib.mkOptionDefault { }).priority) opt.crossSystem; + # pkgs/top-level/default.nix takes great strides to pass the *original* localSystem/crossSystem args + # on to nixpkgsFun to create package sets like pkgsStatic, pkgsMusl. This is to be able to infer default + # values again. Since cfg.xxxPlatform and cfg.xxxSystem are elaborated via apply, those can't be passed + # directly. Instead we use the rawValue before the apply/elaboration step, via opt.xxx.rawValue. defaultPkgs = if opt.hostPlatform.isDefined then let + # This compares elaborated systems on purpose, **not** using rawValue. isCross = cfg.buildPlatform != cfg.hostPlatform; systemArgs = if isCross then { - localSystem = cfg.buildPlatform; - crossSystem = cfg.hostPlatform; + localSystem = opt.buildPlatform.rawValue; + crossSystem = opt.hostPlatform.rawValue; } else { - localSystem = cfg.hostPlatform; + localSystem = opt.hostPlatform.rawValue; }; in import ../../.. ( @@ -96,9 +101,9 @@ let inherit (cfg) config overlays - localSystem - crossSystem ; + localSystem = opt.localSystem.rawValue; + crossSystem = opt.crossSystem.rawValue; }; finalPkgs = if opt.pkgs.isDefined then cfg.pkgs.appendOverlays cfg.overlays else defaultPkgs; From 9fbe356e0a9d136c8f0a62cf8e86f23decfb071a Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Tue, 9 Apr 2024 08:41:18 +0200 Subject: [PATCH 6/9] pkgs/top-level: make package sets composable The various pkgsXYZ top-level package sets did not pass localSystem / crossSystem to lower levels, so far. This change propagates original arguments to lower levels, which include the overrides made by an upper package sets. There is an extensive test-suite to test various combinations of package sets in pkgs/test/top-level. There are a few basic promises made: - Package sets must be idempotent. pkgsMusl.pkgsMusl === pkgsMusl. - Once pkgsCross is used any subsequent package sets should affect the **host platform** and not the build platform. Examples: - pkgsMusl.pkgsCross.aarch64-multiplatform is a cross compilation from musl to glibc/aarch64 - pkgsCross.aarch64-multiplatform.pkgsMusl is a cross compilation to musl/aarch64 - Modifications from an earlier layer should not be lost, unless explicitly overwritten. Examples: - pkgsStatic.pkgsMusl should still be static. - pkgsStatic.pkgsCross.gnu64 should be static, but with glibc instead of musl. Exceptions / TODOs: - pkgsExtraHardening is currently not idempotent, because it applies the same flags over and over again. Supersedes #136549 Resolves #114510 Resolves #212494 Resolves #281596 --- pkgs/test/top-level/stage.nix | 29 ++++++------ pkgs/top-level/default.nix | 2 +- pkgs/top-level/stage.nix | 84 ++++++++++++++++++----------------- 3 files changed, 59 insertions(+), 56 deletions(-) diff --git a/pkgs/test/top-level/stage.nix b/pkgs/test/top-level/stage.nix index 7c53289a960a3..5009903b07e50 100644 --- a/pkgs/test/top-level/stage.nix +++ b/pkgs/test/top-level/stage.nix @@ -72,10 +72,8 @@ assert isIdempotent "pkgsStatic"; assert isIdempotent "pkgsi686Linux"; assert isIdempotent "pkgsx86_64Darwin"; -# TODO: fails -# assert isNoop [ "pkgsStatic" ] "pkgsMusl"; -# TODO: fails because of ppc64-musl -# assert lib.all (sys: isNoop [ "pkgsCross" sys ] "pkgsMusl") allMuslExamples; +assert isNoop [ "pkgsStatic" ] "pkgsMusl"; +assert lib.all (sys: isNoop [ "pkgsCross" sys ] "pkgsMusl") allMuslExamples; assert lib.all (sys: isNoop [ "pkgsCross" sys ] "pkgsLLVM") allLLVMExamples; assert isComposable "pkgsExtraHardening"; @@ -83,22 +81,25 @@ assert isComposable "pkgsLLVM"; assert isComposable "pkgsArocc"; # TODO: unexpected argument 'bintools' - uncomment once https://github.com/NixOS/nixpkgs/pull/331011 is done # assert isComposable "pkgsZig"; -# TODO: attribute 'abi' missing -# assert isComposable "pkgsMusl"; -# TODO: fails -# assert isComposable "pkgsStatic"; -# assert isComposable "pkgsi686Linux"; +assert isComposable "pkgsMusl"; +assert isComposable "pkgsStatic"; +assert isComposable "pkgsi686Linux"; # Special cases regarding buildPlatform vs hostPlatform # TODO: fails # assert discardEvaluationErrors (pkgsCross.gnu64.pkgsMusl.stdenv.hostPlatform.isMusl); # assert discardEvaluationErrors (pkgsCross.gnu64.pkgsi686Linux.stdenv.hostPlatform.isx86_32); -# assert discardEvaluationErrors (pkgsCross.mingwW64.pkgsLinux.stdenv.hostPlatform.isLinux); -# assert discardEvaluationErrors (pkgsCross.aarch64-darwin.pkgsx86_64Darwin.stdenv.hostPlatform.isx86_64); +assert discardEvaluationErrors (pkgsCross.mingwW64.pkgsLinux.stdenv.hostPlatform.isLinux); +assert discardEvaluationErrors ( + pkgsCross.aarch64-darwin.pkgsx86_64Darwin.stdenv.hostPlatform.isx86_64 +); # pkgsCross should keep upper cross settings -# TODO: fails -# assert discardEvaluationErrors (with pkgsStatic.pkgsCross.gnu64.stdenv.hostPlatform; isGnu && isStatic); -# assert discardEvaluationErrors (with pkgsLLVM.pkgsCross.musl64.stdenv.hostPlatform; isMusl && useLLVM); +assert discardEvaluationErrors ( + with pkgsStatic.pkgsCross.gnu64.stdenv.hostPlatform; isGnu && isStatic +); +assert discardEvaluationErrors ( + with pkgsLLVM.pkgsCross.musl64.stdenv.hostPlatform; isMusl && useLLVM +); emptyFile diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index 918a47639f3c6..6787793dbdfc7 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -142,7 +142,7 @@ in let # via `evalModules` is not idempotent. In other words, if you add `config` to # `newArgs`, expect strange very hard to debug errors! (Yes, I'm speaking from # experience here.) - nixpkgsFun = newArgs: import ./. (args // newArgs); + nixpkgsFun = f0: import ./. (args // f0 args); # Partially apply some arguments for building bootstraping stage pkgs # sets. Only apply arguments which no stdenv would want to override. diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index cb5e44ae0602a..26ff10cdeb851 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -178,12 +178,12 @@ let # Convenience attributes for instantitating package sets. Each of # these will instantiate a new version of allPackages. otherPackageSets = let - mkPkgs = name: nixpkgsArgs: nixpkgsFun (nixpkgsArgs // { + mkPkgs = name: fn: nixpkgsFun (prevArgs: let nixpkgsArgs = fn prevArgs; in nixpkgsArgs // { overlays = [ (self': super': { "${name}" = super'; }) - ] ++ nixpkgsArgs.overlays or [] ++ overlays; + ] ++ nixpkgsArgs.overlays or [] ++ prevArgs.overlays or []; }); in self: super: { # This maps each entry in lib.systems.examples to its own package @@ -192,94 +192,96 @@ let # will refer to the "hello" package built for the ARM6-based # Raspberry Pi. pkgsCross = lib.mapAttrs (n: crossSystem: - nixpkgsFun { inherit crossSystem; }) + nixpkgsFun (prevArgs: { crossSystem = (lib.systems.systemToAttrs (lib.defaultTo { } prevArgs.crossSystem or null)) // crossSystem; })) lib.systems.examples; - pkgsLLVM = mkPkgs "pkgsLLVM" { + pkgsLLVM = mkPkgs "pkgsLLVM" (prevArgs: { # Bootstrap a cross stdenv using the LLVM toolchain. # This is currently not possible when compiling natively, - # so we don't need to check hostPlatform != buildPlatform. - crossSystem = stdenv.hostPlatform // { + # so we don't need to check whether we are cross already. + crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { useLLVM = true; linker = "lld"; }; - }; + }); - pkgsArocc = mkPkgs "pkgsArocc" { + pkgsArocc = mkPkgs "pkgsArocc" (prevArgs: { # Bootstrap a cross stdenv using the Aro C compiler. # This is currently not possible when compiling natively, - # so we don't need to check hostPlatform != buildPlatform. - crossSystem = stdenv.hostPlatform // { + # so we don't need to check whether we are cross already. + crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { useArocc = true; linker = "lld"; }; - }; + }); - pkgsZig = mkPkgs "pkgsZig" { + pkgsZig = mkPkgs "pkgsZig" (prevArgs: { # Bootstrap a cross stdenv using the Zig toolchain. # This is currently not possible when compiling natively, - # so we don't need to check hostPlatform != buildPlatform. - crossSystem = stdenv.hostPlatform // { + # so we don't need to check whether we are cross already. + crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { useZig = true; linker = "lld"; }; - }; + }); # All packages built with the Musl libc. This will override the # default GNU libc on Linux systems. Non-Linux systems are not # supported. 32-bit is also not supported. - pkgsMusl = if stdenv.hostPlatform.isLinux && stdenv.buildPlatform.is64bit then mkPkgs "pkgsMusl" { + pkgsMusl = if stdenv.hostPlatform.isLinux && stdenv.buildPlatform.is64bit then mkPkgs "pkgsMusl" (prevArgs: { ${if stdenv.hostPlatform == stdenv.buildPlatform - then "localSystem" else "crossSystem"} = { + then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); }; - } else throw "Musl libc only supports 64-bit Linux systems."; + }) else throw "Musl libc only supports 64-bit Linux systems."; # All packages built for i686 Linux. # Used by wine, firefox with debugging version of Flash, ... - pkgsi686Linux = if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86 then mkPkgs "pkgsi686Linux" { + pkgsi686Linux = if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86 then mkPkgs "pkgsi686Linux" (prevArgs: { ${if stdenv.hostPlatform == stdenv.buildPlatform - then "localSystem" else "crossSystem"} = { + then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { cpu = lib.systems.parse.cpuTypes.i686; }); }; - } else throw "i686 Linux package set can only be used with the x86 family."; + }) else throw "i686 Linux package set can only be used with the x86 family."; # x86_64-darwin packages for aarch64-darwin users to use with Rosetta for incompatible packages - pkgsx86_64Darwin = if stdenv.hostPlatform.isDarwin then mkPkgs "pkgsx86_64Darwin" { - localSystem = { + pkgsx86_64Darwin = if stdenv.hostPlatform.isDarwin then mkPkgs "pkgsx86_64Darwin" (prevArgs: { + ${if stdenv.hostPlatform == stdenv.buildPlatform + then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { cpu = lib.systems.parse.cpuTypes.x86_64; }); }; - } else throw "x86_64 Darwin package set can only be used on Darwin systems."; + }) else throw "x86_64 Darwin package set can only be used on Darwin systems."; # If already linux: the same package set unaltered - # Otherwise, return a natively built linux package set for the current cpu architecture string. + # Otherwise, return a linux package set for the current cpu architecture string. + # (ABI and other details will be set to the default for the cpu/os pair) pkgsLinux = if stdenv.hostPlatform.isLinux then self - else mkPkgs "pkgsLinux" { - localSystem = lib.systems.elaborate "${stdenv.hostPlatform.parsed.cpu.name}-linux"; - }; + else mkPkgs "pkgsLinux" (prevArgs: { + ${if stdenv.hostPlatform == stdenv.buildPlatform + then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { + config = lib.systems.parse.tripleFromSystem (lib.systems.elaborate "${stdenv.hostPlatform.parsed.cpu.name}-linux").parsed; + }; + }); # Fully static packages. # Currently uses Musl on Linux (couldn’t get static glibc to work). - pkgsStatic = mkPkgs "pkgsStatic" { - crossSystem = { + pkgsStatic = mkPkgs "pkgsStatic" (prevArgs: { + crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { isStatic = true; - config = lib.systems.parse.tripleFromSystem ( - if stdenv.hostPlatform.isLinux - then makeMuslParsedPlatform stdenv.hostPlatform.parsed - else stdenv.hostPlatform.parsed - ); - gcc = lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { abi = "elfv2"; } // - stdenv.hostPlatform.gcc or {}; + } // lib.optionalAttrs stdenv.hostPlatform.isLinux { + config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); + } // lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { + gcc = { abi = "elfv2"; } // stdenv.hostPlatform.gcc or {}; }; - }; + }); - pkgsExtraHardening = mkPkgs "pkgsExtraHardening" { + pkgsExtraHardening = mkPkgs "pkgsExtraHardening" (_: { overlays = [ (self': super': { stdenv = super'.withDefaultHardeningFlags ( @@ -301,7 +303,7 @@ let pcre16 = super'.pcre16.override { enableJit = false; }; }) ]; - }; + }); # Extend the package set with zero or more overlays. This preserves # preexisting overlays. Prefer to initialize with the right overlays @@ -309,7 +311,7 @@ let appendOverlays = extraOverlays: if extraOverlays == [] then self - else nixpkgsFun { overlays = args.overlays ++ extraOverlays; }; + else nixpkgsFun (prevArgs: { overlays = prevArgs.overlays ++ extraOverlays; }); # NOTE: each call to extend causes a full nixpkgs rebuild, adding ~130MB # of allocations. DO NOT USE THIS IN NIXPKGS. From 7230b0123d41f5921a7ad4aa65c5f3729fd04708 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 14 Dec 2024 18:54:28 +0100 Subject: [PATCH 7/9] pkgs/top-level: refactor mkCrossPkgs --- pkgs/top-level/stage.nix | 63 ++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 26ff10cdeb851..aeed72697eb4c 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -185,6 +185,10 @@ let }) ] ++ nixpkgsArgs.overlays or [] ++ prevArgs.overlays or []; }); + # This is always cross. + mkCrossPkgs = name: crossAttrs: mkPkgs name (prevArgs: { + crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // crossAttrs; + }); in self: super: { # This maps each entry in lib.systems.examples to its own package # set. Each of these will contain all packages cross compiled for @@ -195,35 +199,26 @@ let nixpkgsFun (prevArgs: { crossSystem = (lib.systems.systemToAttrs (lib.defaultTo { } prevArgs.crossSystem or null)) // crossSystem; })) lib.systems.examples; - pkgsLLVM = mkPkgs "pkgsLLVM" (prevArgs: { - # Bootstrap a cross stdenv using the LLVM toolchain. - # This is currently not possible when compiling natively, - # so we don't need to check whether we are cross already. - crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - useLLVM = true; - linker = "lld"; - }; - }); + # Bootstrap a cross stdenv using the LLVM toolchain. + # This is currently not possible when compiling natively. + pkgsLLVM = mkCrossPkgs "pkgsLLVM" { + useLLVM = true; + linker = "lld"; + }; - pkgsArocc = mkPkgs "pkgsArocc" (prevArgs: { - # Bootstrap a cross stdenv using the Aro C compiler. - # This is currently not possible when compiling natively, - # so we don't need to check whether we are cross already. - crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - useArocc = true; - linker = "lld"; - }; - }); + # Bootstrap a cross stdenv using the Aro C compiler. + # This is currently not possible when compiling natively. + pkgsArocc = mkCrossPkgs "pkgsArocc" { + useArocc = true; + linker = "lld"; + }; - pkgsZig = mkPkgs "pkgsZig" (prevArgs: { - # Bootstrap a cross stdenv using the Zig toolchain. - # This is currently not possible when compiling natively, - # so we don't need to check whether we are cross already. - crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - useZig = true; - linker = "lld"; - }; - }); + # Bootstrap a cross stdenv using the Zig toolchain. + # This is currently not possible when compiling natively. + pkgsZig = mkCrossPkgs "pkgsZig" { + useZig = true; + linker = "lld"; + }; # All packages built with the Musl libc. This will override the # default GNU libc on Linux systems. Non-Linux systems are not @@ -271,14 +266,12 @@ let # Fully static packages. # Currently uses Musl on Linux (couldn’t get static glibc to work). - pkgsStatic = mkPkgs "pkgsStatic" (prevArgs: { - crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - isStatic = true; - } // lib.optionalAttrs stdenv.hostPlatform.isLinux { - config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); - } // lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { - gcc = { abi = "elfv2"; } // stdenv.hostPlatform.gcc or {}; - }; + pkgsStatic = mkCrossPkgs "pkgsStatic" ({ + isStatic = true; + } // lib.optionalAttrs stdenv.hostPlatform.isLinux { + config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); + } // lib.optionalAttrs (stdenv.hostPlatform.system == "powerpc64-linux") { + gcc = { abi = "elfv2"; } // stdenv.hostPlatform.gcc or {}; }); pkgsExtraHardening = mkPkgs "pkgsExtraHardening" (_: { From 631102ab1cf7a4a03916bbec206ce63ffe63b58f Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 14 Dec 2024 19:01:31 +0100 Subject: [PATCH 8/9] pkgs/top-level: refactor mkHybridPkgs --- pkgs/top-level/stage.nix | 52 ++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index aeed72697eb4c..50ea964844e24 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -187,7 +187,13 @@ let }); # This is always cross. mkCrossPkgs = name: crossAttrs: mkPkgs name (prevArgs: { - crossSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // crossAttrs; + crossSystem = + (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // crossAttrs; + }); + # This is only cross when we are already cross, otherwise local. + mkHybridPkgs = name: hybridAttrs: mkPkgs name (prevArgs: { + ${if stdenv.hostPlatform == stdenv.buildPlatform then "localSystem" else "crossSystem"} = + (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // hybridAttrs; }); in self: super: { # This maps each entry in lib.systems.examples to its own package @@ -223,33 +229,24 @@ let # All packages built with the Musl libc. This will override the # default GNU libc on Linux systems. Non-Linux systems are not # supported. 32-bit is also not supported. - pkgsMusl = if stdenv.hostPlatform.isLinux && stdenv.buildPlatform.is64bit then mkPkgs "pkgsMusl" (prevArgs: { - ${if stdenv.hostPlatform == stdenv.buildPlatform - then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); - }; - }) else throw "Musl libc only supports 64-bit Linux systems."; + pkgsMusl = if stdenv.hostPlatform.isLinux && stdenv.buildPlatform.is64bit then mkHybridPkgs "pkgsMusl" { + config = lib.systems.parse.tripleFromSystem (makeMuslParsedPlatform stdenv.hostPlatform.parsed); + } else throw "Musl libc only supports 64-bit Linux systems."; # All packages built for i686 Linux. # Used by wine, firefox with debugging version of Flash, ... - pkgsi686Linux = if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86 then mkPkgs "pkgsi686Linux" (prevArgs: { - ${if stdenv.hostPlatform == stdenv.buildPlatform - then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { - cpu = lib.systems.parse.cpuTypes.i686; - }); - }; - }) else throw "i686 Linux package set can only be used with the x86 family."; + pkgsi686Linux = if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86 then mkHybridPkgs "pkgsi686Linux" { + config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { + cpu = lib.systems.parse.cpuTypes.i686; + }); + } else throw "i686 Linux package set can only be used with the x86 family."; # x86_64-darwin packages for aarch64-darwin users to use with Rosetta for incompatible packages - pkgsx86_64Darwin = if stdenv.hostPlatform.isDarwin then mkPkgs "pkgsx86_64Darwin" (prevArgs: { - ${if stdenv.hostPlatform == stdenv.buildPlatform - then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { - cpu = lib.systems.parse.cpuTypes.x86_64; - }); - }; - }) else throw "x86_64 Darwin package set can only be used on Darwin systems."; + pkgsx86_64Darwin = if stdenv.hostPlatform.isDarwin then mkHybridPkgs "pkgsx86_64Darwin" { + config = lib.systems.parse.tripleFromSystem (stdenv.hostPlatform.parsed // { + cpu = lib.systems.parse.cpuTypes.x86_64; + }); + } else throw "x86_64 Darwin package set can only be used on Darwin systems."; # If already linux: the same package set unaltered # Otherwise, return a linux package set for the current cpu architecture string. @@ -257,12 +254,9 @@ let pkgsLinux = if stdenv.hostPlatform.isLinux then self - else mkPkgs "pkgsLinux" (prevArgs: { - ${if stdenv.hostPlatform == stdenv.buildPlatform - then "localSystem" else "crossSystem"} = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // { - config = lib.systems.parse.tripleFromSystem (lib.systems.elaborate "${stdenv.hostPlatform.parsed.cpu.name}-linux").parsed; - }; - }); + else mkHybridPkgs "pkgsLinux" { + config = lib.systems.parse.tripleFromSystem (lib.systems.elaborate "${stdenv.hostPlatform.parsed.cpu.name}-linux").parsed; + }; # Fully static packages. # Currently uses Musl on Linux (couldn’t get static glibc to work). From 7a9cb10ac3b91ca4e74f058221dbb449e5916b1f Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 21 Dec 2024 16:42:40 +0100 Subject: [PATCH 9/9] pkgs/top-level: fix composing "native cross" package sets When using pkgsCross with a system that ends up the same as the localSystem, then modifications for package sets like pksgMusl need to be done for **both** localSystem and crossSystem. Consider the following on x86_64-linux: pkgsCross.gnu64.pkgsMusl Before this change, this would result in a musl buildPlatform, but a gnu hostPlatform. This breaks the promise of "stacking" package sets on top of each other. After this change, it results in a musl buildPlatform and a musl hostPlatform. This works better. One could expect this to result in the same as pkgsCross.musl64, i.e. a gnu buildPlatform and a musl hostPlatform, however I couldn't get this to work without increasing memory usage for ci/eval by many, many GB. This is caused by usage of pkgsi686Linux inside the main package set, which follows the same hybrid pattern. --- pkgs/test/top-level/stage.nix | 5 ++--- pkgs/top-level/stage.nix | 11 +++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pkgs/test/top-level/stage.nix b/pkgs/test/top-level/stage.nix index 5009903b07e50..26e167fe3d031 100644 --- a/pkgs/test/top-level/stage.nix +++ b/pkgs/test/top-level/stage.nix @@ -86,9 +86,8 @@ assert isComposable "pkgsStatic"; assert isComposable "pkgsi686Linux"; # Special cases regarding buildPlatform vs hostPlatform -# TODO: fails -# assert discardEvaluationErrors (pkgsCross.gnu64.pkgsMusl.stdenv.hostPlatform.isMusl); -# assert discardEvaluationErrors (pkgsCross.gnu64.pkgsi686Linux.stdenv.hostPlatform.isx86_32); +assert discardEvaluationErrors (pkgsCross.gnu64.pkgsMusl.stdenv.hostPlatform.isMusl); +assert discardEvaluationErrors (pkgsCross.gnu64.pkgsi686Linux.stdenv.hostPlatform.isx86_32); assert discardEvaluationErrors (pkgsCross.mingwW64.pkgsLinux.stdenv.hostPlatform.isLinux); assert discardEvaluationErrors ( pkgsCross.aarch64-darwin.pkgsx86_64Darwin.stdenv.hostPlatform.isx86_64 diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 50ea964844e24..3fd0bf7e6b9ae 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -191,10 +191,13 @@ let (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // crossAttrs; }); # This is only cross when we are already cross, otherwise local. - mkHybridPkgs = name: hybridAttrs: mkPkgs name (prevArgs: { - ${if stdenv.hostPlatform == stdenv.buildPlatform then "localSystem" else "crossSystem"} = - (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // hybridAttrs; - }); + # For the case of "native cross", i.e. pkgsCross.gnu64 on a x86_64-linux system, we need to adjust **both** + # localSystem **and** crossSystem, otherwise they're out of sync. + mkHybridPkgs = name: hybridAttrs: mkPkgs name (prevArgs: let + newSystem = (lib.systems.systemToAttrs (lib.defaultTo prevArgs.localSystem prevArgs.crossSystem or null)) // hybridAttrs; + in { crossSystem = newSystem; } + // lib.optionalAttrs (stdenv.hostPlatform == stdenv.buildPlatform) { localSystem = newSystem; } + ); in self: super: { # This maps each entry in lib.systems.examples to its own package # set. Each of these will contain all packages cross compiled for