forked from mirrors/nixpkgs
top-level: Introduce targetPackages and a "double link fold"
Each bootstrapping stage ought to just depend on the previous stage, but poorly-written compilers break this elegence. This provides an easy-enough way to depend on the next stage: targetPackages. PLEASE DO NOT USE IT UNLESS YOU MUST! I'm hoping someday in a pleasant future I can revert this commit :)
This commit is contained in:
parent
d59e4fbb75
commit
863d79b364
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue