1# Coding conventions {#chap-conventions} 2 3## Syntax {#sec-syntax} 4 5- Use 2 spaces of indentation per indentation level in Nix expressions, 4 spaces in shell scripts. 6 7- Do not use tab characters, i.e. configure your editor to use soft tabs. For instance, use `(setq-default indent-tabs-mode nil)` in Emacs. Everybody has different tab settings so it’s asking for trouble. 8 9- Use `lowerCamelCase` for variable names, not `UpperCamelCase`. Note, this rule does not apply to package attribute names, which instead follow the rules in <xref linkend="sec-package-naming"/>. 10 11- Function calls with attribute set arguments are written as 12 13 ```nix 14 foo { 15 arg = ...; 16 } 17 ``` 18 19 not 20 21 ```nix 22 foo 23 { 24 arg = ...; 25 } 26 ``` 27 28 Also fine is 29 30 ```nix 31 foo { arg = ...; } 32 ``` 33 34 if it's a short call. 35 36- In attribute sets or lists that span multiple lines, the attribute names or list elements should be aligned: 37 38 ```nix 39 # A long list. 40 list = [ 41 elem1 42 elem2 43 elem3 44 ]; 45 46 # A long attribute set. 47 attrs = { 48 attr1 = short_expr; 49 attr2 = 50 if true then big_expr else big_expr; 51 }; 52 53 # Combined 54 listOfAttrs = [ 55 { 56 attr1 = 3; 57 attr2 = "fff"; 58 } 59 { 60 attr1 = 5; 61 attr2 = "ggg"; 62 } 63 ]; 64 ``` 65 66- Short lists or attribute sets can be written on one line: 67 68 ```nix 69 # A short list. 70 list = [ elem1 elem2 elem3 ]; 71 72 # A short set. 73 attrs = { x = 1280; y = 1024; }; 74 ``` 75 76- Breaking in the middle of a function argument can give hard-to-read code, like 77 78 ```nix 79 someFunction { x = 1280; 80 y = 1024; } otherArg 81 yetAnotherArg 82 ``` 83 84 (especially if the argument is very large, spanning multiple lines). 85 86 Better: 87 88 ```nix 89 someFunction 90 { x = 1280; y = 1024; } 91 otherArg 92 yetAnotherArg 93 ``` 94 95 or 96 97 ```nix 98 let res = { x = 1280; y = 1024; }; 99 in someFunction res otherArg yetAnotherArg 100 ``` 101 102- The bodies of functions, asserts, and withs are not indented to prevent a lot of superfluous indentation levels, i.e. 103 104 ```nix 105 { arg1, arg2 }: 106 assert system == "i686-linux"; 107 stdenv.mkDerivation { ... 108 ``` 109 110 not 111 112 ```nix 113 { arg1, arg2 }: 114 assert system == "i686-linux"; 115 stdenv.mkDerivation { ... 116 ``` 117 118- Function formal arguments are written as: 119 120 ```nix 121 { arg1, arg2, arg3 }: 122 ``` 123 124 but if they don't fit on one line they're written as: 125 126 ```nix 127 { arg1, arg2, arg3 128 , arg4, ... 129 , # Some comment... 130 argN 131 }: 132 ``` 133 134- Functions should list their expected arguments as precisely as possible. That is, write 135 136 ```nix 137 { stdenv, fetchurl, perl }: ... 138 ``` 139 140 instead of 141 142 ```nix 143 args: with args; ... 144 ``` 145 146 or 147 148 ```nix 149 { stdenv, fetchurl, perl, ... }: ... 150 ``` 151 152 For functions that are truly generic in the number of arguments (such as wrappers around `mkDerivation`) that have some required arguments, you should write them using an `@`-pattern: 153 154 ```nix 155 { stdenv, doCoverageAnalysis ? false, ... } @ args: 156 157 stdenv.mkDerivation (args // { 158 ... if doCoverageAnalysis then "bla" else "" ... 159 }) 160 ``` 161 162 instead of 163 164 ```nix 165 args: 166 167 args.stdenv.mkDerivation (args // { 168 ... if args ? doCoverageAnalysis && args.doCoverageAnalysis then "bla" else "" ... 169 }) 170 ``` 171 172- Unnecessary string conversions should be avoided. Do 173 174 ```nix 175 rev = version; 176 ``` 177 178 instead of 179 180 ```nix 181 rev = "${version}"; 182 ``` 183 184- Arguments should be listed in the order they are used, with the exception of `lib`, which always goes first. 185 186- The top-level `lib` must be used in the master and 21.05 branch over its alias `stdenv.lib` as it now causes evaluation errors when aliases are disabled which is the case for ofborg. 187 `lib` is unrelated to `stdenv`, and so `stdenv.lib` should only be used as a convenience alias when developing locally to avoid having to modify the function inputs just to test something out. 188 189## Package naming {#sec-package-naming} 190 191The key words _must_, _must not_, _required_, _shall_, _shall not_, _should_, _should not_, _recommended_, _may_, and _optional_ in this section are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). Only _emphasized_ words are to be interpreted in this way. 192 193In Nixpkgs, there are generally three different names associated with a package: 194 195- The `name` attribute of the derivation (excluding the version part). This is what most users see, in particular when using `nix-env`. 196 197- The variable name used for the instantiated package in `all-packages.nix`, and when passing it as a dependency to other functions. Typically this is called the _package attribute name_. This is what Nix expression authors see. It can also be used when installing using `nix-env -iA`. 198 199- The filename for (the directory containing) the Nix expression. 200 201Most of the time, these are the same. For instance, the package `e2fsprogs` has a `name` attribute `"e2fsprogs-version"`, is bound to the variable name `e2fsprogs` in `all-packages.nix`, and the Nix expression is in `pkgs/os-specific/linux/e2fsprogs/default.nix`. 202 203There are a few naming guidelines: 204 205- The `name` attribute _should_ be identical to the upstream package name. 206 207- The `name` attribute _must not_ contain uppercase letters — e.g., `"mplayer-1.0rc2"` instead of `"MPlayer-1.0rc2"`. 208 209- The version part of the `name` attribute _must_ start with a digit (following a dash) — e.g., `"hello-0.3.1rc2"`. 210 211- If a package is not a release but a commit from a repository, then the version part of the name _must_ be the date of that (fetched) commit. The date _must_ be in `"YYYY-MM-DD"` format. Also append `"unstable"` to the name - e.g., `"pkgname-unstable-2014-09-23"`. 212 213- Dashes in the package name _should_ be preserved in new variable names, rather than converted to underscores or camel cased — e.g., `http-parser` instead of `http_parser` or `httpParser`. The hyphenated style is preferred in all three package names. 214 215- If there are multiple versions of a package, this _should_ be reflected in the variable names in `all-packages.nix`, e.g. `json-c-0-9` and `json-c-0-11`. If there is an obvious “default” version, make an attribute like `json-c = json-c-0-9;`. See also <xref linkend="sec-versioning" /> 216 217## File naming and organisation {#sec-organisation} 218 219Names of files and directories should be in lowercase, with dashes between words — not in camel case. For instance, it should be `all-packages.nix`, not `allPackages.nix` or `AllPackages.nix`. 220 221### Hierarchy {#sec-hierarchy} 222 223Each package should be stored in its own directory somewhere in the `pkgs/` tree, i.e. in `pkgs/category/subcategory/.../pkgname`. Below are some rules for picking the right category for a package. Many packages fall under several categories; what matters is the _primary_ purpose of a package. For example, the `libxml2` package builds both a library and some tools; but it’s a library foremost, so it goes under `pkgs/development/libraries`. 224 225When in doubt, consider refactoring the `pkgs/` tree, e.g. creating new categories or splitting up an existing category. 226 227**If it’s used to support _software development_:** 228 229- **If it’s a _library_ used by other packages:** 230 231 - `development/libraries` (e.g. `libxml2`) 232 233- **If it’s a _compiler_:** 234 235 - `development/compilers` (e.g. `gcc`) 236 237- **If it’s an _interpreter_:** 238 239 - `development/interpreters` (e.g. `guile`) 240 241- **If it’s a (set of) development _tool(s)_:** 242 243 - **If it’s a _parser generator_ (including lexers):** 244 245 - `development/tools/parsing` (e.g. `bison`, `flex`) 246 247 - **If it’s a _build manager_:** 248 249 - `development/tools/build-managers` (e.g. `gnumake`) 250 251 - **Else:** 252 253 - `development/tools/misc` (e.g. `binutils`) 254 255- **Else:** 256 257 - `development/misc` 258 259**If it’s a (set of) _tool(s)_:** 260 261(A tool is a relatively small program, especially one intended to be used non-interactively.) 262 263- **If it’s for _networking_:** 264 265 - `tools/networking` (e.g. `wget`) 266 267- **If it’s for _text processing_:** 268 269 - `tools/text` (e.g. `diffutils`) 270 271- **If it’s a _system utility_, i.e., something related or essential to the operation of a system:** 272 273 - `tools/system` (e.g. `cron`) 274 275- **If it’s an _archiver_ (which may include a compression function):** 276 277 - `tools/archivers` (e.g. `zip`, `tar`) 278 279- **If it’s a _compression_ program:** 280 281 - `tools/compression` (e.g. `gzip`, `bzip2`) 282 283- **If it’s a _security_-related program:** 284 285 - `tools/security` (e.g. `nmap`, `gnupg`) 286 287- **Else:** 288 289 - `tools/misc` 290 291**If it’s a _shell_:** 292 293- `shells` (e.g. `bash`) 294 295**If it’s a _server_:** 296 297- **If it’s a web server:** 298 299 - `servers/http` (e.g. `apache-httpd`) 300 301- **If it’s an implementation of the X Windowing System:** 302 303 - `servers/x11` (e.g. `xorg` — this includes the client libraries and programs) 304 305- **Else:** 306 307 - `servers/misc` 308 309**If it’s a _desktop environment_:** 310 311- `desktops` (e.g. `kde`, `gnome`, `enlightenment`) 312 313**If it’s a _window manager_:** 314 315- `applications/window-managers` (e.g. `awesome`, `stumpwm`) 316 317**If it’s an _application_:** 318 319A (typically large) program with a distinct user interface, primarily used interactively. 320 321- **If it’s a _version management system_:** 322 323 - `applications/version-management` (e.g. `subversion`) 324 325- **If it’s a _terminal emulator_:** 326 327 - `applications/terminal-emulators` (e.g. `alacritty` or `rxvt` or `termite`) 328 329- **If it’s for _video playback / editing_:** 330 331 - `applications/video` (e.g. `vlc`) 332 333- **If it’s for _graphics viewing / editing_:** 334 335 - `applications/graphics` (e.g. `gimp`) 336 337- **If it’s for _networking_:** 338 339 - **If it’s a _mailreader_:** 340 341 - `applications/networking/mailreaders` (e.g. `thunderbird`) 342 343 - **If it’s a _newsreader_:** 344 345 - `applications/networking/newsreaders` (e.g. `pan`) 346 347 - **If it’s a _web browser_:** 348 349 - `applications/networking/browsers` (e.g. `firefox`) 350 351 - **Else:** 352 353 - `applications/networking/misc` 354 355- **Else:** 356 357 - `applications/misc` 358 359**If it’s _data_ (i.e., does not have a straight-forward executable semantics):** 360 361- **If it’s a _font_:** 362 363 - `data/fonts` 364 365- **If it’s an _icon theme_:** 366 367 - `data/icons` 368 369- **If it’s related to _SGML/XML processing_:** 370 371 - **If it’s an _XML DTD_:** 372 373 - `data/sgml+xml/schemas/xml-dtd` (e.g. `docbook`) 374 375 - **If it’s an _XSLT stylesheet_:** 376 377 (Okay, these are executable...) 378 379 - `data/sgml+xml/stylesheets/xslt` (e.g. `docbook-xsl`) 380 381- **If it’s a _theme_ for a _desktop environment_, a _window manager_ or a _display manager_:** 382 383 - `data/themes` 384 385**If it’s a _game_:** 386 387- `games` 388 389**Else:** 390 391- `misc` 392 393### Versioning {#sec-versioning} 394 395Because every version of a package in Nixpkgs creates a potential maintenance burden, old versions of a package should not be kept unless there is a good reason to do so. For instance, Nixpkgs contains several versions of GCC because other packages don’t build with the latest version of GCC. Other examples are having both the latest stable and latest pre-release version of a package, or to keep several major releases of an application that differ significantly in functionality. 396 397If there is only one version of a package, its Nix expression should be named `e2fsprogs/default.nix`. If there are multiple versions, this should be reflected in the filename, e.g. `e2fsprogs/1.41.8.nix` and `e2fsprogs/1.41.9.nix`. The version in the filename should leave out unnecessary detail. For instance, if we keep the latest Firefox 2.0.x and 3.5.x versions in Nixpkgs, they should be named `firefox/2.0.nix` and `firefox/3.5.nix`, respectively (which, at a given point, might contain versions `2.0.0.20` and `3.5.4`). If a version requires many auxiliary files, you can use a subdirectory for each version, e.g. `firefox/2.0/default.nix` and `firefox/3.5/default.nix`. 398 399All versions of a package _must_ be included in `all-packages.nix` to make sure that they evaluate correctly. 400 401## Fetching Sources {#sec-sources} 402 403There are multiple ways to fetch a package source in nixpkgs. The general guideline is that you should package reproducible sources with a high degree of availability. Right now there is only one fetcher which has mirroring support and that is `fetchurl`. Note that you should also prefer protocols which have a corresponding proxy environment variable. 404 405You can find many source fetch helpers in `pkgs/build-support/fetch*`. 406 407In the file `pkgs/top-level/all-packages.nix` you can find fetch helpers, these have names on the form `fetchFrom*`. The intention of these are to provide snapshot fetches but using the same api as some of the version controlled fetchers from `pkgs/build-support/`. As an example going from bad to good: 408 409- Bad: Uses `git://` which won't be proxied. 410 411 ```nix 412 src = fetchgit { 413 url = "git://github.com/NixOS/nix.git"; 414 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae"; 415 sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg"; 416 } 417 ``` 418 419- Better: This is ok, but an archive fetch will still be faster. 420 421 ```nix 422 src = fetchgit { 423 url = "https://github.com/NixOS/nix.git"; 424 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae"; 425 sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg"; 426 } 427 ``` 428 429- Best: Fetches a snapshot archive and you get the rev you want. 430 431 ```nix 432 src = fetchFromGitHub { 433 owner = "NixOS"; 434 repo = "nix"; 435 rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae"; 436 sha256 = "1i2yxndxb6yc9l6c99pypbd92lfq5aac4klq7y2v93c9qvx2cgpc"; 437 } 438 ``` 439 440 Find the value to put as `sha256` by running `nix run -f '<nixpkgs>' nix-prefetch-github -c nix-prefetch-github --rev 1f795f9f44607cc5bec70d1300150bfefcef2aae NixOS nix` or `nix-prefetch-url --unpack https://github.com/NixOS/nix/archive/1f795f9f44607cc5bec70d1300150bfefcef2aae.tar.gz`. 441 442## Obtaining source hash {#sec-source-hashes} 443 444Preferred source hash type is sha256. There are several ways to get it. 445 4461. Prefetch URL (with `nix-prefetch-XXX URL`, where `XXX` is one of `url`, `git`, `hg`, `cvs`, `bzr`, `svn`). Hash is printed to stdout. 447 4482. Prefetch by package source (with `nix-prefetch-url '<nixpkgs>' -A PACKAGE.src`, where `PACKAGE` is package attribute name). Hash is printed to stdout. 449 450 This works well when you've upgraded existing package version and want to find out new hash, but is useless if package can't be accessed by attribute or package has multiple sources (`.srcs`, architecture-dependent sources, etc). 451 4523. Upstream provided hash: use it when upstream provides `sha256` or `sha512` (when upstream provides `md5`, don't use it, compute `sha256` instead). 453 454 A little nuance is that `nix-prefetch-*` tools produce hash encoded with `base32`, but upstream usually provides hexadecimal (`base16`) encoding. Fetchers understand both formats. Nixpkgs does not standardize on any one format. 455 456 You can convert between formats with nix-hash, for example: 457 458 ```ShellSession 459 $ nix-hash --type sha256 --to-base32 HASH 460 ``` 461 4624. Extracting hash from local source tarball can be done with `sha256sum`. Use `nix-prefetch-url file:///path/to/tarball` if you want base32 hash. 463 4645. Fake hash: set fake hash in package expression, perform build and extract correct hash from error Nix prints. 465 466 For package updates it is enough to change one symbol to make hash fake. For new packages, you can use `lib.fakeSha256`, `lib.fakeSha512` or any other fake hash. 467 468 This is last resort method when reconstructing source URL is non-trivial and `nix-prefetch-url -A` isn't applicable (for example, [one of `kodi` dependencies](https://github.com/NixOS/nixpkgs/blob/d2ab091dd308b99e4912b805a5eb088dd536adb9/pkgs/applications/video/kodi/default.nix#L73")). The easiest way then would be replace hash with a fake one and rebuild. Nix build will fail and error message will contain desired hash. 469 470::: warning 471This method has security problems. Check below for details. 472::: 473 474### Obtaining hashes securely {#sec-source-hashes-security} 475 476Let's say Man-in-the-Middle (MITM) sits close to your network. Then instead of fetching source you can fetch malware, and instead of source hash you get hash of malware. Here are security considerations for this scenario: 477 478- `http://` URLs are not secure to prefetch hash from; 479 480- hashes from upstream (in method 3) should be obtained via secure protocol; 481 482- `https://` URLs are secure in methods 1, 2, 3; 483 484- `https://` URLs are not secure in method 5. When obtaining hashes with fake hash method, TLS checks are disabled. So refetch source hash from several different networks to exclude MITM scenario. Alternatively, use fake hash method to make Nix error, but instead of extracting hash from error, extract `https://` URL and prefetch it with method 1. 485 486## Patches {#sec-patches} 487 488Patches available online should be retrieved using `fetchpatch`. 489 490```nix 491patches = [ 492 (fetchpatch { 493 name = "fix-check-for-using-shared-freetype-lib.patch"; 494 url = "http://git.ghostscript.com/?p=ghostpdl.git;a=patch;h=8f5d285"; 495 sha256 = "1f0k043rng7f0rfl9hhb89qzvvksqmkrikmm38p61yfx51l325xr"; 496 }) 497]; 498``` 499 500Otherwise, you can add a `.patch` file to the `nixpkgs` repository. In the interest of keeping our maintenance burden to a minimum, only patches that are unique to `nixpkgs` should be added in this way. 501 502```nix 503patches = [ ./0001-changes.patch ]; 504``` 505 506If you do need to do create this sort of patch file, one way to do so is with git: 507 5081. Move to the root directory of the source code you're patching. 509 510 ```ShellSession 511 $ cd the/program/source 512 ``` 513 5142. If a git repository is not already present, create one and stage all of the source files. 515 516 ```ShellSession 517 $ git init 518 $ git add . 519 ``` 520 5213. Edit some files to make whatever changes need to be included in the patch. 522 5234. Use git to create a diff, and pipe the output to a patch file: 524 525 ```ShellSession 526 $ git diff > nixpkgs/pkgs/the/package/0001-changes.patch 527 ``` 528 529## Package tests {#sec-package-tests} 530 531Tests are important to ensure quality and make reviews and automatic updates easy. 532 533Nix package tests are a lightweight alternative to [NixOS module tests](https://nixos.org/manual/nixos/stable/#sec-nixos-tests). They can be used to create simple integration tests for packages while the module tests are used to test services or programs with a graphical user interface on a NixOS VM. Unittests that are included in the source code of a package should be executed in the `checkPhase`. 534 535### Writing package tests {#ssec-package-tests-writing} 536 537This is an example using the `phoronix-test-suite` package with the current best practices. 538 539Add the tests in `passthru.tests` to the package definition like this: 540 541```nix 542{ stdenv, lib, fetchurl, callPackage }: 543 544stdenv.mkDerivation { 545546 547 passthru.tests = { 548 simple-execution = callPackage ./tests.nix { }; 549 }; 550 551 meta = { … }; 552} 553``` 554 555Create `tests.nix` in the package directory: 556 557```nix 558{ runCommand, phoronix-test-suite }: 559 560let 561 inherit (phoronix-test-suite) pname version; 562in 563 564runCommand "${pname}-tests" { meta.timeout = 3; } 565 '' 566 # automatic initial setup to prevent interactive questions 567 ${phoronix-test-suite}/bin/phoronix-test-suite enterprise-setup >/dev/null 568 # get version of installed program and compare with package version 569 if [[ `${phoronix-test-suite}/bin/phoronix-test-suite version` != *"${version}"* ]]; then 570 echo "Error: program version does not match package version" 571 exit 1 572 fi 573 # run dummy command 574 ${phoronix-test-suite}/bin/phoronix-test-suite dummy_module.dummy-command >/dev/null 575 # needed for Nix to register the command as successful 576 touch $out 577 '' 578``` 579 580### Running package tests {#ssec-package-tests-running} 581 582You can run these tests with: 583 584```ShellSession 585$ cd path/to/nixpkgs 586$ nix-build -A phoronix-test-suite.tests 587``` 588 589### Examples of package tests {#ssec-package-tests-examples} 590 591Here are examples of package tests: 592 593- [Jasmin compile test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/jasmin/test-assemble-hello-world/default.nix) 594- [Lobster compile test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/lobster/test-can-run-hello-world.nix) 595- [Spacy annotation test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/spacy/annotation-test/default.nix) 596- [Libtorch test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/science/math/libtorch/test/default.nix) 597- [Multiple tests for nanopb](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/nanopb/default.nix)