aboutsummaryrefslogtreecommitdiff
path: root/doc/manual/introduction.xml
blob: feabeef9cdc255a3e221b57d5154cc36988b692e (plain)
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<chapter>
  <title>Introduction</title>

  <sect1>
    <title>The problem space</title>

    <para>
      Nix is a system for controlling the automatic creation and distribution
      of data, such as computer programs and other software artifacts.  This is
      a very general problem, and there are many applications that fall under
      this description.
    </para>

    <sect2>
      <title>Build management</title>

      <para>
        Build management tools are used to perform <emphasis>software
          builds</emphasis>, that is, the construction of derived products
        (<emphasis>derivates)</emphasis>) such as executable programs from
        source code.  A commonly used build tool is Make, which is a standard
        tool on Unix systems. These tools have to deal with several issues:
        <itemizedlist>

          <listitem>
            <para>
              <emphasis>Efficiency</emphasis>.  Since building large systems
              can take a substantial amount of time, it is desirable that build
              steps that have been performed in the past are not repeated
              unnecessarily, i.e., if a new build differs from a previous build
              only with respect to certain sources, then only the build steps
              that (directly or indirectly) <emphasis>depend</emphasis> on
              those sources should be redone.
            </para>
          </listitem>

          <listitem>
            <para>
              <emphasis>Correctness</emphasis> is this context means that the
              derivates produced by a build are always consistent with the
              sources, that is, they are equal to what we would get if we were
              to build the derivates from those sources.  This requirement is
              trivially met when we do a full, unconditional build, but is far
              from trivial under the requirement of efficiency, since it is not
              easy to determine which derivates are affected by a change to a
              source.
            </para>
          </listitem>

          <listitem>
            <para>
              <emphasis>Variability</emphasis> is the property that a software
              system can be built in a (potentially large) number of variants.
              Variation exists both in <emphasis>time</emphasis>---the
              evolution of different versions of an artifact---and in
              <emphasis>space</emphasis>---the artifact might have
              configuration options that lead to variants that differ in the
              features they support (for example, a system might be built with
              or without debugging information).
            </para>

            <para>
              Build managers historically have had good support for variation
              in time (rebuilding the system in an intelligent way when sources
              change is one of the primary reasons to use a build manager), but
              not always for variation in space.  For example,
              <command>make</command> will not automatically ensure that
              variant builds are properly isolated from each other (they will
              in fact overwrite each other unless special precautions are
              taken).
            </para>
          </listitem>

          <listitem>
            <para>
              <emphasis>High-level system modelling language</emphasis>.  The
              language in which one describes what and how derivates are to be
              produced should have sufficient abstraction facilities to make it
              easy to specify the derivation of even very large systems.  Also,
              the language should be <emphasis>modular</emphasis> to enable
              components from possible different sources to be easily combined.
            </para>
          </listitem>

        </itemizedlist>
      </para>

    </sect2>

    <sect2>
      <title>Package management</title>

      <para>
        After software has been built, is must also be
        <emphasis>deployed</emphasis> in the intended target environment, e.g.,
        the user's workstation.  Examples include the Red Hat package manager
        (RPM), Microsoft's MSI, and so on.  Here also we have several issues to
        contend with:
        <itemizedlist>
          <listitem>
            <para>
              The <emphasis>creation</emphasis> of packages from some formal
              description of what artifacts should be distributed in the
              package.
            </para>
          </listitem>
          <listitem>
            <para>
              The <emphasis>deployment</emphasis> of packages, that is, the
              mechanism by which we get them onto the intended target
              environment.  This can be as simple as copying a file, but
              complexity comes from the wide range of possible installation
              media (such as a network install), and the scalability of the
              process (if a program must be installed on a thousand systems, we
              do not want to visit each system and perform some manual steps to
              install the program on that system; that is, the complexity for
              the system administrator should be constant, not linear).
            </para>
          </listitem>
        </itemizedlist>
      </para>
    </sect2>

  </sect1>


  <!--######################################################################-->

  <sect1>
    <title>What Nix provides</title>

    <para>
      Here is a summary of Nix's main features:
    </para>

    <itemizedlist>

      <listitem>
        <para>
          <emphasis>Reliable dependencies.</emphasis>  Builds of file system
          objects depend on other file system object, such as source files,
          tools, and so on.  We would like to ensure that a build does not
          refer to any objects that have not been declared as inputs for that
          build.  This is important for several reasons.  First, if any of the
          inputs change, we need to rebuild the things that depend on them to
          maintain consistency between sources and derivates.  Second, when we
          <emphasis>deploy</emphasis> file system objects (that is, copy them
          to a different system), we want to be certain that we copy everything
          that we need.
        </para>

        <para>
          Nix ensures this by building and storing file system objects in paths
          that are infeasible to predict in advance.  For example, the
          artifacts of a package <literal>X</literal> might be stored in
          <filename>/nix/store/d58a0606ed616820de291d594602665d-X</filename>,
          rather than in, say, <filename>/usr/lib</filename>.  The path
          component <filename>d58a...</filename> is actually a cryptographic
          hash of all the inputs (i.e., sources, requisites, and build flags)
          used in building <literal>X</literal>, and as such is very fragile:
          any change to the inputs will change the hash.  Therefore it is not
          sensible to <emphasis>hard-code</emphasis> such a path into the build
          scripts of a package <literal>Y</literal> that uses
          <literal>X</literal> (as does happen with <quote>fixed</quote> paths
          such as <filename>/usr/lib</filename>).  Rather, the build script of
          package <literal>Y</literal> is parameterised with the actual
          location of <literal>X</literal>, which is supplied by the Nix
          system.
        </para>
      </listitem>

      <listitem>
        <para>
          <emphasis>Support for variability.</emphasis>  
        </para>
        
        <para>
          As stated above, the path name of a file system object contain a
          cryptographic hash of all inputs involved in building it.  A change to
          any of the inputs will cause the hash to change--and by extension,
          the path name.  These inputs include both sources (variation in time)
          and configuration options (variation in space).  Therefore variants
          of the same package don't clash---they can co-exist peacefully within
          the same file system.  So thanks to Nix's mechanism for reliably
          dealing with dependencies, we obtain management of variants for free
          (or, to quote Simon Peyton-Jone, it's not free, but it has already
          been paid for).
        </para>

      </listitem>

      <listitem>
        <para>
          <emphasis>Transparent source/binary deployment.</emphasis>
        </para>
      </listitem>

      <listitem>
        <para>
          <emphasis>Easy configuration duplication.</emphasis>
        </para>
      </listitem>

      <listitem>
        <para>
          <emphasis>Automatic storage management.</emphasis>
        </para>
      </listitem>

      <listitem>
        <para>
          <emphasis>Atomic upgrades and rollbacks.</emphasis>
        </para>
      </listitem>

      <listitem>
        <para>
          <emphasis>Support for many simultaneous configurations.</emphasis>
        </para>
      </listitem>

      <listitem>
        <para>
          <emphasis>Portability.</emphasis>  Nix is quite portable.  Contrary
          to build systems like those in, e.g., Vesta and ClearCase [sic?], it
          does not rely on operating system extensions.
        </para>
      </listitem>

    </itemizedlist>

    <para>
      Here is what Nix doesn't yet provide, but will:
    </para>

    <itemizedlist>

      <listitem>
        <para>
          <emphasis>Build management.</emphasis>  In principle it is already
          possible to do build management using Fix (by writing builders that
          perform appropriate build steps), but the Fix language is not yet
          powerful enough to make this pleasant.  The <ulink
            url='http://www.cs.uu.nl/~eelco/maak/'>Maak build manager</ulink>
          should be retargeted to produce Nix expressions, or alternatively,
          extend Fix with Maak's semantics and concrete syntax (since Fix needs
          a concrete syntax anyway).  Another interesting idea is to write a
          <command>make</command> implementation that uses Nix as a back-end to
          support <ulink
            url='http://www.research.att.com/~bs/bs_faq.html#legacy'>legacy</ulink> 
          build files.
        </para>
      </listitem>

    </itemizedlist>

  </sect1>


  <!--######################################################################-->

  <sect1>
    <title>The Nix system</title>

    <para>
      ...
    </para>

    <para>
      Existing tools in this field generally both a underlying model (such as
      the derivation graph of build tools, or the versioning scheme that
      determines when two packages are <quote>compatible</quote> in a package
      management system) and a formalism that allows ...
    </para>

    <para>
      Following the principle of separation of mechanism and policy, the Nix
      system separates the <emphasis>low-level aspect</emphasis> of file system
      object management form the <emphasis>high-level aspect</emphasis> of the
      ...
    </para>

  </sect1>

</chapter>

<!--
local variables:
sgml-parent-document: ("book.xml" "chapter")
end:
-->