summary refs log tree commit diff
path: root/pkgs/stdenv
diff options
context:
space:
mode:
authorJohn Ericson <Ericson2314@Yahoo.com>2017-02-06 18:13:02 -0500
committerJohn Ericson <Ericson2314@Yahoo.com>2017-04-23 14:01:12 -0400
commit863d79b36446bb2dbcc34d4f57c832ac2dc57f68 (patch)
tree76683d4a723783f27f64b7bdd73c6a9e107167e0 /pkgs/stdenv
parentd59e4fbb75e307fd1a0e98c44627f38bab504aeb (diff)
downloadnixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.tar
nixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.tar.gz
nixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.tar.bz2
nixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.tar.lz
nixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.tar.xz
nixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.tar.zst
nixlib-863d79b36446bb2dbcc34d4f57c832ac2dc57f68.zip
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 :)
Diffstat (limited to 'pkgs/stdenv')
-rw-r--r--pkgs/stdenv/booter.nix41
1 files changed, 36 insertions, 5 deletions
diff --git a/pkgs/stdenv/booter.nix b/pkgs/stdenv/booter.nix
index 2c82d12da95d..d459deb6ab54 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