1<chapter xmlns="http://docbook.org/ns/docbook"
2 xmlns:xlink="http://www.w3.org/1999/xlink"
3 xml:id="chap-conventions">
4
5<title>Coding conventions</title>
6
7
8<section xml:id="sec-syntax"><title>Syntax</title>
9
10<itemizedlist>
11
12 <listitem><para>Use 2 spaces of indentation per indentation level in
13 Nix expressions, 4 spaces in shell scripts.</para></listitem>
14
15 <listitem><para>Do not use tab characters, i.e. configure your
16 editor to use soft tabs. For instance, use <literal>(setq-default
17 indent-tabs-mode nil)</literal> in Emacs. Everybody has different
18 tab settings so it’s asking for trouble.</para></listitem>
19
20 <listitem><para>Use <literal>lowerCamelCase</literal> for variable
21 names, not <literal>UpperCamelCase</literal>. TODO: naming of
22 attributes in
23 <filename>all-packages.nix</filename>?</para></listitem>
24
25 <listitem><para>Function calls with attribute set arguments are
26 written as
27
28<programlisting>
29foo {
30 arg = ...;
31}
32</programlisting>
33
34 not
35
36<programlisting>
37foo
38{
39 arg = ...;
40}
41</programlisting>
42
43 Also fine is
44
45<programlisting>
46foo { arg = ...; }
47</programlisting>
48
49 if it's a short call.</para></listitem>
50
51 <listitem><para>In attribute sets or lists that span multiple lines,
52 the attribute names or list elements should be aligned:
53
54<programlisting>
55# A long list.
56list =
57 [ elem1
58 elem2
59 elem3
60 ];
61
62# A long attribute set.
63attrs =
64 { attr1 = short_expr;
65 attr2 =
66 if true then big_expr else big_expr;
67 };
68
69# Alternatively:
70attrs = {
71 attr1 = short_expr;
72 attr2 =
73 if true then big_expr else big_expr;
74};
75</programlisting>
76
77 </para></listitem>
78
79 <listitem><para>Short lists or attribute sets can be written on one
80 line:
81
82<programlisting>
83# A short list.
84list = [ elem1 elem2 elem3 ];
85
86# A short set.
87attrs = { x = 1280; y = 1024; };
88</programlisting>
89
90 </para></listitem>
91
92 <listitem><para>Breaking in the middle of a function argument can
93 give hard-to-read code, like
94
95<programlisting>
96someFunction { x = 1280;
97 y = 1024; } otherArg
98 yetAnotherArg
99</programlisting>
100
101 (especially if the argument is very large, spanning multiple
102 lines).</para>
103
104 <para>Better:
105
106<programlisting>
107someFunction
108 { x = 1280; y = 1024; }
109 otherArg
110 yetAnotherArg
111</programlisting>
112
113 or
114
115<programlisting>
116let res = { x = 1280; y = 1024; };
117in someFunction res otherArg yetAnotherArg
118</programlisting>
119
120 </para></listitem>
121
122 <listitem><para>The bodies of functions, asserts, and withs are not
123 indented to prevent a lot of superfluous indentation levels, i.e.
124
125<programlisting>
126{ arg1, arg2 }:
127assert system == "i686-linux";
128stdenv.mkDerivation { ...
129</programlisting>
130
131 not
132
133<programlisting>
134{ arg1, arg2 }:
135 assert system == "i686-linux";
136 stdenv.mkDerivation { ...
137</programlisting>
138
139 </para></listitem>
140
141 <listitem><para>Function formal arguments are written as:
142
143<programlisting>
144{ arg1, arg2, arg3 }:
145</programlisting>
146
147 but if they don't fit on one line they're written as:
148
149<programlisting>
150{ arg1, arg2, arg3
151, arg4, ...
152, # Some comment...
153 argN
154}:
155</programlisting>
156
157 </para></listitem>
158
159 <listitem><para>Functions should list their expected arguments as
160 precisely as possible. That is, write
161
162<programlisting>
163{ stdenv, fetchurl, perl }: <replaceable>...</replaceable>
164</programlisting>
165
166 instead of
167
168<programlisting>
169args: with args; <replaceable>...</replaceable>
170</programlisting>
171
172 or
173
174<programlisting>
175{ stdenv, fetchurl, perl, ... }: <replaceable>...</replaceable>
176</programlisting>
177
178 </para>
179
180 <para>For functions that are truly generic in the number of
181 arguments (such as wrappers around <varname>mkDerivation</varname>)
182 that have some required arguments, you should write them using an
183 <literal>@</literal>-pattern:
184
185<programlisting>
186{ stdenv, doCoverageAnalysis ? false, ... } @ args:
187
188stdenv.mkDerivation (args // {
189 <replaceable>...</replaceable> if doCoverageAnalysis then "bla" else "" <replaceable>...</replaceable>
190})
191</programlisting>
192
193 instead of
194
195<programlisting>
196args:
197
198args.stdenv.mkDerivation (args // {
199 <replaceable>...</replaceable> if args ? doCoverageAnalysis && args.doCoverageAnalysis then "bla" else "" <replaceable>...</replaceable>
200})
201</programlisting>
202
203 </para></listitem>
204
205</itemizedlist>
206
207</section>
208
209
210<section xml:id="sec-package-naming"><title>Package naming</title>
211
212<para>In Nixpkgs, there are generally three different names associated with a package:
213
214<itemizedlist>
215
216 <listitem><para>The <varname>name</varname> attribute of the
217 derivation (excluding the version part). This is what most users
218 see, in particular when using
219 <command>nix-env</command>.</para></listitem>
220
221 <listitem><para>The variable name used for the instantiated package
222 in <filename>all-packages.nix</filename>, and when passing it as a
223 dependency to other functions. This is what Nix expression authors
224 see. It can also be used when installing using <command>nix-env
225 -iA</command>.</para></listitem>
226
227 <listitem><para>The filename for (the directory containing) the Nix
228 expression.</para></listitem>
229
230</itemizedlist>
231
232Most of the time, these are the same. For instance, the package
233<literal>e2fsprogs</literal> has a <varname>name</varname> attribute
234<literal>"e2fsprogs-<replaceable>version</replaceable>"</literal>, is
235bound to the variable name <varname>e2fsprogs</varname> in
236<filename>all-packages.nix</filename>, and the Nix expression is in
237<filename>pkgs/os-specific/linux/e2fsprogs/default.nix</filename>.
238</para>
239
240<para>There are a few naming guidelines:
241
242<itemizedlist>
243
244 <listitem><para>Generally, try to stick to the upstream package
245 name.</para></listitem>
246
247 <listitem><para>Don’t use uppercase letters in the
248 <literal>name</literal> attribute — e.g.,
249 <literal>"mplayer-1.0rc2"</literal> instead of
250 <literal>"MPlayer-1.0rc2"</literal>.</para></listitem>
251
252 <listitem><para>The version part of the <literal>name</literal>
253 attribute <emphasis>must</emphasis> start with a digit (following a
254 dash) — e.g., <literal>"hello-0.3-pre-r3910"</literal> instead of
255 <literal>"hello-svn-r3910"</literal>, as the latter would be seen as
256 a package named <literal>hello-svn</literal> by
257 <command>nix-env</command>.</para></listitem>
258
259 <listitem><para>If package is fetched from git's commit then
260 the version part of the name <emphasis>must</emphasis> be the date of that
261 (fetched) commit. The date must be in <literal>"YYYY-MM-DD"</literal> format.
262 Also add <literal>"git"</literal> to the name - e.g.,
263 <literal>"pkgname-git-2014-09-23"</literal>.</para></listitem>
264
265 <listitem><para>Dashes in the package name should be preserved
266 in new variable names, rather than converted to underscores
267 (which was convention up to around 2013 and most names
268 still have underscores instead of dashes) — e.g.,
269 <varname>http-parser</varname> instead of
270 <varname>http_parser</varname>.</para></listitem>
271
272 <listitem><para>If there are multiple versions of a package, this
273 should be reflected in the variable names in
274 <filename>all-packages.nix</filename>,
275 e.g. <varname>json-c-0-9</varname> and <varname>json-c-0-11</varname>.
276 If there is an obvious “default” version, make an attribute like
277 <literal>json-c = json-c-0-9;</literal>.
278 See also <xref linkend="sec-versioning" /></para></listitem>
279
280</itemizedlist>
281
282</para>
283
284</section>
285
286
287<section xml:id="sec-organisation"><title>File naming and organisation</title>
288
289<para>Names of files and directories should be in lowercase, with
290dashes between words — not in camel case. For instance, it should be
291<filename>all-packages.nix</filename>, not
292<filename>allPackages.nix</filename> or
293<filename>AllPackages.nix</filename>.</para>
294
295<section xml:id="sec-hierarchy"><title>Hierarchy</title>
296
297<para>Each package should be stored in its own directory somewhere in
298the <filename>pkgs/</filename> tree, i.e. in
299<filename>pkgs/<replaceable>category</replaceable>/<replaceable>subcategory</replaceable>/<replaceable>...</replaceable>/<replaceable>pkgname</replaceable></filename>.
300Below are some rules for picking the right category for a package.
301Many packages fall under several categories; what matters is the
302<emphasis>primary</emphasis> purpose of a package. For example, the
303<literal>libxml2</literal> package builds both a library and some
304tools; but it’s a library foremost, so it goes under
305<filename>pkgs/development/libraries</filename>.</para>
306
307<para>When in doubt, consider refactoring the
308<filename>pkgs/</filename> tree, e.g. creating new categories or
309splitting up an existing category.</para>
310
311<variablelist>
312 <varlistentry>
313 <term>If it’s used to support <emphasis>software development</emphasis>:</term>
314 <listitem>
315 <variablelist>
316 <varlistentry>
317 <term>If it’s a <emphasis>library</emphasis> used by other packages:</term>
318 <listitem>
319 <para><filename>development/libraries</filename> (e.g. <filename>libxml2</filename>)</para>
320 </listitem>
321 </varlistentry>
322 <varlistentry>
323 <term>If it’s a <emphasis>compiler</emphasis>:</term>
324 <listitem>
325 <para><filename>development/compilers</filename> (e.g. <filename>gcc</filename>)</para>
326 </listitem>
327 </varlistentry>
328 <varlistentry>
329 <term>If it’s an <emphasis>interpreter</emphasis>:</term>
330 <listitem>
331 <para><filename>development/interpreters</filename> (e.g. <filename>guile</filename>)</para>
332 </listitem>
333 </varlistentry>
334 <varlistentry>
335 <term>If it’s a (set of) development <emphasis>tool(s)</emphasis>:</term>
336 <listitem>
337 <variablelist>
338 <varlistentry>
339 <term>If it’s a <emphasis>parser generator</emphasis> (including lexers):</term>
340 <listitem>
341 <para><filename>development/tools/parsing</filename> (e.g. <filename>bison</filename>, <filename>flex</filename>)</para>
342 </listitem>
343 </varlistentry>
344 <varlistentry>
345 <term>If it’s a <emphasis>build manager</emphasis>:</term>
346 <listitem>
347 <para><filename>development/tools/build-managers</filename> (e.g. <filename>gnumake</filename>)</para>
348 </listitem>
349 </varlistentry>
350 <varlistentry>
351 <term>Else:</term>
352 <listitem>
353 <para><filename>development/tools/misc</filename> (e.g. <filename>binutils</filename>)</para>
354 </listitem>
355 </varlistentry>
356 </variablelist>
357 </listitem>
358 </varlistentry>
359 <varlistentry>
360 <term>Else:</term>
361 <listitem>
362 <para><filename>development/misc</filename></para>
363 </listitem>
364 </varlistentry>
365 </variablelist>
366 </listitem>
367 </varlistentry>
368 <varlistentry>
369 <term>If it’s a (set of) <emphasis>tool(s)</emphasis>:</term>
370 <listitem>
371 <para>(A tool is a relatively small program, especially one intented
372 to be used non-interactively.)</para>
373 <variablelist>
374 <varlistentry>
375 <term>If it’s for <emphasis>networking</emphasis>:</term>
376 <listitem>
377 <para><filename>tools/networking</filename> (e.g. <filename>wget</filename>)</para>
378 </listitem>
379 </varlistentry>
380 <varlistentry>
381 <term>If it’s for <emphasis>text processing</emphasis>:</term>
382 <listitem>
383 <para><filename>tools/text</filename> (e.g. <filename>diffutils</filename>)</para>
384 </listitem>
385 </varlistentry>
386 <varlistentry>
387 <term>If it’s a <emphasis>system utility</emphasis>, i.e.,
388 something related or essential to the operation of a
389 system:</term>
390 <listitem>
391 <para><filename>tools/system</filename> (e.g. <filename>cron</filename>)</para>
392 </listitem>
393 </varlistentry>
394 <varlistentry>
395 <term>If it’s an <emphasis>archiver</emphasis> (which may
396 include a compression function):</term>
397 <listitem>
398 <para><filename>tools/archivers</filename> (e.g. <filename>zip</filename>, <filename>tar</filename>)</para>
399 </listitem>
400 </varlistentry>
401 <varlistentry>
402 <term>If it’s a <emphasis>compression</emphasis> program:</term>
403 <listitem>
404 <para><filename>tools/compression</filename> (e.g. <filename>gzip</filename>, <filename>bzip2</filename>)</para>
405 </listitem>
406 </varlistentry>
407 <varlistentry>
408 <term>If it’s a <emphasis>security</emphasis>-related program:</term>
409 <listitem>
410 <para><filename>tools/security</filename> (e.g. <filename>nmap</filename>, <filename>gnupg</filename>)</para>
411 </listitem>
412 </varlistentry>
413 <varlistentry>
414 <term>Else:</term>
415 <listitem>
416 <para><filename>tools/misc</filename></para>
417 </listitem>
418 </varlistentry>
419 </variablelist>
420 </listitem>
421 </varlistentry>
422 <varlistentry>
423 <term>If it’s a <emphasis>shell</emphasis>:</term>
424 <listitem>
425 <para><filename>shells</filename> (e.g. <filename>bash</filename>)</para>
426 </listitem>
427 </varlistentry>
428 <varlistentry>
429 <term>If it’s a <emphasis>server</emphasis>:</term>
430 <listitem>
431 <variablelist>
432 <varlistentry>
433 <term>If it’s a web server:</term>
434 <listitem>
435 <para><filename>servers/http</filename> (e.g. <filename>apache-httpd</filename>)</para>
436 </listitem>
437 </varlistentry>
438 <varlistentry>
439 <term>If it’s an implementation of the X Windowing System:</term>
440 <listitem>
441 <para><filename>servers/x11</filename> (e.g. <filename>xorg</filename> — this includes the client libraries and programs)</para>
442 </listitem>
443 </varlistentry>
444 <varlistentry>
445 <term>Else:</term>
446 <listitem>
447 <para><filename>servers/misc</filename></para>
448 </listitem>
449 </varlistentry>
450 </variablelist>
451 </listitem>
452 </varlistentry>
453 <varlistentry>
454 <term>If it’s a <emphasis>desktop environment</emphasis>:</term>
455 <listitem>
456 <para><filename>desktops</filename> (e.g. <filename>kde</filename>, <filename>gnome</filename>, <filename>enlightenment</filename>)</para>
457 </listitem>
458 </varlistentry>
459 <varlistentry>
460 <term>If it’s a <emphasis>window manager</emphasis>:</term>
461 <listitem>
462 <para><filename>applications/window-managers</filename> (e.g. <filename>awesome</filename>, <filename>compiz</filename>, <filename>stumpwm</filename>)</para>
463 </listitem>
464 </varlistentry>
465 <varlistentry>
466 <term>If it’s an <emphasis>application</emphasis>:</term>
467 <listitem>
468 <para>A (typically large) program with a distinct user
469 interface, primarily used interactively.</para>
470 <variablelist>
471 <varlistentry>
472 <term>If it’s a <emphasis>version management system</emphasis>:</term>
473 <listitem>
474 <para><filename>applications/version-management</filename> (e.g. <filename>subversion</filename>)</para>
475 </listitem>
476 </varlistentry>
477 <varlistentry>
478 <term>If it’s for <emphasis>video playback / editing</emphasis>:</term>
479 <listitem>
480 <para><filename>applications/video</filename> (e.g. <filename>vlc</filename>)</para>
481 </listitem>
482 </varlistentry>
483 <varlistentry>
484 <term>If it’s for <emphasis>graphics viewing / editing</emphasis>:</term>
485 <listitem>
486 <para><filename>applications/graphics</filename> (e.g. <filename>gimp</filename>)</para>
487 </listitem>
488 </varlistentry>
489 <varlistentry>
490 <term>If it’s for <emphasis>networking</emphasis>:</term>
491 <listitem>
492 <variablelist>
493 <varlistentry>
494 <term>If it’s a <emphasis>mailreader</emphasis>:</term>
495 <listitem>
496 <para><filename>applications/networking/mailreaders</filename> (e.g. <filename>thunderbird</filename>)</para>
497 </listitem>
498 </varlistentry>
499 <varlistentry>
500 <term>If it’s a <emphasis>newsreader</emphasis>:</term>
501 <listitem>
502 <para><filename>applications/networking/newsreaders</filename> (e.g. <filename>pan</filename>)</para>
503 </listitem>
504 </varlistentry>
505 <varlistentry>
506 <term>If it’s a <emphasis>web browser</emphasis>:</term>
507 <listitem>
508 <para><filename>applications/networking/browsers</filename> (e.g. <filename>firefox</filename>)</para>
509 </listitem>
510 </varlistentry>
511 <varlistentry>
512 <term>Else:</term>
513 <listitem>
514 <para><filename>applications/networking/misc</filename></para>
515 </listitem>
516 </varlistentry>
517 </variablelist>
518 </listitem>
519 </varlistentry>
520 <varlistentry>
521 <term>Else:</term>
522 <listitem>
523 <para><filename>applications/misc</filename></para>
524 </listitem>
525 </varlistentry>
526 </variablelist>
527 </listitem>
528 </varlistentry>
529 <varlistentry>
530 <term>If it’s <emphasis>data</emphasis> (i.e., does not have a
531 straight-forward executable semantics):</term>
532 <listitem>
533 <variablelist>
534 <varlistentry>
535 <term>If it’s a <emphasis>font</emphasis>:</term>
536 <listitem>
537 <para><filename>data/fonts</filename></para>
538 </listitem>
539 </varlistentry>
540 <varlistentry>
541 <term>If it’s related to <emphasis>SGML/XML processing</emphasis>:</term>
542 <listitem>
543 <variablelist>
544 <varlistentry>
545 <term>If it’s an <emphasis>XML DTD</emphasis>:</term>
546 <listitem>
547 <para><filename>data/sgml+xml/schemas/xml-dtd</filename> (e.g. <filename>docbook</filename>)</para>
548 </listitem>
549 </varlistentry>
550 <varlistentry>
551 <term>If it’s an <emphasis>XSLT stylesheet</emphasis>:</term>
552 <listitem>
553 <para>(Okay, these are executable...)</para>
554 <para><filename>data/sgml+xml/stylesheets/xslt</filename> (e.g. <filename>docbook-xsl</filename>)</para>
555 </listitem>
556 </varlistentry>
557 </variablelist>
558 </listitem>
559 </varlistentry>
560 </variablelist>
561 </listitem>
562 </varlistentry>
563 <varlistentry>
564 <term>If it’s a <emphasis>game</emphasis>:</term>
565 <listitem>
566 <para><filename>games</filename></para>
567 </listitem>
568 </varlistentry>
569 <varlistentry>
570 <term>Else:</term>
571 <listitem>
572 <para><filename>misc</filename></para>
573 </listitem>
574 </varlistentry>
575</variablelist>
576
577</section>
578
579<section xml:id="sec-versioning"><title>Versioning</title>
580
581<para>Because every version of a package in Nixpkgs creates a
582potential maintenance burden, old versions of a package should not be
583kept unless there is a good reason to do so. For instance, Nixpkgs
584contains several versions of GCC because other packages don’t build
585with the latest version of GCC. Other examples are having both the
586latest stable and latest pre-release version of a package, or to keep
587several major releases of an application that differ significantly in
588functionality.</para>
589
590<para>If there is only one version of a package, its Nix expression
591should be named <filename>e2fsprogs/default.nix</filename>. If there
592are multiple versions, this should be reflected in the filename,
593e.g. <filename>e2fsprogs/1.41.8.nix</filename> and
594<filename>e2fsprogs/1.41.9.nix</filename>. The version in the
595filename should leave out unnecessary detail. For instance, if we
596keep the latest Firefox 2.0.x and 3.5.x versions in Nixpkgs, they
597should be named <filename>firefox/2.0.nix</filename> and
598<filename>firefox/3.5.nix</filename>, respectively (which, at a given
599point, might contain versions <literal>2.0.0.20</literal> and
600<literal>3.5.4</literal>). If a version requires many auxiliary
601files, you can use a subdirectory for each version,
602e.g. <filename>firefox/2.0/default.nix</filename> and
603<filename>firefox/3.5/default.nix</filename>.</para>
604
605<para>All versions of a package <emphasis>must</emphasis> be included
606in <filename>all-packages.nix</filename> to make sure that they
607evaluate correctly.</para>
608
609</section>
610
611</section>
612<section xml:id="sec-sources"><title>Fetching Sources</title>
613 <para>There are multiple ways to fetch a package source in nixpkgs. The
614 general guidline is that you should package sources with a high degree of
615 availability. Right now there is only one fetcher which has mirroring
616 support and that is <literal>fetchurl</literal>. Note that you should also
617 prefer protocols which have a corresponding proxy environment variable.
618 </para>
619 <para>You can find many source fetch helpers in <literal>pkgs/build-support/fetch*</literal>.
620 </para>
621 <para>In the file <literal>pkgs/top-level/all-packages.nix</literal> you can
622 find fetch helpers, these have names on the form
623 <literal>fetchFrom*</literal>. The intention of these are to provide
624 snapshot fetches but using the same api as some of the version controlled
625 fetchers from <literal>pkgs/build-support/</literal>. As an example going
626 from bad to good:
627 <itemizedlist>
628 <listitem>
629 <para>Uses <literal>git://</literal> which won't be proxied.
630<programlisting>
631src = fetchgit {
632 url = "git://github.com/NixOS/nix.git";
633 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
634 sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
635}
636</programlisting>
637 </para>
638 </listitem>
639 <listitem>
640 <para>This is ok, but an archive fetch will still be faster.
641<programlisting>
642src = fetchgit {
643 url = "https://github.com/NixOS/nix.git";
644 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
645 sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
646}
647</programlisting>
648 </para>
649 </listitem>
650 <listitem>
651 <para>Fetches a snapshot archive and you get the rev you want.
652<programlisting>
653src = fetchFromGitHub {
654 owner = "NixOS";
655 repo = "nix";
656 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
657 sha256 = "04yri911rj9j19qqqn6m82266fl05pz98inasni0vxr1cf1gdgv9";
658}
659</programlisting>
660 </para>
661 </listitem>
662 </itemizedlist>
663 </para>
664</section>
665</chapter>