diff options
-rw-r--r-- | doc/cross-compilation.xml | 5 | ||||
-rw-r--r-- | pkgs/stdenv/booter.nix | 41 | ||||
-rw-r--r-- | pkgs/top-level/splice.nix | 2 | ||||
-rw-r--r-- | pkgs/top-level/stage.nix | 10 |
4 files changed, 52 insertions, 6 deletions
diff --git a/doc/cross-compilation.xml b/doc/cross-compilation.xml index 06a8919c2a19e..728616a9f2635 100644 --- a/doc/cross-compilation.xml +++ b/doc/cross-compilation.xml @@ -167,6 +167,11 @@ Because of this, a best-of-both-worlds solution is in the works with no splicing or explicit access of <varname>buildPackages</varname> needed. For now, feel free to use either method. </para> + <note><para> + There is also a "backlink" <varname>__targetPackages</varname>, yielding a package set whose <varname>buildPackages</varname> is the current package set. + This is a hack, though, to accommodate compilers with lousy build systems. + Please do not use this unless you are absolutely sure you are packaging such a compiler and there is no other way. + </para></note> </section> </section> diff --git a/pkgs/stdenv/booter.nix b/pkgs/stdenv/booter.nix index 2c82d12da95df..d459deb6ab543 100644 --- a/pkgs/stdenv/booter.nix +++ b/pkgs/stdenv/booter.nix @@ -41,6 +41,35 @@ # other words, this does a foldr not foldl. stageFuns: let + /* "dfold" a ternary function `op' between successive elements of `list' as if + it was a doubly-linked list with `lnul' and `rnul` base cases at either + end. In precise terms, `fold op lnul rnul [x_0 x_1 x_2 ... x_n-1]` is the + same as + + let + f_-1 = lnul; + f_0 = op f_-1 x_0 f_1; + f_1 = op f_0 x_1 f_2; + f_2 = op f_1 x_2 f_3; + ... + f_n = op f_n-1 x_n f_n+1; + f_n+1 = rnul; + in + f_0 + */ + dfold = op: lnul: rnul: list: + let + len = builtins.length list; + go = pred: n: + if n == len + then rnul + else let + # Note the cycle -- call-by-need ensures finite fold. + cur = op pred (builtins.elemAt list n) succ; + succ = go cur (n + 1); + in cur; + in go lnul 0; + # Take the list and disallow custom overrides in all but the final stage, # and allow it in the final flag. Only defaults this boolean field if it # isn't already set. @@ -55,19 +84,21 @@ stageFuns: let # Adds the stdenv to the arguments, and sticks in it the previous stage for # debugging purposes. - folder = stageFun: finalSoFar: let - args = stageFun finalSoFar; + folder = nextStage: stageFun: prevStage: let + args = stageFun prevStage; args' = args // { stdenv = args.stdenv // { # For debugging - __bootPackages = finalSoFar; + __bootPackages = prevStage; + __hatPackages = nextStage; }; }; in if args.__raw or false then args' else allPackages ((builtins.removeAttrs args' ["selfBuild"]) // { - buildPackages = if args.selfBuild or true then null else finalSoFar; + buildPackages = if args.selfBuild or true then null else prevStage; + __targetPackages = if args.selfBuild or true then null else nextStage; }); -in lib.lists.fold folder {} withAllowCustomOverrides +in dfold folder {} {} withAllowCustomOverrides diff --git a/pkgs/top-level/splice.nix b/pkgs/top-level/splice.nix index bb6fc47b1d2b1..43951100de3d7 100644 --- a/pkgs/top-level/splice.nix +++ b/pkgs/top-level/splice.nix @@ -66,7 +66,7 @@ let if actuallySplice then splicer defaultBuildScope defaultRunScope // { # These should never be spliced under any circumstances - inherit (pkgs) pkgs buildPackages + inherit (pkgs) pkgs buildPackages __targetPackages buildPlatform targetPlatform hostPlatform; } else pkgs // pkgs.xorg; diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index ead6ec18fb33b..d8e190cfd4be6 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -50,6 +50,14 @@ # us to avoid expensive splicing. buildPackages +, # The package set used in the next stage. If null, `__targetPackages` will be + # defined internally as the final produced package set itself, just like with + # `buildPackages` and for the same reasons. + # + # THIS IS A HACK for compilers that don't think critically about cross- + # compilation. Please do *not* use unless you really know what you are doing. + __targetPackages + , # The standard environment to use for building packages. stdenv @@ -88,6 +96,8 @@ let stdenvBootstappingAndPlatforms = self: super: { buildPackages = (if buildPackages == null then self else buildPackages) // { recurseForDerivations = false; }; + __targetPackages = (if __targetPackages == null then self else __targetPackages) + // { recurseForDerivations = false; }; inherit stdenv buildPlatform hostPlatform targetPlatform; }; |