summary refs log tree commit diff
path: root/pkgs/system/stdenvs.nix
blob: efbbcb0faada2f7fdcc16bc88e2af3e038ae9f9b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# This file defines the various standard build environments.
#
# On Linux systems, the standard build environment consists of
# Nix-built instances glibc and the `standard' Unix tools, i.e., the
# Posix utilities, the GNU C compiler, and so on.  On other systems,
# we use the native C library.

{system, allPackages}: rec {

  gccWrapper = import ../build-support/gcc-wrapper;
  genericStdenv = import ../stdenv/generic;


  # Trivial environment used for building other environments.
  stdenvInitial = (import ../stdenv/initial) {
    name = "stdenv-initial";
    inherit system;
  };


  # The native (i.e., impure) build environment.  This one uses the
  # tools installed on the system outside of the Nix environment,
  # i.e., the stuff in /bin, /usr/bin, etc.  This environment should
  # be used with care, since many Nix packages will not build properly
  # with it (e.g., because they require GNU Make).
  stdenvNative = (import ../stdenv/native) {
    stdenv = stdenvInitial;
    inherit genericStdenv gccWrapper;
  };

  stdenvNativePkgs = allPackages {
    stdenv = stdenvNative;
    bootCurl = null;
    noSysDirs = false;
  };


  # The Nix build environment.
  stdenvNix = (import ../stdenv/nix) {
    stdenv = stdenvNative;
    pkgs = stdenvNativePkgs;
    inherit genericStdenv gccWrapper;
  };

  stdenvNixPkgs = allPackages {
    stdenv = stdenvNix;
    bootCurl = stdenvNativePkgs.curl;
    noSysDirs = false;
  };


  # The Linux build environment is a fully bootstrapped Nix
  # environment, that is, it should contain no external references.

  # 0) ...
  stdenvLinuxBoot0 = (import ../stdenv/nix-linux-static).stdenvBootFun {
    # Use the statically linked, downloaded glibc/gcc/binutils.
    inherit (import ../stdenv/nix-linux-static) glibc gcc binutils;
    staticGlibc = true;
  };

  stdenvLinuxBoot0Pkgs = allPackages {
    stdenv = stdenvLinuxBoot0;
    bootCurl = (import ../stdenv/nix-linux-static).curl;
    noSysDirs = true;
  };

  # 1) Build glibc in the Nix build environment.  The result is
  #    pure.
  stdenvLinuxGlibc = stdenvLinuxBoot0Pkgs.glibc;

  # 2) Construct a stdenv consisting of the Nix build environment, but
  #    with a gcc-wrapper that causes linking against the glibc from
  #    step 1.  However, since the gcc wrapper here *does* look in
  #    native system directories (e.g., `/usr/lib'), it doesn't
  #    prevent impurity in the things it builds (e.g., through
  #    `-lncurses').
  stdenvLinuxBoot1 = (import ../stdenv/nix-linux-static).stdenvBootFun {
    # Use the statically linked gcc/binutils, but the glibc we just
    # built.
    glibc = stdenvLinuxGlibc;
    staticGlibc = false;
    inherit (import ../stdenv/nix-linux-static) gcc binutils;
  };

  # 3) Now we can build packages that will link against the Nix
  #    glibc.  We are on thin ice here: the compiler used to build
  #    these packages doesn't prevent impurity, so e.g. bash ends up
  #    linking against `/lib/libncurses.so', but the glibc from step 1
  #    *doesn't* search in `/lib' etc.  So these programs won't work.
  stdenvLinuxBoot1Pkgs = allPackages {
    stdenv = stdenvLinuxBoot1;
    bootCurl = (import ../stdenv/nix-linux-static).curl;
  };

  # 4) Therefore we build a new standard environment which is the same
  #    as the one in step 2, but with a gcc and binutils from step 3
  #    merged in.  Since these are pure (they don't search native
  #    system directories), things built by this stdenv should be pure.
  stdenvLinuxBoot2 = (import ../stdenv/nix-linux-static).stdenvBootFun {
    # Use the glibc/gcc/binutils we just built (but all other tools are still downloaded).
    glibc = stdenvLinuxGlibc;
    staticGlibc = false;
    inherit (stdenvLinuxBoot1Pkgs) gcc binutils;
  };

  # 5) So these packages should be pure.
  stdenvLinuxBoot2Pkgs = allPackages {
    stdenv = stdenvLinuxBoot2;
    bootCurl = (import ../stdenv/nix-linux-static).curl;
  };

  # 6) Finally we can construct the Nix build environment from the
  #    packages from step 5.
  stdenvLinux = (import ../stdenv/nix-linux) {
    stdenv = stdenvLinuxBoot2;
    pkgs = stdenvLinuxBoot2Pkgs // {
      inherit (stdenvLinuxBoot1Pkgs) gcc binutils;
    };
    glibc = stdenvLinuxGlibc;
    inherit genericStdenv gccWrapper;
  };

  # 7) And we can build all packages against that, but we don't
  #    rebuild stuff from step 6.
  stdenvLinuxPkgs =
    allPackages {
      stdenv = stdenvLinux;
      bootCurl = stdenvLinuxBoot2Pkgs.curl;
    } //
    {inherit (stdenvLinuxBoot2Pkgs)
      gzip bzip2 bash binutils coreutils diffutils findutils gawk gcc
      gnumake gnused gnutar gnugrep curl;
    } //
    {glibc = stdenvLinuxGlibc;};

  # In summary, we build gcc (and binutils) three times:
  #   - in stdenvLinuxBoot1 (from stdenvNativePkgs); impure
  #   - in stdenvLinuxBoot2 (from stdenvLinuxBoot1Pkgs); pure
  #   - in stdenvLinux (from stdenvLinuxBoot2Pkgs); pure
  # The last one may be redundant, but its good for validation (since
  # the second one may use impure inputs).  To reduce build time, we
  # could reduce the number of bootstrap stages inside each gcc build.
  # Right now there are 3 stages, so gcc is built 9 times!

  # On the other hand, a validating build of glibc is a good idea (it
  # probably won't work right now due to --rpath madness).


  # Darwin (Mac OS X) standard environment.  Very simple for now
  # (essentially it's just the native environment).
  stdenvDarwin = (import ../stdenv/darwin) {
    stdenv = stdenvInitial;
    genericStdenv = import ../stdenv/generic-branch;
    inherit gccWrapper;
  };

  stdenvDarwinPkgs = allPackages {
    stdenv = stdenvDarwin;
    bootCurl = null;
    noSysDirs = false;
  };


  stdenvTestPkgs = allPackages {
    stdenv = (import ../stdenv/nix-linux-static).stdenvInitial;
    bootCurl = (import ../stdenv/nix-linux-static).curl;
    noSysDirs = true;
  };
}