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.1rc2"</literal>.</para></listitem>
255
256 <listitem><para>If a package is not a release but a commit from a repository, then
257 the version part of the name <emphasis>must</emphasis> be the date of that
258 (fetched) commit. The date must be in <literal>"YYYY-MM-DD"</literal> format.
259 Also append <literal>"unstable"</literal> to the name - e.g.,
260 <literal>"pkgname-unstable-2014-09-23"</literal>.</para></listitem>
261
262 <listitem><para>Dashes in the package name should be preserved
263 in new variable names, rather than converted to underscores
264 (which was convention up to around 2013 and most names
265 still have underscores instead of dashes) — e.g.,
266 <varname>http-parser</varname> instead of
267 <varname>http_parser</varname>.</para></listitem>
268
269 <listitem><para>If there are multiple versions of a package, this
270 should be reflected in the variable names in
271 <filename>all-packages.nix</filename>,
272 e.g. <varname>json-c-0-9</varname> and <varname>json-c-0-11</varname>.
273 If there is an obvious “default” version, make an attribute like
274 <literal>json-c = json-c-0-9;</literal>.
275 See also <xref linkend="sec-versioning" /></para></listitem>
276
277</itemizedlist>
278
279</para>
280
281</section>
282
283
284<section xml:id="sec-organisation"><title>File naming and organisation</title>
285
286<para>Names of files and directories should be in lowercase, with
287dashes between words — not in camel case. For instance, it should be
288<filename>all-packages.nix</filename>, not
289<filename>allPackages.nix</filename> or
290<filename>AllPackages.nix</filename>.</para>
291
292<section xml:id="sec-hierarchy"><title>Hierarchy</title>
293
294<para>Each package should be stored in its own directory somewhere in
295the <filename>pkgs/</filename> tree, i.e. in
296<filename>pkgs/<replaceable>category</replaceable>/<replaceable>subcategory</replaceable>/<replaceable>...</replaceable>/<replaceable>pkgname</replaceable></filename>.
297Below are some rules for picking the right category for a package.
298Many packages fall under several categories; what matters is the
299<emphasis>primary</emphasis> purpose of a package. For example, the
300<literal>libxml2</literal> package builds both a library and some
301tools; but it’s a library foremost, so it goes under
302<filename>pkgs/development/libraries</filename>.</para>
303
304<para>When in doubt, consider refactoring the
305<filename>pkgs/</filename> tree, e.g. creating new categories or
306splitting up an existing category.</para>
307
308<variablelist>
309 <varlistentry>
310 <term>If it’s used to support <emphasis>software development</emphasis>:</term>
311 <listitem>
312 <variablelist>
313 <varlistentry>
314 <term>If it’s a <emphasis>library</emphasis> used by other packages:</term>
315 <listitem>
316 <para><filename>development/libraries</filename> (e.g. <filename>libxml2</filename>)</para>
317 </listitem>
318 </varlistentry>
319 <varlistentry>
320 <term>If it’s a <emphasis>compiler</emphasis>:</term>
321 <listitem>
322 <para><filename>development/compilers</filename> (e.g. <filename>gcc</filename>)</para>
323 </listitem>
324 </varlistentry>
325 <varlistentry>
326 <term>If it’s an <emphasis>interpreter</emphasis>:</term>
327 <listitem>
328 <para><filename>development/interpreters</filename> (e.g. <filename>guile</filename>)</para>
329 </listitem>
330 </varlistentry>
331 <varlistentry>
332 <term>If it’s a (set of) development <emphasis>tool(s)</emphasis>:</term>
333 <listitem>
334 <variablelist>
335 <varlistentry>
336 <term>If it’s a <emphasis>parser generator</emphasis> (including lexers):</term>
337 <listitem>
338 <para><filename>development/tools/parsing</filename> (e.g. <filename>bison</filename>, <filename>flex</filename>)</para>
339 </listitem>
340 </varlistentry>
341 <varlistentry>
342 <term>If it’s a <emphasis>build manager</emphasis>:</term>
343 <listitem>
344 <para><filename>development/tools/build-managers</filename> (e.g. <filename>gnumake</filename>)</para>
345 </listitem>
346 </varlistentry>
347 <varlistentry>
348 <term>Else:</term>
349 <listitem>
350 <para><filename>development/tools/misc</filename> (e.g. <filename>binutils</filename>)</para>
351 </listitem>
352 </varlistentry>
353 </variablelist>
354 </listitem>
355 </varlistentry>
356 <varlistentry>
357 <term>Else:</term>
358 <listitem>
359 <para><filename>development/misc</filename></para>
360 </listitem>
361 </varlistentry>
362 </variablelist>
363 </listitem>
364 </varlistentry>
365 <varlistentry>
366 <term>If it’s a (set of) <emphasis>tool(s)</emphasis>:</term>
367 <listitem>
368 <para>(A tool is a relatively small program, especially one intented
369 to be used non-interactively.)</para>
370 <variablelist>
371 <varlistentry>
372 <term>If it’s for <emphasis>networking</emphasis>:</term>
373 <listitem>
374 <para><filename>tools/networking</filename> (e.g. <filename>wget</filename>)</para>
375 </listitem>
376 </varlistentry>
377 <varlistentry>
378 <term>If it’s for <emphasis>text processing</emphasis>:</term>
379 <listitem>
380 <para><filename>tools/text</filename> (e.g. <filename>diffutils</filename>)</para>
381 </listitem>
382 </varlistentry>
383 <varlistentry>
384 <term>If it’s a <emphasis>system utility</emphasis>, i.e.,
385 something related or essential to the operation of a
386 system:</term>
387 <listitem>
388 <para><filename>tools/system</filename> (e.g. <filename>cron</filename>)</para>
389 </listitem>
390 </varlistentry>
391 <varlistentry>
392 <term>If it’s an <emphasis>archiver</emphasis> (which may
393 include a compression function):</term>
394 <listitem>
395 <para><filename>tools/archivers</filename> (e.g. <filename>zip</filename>, <filename>tar</filename>)</para>
396 </listitem>
397 </varlistentry>
398 <varlistentry>
399 <term>If it’s a <emphasis>compression</emphasis> program:</term>
400 <listitem>
401 <para><filename>tools/compression</filename> (e.g. <filename>gzip</filename>, <filename>bzip2</filename>)</para>
402 </listitem>
403 </varlistentry>
404 <varlistentry>
405 <term>If it’s a <emphasis>security</emphasis>-related program:</term>
406 <listitem>
407 <para><filename>tools/security</filename> (e.g. <filename>nmap</filename>, <filename>gnupg</filename>)</para>
408 </listitem>
409 </varlistentry>
410 <varlistentry>
411 <term>Else:</term>
412 <listitem>
413 <para><filename>tools/misc</filename></para>
414 </listitem>
415 </varlistentry>
416 </variablelist>
417 </listitem>
418 </varlistentry>
419 <varlistentry>
420 <term>If it’s a <emphasis>shell</emphasis>:</term>
421 <listitem>
422 <para><filename>shells</filename> (e.g. <filename>bash</filename>)</para>
423 </listitem>
424 </varlistentry>
425 <varlistentry>
426 <term>If it’s a <emphasis>server</emphasis>:</term>
427 <listitem>
428 <variablelist>
429 <varlistentry>
430 <term>If it’s a web server:</term>
431 <listitem>
432 <para><filename>servers/http</filename> (e.g. <filename>apache-httpd</filename>)</para>
433 </listitem>
434 </varlistentry>
435 <varlistentry>
436 <term>If it’s an implementation of the X Windowing System:</term>
437 <listitem>
438 <para><filename>servers/x11</filename> (e.g. <filename>xorg</filename> — this includes the client libraries and programs)</para>
439 </listitem>
440 </varlistentry>
441 <varlistentry>
442 <term>Else:</term>
443 <listitem>
444 <para><filename>servers/misc</filename></para>
445 </listitem>
446 </varlistentry>
447 </variablelist>
448 </listitem>
449 </varlistentry>
450 <varlistentry>
451 <term>If it’s a <emphasis>desktop environment</emphasis>:</term>
452 <listitem>
453 <para><filename>desktops</filename> (e.g. <filename>kde</filename>, <filename>gnome</filename>, <filename>enlightenment</filename>)</para>
454 </listitem>
455 </varlistentry>
456 <varlistentry>
457 <term>If it’s a <emphasis>window manager</emphasis>:</term>
458 <listitem>
459 <para><filename>applications/window-managers</filename> (e.g. <filename>awesome</filename>, <filename>compiz</filename>, <filename>stumpwm</filename>)</para>
460 </listitem>
461 </varlistentry>
462 <varlistentry>
463 <term>If it’s an <emphasis>application</emphasis>:</term>
464 <listitem>
465 <para>A (typically large) program with a distinct user
466 interface, primarily used interactively.</para>
467 <variablelist>
468 <varlistentry>
469 <term>If it’s a <emphasis>version management system</emphasis>:</term>
470 <listitem>
471 <para><filename>applications/version-management</filename> (e.g. <filename>subversion</filename>)</para>
472 </listitem>
473 </varlistentry>
474 <varlistentry>
475 <term>If it’s for <emphasis>video playback / editing</emphasis>:</term>
476 <listitem>
477 <para><filename>applications/video</filename> (e.g. <filename>vlc</filename>)</para>
478 </listitem>
479 </varlistentry>
480 <varlistentry>
481 <term>If it’s for <emphasis>graphics viewing / editing</emphasis>:</term>
482 <listitem>
483 <para><filename>applications/graphics</filename> (e.g. <filename>gimp</filename>)</para>
484 </listitem>
485 </varlistentry>
486 <varlistentry>
487 <term>If it’s for <emphasis>networking</emphasis>:</term>
488 <listitem>
489 <variablelist>
490 <varlistentry>
491 <term>If it’s a <emphasis>mailreader</emphasis>:</term>
492 <listitem>
493 <para><filename>applications/networking/mailreaders</filename> (e.g. <filename>thunderbird</filename>)</para>
494 </listitem>
495 </varlistentry>
496 <varlistentry>
497 <term>If it’s a <emphasis>newsreader</emphasis>:</term>
498 <listitem>
499 <para><filename>applications/networking/newsreaders</filename> (e.g. <filename>pan</filename>)</para>
500 </listitem>
501 </varlistentry>
502 <varlistentry>
503 <term>If it’s a <emphasis>web browser</emphasis>:</term>
504 <listitem>
505 <para><filename>applications/networking/browsers</filename> (e.g. <filename>firefox</filename>)</para>
506 </listitem>
507 </varlistentry>
508 <varlistentry>
509 <term>Else:</term>
510 <listitem>
511 <para><filename>applications/networking/misc</filename></para>
512 </listitem>
513 </varlistentry>
514 </variablelist>
515 </listitem>
516 </varlistentry>
517 <varlistentry>
518 <term>Else:</term>
519 <listitem>
520 <para><filename>applications/misc</filename></para>
521 </listitem>
522 </varlistentry>
523 </variablelist>
524 </listitem>
525 </varlistentry>
526 <varlistentry>
527 <term>If it’s <emphasis>data</emphasis> (i.e., does not have a
528 straight-forward executable semantics):</term>
529 <listitem>
530 <variablelist>
531 <varlistentry>
532 <term>If it’s a <emphasis>font</emphasis>:</term>
533 <listitem>
534 <para><filename>data/fonts</filename></para>
535 </listitem>
536 </varlistentry>
537 <varlistentry>
538 <term>If it’s related to <emphasis>SGML/XML processing</emphasis>:</term>
539 <listitem>
540 <variablelist>
541 <varlistentry>
542 <term>If it’s an <emphasis>XML DTD</emphasis>:</term>
543 <listitem>
544 <para><filename>data/sgml+xml/schemas/xml-dtd</filename> (e.g. <filename>docbook</filename>)</para>
545 </listitem>
546 </varlistentry>
547 <varlistentry>
548 <term>If it’s an <emphasis>XSLT stylesheet</emphasis>:</term>
549 <listitem>
550 <para>(Okay, these are executable...)</para>
551 <para><filename>data/sgml+xml/stylesheets/xslt</filename> (e.g. <filename>docbook-xsl</filename>)</para>
552 </listitem>
553 </varlistentry>
554 </variablelist>
555 </listitem>
556 </varlistentry>
557 </variablelist>
558 </listitem>
559 </varlistentry>
560 <varlistentry>
561 <term>If it’s a <emphasis>game</emphasis>:</term>
562 <listitem>
563 <para><filename>games</filename></para>
564 </listitem>
565 </varlistentry>
566 <varlistentry>
567 <term>Else:</term>
568 <listitem>
569 <para><filename>misc</filename></para>
570 </listitem>
571 </varlistentry>
572</variablelist>
573
574</section>
575
576<section xml:id="sec-versioning"><title>Versioning</title>
577
578<para>Because every version of a package in Nixpkgs creates a
579potential maintenance burden, old versions of a package should not be
580kept unless there is a good reason to do so. For instance, Nixpkgs
581contains several versions of GCC because other packages don’t build
582with the latest version of GCC. Other examples are having both the
583latest stable and latest pre-release version of a package, or to keep
584several major releases of an application that differ significantly in
585functionality.</para>
586
587<para>If there is only one version of a package, its Nix expression
588should be named <filename>e2fsprogs/default.nix</filename>. If there
589are multiple versions, this should be reflected in the filename,
590e.g. <filename>e2fsprogs/1.41.8.nix</filename> and
591<filename>e2fsprogs/1.41.9.nix</filename>. The version in the
592filename should leave out unnecessary detail. For instance, if we
593keep the latest Firefox 2.0.x and 3.5.x versions in Nixpkgs, they
594should be named <filename>firefox/2.0.nix</filename> and
595<filename>firefox/3.5.nix</filename>, respectively (which, at a given
596point, might contain versions <literal>2.0.0.20</literal> and
597<literal>3.5.4</literal>). If a version requires many auxiliary
598files, you can use a subdirectory for each version,
599e.g. <filename>firefox/2.0/default.nix</filename> and
600<filename>firefox/3.5/default.nix</filename>.</para>
601
602<para>All versions of a package <emphasis>must</emphasis> be included
603in <filename>all-packages.nix</filename> to make sure that they
604evaluate correctly.</para>
605
606</section>
607
608</section>
609<section xml:id="sec-sources"><title>Fetching Sources</title>
610 <para>There are multiple ways to fetch a package source in nixpkgs. The
611 general guidline is that you should package sources with a high degree of
612 availability. Right now there is only one fetcher which has mirroring
613 support and that is <literal>fetchurl</literal>. Note that you should also
614 prefer protocols which have a corresponding proxy environment variable.
615 </para>
616 <para>You can find many source fetch helpers in <literal>pkgs/build-support/fetch*</literal>.
617 </para>
618 <para>In the file <literal>pkgs/top-level/all-packages.nix</literal> you can
619 find fetch helpers, these have names on the form
620 <literal>fetchFrom*</literal>. The intention of these are to provide
621 snapshot fetches but using the same api as some of the version controlled
622 fetchers from <literal>pkgs/build-support/</literal>. As an example going
623 from bad to good:
624 <itemizedlist>
625 <listitem>
626 <para>Uses <literal>git://</literal> which won't be proxied.
627<programlisting>
628src = fetchgit {
629 url = "git://github.com/NixOS/nix.git";
630 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
631 sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
632}
633</programlisting>
634 </para>
635 </listitem>
636 <listitem>
637 <para>This is ok, but an archive fetch will still be faster.
638<programlisting>
639src = fetchgit {
640 url = "https://github.com/NixOS/nix.git";
641 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
642 sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
643}
644</programlisting>
645 </para>
646 </listitem>
647 <listitem>
648 <para>Fetches a snapshot archive and you get the rev you want.
649<programlisting>
650src = fetchFromGitHub {
651 owner = "NixOS";
652 repo = "nix";
653 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
654 sha256 = "04yri911rj9j19qqqn6m82266fl05pz98inasni0vxr1cf1gdgv9";
655}
656</programlisting>
657 </para>
658 </listitem>
659 </itemizedlist>
660 </para>
661</section>
662
663<section xml:id="sec-patches"><title>Patches</title>
664 <para>Only patches that are unique to <literal>nixpkgs</literal> should be
665 included in <literal>nixpkgs</literal> source.</para>
666 <para>Patches available online should be retrieved using
667 <literal>fetchpatch</literal>.</para>
668 <para>
669<programlisting>
670patches = [
671 (fetchpatch {
672 name = "fix-check-for-using-shared-freetype-lib.patch";
673 url = "http://git.ghostscript.com/?p=ghostpdl.git;a=patch;h=8f5d285";
674 sha256 = "1f0k043rng7f0rfl9hhb89qzvvksqmkrikmm38p61yfx51l325xr";
675 })
676];
677</programlisting>
678 </para>
679</section>
680</chapter>