at 16.09-beta 23 kB view raw
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 &amp;&amp; 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>