about summary refs log tree commit diff
path: root/doc/manual/introduction.xml
blob: 5eea764592bdd54512c05b695ccff3c34920cb7b (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
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:
-->