Merge branch 'master' into hyper-haskell

This commit is contained in:
Matthew Justin Bauer 2018-03-22 11:29:45 -05:00 committed by GitHub
commit 68f6915083
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10916 changed files with 358238 additions and 283726 deletions

16
.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
**/deps.nix linguist-generated
**/node-packages.nix linguist-generated
pkgs/applications/editors/emacs-modes/*-generated.nix linguist-generated
pkgs/development/r-modules/*-packages.nix linguist-generated
pkgs/development/haskell-modules/hackage-packages.nix linguist-generated
pkgs/development/beam-modules/hex-packages.nix linguist-generated
doc/** linguist-documentation
doc/default.nix linguist-documentation=false
nixos/doc/** linguist-documentation
nixos/doc/default.nix linguist-documentation=false
nixos/modules/module-list.nix merge=union
pkgs/top-level/all-packages.nix merge=union

92
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,92 @@
# CODEOWNERS file
#
# This file is used to describe who owns what in this repository. This file does not
# replace `meta.maintainers` but is instead used for other things than derivations
# and modules, like documentation, package sets, and other assets.
#
# For documentation on this file, see https://help.github.com/articles/about-codeowners/
# Mentioned users will get code review requests.
# This file
/.github/CODEOWNERS @edolstra
# Libraries
/lib @edolstra @nbp
/lib/systems @nbp @ericson2314
# Nixpkgs Internals
/default.nix @nbp
/pkgs/top-level/default.nix @nbp @Ericson2314
/pkgs/top-level/impure.nix @nbp @Ericson2314
/pkgs/top-level/stage.nix @nbp @Ericson2314
/pkgs/stdenv
/pkgs/build-support/cc-wrapper @Ericson2314 @orivej
/pkgs/build-support/bintools-wrapper @Ericson2314 @orivej
/pkgs/build-support/setup-hooks @Ericson2314
# NixOS Internals
/nixos/default.nix @nbp
/nixos/lib/from-env.nix @nbp
/nixos/lib/eval-config.nix @nbp
/nixos/doc/manual/configuration/abstractions.xml @nbp
/nixos/doc/manual/configuration/config-file.xml @nbp
/nixos/doc/manual/configuration/config-syntax.xml @nbp
/nixos/doc/manual/configuration/modularity.xml @nbp
/nixos/doc/manual/development/assertions.xml @nbp
/nixos/doc/manual/development/meta-attributes.xml @nbp
/nixos/doc/manual/development/option-declarations.xml @nbp
/nixos/doc/manual/development/option-def.xml @nbp
/nixos/doc/manual/development/option-types.xml @nbp
/nixos/doc/manual/development/replace-modules.xml @nbp
/nixos/doc/manual/development/writing-modules.xml @nbp
/nixos/doc/manual/man-nixos-option.xml @nbp
/nixos/modules/installer/tools/nixos-option.sh @nbp
# Python-related code and docs
/pkgs/top-level/python-packages.nix @FRidh
/pkgs/development/interpreters/python @FRidh
/pkgs/development/python-modules @FRidh
/doc/languages-frameworks/python.md @FRidh
# Haskell
/pkgs/development/compilers/ghc @peti
/pkgs/development/haskell-modules @peti
/pkgs/development/haskell-modules/default.nix @peti
/pkgs/development/haskell-modules/generic-builder.nix @peti
/pkgs/development/haskell-modules/hoogle.nix @peti
# R
/pkgs/applications/science/math/R @peti
/pkgs/development/r-modules @peti
# Ruby
/pkgs/development/interpreters/ruby @zimbatm
/pkgs/development/ruby-modules @zimbatm
# Darwin-related
/pkgs/stdenv/darwin @NixOS/darwin-maintainers
/pkgs/os-specific/darwin @NixOS/darwin-maintainers
# Beam-related (Erlang, Elixir, LFE, etc)
/pkgs/development/beam-modules @gleber
/pkgs/development/interpreters/erlang @gleber
/pkgs/development/interpreters/lfe @gleber
/pkgs/development/interpreters/elixir @gleber
/pkgs/development/tools/build-managers/rebar @gleber
/pkgs/development/tools/build-managers/rebar3 @gleber
/pkgs/development/tools/erlang @gleber
# Jetbrains
/pkgs/applications/editors/jetbrains @edwtjo
# Eclipse
/pkgs/applications/editors/eclipse @rycee
# https://github.com/NixOS/nixpkgs/issues/31401
/lib/licenses.nix @ghost
# Qt / KDE
/pkgs/applications/kde @ttuegel
/pkgs/desktops/plasma-5 @ttuegel
/pkgs/development/libraries/kde-frameworks @ttuegel
/pkgs/development/libraries/qt-5 @ttuegel

View File

@ -12,31 +12,34 @@ under the terms of [COPYING](../COPYING), which is an MIT-like license.
## Submitting changes
* Format the commits in the following way:
* Format the commit messages in the following way:
```
(pkg-name | nixos/<module>): (from -> to | init at version | refactor | etc)
(Motivation for change. Additional information.)
```
Examples:
* nginx: init at 2.0.1
* firefox: 3.0 -> 3.1.1
* firefox: 54.0.1 -> 55.0
* nixos/hydra: add bazBaz option
Dual baz behavior is needed to do foo.
* nixos/nginx: refactor config generation
The old config generation system used impure shell scripts and could break in specific circumstances (see #1234).
* `meta.description` should:
* Be capitalized
* Not start with the package name
* Not have a dot at the end
* Be capitalized.
* Not start with the package name.
* Not have a period at the end.
* `meta.license` must be set and fit the upstream license.
* If there is no upstream license, `meta.license` should default to `stdenv.lib.licenses.unfree`.
* `meta.maintainers` must be set.
See the nixpkgs manual for more details on how to [Submit changes to nixpkgs](https://nixos.org/nixpkgs/manual/#chap-submitting-changes).
See the nixpkgs manual for more details on [standard meta-attributes](https://nixos.org/nixpkgs/manual/#sec-standard-meta-attributes) and on how to [submit changes to nixpkgs](https://nixos.org/nixpkgs/manual/#chap-submitting-changes).
## Writing good commit messages

View File

@ -8,7 +8,5 @@
## Technical details
* System: (NixOS: `nixos-version`, Ubuntu/Fedora: `lsb_release -a`, ...)
* Nix version: (run `nix-env --version`)
* Nixpkgs version: (run `nix-instantiate --eval '<nixpkgs>' -A lib.nixpkgsVersion`)
* Sandboxing enabled: (run `grep build-use-sandbox /etc/nix/nix.conf`)
Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the
results.

View File

@ -3,16 +3,13 @@
###### Things done
Please check what applies. Note that these are not hard requirements but mereley serve as information for reviewers.
<!-- Please check what applies. Note that these are not hard requirements but merely serve as information for reviewers. -->
- [ ] Tested using sandboxing
([nix.useSandbox](http://nixos.org/nixos/manual/options.html#opt-nix.useSandbox) on NixOS,
or option `build-use-sandbox` in [`nix.conf`](http://nixos.org/nix/manual/#sec-conf-file)
on non-NixOS)
- [ ] Tested using sandboxing ([nix.useSandbox](http://nixos.org/nixos/manual/options.html#opt-nix.useSandbox) on NixOS, or option `build-use-sandbox` in [`nix.conf`](http://nixos.org/nix/manual/#sec-conf-file) on non-NixOS)
- Built on platform(s)
- [ ] NixOS
- [ ] macOS
- [ ] Linux
- [ ] other Linux distributions
- [ ] Tested via one or more NixOS test(s) if existing and applicable for the change (look inside [nixos/tests](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests))
- [ ] Tested compilation of all pkgs that depend on this change using `nix-shell -p nox --run "nox-review wip"`
- [ ] Tested execution of all binary files (usually in `./result/bin/`)

View File

@ -1,14 +0,0 @@
{
"userBlacklist": [
"civodul",
"jhasse",
"shlevy",
"bbenoist"
],
"alwaysNotifyForPaths": [
{ "name": "FRidh", "files": ["pkgs/top-level/python-packages.nix", "pkgs/development/interpreters/python/*", "pkgs/development/python-modules/*" ] },
{ "name": "LnL7", "files": ["pkgs/stdenv/darwin/*", "pkgs/os-specific/darwin/*"] },
{ "name": "copumpkin", "files": ["pkgs/stdenv/darwin/*", "pkgs/os-specific/darwin/apple-source-releases/*"] }
],
"fileBlacklist": ["pkgs/top-level/all-packages.nix"]
}

View File

@ -1,29 +0,0 @@
language: nix
sudo: true
# 'sudo: false' == containers that start fast, but only get 4G ram;
# 'sudo: true' == VMs that start slow, but with 8G
# ..as per: https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments
# Nixpkgs PR tests OOM with 4G: https://github.com/NixOS/nixpkgs/issues/24200
matrix:
include:
- os: linux
sudo: required
script:
- ./maintainers/scripts/travis-nox-review-pr.sh nixpkgs-verify nixpkgs-manual nixpkgs-tarball nixpkgs-unstable
- ./maintainers/scripts/travis-nox-review-pr.sh nixos-options nixos-manual
- os: linux
sudo: required
dist: trusty
before_script:
- sudo mount -o remount,exec,size=2G,mode=755 /run/user
script: ./maintainers/scripts/travis-nox-review-pr.sh nox pr
- os: osx
osx_image: xcode7.3
script: ./maintainers/scripts/travis-nox-review-pr.sh nox pr
env:
global:
- GITHUB_TOKEN=5edaaf1017f691ed34e7f80878f8f5fbd071603f
notifications:
email: false

View File

@ -1 +1 @@
17.09
18.09

View File

@ -1,4 +1,4 @@
Copyright (c) 2003-2017 Eelco Dolstra and the Nixpkgs/NixOS contributors
Copyright (c) 2003-2018 Eelco Dolstra and the Nixpkgs/NixOS contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -23,9 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Note: the license above does not apply to the packages built by the
Nix Packages collection, merely to the package descriptions (i.e., Nix
expressions, build scripts, etc.). Also, the license does not apply
to some of the binaries used for bootstrapping Nixpkgs (e.g.,
pkgs/stdenv/linux/tools/bash). It also might not apply to patches
expressions, build scripts, etc.). It also might not apply to patches
included in Nixpkgs, which may be derivative works of the packages to
which they apply. The aforementioned artifacts are all covered by the
licenses of the respective packages.

View File

@ -1,10 +1,9 @@
[<img src="http://nixos.org/logo/nixos-hires.png" width="500px" alt="logo" />](https://nixos.org/nixos)
[<img src="https://nixos.org/logo/nixos-hires.png" width="500px" alt="logo" />](https://nixos.org/nixos)
[![Build Status](https://travis-ci.org/NixOS/nixpkgs.svg?branch=master)](https://travis-ci.org/NixOS/nixpkgs)
[![Code Triagers Badge](https://www.codetriage.com/nixos/nixpkgs/badges/users.svg)](https://www.codetriage.com/nixos/nixpkgs)
Nixpkgs is a collection of packages for the [Nix](https://nixos.org/nix/) package
manager. It is periodically built and tested by the [hydra](http://hydra.nixos.org/)
manager. It is periodically built and tested by the [Hydra](https://hydra.nixos.org/)
build daemon as so-called channels. To get channel information via git, add
[nixpkgs-channels](https://github.com/NixOS/nixpkgs-channels.git) as a remote:
@ -13,28 +12,28 @@ build daemon as so-called channels. To get channel information via git, add
```
For stability and maximum binary package support, it is recommended to maintain
custom changes on top of one of the channels, e.g. `nixos-17.03` for the latest
custom changes on top of one of the channels, e.g. `nixos-17.09` for the latest
release and `nixos-unstable` for the latest successful build of master:
```
% git remote update channels
% git rebase channels/nixos-17.03
% git rebase channels/nixos-17.09
```
For pull-requests, please rebase onto nixpkgs `master`.
[NixOS](https://nixos.org/nixos/) linux distribution source code is located inside
[NixOS](https://nixos.org/nixos/) Linux distribution source code is located inside
`nixos/` folder.
* [NixOS installation instructions](https://nixos.org/nixos/manual/#ch-installation)
* [Documentation (Nix Expression Language chapter)](https://nixos.org/nix/manual/#ch-expression-language)
* [Manual (How to write packages for Nix)](https://nixos.org/nixpkgs/manual/)
* [Manual (NixOS)](https://nixos.org/nixos/manual/)
* [Nix Wiki](https://nixos.org/wiki/) (deprecated, see milestone ["Move the Wiki!"](https://github.com/NixOS/nixpkgs/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Move+the+wiki%21%22))
* [Community maintained wiki](https://nixos.wiki/)
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Continuous package builds for 17.03 release](https://hydra.nixos.org/jobset/nixos/release-17.03)
* [Continuous package builds for 17.09 release](https://hydra.nixos.org/jobset/nixos/release-17.09)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for 17.03 release](https://hydra.nixos.org/job/nixos/release-17.03/tested#tabs-constituents)
* [Tests for 17.09 release](https://hydra.nixos.org/job/nixos/release-17.09/tested#tabs-constituents)
Communication:

View File

@ -18,9 +18,9 @@
tab settings so its asking for trouble.</para></listitem>
<listitem><para>Use <literal>lowerCamelCase</literal> for variable
names, not <literal>UpperCamelCase</literal>. TODO: naming of
attributes in
<filename>all-packages.nix</filename>?</para></listitem>
names, not <literal>UpperCamelCase</literal>. Note, this rule does
not apply to package attribute names, which instead follow the rules
in <xref linkend="sec-package-naming"/>.</para></listitem>
<listitem><para>Function calls with attribute set arguments are
written as
@ -220,9 +220,10 @@ args.stdenv.mkDerivation (args // {
<listitem><para>The variable name used for the instantiated package
in <filename>all-packages.nix</filename>, and when passing it as a
dependency to other functions. This is what Nix expression authors
see. It can also be used when installing using <command>nix-env
-iA</command>.</para></listitem>
dependency to other functions. Typically this is called the
<emphasis>package attribute name</emphasis>. This is what Nix
expression authors see. It can also be used when installing using
<command>nix-env -iA</command>.</para></listitem>
<listitem><para>The filename for (the directory containing) the Nix
expression.</para></listitem>
@ -254,17 +255,17 @@ bound to the variable name <varname>e2fsprogs</varname> in
dash) — e.g., <literal>"hello-0.3.1rc2"</literal>.</para></listitem>
<listitem><para>If a package is not a release but a commit from a repository, then
the version part of the name <emphasis>must</emphasis> be the date of that
the version part of the name <emphasis>must</emphasis> be the date of that
(fetched) commit. The date must be in <literal>"YYYY-MM-DD"</literal> format.
Also append <literal>"unstable"</literal> to the name - e.g.,
<literal>"pkgname-unstable-2014-09-23"</literal>.</para></listitem>
<listitem><para>Dashes in the package name should be preserved
in new variable names, rather than converted to underscores
(which was convention up to around 2013 and most names
still have underscores instead of dashes) — e.g.,
<varname>http-parser</varname> instead of
<varname>http_parser</varname>.</para></listitem>
<listitem><para>Dashes in the package name should be preserved in
new variable names, rather than converted to underscores or camel
cased — e.g., <varname>http-parser</varname> instead of
<varname>http_parser</varname> or <varname>httpParser</varname>. The
hyphenated style is preferred in all three package
names.</para></listitem>
<listitem><para>If there are multiple versions of a package, this
should be reflected in the variable names in
@ -365,7 +366,7 @@ splitting up an existing category.</para>
<varlistentry>
<term>If its a (set of) <emphasis>tool(s)</emphasis>:</term>
<listitem>
<para>(A tool is a relatively small program, especially one intented
<para>(A tool is a relatively small program, especially one intended
to be used non-interactively.)</para>
<variablelist>
<varlistentry>
@ -456,7 +457,7 @@ splitting up an existing category.</para>
<varlistentry>
<term>If its a <emphasis>window manager</emphasis>:</term>
<listitem>
<para><filename>applications/window-managers</filename> (e.g. <filename>awesome</filename>, <filename>compiz</filename>, <filename>stumpwm</filename>)</para>
<para><filename>applications/window-managers</filename> (e.g. <filename>awesome</filename>, <filename>stumpwm</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
@ -608,7 +609,7 @@ evaluate correctly.</para>
</section>
<section xml:id="sec-sources"><title>Fetching Sources</title>
<para>There are multiple ways to fetch a package source in nixpkgs. The
general guidline is that you should package sources with a high degree of
general guideline is that you should package sources with a high degree of
availability. Right now there is only one fetcher which has mirroring
support and that is <literal>fetchurl</literal>. Note that you should also
prefer protocols which have a corresponding proxy environment variable.
@ -661,9 +662,7 @@ src = fetchFromGitHub {
</section>
<section xml:id="sec-patches"><title>Patches</title>
<para>Only patches that are unique to <literal>nixpkgs</literal> should be
included in <literal>nixpkgs</literal> source.</para>
<para>Patches available online should be retrieved using
<para>Patches available online should be retrieved using
<literal>fetchpatch</literal>.</para>
<para>
<programlisting>
@ -676,5 +675,30 @@ patches = [
];
</programlisting>
</para>
<para>Otherwise, you can add a <literal>.patch</literal> file to the
<literal>nixpkgs</literal> repository. In the interest of keeping our
maintenance burden to a minimum, only patches that are unique
to <literal>nixpkgs</literal> should be added in this way.</para>
<para><programlisting>
patches = [ ./0001-changes.patch ];
</programlisting></para>
<para>If you do need to do create this sort of patch file,
one way to do so is with git:
<orderedlist>
<listitem><para>Move to the root directory of the source code
you're patching.<screen>
$ cd the/program/source</screen></para></listitem>
<listitem><para>If a git repository is not already present,
create one and stage all of the source files.<screen>
$ git init
$ git add .</screen></para></listitem>
<listitem><para>Edit some files to make whatever changes need
to be included in the patch.</para></listitem>
<listitem><para>Use git to create a diff, and pipe the output
to a patch file:<screen>
$ git diff > nixpkgs/pkgs/the/package/0001-changes.patch</screen>
</para></listitem>
</orderedlist></para>
</section>
</chapter>

View File

@ -55,6 +55,10 @@ configuration file located at
</programlisting>
</para>
<para>Note that we are not able to test or build unfree software on Hydra
due to policy. Most unfree licenses prohibit us from either executing or
distributing the software.</para>
<section xml:id="sec-allow-broken">
<title>Installing broken packages</title>

View File

@ -11,7 +11,7 @@
For example, a typical use of cross compilation is to compile programs for embedded devices.
These devices often don't have the computing power and memory to compile their own programs.
One might think that cross-compilation is a fairly niche concern, but there are advantages to being rigorous about distinguishing build-time vs run-time environments even when one is developing and deploying on the same machine.
Nixpkgs is increasingly adopting this opinion in that packages should be written with cross-compilation in mind, and nixpkgs should evaluate in a similar way (by minimizing cross-compilation-specific special cases) whether or not one is cross-compiling.
Nixpkgs is increasingly adopting the opinion that packages should be written with cross-compilation in mind, and nixpkgs should evaluate in a similar way (by minimizing cross-compilation-specific special cases) whether or not one is cross-compiling.
</para>
<para>
@ -30,11 +30,11 @@
<section>
<title>Platform parameters</title>
<para>
The three GNU Autoconf platforms, <wordasword>build</wordasword>, <wordasword>host</wordasword>, and <wordasword>target</wordasword>, are historically the result of much confusion.
<link xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html" /> clears this up somewhat but there is more to be said.
An important advice to get out the way is, unless you are packaging a compiler or other build tool, just worry about the build and host platforms.
Dealing with just two platforms usually better matches people's preconceptions, and in this case is completely correct.
Nixpkgs follows the <link xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html">common historical convention of GNU autoconf</link> of distinguishing between 3 types of platform: <wordasword>build</wordasword>, <wordasword>host</wordasword>, and <wordasword>target</wordasword>.
In summary, <wordasword>build</wordasword> is the platform on which a package is being built, <wordasword>host</wordasword> is the platform on which it is to run. The third attribute, <wordasword>target</wordasword>, is relevant only for certain specific compilers and build tools.
</para>
<para>
In Nixpkgs, these three platforms are defined as attribute sets under the names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>, and <literal>targetPlatform</literal>.
All three are always defined as attributes in the standard environment, and at the top level. That means one can get at them just like a dependency in a function that is imported with <literal>callPackage</literal>:
@ -52,7 +52,7 @@
<varlistentry>
<term><varname>hostPlatform</varname></term>
<listitem><para>
The "host platform" is the platform on which a package is run.
The "host platform" is the platform on which a package will be run.
This is the simplest platform to understand, but also the one with the worst name.
</para></listitem>
</varlistentry>
@ -60,22 +60,24 @@
<term><varname>targetPlatform</varname></term>
<listitem>
<para>
The "target platform" is black sheep.
The other two intrinsically apply to all compiled software—or any build process with a notion of "build-time" followed by "run-time".
The target platform only applies to programming tools, and even then only is a good for for some of them.
Briefly, GCC, Binutils, GHC, and certain other tools are written in such a way such that a single build can only compile code for a single platform.
Thus, when building them, one must think ahead about which platforms they wish to use the tool to produce machine code for, and build binaries for each.
The "target platform" attribute is, unlike the other two attributes, not actually fundamental to the process of building software.
Instead, it is only relevant for compatibility with building certain specific compilers and build tools.
It can be safely ignored for all other packages.
</para>
<para>
There is no fundamental need to think about the target ahead of time like this.
LLVM, for example, was designed from the beginning with cross-compilation in mind, and so a normal LLVM binary will support every architecture that LLVM supports.
If the tool supports modular or pluggable backends, one might imagine specifying a <emphasis>set</emphasis> of target platforms / backends one wishes to support, rather than a single one.
The build process of certain compilers is written in such a way that the compiler resulting from a single build can itself only produce binaries for a single platform.
The task specifying this single "target platform" is thus pushed to build time of the compiler.
The root cause of this mistake is often that the compiler (which will be run on the host) and the the standard library/runtime (which will be run on the target) are built by a single build process.
</para>
<para>
The biggest reason for mess, if there is one, is that many compilers have the bad habit a build process that builds the compiler and standard library/runtime together.
Then the specifying target platform is essential, because it determines the host platform of the standard library/runtime.
Nixpkgs tries to avoid this where possible too, but still, because the concept of a target platform is so ingrained now in Autoconf and other tools, it is best to support it as is.
Tools like LLVM that don't need up-front target platforms can safely ignore it like normal packages, and it will do no harm.
There is no fundamental need to think about a single target ahead of time like this.
If the tool supports modular or pluggable backends, both the need to specify the target at build time and the constraint of having only a single target disappear.
An example of such a tool is LLVM.
</para>
<para>
Although the existance of a "target platfom" is arguably a historical mistake, it is a common one: examples of tools that suffer from it are GCC, Binutils, GHC and Autoconf.
Nixpkgs tries to avoid sharing in the mistake where possible.
Still, because the concept of a target platform is so ingrained, it is best to support it as is.
</para>
</listitem>
</varlistentry>
@ -155,14 +157,22 @@
<section>
<title>Specifying Dependencies</title>
<para>
As mentioned in the introduction to this chapter, one can think about a build time vs run time distinction whether cross-compiling or not.
In the case of cross-compilation, this corresponds with whether a derivation running on the native or foreign platform is produced.
An interesting thing to think about is how this corresponds with the three Autoconf platforms.
In the run-time case, the depending and depended-on package simply have matching build, host, and target platforms.
But in the build-time case, one can imagine "sliding" the platforms one over.
The depended-on package's host and target platforms (respectively) become the depending package's build and host platforms.
This is the most important guiding principle behind cross-compilation with Nixpkgs, and will be called the <wordasword>sliding window principle</wordasword>.
In this section we explore the relationship between both runtime and buildtime dependencies and the 3 Autoconf platforms.
</para>
<para>
A runtime dependency between 2 packages implies that between them both the host and target platforms match.
This is directly implied by the meaning of "host platform" and "runtime dependency":
The package dependency exists while both packages are running on a single host platform.
</para>
<para>
A build time dependency, however, implies a shift in platforms between the depending package and the depended-on package.
The meaning of a build time dependency is that to build the depending package we need to be able to run the depended-on's package.
The depending package's build platform is therefore equal to the depended-on package's host platform.
Analogously, the depending package's host platform is equal to the depended-on package's target platform.
</para>
<para>
In this manner, given the 3 platforms for one package, we can determine the three platforms for all its transitive dependencies.
This is the most important guiding principle behind cross-compilation with Nixpkgs, and will be called the <wordasword>sliding window principle</wordasword>.
</para>
<para>
Some examples will probably make this clearer.
@ -177,19 +187,58 @@
How does this work in practice? Nixpkgs is now structured so that build-time dependencies are taken from <varname>buildPackages</varname>, whereas run-time dependencies are taken from the top level attribute set.
For example, <varname>buildPackages.gcc</varname> should be used at build time, while <varname>gcc</varname> should be used at run time.
Now, for most of Nixpkgs's history, there was no <varname>buildPackages</varname>, and most packages have not been refactored to use it explicitly.
Instead, one can use the four attributes used for specifying dependencies as documented in <xref linkend="ssec-stdenv-attributes"/>.
Instead, one can use the six (<emphasis>gasp</emphasis>) attributes used for specifying dependencies as documented in <xref linkend="ssec-stdenv-dependencies"/>.
We "splice" together the run-time and build-time package sets with <varname>callPackage</varname>, and then <varname>mkDerivation</varname> for each of four attributes pulls the right derivation out.
This splicing can be skipped when not cross compiling as the package sets are the same, but is a bit slow for cross compiling.
Because of this, a best-of-both-worlds solution is in the works with no splicing or explicit access of <varname>buildPackages</varname> needed.
For now, feel free to use either method.
</para>
<note><para>
There is also a "backlink" <varname>__targetPackages</varname>, yielding a package set whose <varname>buildPackages</varname> is the current package set.
There is also a "backlink" <varname>targetPackages</varname>, yielding a package set whose <varname>buildPackages</varname> is the current package set.
This is a hack, though, to accommodate compilers with lousy build systems.
Please do not use this unless you are absolutely sure you are packaging such a compiler and there is no other way.
</para></note>
</section>
<section>
<title>Cross packagaing cookbook</title>
<para>
Some frequently problems when packaging for cross compilation are good to just spell and answer.
Ideally the information above is exhaustive, so this section cannot provide any new information,
but its ludicrous and cruel to expect everyone to spend effort working through the interaction of many features just to figure out the same answer to the same common problem.
Feel free to add to this list!
</para>
<qandaset>
<qandaentry>
<question><para>
What if my package's build system needs to build a C program to be run under the build environment?
</para></question>
<answer><para>
<programlisting>depsBuildBuild = [ buildPackages.stdenv.cc ];</programlisting>
Add it to your <function>mkDerivation</function> invocation.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
My package fails to find <command>ar</command>.
</para></question>
<answer><para>
Many packages assume that an unprefixed <command>ar</command> is available, but Nix doesn't provide one.
It only provides a prefixed one, just as it only does for all the other binutils programs.
It may be necessary to patch the package to fix the build system to use a prefixed `ar`.
</para></answer>
</qandaentry>
<qandaentry>
<question><para>
My package's testsuite needs to run host platform code.
</para></question>
<answer><para>
<programlisting>doCheck = stdenv.hostPlatform != stdenv.buildPlatfrom;</programlisting>
Add it to your <function>mkDerivation</function> invocation.
</para></answer>
</qandaentry>
</qandaset>
</section>
</section>
<!--============================================================-->
@ -204,8 +253,19 @@
or also with <varname>crossSystem</varname>, in which case packages run on the latter, but all building happens on the former.
Both parameters take the same schema as the 3 (build, host, and target) platforms defined in the previous section.
As mentioned above, <literal>lib.systems.examples</literal> has some platforms which are used as arguments for these parameters in practice.
You can use them programmatically, or on the command line like <command>nix-build &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).systems.examples.fooBarBaz'</command>.
You can use them programmatically, or on the command line: <programlisting>
nix-build &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).systems.examples.fooBarBaz' -A whatever</programlisting>
</para>
<note>
<para>
Eventually we would like to make these platform examples an unnecessary convenience so that <programlisting>
nix-build &lt;nixpkgs&gt; --arg crossSystem.config '&lt;arch&gt;-&lt;os&gt;-&lt;vendor&gt;-&lt;abi&gt;' -A whatever</programlisting>
works in the vast majority of cases.
The problem today is dependencies on other sorts of configuration which aren't given proper defaults.
We rely on the examples to crudely to set those configuration parameters in some vaguely sane manner on the users behalf.
Issue <link xlink:href="https://github.com/NixOS/nixpkgs/issues/34274">#34274</link> tracks this inconvenience along with its root cause in crufty configuration options.
</para>
</note>
<para>
While one is free to pass both parameters in full, there's a lot of logic to fill in missing fields.
As discussed in the previous section, only one of <varname>system</varname>, <varname>config</varname>, and <varname>parsed</varname> is needed to infer the other two.

View File

@ -23,11 +23,12 @@ pkgs.stdenv.mkDerivation {
buildCommand = let toDocbook = { useChapters ? false, inputFile, outputFile }:
let
extraHeader = ''xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" '';
extraHeader = lib.optionalString (!useChapters)
''xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" '';
in ''
{
pandoc '${inputFile}' -w docbook ${lib.optionalString useChapters "--top-level-division=chapter"} \
--smart \
pandoc '${inputFile}' -w docbook+smart ${lib.optionalString useChapters "--top-level-division=chapter"} \
-f markdown+smart \
| sed -e 's|<ulink url=|<link xlink:href=|' \
-e 's|</ulink>|</link>|' \
-e 's|<sect. id=|<section xml:id=|' \
@ -48,6 +49,10 @@ pkgs.stdenv.mkDerivation {
outputFile = "introduction.xml";
useChapters = true;
}
+ toDocbook {
inputFile = ./shell.md;
outputFile = "shell.xml";
}
+ toDocbook {
inputFile = ./languages-frameworks/python.md;
outputFile = "./languages-frameworks/python.xml";
@ -76,6 +81,10 @@ pkgs.stdenv.mkDerivation {
inputFile = ./languages-frameworks/vim.md;
outputFile = "./languages-frameworks/vim.xml";
}
+ toDocbook {
inputFile = ./languages-frameworks/emscripten.md;
outputFile = "./languages-frameworks/emscripten.xml";
}
+ ''
echo ${lib.nixpkgsVersion} > .version

View File

@ -358,8 +358,8 @@
<para>
<varname>pkgs.dockerTools</varname> is a set of functions for creating and
manipulating Docker images according to the
<link xlink:href="https://github.com/docker/docker/blob/master/image/spec/v1.md#docker-image-specification-v100">
Docker Image Specification v1.0.0
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#docker-image-specification-v120">
Docker Image Specification v1.2.0
</link>. Docker itself is not used to perform any of the operations done by these
functions.
</para>
@ -493,8 +493,8 @@
<varname>config</varname> is used to specify the configuration of the
containers that will be started off the built image in Docker.
The available options are listed in the
<link xlink:href="https://github.com/docker/docker/blob/master/image/spec/v1.md#container-runconfig-field-descriptions">
Docker Image Specification v1.0.0
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0
</link>.
</para>
</callout>

View File

@ -48,6 +48,4 @@ The binaries are made available via a [binary cache](https://cache.nixos.org).
The current Nix expressions of the channels are available in the
[`nixpkgs-channels`](https://github.com/NixOS/nixpkgs-channels) repository,
which has branches corresponding to the available channels. There is also the
[Nixpkgs Monitor](http://monitor.nixos.org) which keeps track of updates
and security vulnerabilities.
which has branches corresponding to the available channels.

View File

@ -11,31 +11,53 @@
in the Coq derivation.
</para>
<para>
Some libraries require OCaml and sometimes also Camlp5. The exact
versions that were used to build Coq are saved in the
Some libraries require OCaml and sometimes also Camlp5 or findlib.
The exact versions that were used to build Coq are saved in the
<literal>coq.ocaml</literal> and <literal>coq.camlp5</literal>
attributes.
and <literal>coq.findlib</literal> attributes.
</para>
<para>
Coq libraries may be compatible with some specific versions of Coq only.
The <literal>compatibleCoqVersions</literal> attribute is used to
precisely select those versions of Coq that are compatible with this
derivation.
</para>
<para>
Here is a simple package example. It is a pure Coq library, thus it
only depends on Coq. Its <literal>makefile</literal> has been
generated using <literal>coq_makefile</literal> so we only have to
depends on Coq. It builds on the Mathematical Components library, thus it
also takes <literal>mathcomp</literal> as <literal>buildInputs</literal>.
Its <literal>Makefile</literal> has been generated using
<literal>coq_makefile</literal> so we only have to
set the <literal>$COQLIB</literal> variable at install time.
</para>
<programlisting>
{stdenv, fetchurl, coq}:
stdenv.mkDerivation {
src = fetchurl {
url = http://coq.inria.fr/pylons/contribs/files/Karatsuba/v8.4/Karatsuba.tar.gz;
sha256 = "0ymfpv4v49k4fm63nq6gcl1hbnnxrvjjp7yzc4973n49b853c5b1";
{ stdenv, fetchFromGitHub, coq, mathcomp }:
stdenv.mkDerivation rec {
name = "coq${coq.coq-version}-multinomials-${version}";
version = "1.0";
src = fetchFromGitHub {
owner = "math-comp";
repo = "multinomials";
rev = version;
sha256 = "1qmbxp1h81cy3imh627pznmng0kvv37k4hrwi2faa101s6bcx55m";
};
name = "coq-karatsuba";
buildInputs = [ coq ];
propagatedBuildInputs = [ mathcomp ];
installFlags = "COQLIB=$(out)/lib/coq/${coq.coq-version}/";
meta = {
description = "A Coq/SSReflect Library for Monoidal Rings and Multinomials";
inherit (src.meta) homepage;
license = stdenv.lib.licenses.cecill-b;
inherit (coq.meta) platforms;
};
passthru = {
compatibleCoqVersions = v: builtins.elem v [ "8.5" "8.6" "8.7" ];
};
}
</programlisting>
</section>

View File

@ -0,0 +1,185 @@
# User's Guide to Emscripten in Nixpkgs
[Emscripten](https://github.com/kripken/emscripten): An LLVM-to-JavaScript Compiler
This section of the manual covers how to use `emscripten` in nixpkgs.
Minimal requirements:
* nix
* nixpkgs
Modes of use of `emscripten`:
* **Imperative usage** (on the command line):
If you want to work with `emcc`, `emconfigure` and `emmake` as you are used to from Ubuntu and similar distributions you can use these commands:
* `nix-env -i emscripten`
* `nix-shell -p emscripten`
* **Declarative usage**:
This mode is far more power full since this makes use of `nix` for dependency management of emscripten libraries and targets by using the `mkDerivation` which is implemented by `pkgs.emscriptenStdenv` and `pkgs.buildEmscriptenPackage`. The source for the packages is in `pkgs/top-level/emscripten-packages.nix` and the abstraction behind it in `pkgs/development/em-modules/generic/default.nix`.
* build and install all packages:
* `nix-env -iA emscriptenPackages`
* dev-shell for zlib implementation hacking:
* `nix-shell -A emscriptenPackages.zlib`
## Imperative usage
A few things to note:
* `export EMCC_DEBUG=2` is nice for debugging
* `~/.emscripten`, the build artifact cache sometimes creates issues and needs to be removed from time to time
## Declarative usage
Let's see two different examples from `pkgs/top-level/emscripten-packages.nix`:
* `pkgs.zlib.override`
* `pkgs.buildEmscriptenPackage`
Both are interesting concepts.
A special requirement of the `pkgs.buildEmscriptenPackage` is the `doCheck = true` is a default meaning that each emscriptenPackage requires a `checkPhase` implemented.
* Use `export EMCC_DEBUG=2` from within a emscriptenPackage's `phase` to get more detailed debug output what is going wrong.
* ~/.emscripten cache is requiring us to set `HOME=$TMPDIR` in individual phases. This makes compilation slower but also makes it more deterministic.
### Usage 1: pkgs.zlib.override
This example uses `zlib` from nixpkgs but instead of compiling **C** to **ELF** it compiles **C** to **JS** since we were using `pkgs.zlib.override` and changed stdenv to `pkgs.emscriptenStdenv`. A few adaptions and hacks were set in place to make it working. One advantage is that when `pkgs.zlib` is updated, it will automatically update this package as well. However, this can also be the downside...
See the `zlib` example:
zlib = (pkgs.zlib.override {
stdenv = pkgs.emscriptenStdenv;
}).overrideDerivation
(old: rec {
buildInputs = old.buildInputs ++ [ pkgconfig ];
# we need to reset this setting!
NIX_CFLAGS_COMPILE="";
configurePhase = ''
# FIXME: Some tests require writing at $HOME
HOME=$TMPDIR
runHook preConfigure
#export EMCC_DEBUG=2
emconfigure ./configure --prefix=$out --shared
runHook postConfigure
'';
dontStrip = true;
outputs = [ "out" ];
buildPhase = ''
emmake make
'';
installPhase = ''
emmake make install
'';
checkPhase = ''
echo "================= testing zlib using node ================="
echo "Compiling a custom test"
set -x
emcc -O2 -s EMULATE_FUNCTION_POINTER_CASTS=1 test/example.c -DZ_SOLO \
libz.so.${old.version} -I . -o example.js
echo "Using node to execute the test"
${pkgs.nodejs}/bin/node ./example.js
set +x
if [ $? -ne 0 ]; then
echo "test failed for some reason"
exit 1;
else
echo "it seems to work! very good."
fi
echo "================= /testing zlib using node ================="
'';
postPatch = pkgs.stdenv.lib.optionalString pkgs.stdenv.isDarwin ''
substituteInPlace configure \
--replace '/usr/bin/libtool' 'ar' \
--replace 'AR="libtool"' 'AR="ar"' \
--replace 'ARFLAGS="-o"' 'ARFLAGS="-r"'
'';
});
### Usage 2: pkgs.buildEmscriptenPackage
This `xmlmirror` example features a emscriptenPackage which is defined completely from this context and no `pkgs.zlib.override` is used.
xmlmirror = pkgs.buildEmscriptenPackage rec {
name = "xmlmirror";
buildInputs = [ pkgconfig autoconf automake libtool gnumake libxml2 nodejs openjdk json_c ];
nativeBuildInputs = [ pkgconfig zlib ];
src = pkgs.fetchgit {
url = "https://gitlab.com/odfplugfest/xmlmirror.git";
rev = "4fd7e86f7c9526b8f4c1733e5c8b45175860a8fd";
sha256 = "1jasdqnbdnb83wbcnyrp32f36w3xwhwp0wq8lwwmhqagxrij1r4b";
};
configurePhase = ''
rm -f fastXmlLint.js*
# a fix for ERROR:root:For asm.js, TOTAL_MEMORY must be a multiple of 16MB, was 234217728
# https://gitlab.com/odfplugfest/xmlmirror/issues/8
sed -e "s/TOTAL_MEMORY=234217728/TOTAL_MEMORY=268435456/g" -i Makefile.emEnv
# https://github.com/kripken/emscripten/issues/6344
# https://gitlab.com/odfplugfest/xmlmirror/issues/9
sed -e "s/\$(JSONC_LDFLAGS) \$(ZLIB_LDFLAGS) \$(LIBXML20_LDFLAGS)/\$(JSONC_LDFLAGS) \$(LIBXML20_LDFLAGS) \$(ZLIB_LDFLAGS) /g" -i Makefile.emEnv
# https://gitlab.com/odfplugfest/xmlmirror/issues/11
sed -e "s/-o fastXmlLint.js/-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]' -o fastXmlLint.js/g" -i Makefile.emEnv
'';
buildPhase = ''
HOME=$TMPDIR
make -f Makefile.emEnv
'';
outputs = [ "out" "doc" ];
installPhase = ''
mkdir -p $out/share
mkdir -p $doc/share/${name}
cp Demo* $out/share
cp -R codemirror-5.12 $out/share
cp fastXmlLint.js* $out/share
cp *.xsd $out/share
cp *.js $out/share
cp *.xhtml $out/share
cp *.html $out/share
cp *.json $out/share
cp *.rng $out/share
cp README.md $doc/share/${name}
'';
checkPhase = ''
'';
};
### Declarative debugging
Use `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz` and from there you can go trough the individual steps. This makes it easy to build a good `unit test` or list the files of the project.
1. `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz`
2. `cd /tmp/`
3. `unpackPhase`
4. cd libz-1.2.3
5. `configurePhase`
6. `buildPhase`
7. ... happy hacking...
## Summary
Using this toolchain makes it easy to leverage `nix` from NixOS, MacOSX or even Windows (WSL+ubuntu+nix). This toolchain is reproducible, behaves like the rest of the packages from nixpkgs and contains a set of well working examples to learn and adapt from.
If in trouble, ask the maintainers.

View File

@ -48,7 +48,7 @@ trouble with packages like `3dmodels` and `4Blocks`, because these names are
invalid identifiers in the Nix language. The issue of how to deal with these
rare corner cases is currently unresolved.)
Haskell packages who's Nix name (second column) begins with a `haskell-` prefix
Haskell packages whose Nix name (second column) begins with a `haskell-` prefix
are packages that provide a library whereas packages without that prefix
provide just executables. Libraries may provide executables too, though: the
package `haskell-pandoc`, for example, installs both a library and an
@ -334,14 +334,10 @@ navigate there.
Finally, you can run
```shell
hoogle server -p 8080
hoogle server -p 8080 --local
```
and navigate to http://localhost:8080/ for your own local
[Hoogle](https://www.haskell.org/hoogle/). Note, however, that Firefox and
possibly other browsers disallow navigation from `http:` to `file:` URIs for
security reasons, which might be quite an inconvenience. See [this
page](http://kb.mozillazine.org/Links_to_local_pages_do_not_work) for
workarounds.
[Hoogle](https://www.haskell.org/hoogle/).
### How to build a Haskell project using Stack
@ -581,8 +577,8 @@ nix-shell "<nixpkgs>" -A haskellPackages.bar.env
Every Haskell package set takes a function called `overrides` that you can use
to manipulate the package as much as you please. One useful application of this
feature is to replace the default `mkDerivation` function with one that enables
library profiling for all packages. To accomplish that, add configure the
following snippet in your `~/.config/nixpkgs/config.nix` file:
library profiling for all packages. To accomplish that add the following
snippet to your `~/.config/nixpkgs/config.nix` file:
```nix
{
packageOverrides = super: let self = super.pkgs; in
@ -693,9 +689,7 @@ might be necessary to purge the local caches that store data from those
machines to disable these binary channels for the duration of the previous
command, i.e. by running:
```shell
rm /nix/var/nix/binary-cache-v3.sqlite
rm /nix/var/nix/manifests/*
rm /nix/var/nix/channel-cache/*
rm ~/.cache/nix/binary-cache*.sqlite
```
### Builds on Darwin fail with `math.h` not found
@ -777,14 +771,14 @@ to find out the store path of the system's zlib library. Now, you can
stack --extra-lib-dirs=/nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8/lib build
```
Typically, you'll need `--extra-include-dirs` as well. It's possible
to add those flag to the project's `stack.yaml` or your user's
global `~/.stack/global/stack.yaml` file so that you don't have to
specify them manually every time. But again, you're likely better off
using Stack's Nix support instead.
Typically, you'll need `--extra-include-dirs` as well. It's possible
to add those flag to the project's `stack.yaml` or your user's
global `~/.stack/global/stack.yaml` file so that you don't have to
specify them manually every time. But again, you're likely better off
using Stack's Nix support instead.
The same thing applies to `cabal configure`, of course, if you're
building with `cabal-install` instead of Stack.
The same thing applies to `cabal configure`, of course, if you're
building with `cabal-install` instead of Stack.
### Creating statically linked binaries
@ -827,7 +821,7 @@ the work to be licensed" under the terms of the LGPL (including for free).
The LGPL licensing for GMP is a problem for the overall licensing of binary
programs compiled with GHC because most distributions (and builds) of GHC use
static libraries. (Dynamic libraries are currently distributed only for OS X.)
static libraries. (Dynamic libraries are currently distributed only for macOS.)
The LGPL licensing situation may be worse: even though
[The Glasgow Haskell Compiler License](https://www.haskell.org/ghc/license)
is essentially a "free software" license (BSD3), according to
@ -867,6 +861,67 @@ use the following to get the `scientific` package build with `integer-simple`:
nix-build -A haskell.packages.integer-simple.ghc802.scientific
```
### Quality assurance
The `haskell.lib` library includes a number of functions for checking for
various imperfections in Haskell packages. It's useful to apply these functions
to your own Haskell packages and integrate that in a Continuous Integration
server like [hydra](https://nixos.org/hydra/) to assure your packages maintain a
minimum level of quality. This section discusses some of these functions.
#### failOnAllWarnings
Applying `haskell.lib.failOnAllWarnings` to a Haskell package enables the
`-Wall` and `-Werror` GHC options to turn all warnings into build failures.
#### buildStrictly
Applying `haskell.lib.buildStrictly` to a Haskell package calls
`failOnAllWarnings` on the given package to turn all warnings into build
failures. Additionally the source of your package is gotten from first invoking
`cabal sdist` to ensure all needed files are listed in the Cabal file.
#### checkUnusedPackages
Applying `haskell.lib.checkUnusedPackages` to a Haskell package invokes
the [packunused](http://hackage.haskell.org/package/packunused) tool on the
package. `packunused` complains when it finds packages listed as build-depends
in the Cabal file which are redundant. For example:
```
$ nix-build -E 'let pkgs = import <nixpkgs> {}; in pkgs.haskell.lib.checkUnusedPackages {} pkgs.haskellPackages.scientific'
these derivations will be built:
/nix/store/3lc51cxj2j57y3zfpq5i69qbzjpvyci1-scientific-0.3.5.1.drv
...
detected package components
~~~~~~~~~~~~~~~~~~~~~~~~~~~
- library
- testsuite(s): test-scientific
- benchmark(s): bench-scientific*
(component names suffixed with '*' are not configured to be built)
library
~~~~~~~
The following package dependencies seem redundant:
- ghc-prim-0.5.0.0
testsuite(test-scientific)
~~~~~~~~~~~~~~~~~~~~~~~~~~
no redundant packages dependencies found
builder for /nix/store/3lc51cxj2j57y3zfpq5i69qbzjpvyci1-scientific-0.3.5.1.drv failed with exit code 1
error: build of /nix/store/3lc51cxj2j57y3zfpq5i69qbzjpvyci1-scientific-0.3.5.1.drv failed
```
As you can see, `packunused` finds out that although the testsuite component has
no redundant dependencies the library component of `scientific-0.3.5.1` depends
on `ghc-prim` which is unused in the library.
## Other resources
- The Youtube video [Nix Loves Haskell](https://www.youtube.com/watch?v=BsBhi_r-OeE)

View File

@ -30,6 +30,7 @@ such as Perl or Haskell. These are described in this chapter.</para>
<xi:include href="rust.xml" />
<xi:include href="texlive.xml" />
<xi:include href="vim.xml" />
<xi:include href="emscripten.xml" />
</chapter>

View File

@ -177,5 +177,19 @@ you need it.</para>
</section>
<section xml:id="ssec-perl-cross-compilation"><title>Cross-compiling modules</title>
<para>Nixpkgs has experimental support for cross-compiling Perl
modules. In many cases, it will just work out of the box, even for
modules with native extensions. Sometimes, however, the Makefile.PL
for a module may (indirectly) import a native module. In that case,
you will need to make a stub for that module that will satisfy the
Makefile.PL and install it into
<filename>lib/perl5/site_perl/cross_perl/${perl.version}</filename>.
See the <varname>postInstall</varname> for <varname>DBI</varname> for
an example.</para>
</section>
</section>

View File

@ -2,115 +2,203 @@
## User Guide
Several versions of Python are available on Nix as well as a high amount of
packages. The default interpreter is CPython 2.7.
### Using Python
#### Overview
Several versions of the Python interpreter are available on Nix, as well as a
high amount of packages. The attribute `python` refers to the default
interpreter, which is currently CPython 2.7. It is also possible to refer to
specific versions, e.g. `python35` refers to CPython 3.5, and `pypy` refers to
the default PyPy interpreter.
Python is used a lot, and in different ways. This affects also how it is
packaged. In the case of Python on Nix, an important distinction is made between
whether the package is considered primarily an application, or whether it should
be used as a library, i.e., of primary interest are the modules in
`site-packages` that should be importable.
In the Nixpkgs tree Python applications can be found throughout, depending on
what they do, and are called from the main package set. Python libraries,
however, are in separate sets, with one set per interpreter version.
The interpreters have several common attributes. One of these attributes is
`pkgs`, which is a package set of Python libraries for this specific
interpreter. E.g., the `toolz` package corresponding to the default interpreter
is `python.pkgs.toolz`, and the CPython 3.5 version is `python35.pkgs.toolz`.
The main package set contains aliases to these package sets, e.g.
`pythonPackages` refers to `python.pkgs` and `python35Packages` to
`python35.pkgs`.
#### Installing Python and packages
It is important to make a distinction between Python packages that are
used as libraries, and applications that are written in Python.
The Nix and NixOS manuals explain how packages are generally installed. In the
case of Python and Nix, it is important to make a distinction between whether the
package is considered an application or a library.
Applications on Nix are installed typically into your user
Applications on Nix are typically installed into your user
profile imperatively using `nix-env -i`, and on NixOS declaratively by adding the
package name to `environment.systemPackages` in `/etc/nixos/configuration.nix`.
Dependencies such as libraries are automatically installed and should not be
installed explicitly.
The same goes for Python applications and libraries. Python applications can be
installed in your profile, but Python libraries you would like to use to develop
cannot. If you do install libraries in your profile, then you will end up with
import errors.
installed in your profile. But Python libraries you would like to use for
development cannot be installed, at least not individually, because they won't
be able to find each other resulting in import errors. Instead, it is possible
to create an environment with `python.buildEnv` or `python.withPackages` where
the interpreter and other executables are able to find each other and all of the
modules.
#### Python environments using `nix-shell`
In the following examples we create an environment with Python 3.5, `numpy` and
`toolz`. As you may imagine, there is one limitation here, and that's that
you can install only one environment at a time. You will notice the complaints
about collisions when you try to install a second environment.
The recommended method for creating Python environments for development is with
`nix-shell`. Executing
##### Environment defined in separate `.nix` file
```sh
$ nix-shell -p python35Packages.numpy python35Packages.toolz
Create a file, e.g. `build.nix`, with the following expression
```nix
with import <nixpkgs> {};
python35.withPackages (ps: with ps; [ numpy toolz ])
```
and install it in your profile with
```shell
nix-env -if build.nix
```
Now you can use the Python interpreter, as well as the extra packages (`numpy`,
`toolz`) that you added to the environment.
##### Environment defined in `~/.config/nixpkgs/config.nix`
If you prefer to, you could also add the environment as a package override to the Nixpkgs set, e.g.
using `config.nix`,
```nix
{ # ...
packageOverrides = pkgs: with pkgs; {
myEnv = python35.withPackages (ps: with ps; [ numpy toolz ]);
};
}
```
and install it in your profile with
```shell
nix-env -iA nixpkgs.myEnv
```
The environment is is installed by referring to the attribute, and considering
the `nixpkgs` channel was used.
##### Environment defined in `/etc/nixos/configuration.nix`
For the sake of completeness, here's another example how to install the environment system-wide.
```nix
{ # ...
environment.systemPackages = with pkgs; [
(python35.withPackages(ps: with ps; [ numpy toolz ]))
];
}
```
opens a Nix shell which has available the requested packages and dependencies.
Now you can launch the Python interpreter (which is itself a dependency)
#### Temporary Python environment with `nix-shell`
The examples in the previous section showed how to install a Python environment
into a profile. For development you may need to use multiple environments.
`nix-shell` gives the possibility to temporarily load another environment, akin
to `virtualenv`.
There are two methods for loading a shell with Python packages. The first and recommended method
is to create an environment with `python.buildEnv` or `python.withPackages` and load that. E.g.
```sh
$ nix-shell -p 'python35.withPackages(ps: with ps; [ numpy toolz ])'
```
opens a shell from which you can launch the interpreter
```sh
[nix-shell:~] python3
```
The other method, which is not recommended, does not create an environment and requires you to list the packages directly,
If the packages were not available yet in the Nix store, Nix would download or
build them automatically. A convenient option with `nix-shell` is the `--run`
option, with which you can execute a command in the `nix-shell`. Let's say we
want the above environment and directly run the Python interpreter
```sh
$ nix-shell -p python35.pkgs.numpy python35.pkgs.toolz
```
Again, it is possible to launch the interpreter from the shell.
The Python interpreter has the attribute `pkgs` which contains all Python libraries for that specific interpreter.
##### Load environment from `.nix` expression
As explained in the Nix manual, `nix-shell` can also load an
expression from a `.nix` file. Say we want to have Python 3.5, `numpy`
and `toolz`, like before, in an environment. Consider a `shell.nix` file
with
```nix
with import <nixpkgs> {};
(python35.withPackages (ps: [ps.numpy ps.toolz])).env
```
Executing `nix-shell` gives you again a Nix shell from which you can run Python.
What's happening here?
1. We begin with importing the Nix Packages collections. `import <nixpkgs>` imports the `<nixpkgs>` function, `{}` calls it and the `with` statement brings all attributes of `nixpkgs` in the local scope. These attributes form the main package set.
2. Then we create a Python 3.5 environment with the `withPackages` function.
3. The `withPackages` function expects us to provide a function as an argument that takes the set of all python packages and returns a list of packages to include in the environment. Here, we select the packages `numpy` and `toolz` from the package set.
##### Execute command with `--run`
A convenient option with `nix-shell` is the `--run`
option, with which you can execute a command in the `nix-shell`. We can
e.g. directly open a Python shell
```sh
$ nix-shell -p python35Packages.numpy python35Packages.toolz --run "python3"
```
This way you can use the `--run` option also to directly run a script
or run a script
```sh
$ nix-shell -p python35Packages.numpy python35Packages.toolz --run "python3 myscript.py"
```
In fact, for this specific use case there is a more convenient method. You can
##### `nix-shell` as shebang
In fact, for the second use case, there is a more convenient method. You can
add a [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) to your script
specifying which dependencies Nix shell needs. With the following shebang, you
can use `nix-shell myscript.py` and it will make available all dependencies and
specifying which dependencies `nix-shell` needs. With the following shebang, you
can just execute `./myscript.py`, and it will make available all dependencies and
run the script in the `python3` shell.
```py
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3Packages.numpy
#! nix-shell -i python3 -p "python3.withPackages(ps: [ps.numpy])"
import numpy
print(numpy.__version__)
```
Likely you do not want to type your dependencies each and every time. What you
can do is write a simple Nix expression which sets up an environment for you,
requiring you only to type `nix-shell`. Say we want to have Python 3.5, `numpy`
and `toolz`, like before, in an environment. With a `shell.nix` file
containing
```nix
with import <nixpkgs> {};
(pkgs.python35.withPackages (ps: [ps.numpy ps.toolz])).env
```
executing `nix-shell` gives you again a Nix shell from which you can run Python.
What's happening here?
1. We begin with importing the Nix Packages collections. `import <nixpkgs>` import the `<nixpkgs>` function, `{}` calls it and the `with` statement brings all attributes of `nixpkgs` in the local scope. Therefore we can now use `pkgs`.
2. Then we create a Python 3.5 environment with the `withPackages` function.
3. The `withPackages` function expects us to provide a function as an argument that takes the set of all python packages and returns a list of packages to include in the environment. Here, we select the packages `numpy` and `toolz` from the package set.
4. And finally, for in interactive use we return the environment by using the `env` attribute.
### Developing with Python
Now that you know how to get a working Python environment with Nix, it is time
to go forward and start actually developing with Python. We will first have a
look at how Python packages are packaged on Nix. Then, we will look at how you
can use development mode with your code.
Now that you know how to get a working Python environment on Nix, it is time to go forward and start actually developing with Python.
We will first have a look at how Python packages are packaged on Nix. Then, we will look how you can use development mode with your code.
#### Packaging a library
#### Python packaging on Nix
On Nix all packages are built by functions. The main function in Nix for building Python packages is [`buildPythonPackage`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/interpreters/python/build-python-package.nix).
Let's see how we would build the `toolz` package. According to [`python-packages.nix`](https://raw.githubusercontent.com/NixOS/nixpkgs/master/pkgs/top-level/python-packages.nix) `toolz` is build using
With Nix all packages are built by functions. The main function in Nix for
building Python libraries is `buildPythonPackage`. Let's see how we can build the
`toolz` package.
```nix
{ # ...
toolz = buildPythonPackage rec {
name = "toolz-${version}";
pname = "toolz";
version = "0.7.4";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
src = fetchPypi {
inherit pname version;
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
};
doCheck = false;
meta = {
homepage = "http://github.com/pytoolz/toolz/";
description = "List processing tools and functional utilities";
@ -122,63 +210,36 @@ Let's see how we would build the `toolz` package. According to [`python-packages
```
What happens here? The function `buildPythonPackage` is called and as argument
it accepts a set. In this case the set is a recursive set ([`rec`](http://nixos.org/nix/manual/#sec-constructs)).
One of the arguments is the name of the package, which consists of a basename
(generally following the name on PyPi) and a version. Another argument, `src`
specifies the source, which in this case is fetched from an url. `fetchurl` not
only downloads the target file, but also validates its hash. Furthermore, we
specify some (optional) [meta information](http://nixos.org/nixpkgs/manual/#chap-meta).
The output of the function is a derivation, which is an attribute with the name
`toolz` of the set `pythonPackages`. Actually, sets are created for all interpreter versions,
so e.g. `python27Packages`, `python35Packages` and `pypyPackages`.
it accepts a set. In this case the set is a recursive set, `rec`. One of the
arguments is the name of the package, which consists of a basename (generally
following the name on PyPi) and a version. Another argument, `src` specifies the
source, which in this case is fetched from PyPI using the helper function
`fetchPypi`. The argument `doCheck` is used to set whether tests should be run
when building the package. Furthermore, we specify some (optional) meta
information. The output of the function is a derivation.
An expression for `toolz` can be found in the Nixpkgs repository. As explained
in the introduction of this Python section, a derivation of `toolz` is available
for each interpreter version, e.g. `python35.pkgs.toolz` refers to the `toolz`
derivation corresponding to the CPython 3.5 interpreter.
The above example works when you're directly working on
`pkgs/top-level/python-packages.nix` in the Nixpkgs repository. Often though,
you will want to test a Nix expression outside of the Nixpkgs tree. If you
create a `shell.nix` file with the following contents
you will want to test a Nix expression outside of the Nixpkgs tree.
```nix
with import <nixpkgs> {};
pkgs.python35Packages.buildPythonPackage rec {
name = "toolz-${version}";
version = "0.8.0";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
sha256 = "e8451af61face57b7c5d09e71c0d27b8005f001ead56e9fdf470417e5cc6d479";
};
doCheck = false;
meta = {
homepage = "http://github.com/pytoolz/toolz/";
description = "List processing tools and functional utilities";
license = licenses.bsd3;
maintainers = with maintainers; [ fridh ];
};
}
```
and then execute `nix-shell` will result in an environment in which you can use
Python 3.5 and the `toolz` package. As you can see we had to explicitly mention
for which Python version we want to build a package.
The above example considered only a single package. Generally you will want to use multiple packages.
If we create a `shell.nix` file with the following contents
The following expression creates a derivation for the `toolz` package,
and adds it along with a `numpy` package to a Python environment.
```nix
with import <nixpkgs> {};
( let
toolz = pkgs.python35Packages.buildPythonPackage rec {
name = "toolz-${version}";
version = "0.8.0";
my_toolz = python35.pkgs.buildPythonPackage rec {
pname = "toolz";
version = "0.7.4";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
sha256 = "e8451af61face57b7c5d09e71c0d27b8005f001ead56e9fdf470417e5cc6d479";
src = python35.pkgs.fetchPypi {
inherit pname version;
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
};
doCheck = false;
@ -189,24 +250,24 @@ with import <nixpkgs> {};
};
};
in pkgs.python35.withPackages (ps: [ps.numpy toolz])
in python35.withPackages (ps: [ps.numpy my_toolz])
).env
```
Executing `nix-shell` will result in an environment in which you can use
Python 3.5 and the `toolz` package. As you can see we had to explicitly mention
for which Python version we want to build a package.
and again execute `nix-shell`, then we get a Python 3.5 environment with our
locally defined package as well as `numpy` which is build according to the
definition in Nixpkgs. What did we do here? Well, we took the Nix expression
that we used earlier to build a Python environment, and said that we wanted to
include our own version of `toolz`. To introduce our own package in the scope of
`withPackages` we used a
[`let`](http://nixos.org/nix/manual/#sec-constructs) expression.
You can see that we used `ps.numpy` to select numpy from the nixpkgs package set (`ps`).
But we do not take `toolz` from the nixpkgs package set this time.
Instead, `toolz` will resolve to our local definition that we introduced with `let`.
So, what did we do here? Well, we took the Nix expression that we used earlier
to build a Python environment, and said that we wanted to include our own
version of `toolz`, named `my_toolz`. To introduce our own package in the scope
of `withPackages` we used a `let` expression. You can see that we used
`ps.numpy` to select numpy from the nixpkgs package set (`ps`). We did not take
`toolz` from the Nixpkgs package set this time, but instead took our own version
that we introduced with the `let` expression.
### Handling dependencies
#### Handling dependencies
Our example, `toolz`, doesn't have any dependencies on other Python
Our example, `toolz`, does not have any dependencies on other Python
packages or system libraries. According to the manual, `buildPythonPackage`
uses the arguments `buildInputs` and `propagatedBuildInputs` to specify dependencies. If something is
exclusively a build-time dependency, then the dependency should be included as a
@ -220,15 +281,15 @@ order to build [`datashape`](https://github.com/blaze/datashape).
{ # ...
datashape = buildPythonPackage rec {
name = "datashape-${version}";
pname = "datashape";
version = "0.4.7";
src = pkgs.fetchurl {
url = "mirror://pypi/D/DataShape/${name}.tar.gz";
src = fetchPypi {
inherit pname version;
sha256 = "14b2ef766d4c9652ab813182e866f493475e65e558bed0822e38bf07bba1a278";
};
buildInputs = with self; [ pytest ];
checkInputs = with self; [ pytest ];
propagatedBuildInputs = with self; [ numpy multipledispatch dateutil ];
meta = {
@ -255,10 +316,11 @@ when building the bindings and are therefore added as `buildInputs`.
{ # ...
lxml = buildPythonPackage rec {
name = "lxml-3.4.4";
pname = "lxml";
version = "3.4.4";
src = pkgs.fetchurl {
url = "mirror://pypi/l/lxml/${name}.tar.gz";
src = fetchPypi {
inherit pname version;
sha256 = "16a0fa97hym9ysdk3rmqz32xdjqmy4w34ld3rm3jf5viqjx65lxk";
};
@ -288,11 +350,11 @@ and `CFLAGS`.
{ # ...
pyfftw = buildPythonPackage rec {
name = "pyfftw-${version}";
pname = "pyFFTW";
version = "0.9.2";
src = pkgs.fetchurl {
url = "mirror://pypi/p/pyFFTW/pyFFTW-${version}.tar.gz";
src = fetchPypi {
inherit pname version;
sha256 = "f6bbb6afa93085409ab24885a1a3cdb8909f095a142f4d49e346f2bd1b789074";
};
@ -340,7 +402,7 @@ other packages we like to have in the environment, all specified with `propagate
Indeed, we can just add any package we like to have in our environment to `propagatedBuildInputs`.
```nix
with import <nixpkgs>;
with import <nixpkgs> {};
with pkgs.python35Packages;
buildPythonPackage rec {
@ -377,11 +439,11 @@ We first create a function that builds `toolz` in `~/path/to/toolz/release.nix`
{ pkgs, buildPythonPackage }:
buildPythonPackage rec {
name = "toolz-${version}";
pname = "toolz";
version = "0.7.4";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
src = fetchPypi {
inherit pname version;
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
};
@ -423,7 +485,7 @@ and in this case the `python35` interpreter is automatically used.
### Interpreters
Versions 2.7, 3.3, 3.4, 3.5 and 3.6 of the CPython interpreter are available as
respectively `python27`, `python33`, `python34`, `python35` and `python36`. The PyPy interpreter
respectively `python27`, `python34`, `python35` and `python36`. The PyPy interpreter
is available as `pypy`. The aliases `python2` and `python3` correspond to respectively `python27` and
`python35`. The default interpreter, `python`, maps to `python2`.
The Nix expressions for the interpreters can be found in
@ -467,9 +529,7 @@ Based on the packages defined in `pkgs/top-level/python-packages.nix` an
attribute set is created for each available Python interpreter. The available
sets are
* `pkgs.python26Packages`
* `pkgs.python27Packages`
* `pkgs.python33Packages`
* `pkgs.python34Packages`
* `pkgs.python35Packages`
* `pkgs.python36Packages`
@ -478,7 +538,7 @@ sets are
and the aliases
* `pkgs.python2Packages` pointing to `pkgs.python27Packages`
* `pkgs.python3Packages` pointing to `pkgs.python35Packages`
* `pkgs.python3Packages` pointing to `pkgs.python36Packages`
* `pkgs.pythonPackages` pointing to `pkgs.python2Packages`
#### `buildPythonPackage` function
@ -488,25 +548,31 @@ The `buildPythonPackage` function is implemented in
The following is an example:
```nix
{ # ...
twisted = buildPythonPackage {
name = "twisted-8.1.0";
buildPythonPackage rec {
version = "3.3.1";
pname = "pytest";
src = pkgs.fetchurl {
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
};
preCheck = ''
# don't test bash builtins
rm testing/test_argcomplete.py
'';
propagatedBuildInputs = [ self.ZopeInterface ];
src = fetchPypi {
inherit pname version;
sha256 = "cf8436dc59d8695346fcd3ab296de46425ecab00d64096cebe79fb51ecb2eb93";
};
meta = {
homepage = http://twistedmatrix.com/;
description = "Twisted, an event-driven networking engine written in Python";
license = stdenv.lib.licenses.mit;
};
checkInputs = [ hypothesis ];
buildInputs = [ setuptools_scm ];
propagatedBuildInputs = [ attrs py setuptools six pluggy ];
meta = with stdenv.lib; {
maintainers = with maintainers; [ domenkozar lovek323 madjar lsix ];
description = "Framework for writing tests";
};
}
```
The `buildPythonPackage` mainly does four things:
@ -528,7 +594,7 @@ By default tests are run because `doCheck = true`. Test dependencies, like
e.g. the test runner, should be added to `buildInputs`.
By default `meta.platforms` is set to the same value
as the interpreter unless overriden otherwise.
as the interpreter unless overridden otherwise.
##### `buildPythonPackage` parameters
@ -546,6 +612,34 @@ All parameters from `mkDerivation` function are still supported.
* `catchConflicts` If `true`, abort package build if a package name appears more than once in dependency tree. Default is `true`.
* `checkInputs` Dependencies needed for running the `checkPhase`. These are added to `buildInputs` when `doCheck = true`.
##### Overriding Python packages
The `buildPythonPackage` function has a `overridePythonAttrs` method that
can be used to override the package. In the following example we create an
environment where we have the `blaze` package using an older version of `pandas`.
We override first the Python interpreter and pass
`packageOverrides` which contains the overrides for packages in the package set.
```nix
with import <nixpkgs> {};
(let
python = let
packageOverrides = self: super: {
pandas = super.pandas.overridePythonAttrs(old: rec {
version = "0.19.1";
src = super.fetchPypi {
pname = "pandas";
inherit version;
sha256 = "08blshqj9zj1wyjhhw3kl2vas75vhhicvv72flvf1z3jvapgw295";
};
});
};
in pkgs.python3.override {inherit packageOverrides;};
in python.withPackages(ps: [ps.blaze])).env
```
#### `buildPythonApplication` function
The `buildPythonApplication` function is practically the same as `buildPythonPackage`.
@ -622,7 +716,7 @@ attribute. The `shell.nix` file from the previous section can thus be also writt
```nix
with import <nixpkgs> {};
(python33.withPackages (ps: [ps.numpy ps.requests])).env
(python36.withPackages (ps: [ps.numpy ps.requests])).env
```
In contrast to `python.buildEnv`, `python.withPackages` does not support the more advanced options
@ -683,65 +777,36 @@ The `buildPythonPackage` function sets `DETERMINISTIC_BUILD=1` and
Both are also exported in `nix-shell`.
### Automatic tests
It is recommended to test packages as part of the build process.
Source distributions (`sdist`) often include test files, but not always.
By default the command `python setup.py test` is run as part of the
`checkPhase`, but often it is necessary to pass a custom `checkPhase`. An
example of such a situation is when `py.test` is used.
#### Common issues
- Non-working tests can often be deselected. By default `buildPythonPackage` runs `python setup.py test`.
Most python modules follows the standard test protocol where the pytest runner can be used instead.
`py.test` supports a `-k` parameter to ignore test methods or classes:
```nix
buildPythonPackage {
# ...
# assumes the tests are located in tests
checkInputs = [ pytest ];
checkPhase = ''
py.test -k 'not function_name and not other_function' tests
'';
}
```
- Unicode issues can typically be fixed by including `glibcLocales` in `buildInputs` and exporting `LC_ALL=en_US.utf-8`.
- Tests that attempt to access `$HOME` can be fixed by using the following work-around before running tests (e.g. `preCheck`): `export HOME=$(mktemp -d)`
## FAQ
### How can I install a working Python environment?
As explained in the user's guide installing individual Python packages
imperatively with `nix-env -i` or declaratively in `environment.systemPackages`
is not supported. However, it is possible to install a Python environment with packages (`python.buildEnv`).
In the following examples we create an environment with Python 3.5, `numpy` and `ipython`.
As you might imagine there is one limitation here, and that's you can install
only one environment at a time. You will notice the complaints about collisions
when you try to install a second environment.
#### Environment defined in separate `.nix` file
Create a file, e.g. `build.nix`, with the following expression
```nix
with import <nixpkgs> {};
pkgs.python35.withPackages (ps: with ps; [ numpy ipython ])
```
and install it in your profile with
```shell
nix-env -if build.nix
```
Now you can use the Python interpreter, as well as the extra packages that you added to the environment.
#### Environment defined in `~/.config/nixpkgs/config.nix`
If you prefer to, you could also add the environment as a package override to the Nixpkgs set.
```nix
{ # ...
packageOverrides = pkgs: with pkgs; {
myEnv = python35.withPackages (ps: with ps; [ numpy ipython ]);
};
}
```
and install it in your profile with
```shell
nix-env -iA nixpkgs.myEnv
```
We're installing using the attribute path and assume the channels is named `nixpkgs`.
Note that I'm using the attribute path here.
#### Environment defined in `/etc/nixos/configuration.nix`
For the sake of completeness, here's another example how to install the environment system-wide.
```nix
{ # ...
environment.systemPackages = with pkgs; [
(python35.withPackages(ps: with ps; [ numpy ipython ]))
];
}
```
### How to solve circular dependencies?
Consider the packages `A` and `B` that depend on each other. When packaging `B`,
@ -755,17 +820,17 @@ In the following example we rename the `pandas` package and build it.
```nix
with import <nixpkgs> {};
let
(let
python = let
packageOverrides = self: super: {
pandas = super.pandas.override {name="foo";};
pandas = super.pandas.overridePythonAttrs(old: {name="foo";});
};
in pkgs.python35.override {inherit packageOverrides;};
in python.pkgs.pandas
in python.withPackages(ps: [ps.pandas])).env
```
Using `nix-build` on this expression will build the package `pandas`
but with the new name `foo`.
Using `nix-build` on this expression will build an environment that contains the
package `pandas` but with the new name `foo`.
All packages in the package set will use the renamed package.
A typical use case is to switch to another version of a certain package.
@ -806,8 +871,10 @@ Executing `python setup.py bdist_wheel` in a `nix-shell `fails with
```
ValueError: ZIP does not support timestamps before 1980
```
This is because files are included that depend on items in the Nix store which have a timestamp of, that is, it corresponds to January the 1st, 1970 at 00:00:00. And as the error informs you, ZIP does not support that.
The command `bdist_wheel` takes into account `SOURCE_DATE_EPOCH`, and `nix-shell` sets this to 1. By setting it to a value corresponding to 1980 or later, or by unsetting it, it is possible to build wheels.
This is because files from the Nix store (which have a timestamp of the UNIX epoch of January 1, 1970) are included in the .ZIP, but .ZIP archives follow the DOS convention of counting timestamps from 1980.
The command `bdist_wheel` reads the `SOURCE_DATE_EPOCH` environment variable, which `nix-shell` sets to 1. Unsetting this variable or giving it a value corresponding to 1980 or later enables building wheels.
Use 1980 as timestamp:
```shell
@ -817,7 +884,7 @@ or the current time:
```shell
nix-shell --run "SOURCE_DATE_EPOCH=$(date +%s) python3 setup.py bdist_wheel"
```
or unset:
or unset `SOURCE_DATE_EPOCH`:
```shell
nix-shell --run "unset SOURCE_DATE_EPOCH; python3 setup.py bdist_wheel"
```
@ -951,8 +1018,9 @@ rec {
Following rules are desired to be respected:
* Python libraries are supposed to be called from `python-packages.nix` and packaged with `buildPythonPackage`. The expression of a library should be in `pkgs/development/python-modules/<name>/default.nix`. Libraries in `pkgs/top-level/python-packages.nix` are sorted quasi-alphabetically to avoid merge conflicts.
* Python libraries are called from `python-packages.nix` and packaged with `buildPythonPackage`. The expression of a library should be in `pkgs/development/python-modules/<name>/default.nix`. Libraries in `pkgs/top-level/python-packages.nix` are sorted quasi-alphabetically to avoid merge conflicts.
* Python applications live outside of `python-packages.nix` and are packaged with `buildPythonApplication`.
* Make sure libraries build for all Python interpreters.
* By default we enable tests. Make sure the tests are found and, in the case of libraries, are passing for all interpreters. If certain tests fail they can be disabled individually. Try to avoid disabling the tests altogether. In any case, when you disable tests, leave a comment explaining why.
* Commit names of Python libraries should include `pythonPackages`, for example `pythonPackages.numpy: 1.11 -> 1.12`.
* Commit names of Python libraries should reflect that they are Python libraries, so write for example `pythonPackages.numpy: 1.11 -> 1.12`.

View File

@ -4,10 +4,14 @@
<title>Ruby</title>
<para>There currently is support to bundle applications that are packaged as Ruby gems. The utility "bundix" allows you to write a <filename>Gemfile</filename>, let bundler create a <filename>Gemfile.lock</filename>, and then convert
this into a nix expression that contains all Gem dependencies automatically.</para>
<para>There currently is support to bundle applications that are packaged as
Ruby gems. The utility "bundix" allows you to write a
<filename>Gemfile</filename>, let bundler create a
<filename>Gemfile.lock</filename>, and then convert this into a nix
expression that contains all Gem dependencies automatically.
</para>
<para>For example, to package sensu, we did:</para>
<para>For example, to package sensu, we did:</para>
<screen>
<![CDATA[$ cd pkgs/servers/monitoring
@ -16,7 +20,7 @@ $ cd sensu
$ cat > Gemfile
source 'https://rubygems.org'
gem 'sensu'
$ $(nix-build '<nixpkgs>' -A bundix)/bin/bundix --magic
$ $(nix-build '<nixpkgs>' -A bundix --no-out-link)/bin/bundix --magic
$ cat > default.nix
{ lib, bundlerEnv, ruby }:
@ -38,15 +42,61 @@ bundlerEnv rec {
}]]>
</screen>
<para>Please check in the <filename>Gemfile</filename>, <filename>Gemfile.lock</filename> and the <filename>gemset.nix</filename> so future updates can be run easily.
<para>Please check in the <filename>Gemfile</filename>,
<filename>Gemfile.lock</filename> and the
<filename>gemset.nix</filename> so future updates can be run easily.
</para>
<para>Resulting derivations also have two helpful items, <literal>env</literal> and <literal>wrapper</literal>. The first one allows one to quickly drop into
<command>nix-shell</command> with the specified environment present. E.g. <command>nix-shell -A sensu.env</command> would give you an environment with Ruby preset
so it has all the libraries necessary for <literal>sensu</literal> in its paths. The second one can be used to make derivations from custom Ruby scripts which have
<filename>Gemfile</filename>s with their dependencies specified. It is a derivation with <command>ruby</command> wrapped so it can find all the needed dependencies.
For example, to make a derivation <literal>my-script</literal> for a <filename>my-script.rb</filename> (which should be placed in <filename>bin</filename>) you should
run <command>bundix</command> as specified above and then use <literal>bundlerEnv</literal> like this:</para>
<para>For tools written in Ruby - i.e. where the desire is to install
a package and then execute e.g. <command>rake</command> at the command
line, there is an alternative builder called <literal>bundlerApp</literal>.
Set up the <filename>gemset.nix</filename> the same way, and then, for
example:
</para>
<screen>
<![CDATA[{ lib, bundlerApp }:
bundlerApp {
pname = "corundum";
gemdir = ./.;
exes = [ "corundum-skel" ];
meta = with lib; {
description = "Tool and libraries for maintaining Ruby gems.";
homepage = https://github.com/nyarly/corundum;
license = licenses.mit;
maintainers = [ maintainers.nyarly ];
platforms = platforms.unix;
};
}]]>
</screen>
<para>The chief advantage of <literal>bundlerApp</literal> over
<literal>bundlerEnv</literal> is the executables introduced in the
environment are precisely those selected in the <literal>exes</literal>
list, as opposed to <literal>bundlerEnv</literal> which adds all the
executables made available by gems in the gemset, which can mean e.g.
<command>rspec</command> or <command>rake</command> in unpredictable
versions available from various packages.
</para>
<para>Resulting derivations for both builders also have two helpful
attributes, <literal>env</literal> and <literal>wrappedRuby</literal>.
The first one allows one to quickly drop into
<command>nix-shell</command> with the specified environment present.
E.g. <command>nix-shell -A sensu.env</command> would give you an
environment with Ruby preset so it has all the libraries necessary
for <literal>sensu</literal> in its paths. The second one can be
used to make derivations from custom Ruby scripts which have
<filename>Gemfile</filename>s with their dependencies specified. It is
a derivation with <command>ruby</command> wrapped so it can find all
the needed dependencies. For example, to make a derivation
<literal>my-script</literal> for a <filename>my-script.rb</filename>
(which should be placed in <filename>bin</filename>) you should run
<command>bundix</command> as specified above and then use
<literal>bundlerEnv</literal> like this:
</para>
<programlisting>
<![CDATA[let env = bundlerEnv {
@ -60,13 +110,9 @@ run <command>bundix</command> as specified above and then use <literal>bundlerEn
in stdenv.mkDerivation {
name = "my-script";
buildInputs = [ env.wrapper ];
buildInputs = [ env.wrappedRuby ];
script = ./my-script.rb;
buildCommand = ''
mkdir -p $out/bin
install -D -m755 $script $out/bin/my-script
patchShebangs $out/bin/my-script
'';
@ -74,4 +120,3 @@ in stdenv.mkDerivation {
</programlisting>
</section>

View File

@ -9,25 +9,23 @@ date: 2017-03-05
To install the rust compiler and cargo put
```
rustStable.rustc
rustStable.cargo
rustc
cargo
```
into the `environment.systemPackages` or bring them into scope with
`nix-shell -p rustStable.rustc -p rustStable.cargo`.
into the `environment.systemPackages` or bring them into
scope with `nix-shell -p rustc cargo`.
There are also `rustBeta` and `rustNightly` package sets available.
These are not updated very regulary. For daily builds use either rustup from
nixpkgs or use the [Rust nightlies overlay](#using-the-rust-nightlies-overlay).
For daily builds (beta and nightly) use either rustup from
nixpkgs or use the [Rust nightlies
overlay](#using-the-rust-nightlies-overlay).
## Packaging Rust applications
## Compiling Rust applications with Cargo
Rust applications are packaged by using the `buildRustPackage` helper from `rustPlatform`:
```
with rustPlatform;
buildRustPackage rec {
rustPlatform.buildRustPackage rec {
name = "ripgrep-${version}";
version = "0.4.0";
@ -38,19 +36,19 @@ buildRustPackage rec {
sha256 = "0y5d1n6hkw85jb3rblcxqas2fp82h3nghssa4xqrhqnz25l799pj";
};
depsSha256 = "0q68qyl2h6i0qsz82z840myxlnjay8p1w5z7hfyr8fqp7wgwa9cx";
cargoSha256 = "0q68qyl2h6i0qsz82z840myxlnjay8p1w5z7hfyr8fqp7wgwa9cx";
meta = with stdenv.lib; {
description = "A utility that combines the usability of The Silver Searcher with the raw speed of grep";
description = "A fast line-oriented regex search tool, similar to ag and ack";
homepage = https://github.com/BurntSushi/ripgrep;
license = with licenses; [ unlicense ];
license = licenses.unlicense;
maintainers = [ maintainers.tailhook ];
platforms = platforms.all;
};
}
```
`buildRustPackage` requires a `depsSha256` attribute which is computed over
`buildRustPackage` requires a `cargoSha256` attribute which is computed over
all crate sources of this package. Currently it is obtained by inserting a
fake checksum into the expression and building the package once. The correct
checksum can be then take from the failed build.
@ -58,6 +56,226 @@ checksum can be then take from the failed build.
To install crates with nix there is also an experimental project called
[nixcrates](https://github.com/fractalide/nixcrates).
## Compiling Rust crates using Nix instead of Cargo
### Simple operation
When run, `cargo build` produces a file called `Cargo.lock`,
containing pinned versions of all dependencies. Nixpkgs contains a
tool called `carnix` (`nix-env -iA nixos.carnix`), which can be used
to turn a `Cargo.lock` into a Nix expression.
That Nix expression calls `rustc` directly (hence bypassing Cargo),
and can be used to compile a crate and all its dependencies. Here is
an example for a minimal `hello` crate:
$ cargo new hello
$ cd hello
$ cargo build
Compiling hello v0.1.0 (file:///tmp/hello)
Finished dev [unoptimized + debuginfo] target(s) in 0.20 secs
$ carnix -o hello.nix --src ./. Cargo.lock --standalone
$ nix-build hello.nix
Now, the file produced by the call to `carnix`, called `hello.nix`, looks like:
```
# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone
{ lib, buildPlatform, buildRustCrate, fetchgit }:
let kernel = buildPlatform.parsed.kernel.name;
# ... (content skipped)
in
rec {
hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; };
hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
crateName = "hello";
version = "0.1.0";
authors = [ "pe@pijul.org <pe@pijul.org>" ];
src = ./.;
inherit dependencies buildDependencies features;
};
hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ {};
hello_0_1_0_features = f: updateFeatures f (rec {
hello_0_1_0.default = (f.hello_0_1_0.default or true);
}) [ ];
}
```
In particular, note that the argument given as `--src` is copied
verbatim to the source. If we look at a more complicated
dependencies, for instance by adding a single line `libc="*"` to our
`Cargo.toml`, we first need to run `cargo build` to update the
`Cargo.lock`. Then, `carnix` needs to be run again, and produces the
following nix file:
```
# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone
{ lib, buildPlatform, buildRustCrate, fetchgit }:
let kernel = buildPlatform.parsed.kernel.name;
# ... (content skipped)
in
rec {
hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; };
hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
crateName = "hello";
version = "0.1.0";
authors = [ "pe@pijul.org <pe@pijul.org>" ];
src = ./.;
inherit dependencies buildDependencies features;
};
libc_0_2_36_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
crateName = "libc";
version = "0.2.36";
authors = [ "The Rust Project Developers" ];
sha256 = "01633h4yfqm0s302fm0dlba469bx8y6cs4nqc8bqrmjqxfxn515l";
inherit dependencies buildDependencies features;
};
hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ {
dependencies = mapFeatures features ([ libc_0_2_36 ]);
};
hello_0_1_0_features = f: updateFeatures f (rec {
hello_0_1_0.default = (f.hello_0_1_0.default or true);
libc_0_2_36.default = true;
}) [ libc_0_2_36_features ];
libc_0_2_36 = { features?(libc_0_2_36_features {}) }: libc_0_2_36_ {
features = mkFeatures (features.libc_0_2_36 or {});
};
libc_0_2_36_features = f: updateFeatures f (rec {
libc_0_2_36.default = (f.libc_0_2_36.default or true);
libc_0_2_36.use_std =
(f.libc_0_2_36.use_std or false) ||
(f.libc_0_2_36.default or false) ||
(libc_0_2_36.default or false);
}) [];
}
```
Here, the `libc` crate has no `src` attribute, so `buildRustCrate`
will fetch it from [crates.io](https://crates.io). A `sha256`
attribute is still needed for Nix purity.
### Handling external dependencies
Some crates require external libraries. For crates from
[crates.io](https://crates.io), such libraries can be specified in
`defaultCrateOverrides` package in nixpkgs itself.
Starting from that file, one can add more overrides, to add features
or build inputs by overriding the hello crate in a seperate file.
```
with import <nixpkgs> {};
((import ./hello.nix).hello {}).override {
crateOverrides = defaultCrateOverrides // {
hello = attrs: { buildInputs = [ openssl ]; };
};
}
```
Here, `crateOverrides` is expected to be a attribute set, where the
key is the crate name without version number and the value a function.
The function gets all attributes passed to `buildRustCrate` as first
argument and returns a set that contains all attribute that should be
overwritten.
For more complicated cases, such as when parts of the crate's
derivation depend on the the crate's version, the `attrs` argument of
the override above can be read, as in the following example, which
patches the derivation:
```
with import <nixpkgs> {};
((import ./hello.nix).hello {}).override {
crateOverrides = defaultCrateOverrides // {
hello = attrs: lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0") {
postPatch = ''
substituteInPlace lib/zoneinfo.rs \
--replace "/usr/share/zoneinfo" "${tzdata}/share/zoneinfo"
'';
};
};
}
```
Another situation is when we want to override a nested
dependency. This actually works in the exact same way, since the
`crateOverrides` parameter is forwarded to the crate's
dependencies. For instance, to override the build inputs for crate
`libc` in the example above, where `libc` is a dependency of the main
crate, we could do:
```
with import <nixpkgs> {};
((import hello.nix).hello {}).override {
crateOverrides = defaultCrateOverrides // {
libc = attrs: { buildInputs = []; };
};
}
```
### Options and phases configuration
Actually, the overrides introduced in the previous section are more
general. A number of other parameters can be overridden:
- The version of rustc used to compile the crate:
```
(hello {}).override { rust = pkgs.rust; };
```
- Whether to build in release mode or debug mode (release mode by
default):
```
(hello {}).override { release = false; };
```
- Whether to print the commands sent to rustc when building
(equivalent to `--verbose` in cargo:
```
(hello {}).override { verbose = false; };
```
- Extra arguments to be passed to `rustc`:
```
(hello {}).override { extraRustcOpts = "-Z debuginfo=2"; };
```
- Phases, just like in any other derivation, can be specified using
the following attributes: `preUnpack`, `postUnpack`, `prePatch`,
`patches`, `postPatch`, `preConfigure` (in the case of a Rust crate,
this is run before calling the "build" script), `postConfigure`
(after the "build" script),`preBuild`, `postBuild`, `preInstall` and
`postInstall`. As an example, here is how to create a new module
before running the build script:
```
(hello {}).override {
preConfigure = ''
echo "pub const PATH=\"${hi.out}\";" >> src/path.rs"
'';
};
```
### Features
One can also supply features switches. For example, if we want to
compile `diesel_cli` only with the `postgres` feature, and no default
features, we would write:
```
(callPackage ./diesel.nix {}).diesel {
default = false;
postgres = true;
}
```
Where `diesel.nix` is the file generated by Carnix, as explained above.
## Using the Rust nightlies overlay
Mozilla provides an overlay for nixpkgs to bring a nightly version of Rust into scope.
@ -76,11 +294,11 @@ in the `~/.config/nixpkgs/overlays` directory.
The latest version can be installed with the following command:
$ nix-env -Ai nixos.rustChannels.stable.rust
$ nix-env -Ai nixos.latest.rustChannels.stable.rust
Or using the attribute with nix-shell:
$ nix-shell -p nixos.rustChannels.stable.rust
$ nix-shell -p nixos.latest.rustChannels.stable.rust
To install the beta or nightly channel, "stable" should be substituted by
"nightly" or "beta", or

View File

@ -39,6 +39,9 @@ nix-repl> :l &lt;nixpkgs>
nix-repl> texlive.collection-&lt;TAB>
</programlisting>
</para></listitem>
<listitem><para>
Note that the wrapper assumes that the result has a chance to be useful. For example, the core executables should be present, as well as some core data files. The supported way of ensuring this is by including some scheme, for example <varname>scheme-basic</varname>, into the combination.
</para></listitem>
</itemizedlist>
</section>

View File

@ -18,6 +18,7 @@
<xi:include href="functions.xml" />
<xi:include href="meta.xml" />
<xi:include href="languages-frameworks/index.xml" />
<xi:include href="platform-notes.xml" />
<xi:include href="package-notes.xml" />
<xi:include href="overlays.xml" />
<xi:include href="coding-conventions.xml" />

View File

@ -53,7 +53,7 @@ $ nix-env -qa hello --json
"x86_64-linux",
"armv5tel-linux",
"armv7l-linux",
"mips64el-linux",
"mips32-linux",
"x86_64-darwin",
"i686-cygwin",
"i686-freebsd",
@ -174,7 +174,7 @@ meta-attributes</title>
maintainers of this Nix expression. If
you would like to be a maintainer of a package, you may want to add
yourself to <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/maintainers.nix"><filename>nixpkgs/lib/maintainers.nix</filename></link>
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix"><filename>nixpkgs/maintainers/maintainer-list.nix</filename></link>
and write something like <literal>[ stdenv.lib.maintainers.alice
stdenv.lib.maintainers.bob ]</literal>.</para></listitem>
</varlistentry>
@ -200,11 +200,9 @@ meta-attributes</title>
meta.platforms = stdenv.lib.platforms.linux;
</programlisting>
Attribute Set <varname>stdenv.lib.platforms</varname> in
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/platforms.nix">
<filename>nixpkgs/lib/platforms.nix</filename></link> defines various common
lists of platforms types.
</para></listitem>
Attribute Set <varname>stdenv.lib.platforms</varname> defines
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/systems/doubles.nix">
various common lists</link> of platforms types.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -68,12 +68,12 @@
<varlistentry><term><varname>
$outputDevdoc</varname></term><listitem><para>
is for <emphasis>developer</emphasis> documentation. Currently we count gtk-doc in there. It goes to <varname>devdoc</varname> or is removed (!) by default. This is because e.g. gtk-doc tends to be rather large and completely unused by nixpkgs users.
is for <emphasis>developer</emphasis> documentation. Currently we count gtk-doc and devhelp books in there. It goes to <varname>devdoc</varname> or is removed (!) by default. This is because e.g. gtk-doc tends to be rather large and completely unused by nixpkgs users.
</para></listitem></varlistentry>
<varlistentry><term><varname>
$outputMan</varname></term><listitem><para>
is for man pages (except for section 3). They go to <varname>man</varname> or <varname>doc</varname> or <varname>$outputBin</varname> by default.
is for man pages (except for section 3). They go to <varname>man</varname> or <varname>$outputBin</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
@ -83,7 +83,7 @@
<varlistentry><term><varname>
$outputInfo</varname></term><listitem><para>
is for info pages. They go to <varname>info</varname> or <varname>doc</varname> or <varname>$outputMan</varname> by default.
is for info pages. They go to <varname>info</varname> or <varname>$outputBin</varname> by default.
</para></listitem></varlistentry>
</variablelist>

View File

@ -8,59 +8,88 @@
overlays. Overlays are used to add layers in the fix-point used by Nixpkgs
to compose the set of all packages.</para>
<para>Nixpkgs can be configured with a list of overlays, which are
applied in order. This means that the order of the overlays can be significant
if multiple layers override the same package.</para>
<!--============================================================-->
<section xml:id="sec-overlays-install">
<title>Installing Overlays</title>
<title>Installing overlays</title>
<para>The set of overlays is looked for in the following places. The
first one present is considered, and all the rest are ignored:
<para>The list of overlays is determined as follows.</para>
<para>If the <varname>overlays</varname> argument is not provided explicitly, we look for overlays in a path. The path
is determined as follows:
<orderedlist>
<listitem>
<para>First, if an <varname>overlays</varname> argument to the nixpkgs function itself is given,
then that is used.</para>
<para>As an argument of the imported attribute set. When importing Nixpkgs,
the <varname>overlays</varname> attribute argument can be set to a list of
functions, which is described in <xref linkend="sec-overlays-layout"/>.</para>
<para>This can be passed explicitly when importing nipxkgs, for example
<literal>import &lt;nixpkgs> { overlays = [ overlay1 overlay2 ]; }</literal>.</para>
</listitem>
<listitem>
<para>Otherwise, if the Nix path entry <literal>&lt;nixpkgs-overlays></literal> exists, we look for overlays
at that path, as described below.</para>
<para>In the directory pointed to by the Nix search path entry
<literal>&lt;nixpkgs-overlays></literal>.</para>
<para>See the section on <literal>NIX_PATH</literal> in the Nix manual for more details on how to
set a value for <literal>&lt;nixpkgs-overlays>.</literal></para>
</listitem>
<listitem>
<para>In the directory <filename>~/.config/nixpkgs/overlays/</filename>.</para>
<para>If one of <filename>~/.config/nixpkgs/overlays.nix</filename> and
<filename>~/.config/nixpkgs/overlays/</filename> exists, then we look for overlays at that path, as
described below. It is an error if both exist.</para>
</listitem>
</orderedlist>
</para>
<para>For the second and third options, the directory should contain Nix expressions defining the
overlays. Each overlay can be a file, a directory containing a
<filename>default.nix</filename>, or a symlink to one of those. The expressions should follow
the syntax described in <xref linkend="sec-overlays-layout"/>.</para>
<para>If we are looking for overlays at a path, then there are two cases:
<itemizedlist>
<listitem>
<para>If the path is a file, then the file is imported as a Nix expression and used as the list of
overlays.</para>
</listitem>
<para>The order of the overlay layers can influence the recipe of packages if multiple layers override
the same recipe. In the case where overlays are loaded from a directory, they are loaded in
alphabetical order.</para>
<listitem>
<para>If the path is a directory, then we take the content of the directory, order it
lexicographically, and attempt to interpret each as an overlay by:
<itemizedlist>
<listitem>
<para>Importing the file, if it is a <literal>.nix</literal> file.</para>
</listitem>
<listitem>
<para>Importing a top-level <filename>default.nix</filename> file, if it is a directory.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
<para>To install an overlay using the last option, you can clone the overlay's repository and add
a symbolic link to it in <filename>~/.config/nixpkgs/overlays/</filename> directory.</para>
<para>On a NixOS system the value of the <literal>nixpkgs.overlays</literal> option, if present,
is passed to the system Nixpkgs directly as an argument. Note that this does not affect the overlays for
non-NixOS operations (e.g. <literal>nix-env</literal>), which are looked up independently.</para>
<para>The <filename>overlays.nix</filename> option therefore provides a convenient way to use the same
overlays for a NixOS system configuration and user configuration: the same file can be used
as <filename>overlays.nix</filename> and imported as the value of <literal>nixpkgs.overlays</literal>.</para>
</section>
<!--============================================================-->
<section xml:id="sec-overlays-layout">
<title>Overlays Layout</title>
<section xml:id="sec-overlays-definition">
<title>Defining overlays</title>
<para>Overlays are expressed as Nix functions which accept 2 arguments and return a set of
packages.</para>
<para>Overlays are Nix functions which accept two arguments,
conventionally called <varname>self</varname> and <varname>super</varname>,
and return a set of packages. For example, the following is a valid overlay.</para>
<programlisting>
self: super:
@ -75,25 +104,31 @@ self: super:
}
</programlisting>
<para>The first argument, usually named <varname>self</varname>, corresponds to the final package
<para>The first argument (<varname>self</varname>) corresponds to the final package
set. You should use this set for the dependencies of all packages specified in your
overlay. For example, all the dependencies of <varname>rr</varname> in the example above come
from <varname>self</varname>, as well as the overridden dependencies used in the
<varname>boost</varname> override.</para>
<para>The second argument, usually named <varname>super</varname>,
<para>The second argument (<varname>super</varname>)
corresponds to the result of the evaluation of the previous stages of
Nixpkgs. It does not contain any of the packages added by the current
overlay nor any of the following overlays. This set should be used either
overlay, nor any of the following overlays. This set should be used either
to refer to packages you wish to override, or to access functions defined
in Nixpkgs. For example, the original recipe of <varname>boost</varname>
in the above example, comes from <varname>super</varname>, as well as the
<varname>callPackage</varname> function.</para>
<para>The value returned by this function should be a set similar to
<filename>pkgs/top-level/all-packages.nix</filename>, which contains
<filename>pkgs/top-level/all-packages.nix</filename>, containing
overridden and/or new packages.</para>
<para>Overlays are similar to other methods for customizing Nixpkgs, in particular
the <literal>packageOverrides</literal> attribute described in <xref linkend="sec-modify-via-packageOverrides"/>.
Indeed, <literal>packageOverrides</literal> acts as an overlay with only the
<varname>super</varname> argument. It is therefore appropriate for basic use,
but overlays are more powerful and easier to distribute.</para>
</section>
</chapter>

View File

@ -101,7 +101,7 @@ modulesTree = [kernel]
$ nix-env -i ncurses
$ export NIX_CFLAGS_LINK=-lncurses
$ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
</para>
</listitem>
@ -111,9 +111,9 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
</listitem>
</orderedlist>
</para>
</listitem>
<listitem>
@ -366,15 +366,33 @@ it. Place the resulting <filename>package.nix</filename> file into
</section>
<section xml:id="sec-autojump">
<section xml:id="sec-shell-helpers">
<title>Autojump</title>
<title>Interactive shell helpers</title>
<para>
autojump needs the shell integration to be useful but unlike other systems,
nix doesn't have a standard share directory location. This is why a
<command>autojump-share</command> script is shipped that prints the location
of the shared folder. This can then be used in the .bashrc like this:
Some packages provide the shell integration to be more useful. But
unlike other systems, nix doesn't have a standard share directory
location. This is why a bunch <command>PACKAGE-share</command>
scripts are shipped that print the location of the corresponding
shared folder.
Current list of such packages is as following:
<itemizedlist>
<listitem>
<para>
<literal>autojump</literal>: <command>autojump-share</command>
</para>
</listitem>
<listitem>
<para>
<literal>fzf</literal>: <command>fzf-share</command>
</para>
</listitem>
</itemizedlist>
E.g. <literal>autojump</literal> can then used in the .bashrc like this:
<screen>
source "$(autojump-share)/autojump.bash"
</screen>
@ -391,24 +409,24 @@ it. Place the resulting <filename>package.nix</filename> file into
<title>Steam in Nix</title>
<para>
Steam is distributed as a <filename>.deb</filename> file, for now only
as an i686 package (the amd64 package only has documentation).
When unpacked, it has a script called <filename>steam</filename> that
Steam is distributed as a <filename>.deb</filename> file, for now only
as an i686 package (the amd64 package only has documentation).
When unpacked, it has a script called <filename>steam</filename> that
in ubuntu (their target distro) would go to <filename>/usr/bin
</filename>. When run for the first time, this script copies some
files to the user's home, which include another script that is the
ultimate responsible for launching the steam binary, which is also
</filename>. When run for the first time, this script copies some
files to the user's home, which include another script that is the
ultimate responsible for launching the steam binary, which is also
in $HOME.
</para>
<para>
Nix problems and constraints:
<itemizedlist>
<listitem><para>We don't have <filename>/bin/bash</filename> and many
<listitem><para>We don't have <filename>/bin/bash</filename> and many
scripts point there. Similarly for <filename>/usr/bin/python</filename>
.</para></listitem>
<listitem><para>We don't have the dynamic loader in <filename>/lib
</filename>.</para></listitem>
<listitem><para>The <filename>steam.sh</filename> script in $HOME can
<listitem><para>The <filename>steam.sh</filename> script in $HOME can
not be patched, as it is checked and rewritten by steam.</para></listitem>
<listitem><para>The steam binary cannot be patched, it's also checked.</para></listitem>
</itemizedlist>
@ -428,10 +446,10 @@ it. Place the resulting <filename>package.nix</filename> file into
<title>How to play</title>
<para>
For 64-bit systems it's important to have
<programlisting>hardware.opengl.driSupport32Bit = true;</programlisting>
in your <filename>/etc/nixos/configuration.nix</filename>. You'll also need
<programlisting>hardware.pulseaudio.support32Bit = true;</programlisting>
For 64-bit systems it's important to have
<programlisting>hardware.opengl.driSupport32Bit = true;</programlisting>
in your <filename>/etc/nixos/configuration.nix</filename>. You'll also need
<programlisting>hardware.pulseaudio.support32Bit = true;</programlisting>
if you are using PulseAudio - this will enable 32bit ALSA apps integration.
To use the Steam controller, you need to add
<programlisting>services.udev.extraRules = ''
@ -452,31 +470,25 @@ it. Place the resulting <filename>package.nix</filename> file into
<varlistentry>
<term>Steam fails to start. What do I do?</term>
<listitem><para>Try to run
<listitem><para>Try to run
<programlisting>strace steam</programlisting>
to see what is causing steam to fail.</para></listitem>
</varlistentry>
<varlistentry>
<term>Using the FOSS Radeon drivers</term>
<listitem><itemizedlist><listitem><para>
The open source radeon drivers need a newer libc++ than is provided
by the default runtime, which leads to a crash on launch. Use
<programlisting>environment.systemPackages = [(pkgs.steam.override { newStdcpp = true; })];</programlisting>
in your config if you get an error like
<programlisting>
libGL error: unable to load driver: radeonsi_dri.so
libGL error: driver pointer missing
libGL error: failed to load driver: radeonsi
libGL error: unable to load driver: swrast_dri.so
libGL error: failed to load driver: swrast</programlisting></para></listitem>
<listitem><para>
Steam ships statically linked with a version of libcrypto that
conflics with the one dynamically loaded by radeonsi_dri.so.
If you get the error
<programlisting>steam.sh: line 713: 7842 Segmentation fault (core dumped)</programlisting>
have a look at <link xlink:href="https://github.com/NixOS/nixpkgs/pull/20269">this pull request</link>.
</para></listitem>
<term>Using the FOSS Radeon or nouveau (nvidia) drivers</term>
<listitem><itemizedlist>
<listitem><para>The <literal>newStdcpp</literal> parameter
was removed since NixOS 17.09 and should not be needed anymore.
</para></listitem>
<listitem><para>
Steam ships statically linked with a version of libcrypto that
conflics with the one dynamically loaded by radeonsi_dri.so.
If you get the error
<programlisting>steam.sh: line 713: 7842 Segmentation fault (core dumped)</programlisting>
have a look at <link xlink:href="https://github.com/NixOS/nixpkgs/pull/20269">this pull request</link>.
</para></listitem>
</itemizedlist></listitem></varlistentry>
@ -486,7 +498,7 @@ libGL error: failed to load driver: swrast</programlisting></para></listitem>
<listitem><para>
There is no java in steam chrootenv by default. If you get a message like
<programlisting>/home/foo/.local/share/Steam/SteamApps/common/towns/towns.sh: line 1: java: command not found</programlisting>
You need to add
You need to add
<programlisting> steam.override { withJava = true; };</programlisting>
to your configuration.
</para></listitem>
@ -501,14 +513,14 @@ libGL error: failed to load driver: swrast</programlisting></para></listitem>
<title>steam-run</title>
<para>
The FHS-compatible chroot used for steam can also be used to run
The FHS-compatible chroot used for steam can also be used to run
other linux games that expect a FHS environment.
To do it, add
To do it, add
<programlisting>pkgs.(steam.override {
nativeOnly = true;
newStdcpp = true;
}).run</programlisting>
to your configuration, rebuild, and run the game with
to your configuration, rebuild, and run the game with
<programlisting>steam-run ./foo</programlisting>
</para>
@ -648,8 +660,66 @@ cp ${myEmacsConfig} $out/share/emacs/site-lisp/default.el
passing <command>-q</command> to the Emacs command.
</para>
<para>
Sometimes <varname>emacsWithPackages</varname> is not enough, as
this package set has some priorities imposed on packages (with
the lowest priority assigned to Melpa Unstable, and the highest for
packages manually defined in
<filename>pkgs/top-level/emacs-packages.nix</filename>). But you
can't control this priorities when some package is installed as a
dependency. You can override it on per-package-basis, providing all
the required dependencies manually - but it's tedious and there is
always a possibility that an unwanted dependency will sneak in
through some other package. To completely override such a package
you can use <varname>overrideScope</varname>.
</para>
<screen>
overrides = super: self: rec {
haskell-mode = self.melpaPackages.haskell-mode;
...
};
((emacsPackagesNgGen emacs).overrideScope overrides).emacsWithPackages (p: with p; [
# here both these package will use haskell-mode of our own choice
ghc-mod
dante
])
</screen>
</section>
</section>
<section xml:id="sec-weechat">
<title>Weechat</title>
<para>
Weechat can be configured to include your choice of plugins, reducing its
closure size from the default configuration which includes all available
plugins. To make use of this functionality, install an expression that
overrides its configuration such as
<programlisting>weechat.override {configure = {availablePlugins, ...}: {
plugins = with availablePlugins; [ python perl ];
}
}</programlisting>
</para>
<para>
The plugins currently available are <literal>python</literal>,
<literal>perl</literal>, <literal>ruby</literal>, <literal>guile</literal>,
<literal>tcl</literal> and <literal>lua</literal>.
</para>
<para>
The python plugin allows the addition of extra libraries. For instance,
the <literal>inotify.py</literal> script in weechat-scripts requires
D-Bus or libnotify, and the <literal>fish.py</literal> script requires
pycrypto. To use these scripts, use the <literal>python</literal>
plugin's <literal>withPackages</literal> attribute:
<programlisting>weechat.override {configure = {availablePlugins, ...}: {
plugins = with availablePlugins; [
(python.withPackages (ps: with ps; [ pycrypto python-dbus ]))
];
}
}
</programlisting>
</para>
</section>
</chapter>

83
doc/platform-notes.xml Normal file
View File

@ -0,0 +1,83 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-platform-nodes">
<title>Platform Notes</title>
<section xml:id="sec-darwin">
<title>Darwin (macOS)</title>
<para>Some common issues when packaging software for darwin:</para>
<itemizedlist>
<listitem>
<para>
The darwin <literal>stdenv</literal> uses clang instead of gcc.
When referring to the compiler <varname>$CC</varname> or <command>cc</command>
will work in both cases. Some builds hardcode gcc/g++ in their
build scripts, that can usually be fixed with using something
like <literal>makeFlags = [ "CC=cc" ];</literal> or by patching
the build scripts.
</para>
<programlisting>
stdenv.mkDerivation {
name = "libfoo-1.2.3";
# ...
buildPhase = ''
$CC -o hello hello.c
'';
}
</programlisting>
</listitem>
<listitem>
<para>
On darwin libraries are linked using absolute paths, libraries
are resolved by their <literal>install_name</literal> at link
time. Sometimes packages won't set this correctly causing the
library lookups to fail at runtime. This can be fixed by adding
extra linker flags or by running <command>install_name_tool -id</command>
during the <function>fixupPhase</function>.
</para>
<programlisting>
stdenv.mkDerivation {
name = "libfoo-1.2.3";
# ...
makeFlags = stdenv.lib.optional stdenv.isDarwin "LDFLAGS=-Wl,-install_name,$(out)/lib/libfoo.dylib";
}
</programlisting>
</listitem>
<listitem>
<para>
Some packages assume xcode is available and use <command>xcrun</command>
to resolve build tools like <command>clang</command>, etc.
This causes errors like <code>xcode-select: error: no developer tools were found at '/Applications/Xcode.app'</code>
while the build doesn't actually depend on xcode.
</para>
<programlisting>
stdenv.mkDerivation {
name = "libfoo-1.2.3";
# ...
prePatch = ''
substituteInPlace Makefile \
--replace '/usr/bin/xcrun clang' clang
'';
}
</programlisting>
<para>
The package <literal>xcbuild</literal> can be used to build projects
that really depend on Xcode, however projects that build some kind of
graphical interface won't work without using Xcode in an impure way.
</para>
</listitem>
</itemizedlist>
</section>
</chapter>

View File

@ -7,123 +7,123 @@
<title>Reviewing contributions</title>
<warning>
<para>The following section is a draft and reviewing policy is still being
<para>The following section is a draft and reviewing policy is still being
discussed.</para>
</warning>
<para>The nixpkgs projects receives a fairly high number of contributions via
GitHub pull-requests. Reviewing and approving these is an important task and a
<para>The nixpkgs projects receives a fairly high number of contributions via
GitHub pull-requests. Reviewing and approving these is an important task and a
way to contribute to the project.</para>
<para>The high change rate of nixpkgs make any pull request that is open for
long enough subject to conflicts that will require extra work from the
submitter or the merger. Reviewing pull requests in a timely manner and being
responsive to the comments is the key to avoid these. GitHub provides sort
filters that can be used to see the <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc">most
recently</link> and the <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-asc">least
<para>The high change rate of nixpkgs make any pull request that is open for
long enough subject to conflicts that will require extra work from the
submitter or the merger. Reviewing pull requests in a timely manner and being
responsive to the comments is the key to avoid these. GitHub provides sort
filters that can be used to see the <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc">most
recently</link> and the <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-asc">least
recently</link> updated pull-requests.</para>
<para>When reviewing a pull request, please always be nice and polite.
Controversial changes can lead to controversial opinions, but it is important
<para>When reviewing a pull request, please always be nice and polite.
Controversial changes can lead to controversial opinions, but it is important
to respect every community members and their work.</para>
<para>GitHub provides reactions, they are a simple and quick way to provide
feedback to pull-requests or any comments. The thumb-down reaction should be
used with care and if possible accompanied with some explanations so the
<para>GitHub provides reactions, they are a simple and quick way to provide
feedback to pull-requests or any comments. The thumb-down reaction should be
used with care and if possible accompanied with some explanations so the
submitter has directions to improve his contribution.</para>
<para>Pull-requests reviews should include a list of what has been reviewed in a
comment, so other reviewers and mergers can know the state of the
<para>Pull-requests reviews should include a list of what has been reviewed in a
comment, so other reviewers and mergers can know the state of the
review.</para>
<para>All the review template samples provided in this section are generic and
meant as examples. Their usage is optional and the reviewer is free to adapt
<para>All the review template samples provided in this section are generic and
meant as examples. Their usage is optional and the reviewer is free to adapt
them to his liking.</para>
<section><title>Package updates</title>
<para>A package update is the most trivial and common type of pull-request.
These pull-requests mainly consist in updating the version part of the package
<para>A package update is the most trivial and common type of pull-request.
These pull-requests mainly consist in updating the version part of the package
name and the source hash.</para>
<para>It can happen that non trivial updates include patches or more complex
<para>It can happen that non trivial updates include patches or more complex
changes.</para>
<para>Reviewing process:</para>
<itemizedlist>
<listitem><para>Add labels to the pull-request. (Requires commit
<listitem><para>Add labels to the pull-request. (Requires commit
rights)</para>
<itemizedlist>
<listitem><para><literal>8.has: package (update)</literal> and any topic
<listitem><para><literal>8.has: package (update)</literal> and any topic
label that fit the updated package.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the package versioning is fitting the
<listitem><para>Ensure that the package versioning is fitting the
guidelines.</para></listitem>
<listitem><para>Ensure that the commit text is fitting the
<listitem><para>Ensure that the commit text is fitting the
guidelines.</para></listitem>
<listitem><para>Ensure that the package maintainers are notified.</para>
<itemizedlist>
<listitem><para>mention-bot usually notify GitHub users based on the
submitted changes, but it can happen that it misses some of the
<listitem><para>mention-bot usually notify GitHub users based on the
submitted changes, but it can happen that it misses some of the
package maintainers.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the meta field contains correct
<listitem><para>Ensure that the meta field contains correct
information.</para>
<itemizedlist>
<listitem><para>License can change with version updates, so it should be
<listitem><para>License can change with version updates, so it should be
checked to be fitting upstream license.</para></listitem>
<listitem><para>If the package has no maintainer, a maintainer must be
set. This can be the update submitter or a community member that
<listitem><para>If the package has no maintainer, a maintainer must be
set. This can be the update submitter or a community member that
accepts to take maintainership of the package.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the code contains no typos.</para></listitem>
<listitem><para>Building the package locally.</para>
<itemizedlist>
<listitem><para>Pull-requests are often targeted to the master or staging
branch so building the pull-request locally as it is submitted can
<listitem><para>Pull-requests are often targeted to the master or staging
branch so building the pull-request locally as it is submitted can
trigger a large amount of source builds.</para>
<para>It is possible to rebase the changes on nixos-unstable or
nixpkgs-unstable for easier review by running the following commands
<para>It is possible to rebase the changes on nixos-unstable or
nixpkgs-unstable for easier review by running the following commands
from a nixpkgs clone.
<screen>
$ git remote add channels https://github.com/NixOS/nixpkgs-channels.git <co
$ git remote add channels https://github.com/NixOS/nixpkgs-channels.git <co
xml:id='reviewing-rebase-1' />
$ git fetch channels nixos-unstable <co xml:id='reviewing-rebase-2' />
$ git fetch origin pull/PRNUMBER/head <co xml:id='reviewing-rebase-3' />
$ git rebase --onto nixos-unstable BASEBRANCH FETCH_HEAD <co
$ git rebase --onto nixos-unstable BASEBRANCH FETCH_HEAD <co
xml:id='reviewing-rebase-4' />
</screen>
<calloutlist>
<callout arearefs='reviewing-rebase-1'>
<para>This should be done only once to be able to fetch channel
<para>This should be done only once to be able to fetch channel
branches from the nixpkgs-channels repository.</para>
</callout>
<callout arearefs='reviewing-rebase-2'>
<para>Fetching the nixos-unstable branch.</para>
</callout>
<callout arearefs='reviewing-rebase-3'>
<para>Fetching the pull-request changes, <varname>PRNUMBER</varname>
is the number at the end of the pull-request title and
<varname>BASEBRANCH</varname> the base branch of the
<para>Fetching the pull-request changes, <varname>PRNUMBER</varname>
is the number at the end of the pull-request title and
<varname>BASEBRANCH</varname> the base branch of the
pull-request.</para>
</callout>
<callout arearefs='reviewing-rebase-3'>
<para>Rebasing the pull-request changes to the nixos-unstable
<para>Rebasing the pull-request changes to the nixos-unstable
branch.</para>
</callout>
</calloutlist>
</para>
</listitem>
<listitem>
<para>The <link xlink:href="https://github.com/madjar/nox">nox</link>
tool can be used to review a pull-request content in a single command.
It doesn't rebase on a channel branch so it might trigger multiple
source builds. <varname>PRNUMBER</varname> should be replaced by the
<para>The <link xlink:href="https://github.com/madjar/nox">nox</link>
tool can be used to review a pull-request content in a single command.
It doesn't rebase on a channel branch so it might trigger multiple
source builds. <varname>PRNUMBER</varname> should be replaced by the
number at the end of the pull-request title.</para>
<screen>
$ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
@ -153,42 +153,42 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<section><title>New packages</title>
<para>New packages are a common type of pull-requests. These pull requests
<para>New packages are a common type of pull-requests. These pull requests
consists in adding a new nix-expression for a package.</para>
<para>Reviewing process:</para>
<itemizedlist>
<listitem><para>Add labels to the pull-request. (Requires commit
<listitem><para>Add labels to the pull-request. (Requires commit
rights)</para>
<itemizedlist>
<listitem><para><literal>8.has: package (new)</literal> and any topic
<listitem><para><literal>8.has: package (new)</literal> and any topic
label that fit the new package.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the package versioning is fitting the
<listitem><para>Ensure that the package versioning is fitting the
guidelines.</para></listitem>
<listitem><para>Ensure that the commit name is fitting the
<listitem><para>Ensure that the commit name is fitting the
guidelines.</para></listitem>
<listitem><para>Ensure that the meta field contains correct
<listitem><para>Ensure that the meta field contains correct
information.</para>
<itemizedlist>
<listitem><para>License must be checked to be fitting upstream
<listitem><para>License must be checked to be fitting upstream
license.</para></listitem>
<listitem><para>Platforms should be set or the package will not get binary
<listitem><para>Platforms should be set or the package will not get binary
substitutes.</para></listitem>
<listitem><para>A maintainer must be set, this can be the package
submitter or a community member that accepts to take maintainership of
<listitem><para>A maintainer must be set, this can be the package
submitter or a community member that accepts to take maintainership of
the package.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the code contains no typos.</para></listitem>
<listitem><para>Ensure the package source.</para>
<itemizedlist>
<listitem><para>Mirrors urls should be used when
<listitem><para>Mirrors urls should be used when
available.</para></listitem>
<listitem><para>The most appropriate function should be used (e.g.
packages from GitHub should use
<listitem><para>The most appropriate function should be used (e.g.
packages from GitHub should use
<literal>fetchFromGitHub</literal>).</para></listitem>
</itemizedlist>
</listitem>
@ -223,49 +223,49 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<section><title>Module updates</title>
<para>Module updates are submissions changing modules in some ways. These often
<para>Module updates are submissions changing modules in some ways. These often
contains changes to the options or introduce new options.</para>
<para>Reviewing process</para>
<itemizedlist>
<listitem><para>Add labels to the pull-request. (Requires commit
<listitem><para>Add labels to the pull-request. (Requires commit
rights)</para>
<itemizedlist>
<listitem><para><literal>8.has: module (update)</literal> and any topic
<listitem><para><literal>8.has: module (update)</literal> and any topic
label that fit the module.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the module maintainers are notified.</para>
<itemizedlist>
<listitem><para>Mention-bot notify GitHub users based on the submitted
changes, but it can happen that it miss some of the package
<listitem><para>Mention-bot notify GitHub users based on the submitted
changes, but it can happen that it miss some of the package
maintainers.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the module tests, if any, are
<listitem><para>Ensure that the module tests, if any, are
succeeding.</para></listitem>
<listitem><para>Ensure that the introduced options are correct.</para>
<itemizedlist>
<listitem><para>Type should be appropriate (string related types differs
in their merging capabilities, <literal>optionSet</literal> and
<listitem><para>Type should be appropriate (string related types differs
in their merging capabilities, <literal>optionSet</literal> and
<literal>string</literal> types are deprecated).</para></listitem>
<listitem><para>Description, default and example should be
<listitem><para>Description, default and example should be
provided.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that option changes are backward compatible.</para>
<itemizedlist>
<listitem><para><literal>mkRenamedOptionModule</literal> and
<literal>mkAliasOptionModule</literal> functions provide way to make
<listitem><para><literal>mkRenamedOptionModule</literal> and
<literal>mkAliasOptionModule</literal> functions provide way to make
option changes backward compatible.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that removed options are declared with
<listitem><para>Ensure that removed options are declared with
<literal>mkRemovedOptionModule</literal></para></listitem>
<listitem><para>Ensure that changes that are not backward compatible are
<listitem><para>Ensure that changes that are not backward compatible are
mentioned in release notes.</para></listitem>
<listitem><para>Ensure that documentations affected by the change is
<listitem><para>Ensure that documentations affected by the change is
updated.</para></listitem>
</itemizedlist>
@ -294,37 +294,37 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<para>New modules submissions introduce a new module to NixOS.</para>
<itemizedlist>
<listitem><para>Add labels to the pull-request. (Requires commit
<listitem><para>Add labels to the pull-request. (Requires commit
rights)</para>
<itemizedlist>
<listitem><para><literal>8.has: module (new)</literal> and any topic label
<listitem><para><literal>8.has: module (new)</literal> and any topic label
that fit the module.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the module tests, if any, are
<listitem><para>Ensure that the module tests, if any, are
succeeding.</para></listitem>
<listitem><para>Ensure that the introduced options are correct.</para>
<itemizedlist>
<listitem><para>Type should be appropriate (string related types differs
in their merging capabilities, <literal>optionSet</literal> and
<listitem><para>Type should be appropriate (string related types differs
in their merging capabilities, <literal>optionSet</literal> and
<literal>string</literal> types are deprecated).</para></listitem>
<listitem><para>Description, default and example should be
<listitem><para>Description, default and example should be
provided.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that module <literal>meta</literal> field is
<listitem><para>Ensure that module <literal>meta</literal> field is
present</para>
<itemizedlist>
<listitem><para>Maintainers should be declared in
<listitem><para>Maintainers should be declared in
<literal>meta.maintainers</literal>.</para></listitem>
<listitem><para>Module documentation should be declared with
<listitem><para>Module documentation should be declared with
<literal>meta.doc</literal>.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para>Ensure that the module respect other modules
<listitem><para>Ensure that the module respect other modules
functionality.</para>
<itemizedlist>
<listitem><para>For example, enabling a module should not open firewall
<listitem><para>For example, enabling a module should not open firewall
ports by default.</para></listitem>
</itemizedlist>
</listitem>
@ -340,7 +340,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
- [ ] options have default
- [ ] options have example
- [ ] options have descriptions
- [ ] No unneeded package is added to system.environmentPackages
- [ ] No unneeded package is added to environment.systemPackages
- [ ] meta.maintainers is set
- [ ] module documentation is declared in meta.doc
@ -355,22 +355,22 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<para>Other type of submissions requires different reviewing steps.</para>
<para>If you consider having enough knowledge and experience in a topic and
would like to be a long-term reviewer for related submissions, please contact
the current reviewers for that topic. They will give you information about the
<para>If you consider having enough knowledge and experience in a topic and
would like to be a long-term reviewer for related submissions, please contact
the current reviewers for that topic. They will give you information about the
reviewing process.
The main reviewers for a topic can be hard to find as there is no list, but
checking past pull-requests to see who reviewed or git-blaming the code to see
The main reviewers for a topic can be hard to find as there is no list, but
checking past pull-requests to see who reviewed or git-blaming the code to see
who committed to that topic can give some hints.</para>
<para>Container system, boot system and library changes are some examples of the
<para>Container system, boot system and library changes are some examples of the
pull requests fitting this category.</para>
</section>
<section><title>Merging pull-requests</title>
<para>It is possible for community members that have enough knowledge and
<para>It is possible for community members that have enough knowledge and
experience on a special topic to contribute by merging pull requests.</para>
<para>TODO: add the procedure to request merging rights.</para>
@ -380,13 +380,13 @@ The following paragraph about how to deal with unactive contributors is just a
proposition and should be modified to what the community agrees to be the right
policy.
<para>Please note that contributors with commit rights unactive for more than
<para>Please note that contributors with commit rights unactive for more than
three months will have their commit rights revoked.</para>
-->
<para>In a case a contributor leaves definitively the Nix community, he should
create an issue or notify the mailing list with references of packages and
modules he maintains so the maintainership can be taken over by other
<para>In a case a contributor leaves definitively the Nix community, he should
create an issue or notify the mailing list with references of packages and
modules he maintains so the maintainership can be taken over by other
contributors.</para>
</section>

20
doc/shell.md Normal file
View File

@ -0,0 +1,20 @@
---
title: pkgs.mkShell
author: zimbatm
date: 2017-10-30
---
pkgs.mkShell is a special kind of derivation that is only useful when using
it combined with nix-shell. It will in fact fail to instantiate when invoked
with nix-build.
## Usage
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar available to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
```

View File

@ -179,6 +179,269 @@ genericBuild
</section>
<section xml:id="ssec-stdenv-dependencies"><title>Specifying dependencies</title>
<para>
As described in the Nix manual, almost any <filename>*.drv</filename> store path in a derivation's attribute set will induce a dependency on that derivation.
<varname>mkDerivation</varname>, however, takes a few attributes intended to, between them, include all the dependencies of a package.
This is done both for structure and consistency, but also so that certain other setup can take place.
For example, certain dependencies need their bin directories added to the <envar>PATH</envar>.
That is built-in, but other setup is done via a pluggable mechanism that works in conjunction with these dependency attributes.
See <xref linkend="ssec-setup-hooks"/> for details.
</para>
<para>
Dependencies can be broken down along three axes: their host and target platforms relative to the new derivation's, and whether they are propagated.
The platform distinctions are motivated by cross compilation; see <xref linkend="chap-cross"/> for exactly what each platform means.
<footnote><para>
The build platform is ignored because it is a mere implementation detail of the package satisfying the dependency:
As a general programming principle, dependencies are always <emphasis>specified</emphasis> as interfaces, not concrete implementation.
</para></footnote>
But even if one is not cross compiling, the platforms imply whether or not the dependency is needed at run-time or build-time, a concept that makes perfect sense outside of cross compilation.
For now, the run-time/build-time distinction is just a hint for mental clarity, but in the future it perhaps could be enforced.
</para>
<para>
The extension of <envar>PATH</envar> with dependencies, alluded to above, proceeds according to the relative platforms alone.
The process is carried out only for dependencies whose host platform matches the new derivation's build platformi.e. which run on the platform where the new derivation will be built.
<footnote><para>
Currently, that means for native builds all dependencies are put on the <envar>PATH</envar>.
But in the future that may not be the case for sake of matching cross:
the platforms would be assumed to be unique for native and cross builds alike, so only the <varname>depsBuild*</varname> and <varname>nativeBuildDependencies</varname> dependencies would affect the <envar>PATH</envar>.
</para></footnote>
For each dependency <replaceable>dep</replaceable> of those dependencies, <filename><replaceable>dep</replaceable>/bin</filename>, if present, is added to the <envar>PATH</envar> environment variable.
</para>
<para>
The dependency is propagated when it forces some of its other-transitive (non-immediate) downstream dependencies to also take it on as an immediate dependency.
Nix itself already takes a package's transitive dependencies into account, but this propagation ensures nixpkgs-specific infrastructure like setup hooks (mentioned above) also are run as if the propagated dependency.
</para>
<para>
It is important to note dependencies are not necessary propagated as the same sort of dependency that they were before, but rather as the corresponding sort so that the platform rules still line up.
The exact rules for dependency propagation can be given by assigning each sort of dependency two integers based one how it's host and target platforms are offset from the depending derivation's platforms.
Those offsets are given are given below in the descriptions of each dependency list attribute.
Algorithmically, we traverse propagated inputs, accumulating every propagated dep's propagated deps and adjusting them to account for the "shift in perspective" described by the current dep's platform offsets.
This results in sort a transitive closure of the dependency relation, with the offsets being approximately summed when two dependency links are combined.
We also prune transitive deps whose combined offsets go out-of-bounds, which can be viewed as a filter over that transitive closure removing dependencies that are blatantly absurd.
</para>
<para>
We can define the process precisely with <link xlink:href="https://en.wikipedia.org/wiki/Natural_deduction">Natural Deduction</link> using the inference rules.
This probably seems a bit obtuse, but so is the bash code that actually implements it!
<footnote><para>
The <function>findInputs</function> function, currently residing in <filename>pkgs/stdenv/generic/setup.sh</filename>, implements the propagation logic.
</para></footnote>
They're confusing in very different ways so...hopefully if something doesn't make sense in one presentation, it does in the other!
<programlisting>
let mapOffset(h, t, i) = i + (if i &lt;= 0 then h else t - 1)
propagated-dep(h0, t0, A, B)
propagated-dep(h1, t1, B, C)
h0 + h1 in {-1, 0, 1}
h0 + t1 in {-1, 0, 1}
-------------------------------------- Transitive property
propagated-dep(mapOffset(h0, t0, h1),
mapOffset(h0, t0, t1),
A, C)</programlisting>
<programlisting>
let mapOffset(h, t, i) = i + (if i &lt;= 0 then h else t - 1)
dep(h0, _, A, B)
propagated-dep(h1, t1, B, C)
h0 + h1 in {-1, 0, 1}
h0 + t1 in {-1, 0, -1}
-------------------------------------- Take immediate deps' propagated deps
propagated-dep(mapOffset(h0, t0, h1),
mapOffset(h0, t0, t1),
A, C)</programlisting>
<programlisting>
propagated-dep(h, t, A, B)
-------------------------------------- Propagated deps count as deps
dep(h, t, A, B)</programlisting>
Some explanation of this monstrosity is in order.
In the common case, the target offset of a dependency is the successor to the target offset: <literal>t = h + 1</literal>.
That means that:
<programlisting>
let f(h, t, i) = i + (if i &lt;= 0 then h else t - 1)
let f(h, h + 1, i) = i + (if i &lt;= 0 then h else (h + 1) - 1)
let f(h, h + 1, i) = i + (if i &lt;= 0 then h else h)
let f(h, h + 1, i) = i + h
</programlisting>
This is where the "sum-like" comes from above:
We can just sum all the host offset to get the host offset of the transitive dependency.
The target offset is the transitive dep is simply the host offset + 1, just as it was with the dependencies composed to make this transitive one;
it can be ignored as it doesn't add any new information.
</para>
<para>
Because of the bounds checks, the uncommon cases are <literal>h = t</literal> and <literal>h + 2 = t</literal>.
In the former case, the motivation for <function>mapOffset</function> is that since its host and target platforms are the same, no transitive dep of it should be able to "discover" an offset greater than its reduced target offsets.
<function>mapOffset</function> effectively "squashes" all its transitive dependencies' offsets so that none will ever be greater than the target offset of the original <literal>h = t</literal> package.
In the other case, <literal>h + 1</literal> is skipped over between the host and target offsets.
Instead of squashing the offsets, we need to "rip" them apart so no transitive dependencies' offset is that one.
</para>
<para>
Overall, the unifying theme here is that propagation shouldn't be introducing transitive dependencies involving platforms the needing package is unaware of.
The offset bounds checking and definition of <function>mapOffset</function> together ensure that this is the case.
Discovering a new offset is discovering a new platform, and since those platforms weren't in the derivation "spec" of the needing package, they cannot be relevant.
From a capability perspective, we can imagine that the host and target platforms of a package are the capabilities a package requires, and the depending package must provide the capability to the dependency.
</para>
<variablelist>
<title>Variables specifying dependencies</title>
<varlistentry>
<term><varname>depsBuildBuild</varname></term>
<listitem>
<para>
A list of dependencies whose host and target platforms are the new derivation's build platform.
This means a <literal>-1</literal> host and <literal>-1</literal> target offset from the new derivation's platforms.
They are programs/libraries used at build time that furthermore produce programs/libraries also used at build time.
If the dependency doesn't care about the target platform (i.e. isn't a compiler or similar tool), put it in <varname>nativeBuildInputs</varname>instead.
The most common use for this <literal>buildPackages.stdenv.cc</literal>, the default C compiler for this role.
That example crops up more than one might think in old commonly used C libraries.
</para>
<para>
Since these packages are able to be run at build time, that are always added to the <envar>PATH</envar>, as described above.
But since these packages are only guaranteed to be able to run then, they shouldn't persist as run-time dependencies.
This isn't currently enforced, but could be in the future.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>nativeBuildInputs</varname></term>
<listitem>
<para>
A list of dependencies whose host platform is the new derivation's build platform, and target platform is the new derivation's host platform.
This means a <literal>-1</literal> host offset and <literal>0</literal> target offset from the new derivation's platforms.
They are programs/libraries used at build time that, if they are a compiler or similar tool, produce code to run at run time—i.e. tools used to build the new derivation.
If the dependency doesn't care about the target platform (i.e. isn't a compiler or similar tool), put it here, rather than in <varname>depsBuildBuild</varname> or <varname>depsBuildTarget</varname>.
This would be called <varname>depsBuildHost</varname> but for historical continuity.
</para>
<para>
Since these packages are able to be run at build time, that are added to the <envar>PATH</envar>, as described above.
But since these packages only are guaranteed to be able to run then, they shouldn't persist as run-time dependencies.
This isn't currently enforced, but could be in the future.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>depsBuildTarget</varname></term>
<listitem>
<para>
A list of dependencies whose host platform is the new derivation's build platform, and target platform is the new derivation's target platform.
This means a <literal>-1</literal> host offset and <literal>1</literal> target offset from the new derivation's platforms.
They are programs used at build time that produce code to run at run with code produced by the depending package.
Most commonly, these would tools used to build the runtime or standard library the currently-being-built compiler will inject into any code it compiles.
In many cases, the currently-being built compiler is itself employed for that task, but when that compiler won't run (i.e. its build and host platform differ) this is not possible.
Other times, the compiler relies on some other tool, like binutils, that is always built separately so the dependency is unconditional.
</para>
<para>
This is a somewhat confusing dependency to wrap ones head around, and for good reason.
As the only one where the platform offsets are not adjacent integers, it requires thinking of a bootstrapping stage <emphasis>two</emphasis> away from the current one.
It and it's use-case go hand in hand and are both considered poor form:
try not to need this sort dependency, and try not avoid building standard libraries / runtimes in the same derivation as the compiler produces code using them.
Instead strive to build those like a normal library, using the newly-built compiler just as a normal library would.
In short, do not use this attribute unless you are packaging a compiler and are sure it is needed.
</para>
<para>
Since these packages are able to be run at build time, that are added to the <envar>PATH</envar>, as described above.
But since these packages only are guaranteed to be able to run then, they shouldn't persist as run-time dependencies.
This isn't currently enforced, but could be in the future.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>depsHostHost</varname></term>
<listitem><para>
A list of dependencies whose host and target platforms match the new derivation's host platform.
This means a both <literal>0</literal> host offset and <literal>0</literal> target offset from the new derivation's host platform.
These are packages used at run-time to generate code also used at run-time.
In practice, that would usually be tools used by compilers for metaprogramming/macro systems, or libraries used by the macros/metaprogramming code itself.
It's always preferable to use a <varname>depsBuildBuild</varname> dependency in the derivation being built than a <varname>depsHostHost</varname> on the tool doing the building for this purpose.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>buildInputs</varname></term>
<listitem>
<para>
A list of dependencies whose host platform and target platform match the new derivation's.
This means a <literal>0</literal> host offset and <literal>1</literal> target offset from the new derivation's host platform.
This would be called <varname>depsHostTarget</varname> but for historical continuity.
If the dependency doesn't care about the target platform (i.e. isn't a compiler or similar tool), put it here, rather than in <varname>depsBuildBuild</varname>.
</para>
<para>
These often are programs/libraries used by the new derivation at <emphasis>run</emphasis>-time, but that isn't always the case.
For example, the machine code in a statically linked library is only used at run time, but the derivation containing the library is only needed at build time.
Even in the dynamic case, the library may also be needed at build time to appease the linker.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>depsTargetTarget</varname></term>
<listitem><para>
A list of dependencies whose host platform matches the new derivation's target platform.
This means a <literal>1</literal> offset from the new derivation's platforms.
These are packages that run on the target platform, e.g. the standard library or run-time deps of standard library that a compiler insists on knowing about.
It's poor form in almost all cases for a package to depend on another from a future stage [future stage corresponding to positive offset].
Do not use this attribute unless you are packaging a compiler and are sure it is needed.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>depsBuildBuildPropagated</varname></term>
<listitem><para>
The propagated equivalent of <varname>depsBuildBuild</varname>.
This perhaps never ought to be used, but it is included for consistency [see below for the others].
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>propagatedNativeBuildInputs</varname></term>
<listitem><para>
The propagated equivalent of <varname>nativeBuildInputs</varname>.
This would be called <varname>depsBuildHostPropagated</varname> but for historical continuity.
For example, if package <varname>Y</varname> has <literal>propagatedNativeBuildInputs = [X]</literal>, and package <varname>Z</varname> has <literal>buildInputs = [Y]</literal>, then package <varname>Z</varname> will be built as if it included package <varname>X</varname> in its <varname>nativeBuildInputs</varname>.
If instead, package <varname>Z</varname> has <literal>nativeBuildInputs = [Y]</literal>, then <varname>Z</varname> will be built as if it included <varname>X</varname> in the <varname>depsBuildBuild</varname> of package <varname>Z</varname>, because of the sum of the two <literal>-1</literal> host offsets.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>depsBuildTargetPropagated</varname></term>
<listitem><para>
The propagated equivalent of <varname>depsBuildTarget</varname>.
This is prefixed for the same reason of alerting potential users.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>depsHostHostPropagated</varname></term>
<listitem><para>
The propagated equivalent of <varname>depsHostHost</varname>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>propagatedBuildInputs</varname></term>
<listitem><para>
The propagated equivalent of <varname>buildInputs</varname>.
This would be called <varname>depsHostTargetPropagated</varname> but for historical continuity.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>depsTargetTarget</varname></term>
<listitem><para>
The propagated equivalent of <varname>depsTargetTarget</varname>.
This is prefixed for the same reason of alerting potential users.
</para></listitem>
</varlistentry>
</variablelist>
</section>
<section xml:id="ssec-stdenv-attributes"><title>Attributes</title>
<variablelist>
@ -187,57 +450,12 @@ genericBuild
<varlistentry>
<term><varname>NIX_DEBUG</varname></term>
<listitem><para>If set, <literal>stdenv</literal> will print some
debug information during the build. In particular, the
<command>gcc</command> and <command>ld</command> wrapper scripts
will print out the complete command line passed to the wrapped
tools.</para></listitem>
</varlistentry>
</variablelist>
<variablelist>
<title>Variables specifying dependencies</title>
<varlistentry>
<term><varname>nativeBuildInputs</varname></term>
<listitem><para>
A list of dependencies used by the new derivation at <emphasis>build</emphasis>-time.
I.e. these dependencies should not make it into the package's runtime-closure, though this is currently not checked.
For each dependency <replaceable>dir</replaceable>, the directory <filename><replaceable>dir</replaceable>/bin</filename>, if it exists, is added to the <envar>PATH</envar> environment variable.
Other environment variables are also set up via a pluggable mechanism.
For instance, if <varname>buildInputs</varname> contains Perl, then the <filename>lib/site_perl</filename> subdirectory of each input is added to the <envar>PERL5LIB</envar> environment variable.
See <xref linkend="ssec-setup-hooks"/> for details.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>buildInputs</varname></term>
<listitem><para>
A list of dependencies used by the new derivation at <emphasis>run</emphasis>-time.
Currently, the build-time environment is modified in the exact same way as with <varname>nativeBuildInputs</varname>.
This is problematic in that when cross-compiling, foreign executables can clobber native ones on the <envar>PATH</envar>.
Even more confusing is static-linking.
A statically-linked library should be listed here because ultimately that generated machine code will be used at run-time, even though a derivation containing the object files or static archives will only be used at build-time.
A less confusing solution to this would be nice.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>propagatedNativeBuildInputs</varname></term>
<listitem><para>
Like <varname>nativeBuildInputs</varname>, but these dependencies are <emphasis>propagated</emphasis>:
that is, the dependencies listed here are added to the <varname>nativeBuildInputs</varname> of any package that uses <emphasis>this</emphasis> package as a dependency.
So if package Y has <literal>propagatedBuildInputs = [X]</literal>, and package Z has <literal>buildInputs = [Y]</literal>, then package X will appear in Zs build environment automatically.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>propagatedBuildInputs</varname></term>
<listitem><para>
Like <varname>buildInputs</varname>, but propagated just like <varname>propagatedNativeBuildInputs</varname>.
This inherits <varname>buildInputs</varname>'s flaws of clobbering native executables when cross-compiling and being confusing for static linking.
A natural number indicating how much information to log.
If set to 1 or higher, <literal>stdenv</literal> will print moderate debug information during the build.
In particular, the <command>gcc</command> and <command>ld</command> wrapper scripts will print out the complete command line passed to the wrapped tools.
If set to 6 or higher, the <literal>stdenv</literal> setup script will be run with <literal>set -x</literal> tracing.
If set to 7 or higher, the <command>gcc</command> and <command>ld</command> wrapper scripts will also be run with <literal>set -x</literal> tracing.
</para></listitem>
</varlistentry>
@ -248,10 +466,17 @@ genericBuild
<varlistentry>
<term><varname>enableParallelBuilding</varname></term>
<listitem><para>If set, <literal>stdenv</literal> will pass specific
flags to <literal>make</literal> and other build tools to enable
parallel building with up to <literal>build-cores</literal>
workers.</para></listitem>
<listitem>
<para>If set to <literal>true</literal>, <literal>stdenv</literal> will
pass specific flags to <literal>make</literal> and other build tools to
enable parallel building with up to <literal>build-cores</literal>
workers.</para>
<para>Unless set to <literal>false</literal>, some build systems with good
support for parallel building including <literal>cmake</literal>,
<literal>meson</literal>, and <literal>qmake</literal> will set it to
<literal>true</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -646,7 +871,7 @@ script) if it exists.</para>
By default, when cross compiling, the configure script has <option>--build=...</option> and <option>--host=...</option> passed.
Packages can instead pass <literal>[ "build" "host" "target" ]</literal> or a subset to control exactly which platform flags are passed.
Compilers and other tools should use this to also pass the target platform, for example.
Note eventually these will be passed when in native builds too, to improve determinism: build-time guessing, as is done today, is a risk of impurity.
<footnote><para>Eventually these will be passed when in native builds too, to improve determinism: build-time guessing, as is done today, is a risk of impurity.</para></footnote>
</para></listitem>
</varlistentry>
@ -696,8 +921,14 @@ nothing.</para>
<listitem><para>A list of strings passed as additional flags to
<command>make</command>. These flags are also used by the default
install and check phase. For setting make flags specific to the
build phase, use <varname>buildFlags</varname> (see
below).</para></listitem>
build phase, use <varname>buildFlags</varname> (see below).
<programlisting>
makeFlags = [ "PREFIX=$(out)" ];
</programlisting>
<note><para>The flags are quoted in bash, but environment variables can
be specified by using the make syntax.</para></note></para></listitem>
</varlistentry>
<varlistentry>
@ -764,13 +995,14 @@ but only if the <varname>doCheck</varname> variable is enabled.</para>
<varlistentry>
<term><varname>doCheck</varname></term>
<listitem><para>If set to a non-empty string, the check phase is
executed, otherwise it is skipped (default). Thus you should set
<programlisting>
doCheck = true;</programlisting>
in the derivation to enable checks.</para></listitem>
<listitem><para>
Controls whether the check phase is executed.
By default it is skipped, but if <varname>doCheck</varname> is set to true, the check phase is usually executed.
Thus you should set <programlisting>doCheck = true;</programlisting> in the derivation to enable checks.
The exception is cross compilation.
Cross compiled builds never run tests, no matter how <varname>doCheck</varname> is set,
as the newly-built program won't run on the platform used to build it.
</para></listitem>
</varlistentry>
<varlistentry>
@ -907,6 +1139,20 @@ following:
<listitem><para>If set, libraries and executables are not
stripped. By default, they are.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>dontStripHost</varname></term>
<listitem><para>
Like <varname>dontStripHost</varname>, but only affects the <command>strip</command> command targetting the package's host platform.
Useful when supporting cross compilation, but otherwise feel free to ignore.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>dontStripTarget</varname></term>
<listitem><para>
Like <varname>dontStripHost</varname>, but only affects the <command>strip</command> command targetting the packages' target platform.
Useful when supporting cross compilation, but otherwise feel free to ignore.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>dontMoveSbin</varname></term>
@ -1035,12 +1281,14 @@ installcheck</command>.</para>
<varlistentry>
<term><varname>doInstallCheck</varname></term>
<listitem><para>If set to a non-empty string, the installCheck phase is
executed, otherwise it is skipped (default). Thus you should set
<programlisting>doInstallCheck = true;</programlisting>
in the derivation to enable install checks.</para></listitem>
<listitem><para>
Controls whether the installCheck phase is executed.
By default it is skipped, but if <varname>doInstallCheck</varname> is set to true, the installCheck phase is usually executed.
Thus you should set <programlisting>doInstallCheck = true;</programlisting> in the derivation to enable install checks.
The exception is cross compilation.
Cross compiled builds never run tests, no matter how <varname>doInstallCheck</varname> is set,
as the newly-built program won't run on the platform used to build it.
</para></listitem>
</varlistentry>
<varlistentry>
@ -1153,7 +1401,7 @@ makeWrapper $out/bin/foo $wrapperfile --prefix PATH : ${lib.makeBinPath [ hello
</listitem>
</varlistentry>
<varlistentry xml:id='fun-substitute'>
<term><function>substitute</function>
@ -1312,7 +1560,7 @@ someVar=$(stripHash $name)
</para></listitem>
</varlistentry>
<varlistentry xml:id='fun-wrapProgram'>
<term><function>wrapProgram</function>
@ -1337,24 +1585,127 @@ someVar=$(stripHash $name)
<section xml:id="ssec-setup-hooks"><title>Package setup hooks</title>
<para>The following packages provide a setup hook:
<para>
Nix itself considers a build-time dependency merely something that should previously be built and accessible at build time—packages themselves are on their own to perform any additional setup.
In most cases, that is fine, and the downstream derivation can deal with it's own dependencies.
But for a few common tasks, that would result in almost every package doing the same sort of setup work---depending not on the package itself, but entirely on which dependencies were used.
</para>
<para>
In order to alleviate this burden, the <firstterm>setup hook></firstterm>mechanism was written, where any package can include a shell script that [by convention rather than enforcement by Nix], any downstream reverse-dependency will source as part of its build process.
That allows the downstream dependency to merely specify its dependencies, and lets those dependencies effectively initialize themselves.
No boilerplate mirroring the list of dependencies is needed.
</para>
<para>
The Setup hook mechanism is a bit of a sledgehammer though: a powerful feature with a broad and indiscriminate area of effect.
The combination of its power and implicit use may be expedient, but isn't without costs.
Nix itself is unchanged, but the spirit of adding dependencies being effect-free is violated even if the letter isn't.
For example, if a derivation path is mentioned more than once, Nix itself doesn't care and simply makes sure the dependency derivation is already built just the same—depending is just needing something to exist, and needing is idempotent.
However, a dependency specified twice will have its setup hook run twice, and that could easily change the build environment (though a well-written setup hook will therefore strive to be idempotent so this is in fact not observable).
More broadly, setup hooks are anti-modular in that multiple dependencies, whether the same or different, should not interfere and yet their setup hooks may well do so.
</para>
<para>
The most typical use of the setup hook is actually to add other hooks which are then run (i.e. after all the setup hooks) on each dependency.
For example, the C compiler wrapper's setup hook feeds itself flags for each dependency that contains relevant libaries and headers.
This is done by defining a bash function, and appending its name to one of
<envar>envBuildBuildHooks</envar>`,
<envar>envBuildHostHooks</envar>`,
<envar>envBuildTargetHooks</envar>`,
<envar>envHostHostHooks</envar>`,
<envar>envHostTargetHooks</envar>`, or
<envar>envTargetTargetHooks</envar>`.
These 6 bash variables correspond to the 6 sorts of dependencies by platform (there's 12 total but we ignore the propagated/non-propagated axis).
</para>
<para>
Packages adding a hook should not hard code a specific hook, but rather choose a variable <emphasis>relative</emphasis> to how they are included.
Returning to the C compiler wrapper example, if it itself is an <literal>n</literal> dependency, then it only wants to accumulate flags from <literal>n + 1</literal> dependencies, as only those ones match the compiler's target platform.
The <envar>hostOffset</envar> variable is defined with the current dependency's host offset <envar>targetOffset</envar> with its target offset, before it's setup hook is sourced.
Additionally, since most environment hooks don't care about the target platform,
That means the setup hook can append to the right bash array by doing something like
<programlisting language="bash">
addEnvHooks "$hostOffset" myBashFunction
</programlisting>
</para>
<para>
The <emphasis>existence</emphasis> of setups hooks has long been documented and packages inside Nixpkgs are free to use these mechanism.
Other packages, however, should not rely on these mechanisms not changing between Nixpkgs versions.
Because of the existing issues with this system, there's little benefit from mandating it be stable for any period of time.
</para>
<para>
Here are some packages that provide a setup hook.
Since the mechanism is modular, this probably isn't an exhaustive list.
Then again, since the mechanism is only to be used as a last resort, it might be.
<variablelist>
<varlistentry>
<term>GCC wrapper</term>
<listitem><para>Adds the <filename>include</filename> subdirectory
of each build input to the <envar>NIX_CFLAGS_COMPILE</envar>
environment variable, and the <filename>lib</filename> and
<filename>lib64</filename> subdirectories to
<envar>NIX_LDFLAGS</envar>.</para></listitem>
<term>Bintools Wrapper</term>
<listitem>
<para>
Bintools Wrapper wraps the binary utilities for a bunch of miscellaneous purposes.
These are GNU Binutils when targetting Linux, and a mix of cctools and GNU binutils for Darwin.
[The "Bintools" name is supposed to be a compromise between "Binutils" and "cctools" not denoting any specific implementation.]
Specifically, the underlying bintools package, and a C standard library (glibc or Darwin's libSystem, just for the dynamic loader) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by Bintools Wrapper.
Packages typically depend on CC Wrapper, which in turn (at run time) depends on Bintools Wrapper.
</para>
<para>
Bintools Wrapper was only just recently split off from CC Wrapper, so the division of labor is still being worked out.
For example, it shouldn't care about about the C standard library, but just take a derivation with the dynamic loader (which happens to be the glibc on linux).
Dependency finding however is a task both wrappers will continue to need to share, and probably the most important to understand.
It is currently accomplished by collecting directories of host-platform dependencies (i.e. <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>) in environment variables.
Bintools Wrapper's setup hook causes any <filename>lib</filename> and <filename>lib64</filename> subdirectories to be added to <envar>NIX_LDFLAGS</envar>.
Since CC Wrapper and Bintools Wrapper use the same strategy, most of the Bintools Wrapper code is sparsely commented and refers to CC Wrapper.
But CC Wrapper's code, by contrast, has quite lengthy comments.
Bintools Wrapper merely cites those, rather than repeating them, to avoid falling out of sync.
</para>
<para>
A final task of the setup hook is defining a number of standard environment variables to tell build systems which executables full-fill which purpose.
They are defined to just be the base name of the tools, under the assumption that Bintools Wrapper's binaries will be on the path.
Firstly, this helps poorly-written packages, e.g. ones that look for just <command>gcc</command> when <envar>CC</envar> isn't defined yet <command>clang</command> is to be used.
Secondly, this helps packages not get confused when cross-compiling, in which case multiple Bintools Wrappers may simultaneously be in use.
<footnote><para>
Each wrapper targets a single platform, so if binaries for multiple platforms are needed, the underlying binaries must be wrapped multiple times.
As this is a property of the wrapper itself, the multiple wrappings are needed whether or not the same underlying binaries can target multiple platforms.
</para></footnote>
<envar>BUILD_</envar>- and <envar>TARGET_</envar>-prefixed versions of the normal environment variable are defined for the additional Bintools Wrappers, properly disambiguating them.
</para>
<para>
A problem with this final task is that Bintools Wrapper is honest and defines <envar>LD</envar> as <command>ld</command>.
Most packages, however, firstly use the C compiler for linking, secondly use <envar>LD</envar> anyways, defining it as the C compiler, and thirdly, only so define <envar>LD</envar> when it is undefined as a fallback.
This triple-threat means Bintools Wrapper will break those packages, as LD is already defined as the actual linker which the package won't override yet doesn't want to use.
The workaround is to define, just for the problematic package, <envar>LD</envar> as the C compiler.
A good way to do this would be <command>preConfigure = "LD=$CC"</command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>CC Wrapper</term>
<listitem>
<para>
CC Wrapper wraps a C toolchain for a bunch of miscellaneous purposes.
Specifically, a C compiler (GCC or Clang), wrapped binary tools, and a C standard library (glibc or Darwin's libSystem, just for the dynamic loader) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by CC Wrapper.
Packages typically depend on CC Wrapper, which in turn (at run time) depends on Bintools Wrapper.
</para>
<para>
Dependency finding is undoubtedly the main task of CC Wrapper.
This works just like Bintools Wrapper, except that any <filename>include</filename> subdirectory of any relevant dependency is added to <envar>NIX_CFLAGS_COMPILE</envar>.
The setup hook itself contains some lengthy comments describing the exact convoluted mechanism by which this is accomplished.
</para>
<para>
CC Wrapper also like Bintools Wrapper defines standard environment variables with the names of the tools it wraps, for the same reasons described above.
Importantly, while it includes a <command>cc</command> symlink to the c compiler for portability, the <envar>CC</envar> will be defined using the compiler's "real name" (i.e. <command>gcc</command> or <command>clang</command>).
This helps lousy build systems that inspect on the name of the compiler rather than run it.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Perl</term>
<listitem><para>Adds the <filename>lib/site_perl</filename> subdirectory
of each build input to the <envar>PERL5LIB</envar>
environment variable.</para></listitem>
<listitem>
<para>
Adds the <filename>lib/site_perl</filename> subdirectory of each build input to the <envar>PERL5LIB</envar> environment variable.
For instance, if <varname>buildInputs</varname> contains Perl, then the <filename>lib/site_perl</filename> subdirectory of each input is added to the <envar>PERL5LIB</envar> environment variable.
</para>
</listitem>
</varlistentry>
<varlistentry>
@ -1451,6 +1802,20 @@ someVar=$(stripHash $name)
disabled or patched to work with PaX.</para></listitem>
</varlistentry>
<varlistentry>
<term>autoPatchelfHook</term>
<listitem><para>This is a special setup hook which helps in packaging
proprietary software in that it automatically tries to find missing shared
library dependencies of ELF files. All packages within the
<envar>runtimeDependencies</envar> environment variable are unconditionally
added to executables, which is useful for programs that use
<citerefentry>
<refentrytitle>dlopen</refentrytitle>
<manvolnum>3</manvolnum>
</citerefentry>
to load libraries at runtime.</para></listitem>
</varlistentry>
</variablelist>
</para>

View File

@ -61,7 +61,7 @@ $ git checkout -b 'fix/pkg-name-update'
<listitem>
<para>Format the commit in a following way:</para>
<programlisting>
(pkg-name | service-name): (from -> to | init at version | refactor | etc)
(pkg-name | nixos/&lt;module>): (from -> to | init at version | refactor | etc)
Additional information.
</programlisting>
@ -78,19 +78,19 @@ Additional information.
<listitem>
<para>
<command>firefox: 3.0 -> 3.1.1</command>
<command>firefox: 54.0.1 -> 55.0</command>
</para>
</listitem>
<listitem>
<para>
<command>hydra service: add bazBaz option</command>
<command>nixos/hydra: add bazBaz option</command>
</para>
</listitem>
<listitem>
<para>
<command>nginx service: refactor config generation</command>
<command>nixos/nginx: refactor config generation</command>
</para>
</listitem>
</itemizedlist>
@ -196,7 +196,7 @@ Additional information.
<itemizedlist>
<listitem>
<para>Write the title in format <command>(pkg-name | service): improvement</command>.
<para>Write the title in format <command>(pkg-name | nixos/&lt;module>): improvement</command>.
<itemizedlist>
<listitem>
@ -223,6 +223,133 @@ Additional information.
</itemizedlist>
</section>
<section>
<title>Pull Request Template</title>
<para>
The pull request template helps determine what steps have been made for a
contribution so far, and will help guide maintainers on the status of a
change. The motivation section of the PR should include any extra details
the title does not address and link any existing issues related to the pull
request.
</para>
<para>When a PR is created, it will be pre-populated with some checkboxes detailed below:
</para>
<section>
<title>Tested using sandboxing</title>
<para>
When sandbox builds are enabled, Nix will setup an isolated environment
for each build process. It is used to remove further hidden dependencies
set by the build environment to improve reproducibility. This includes
access to the network during the build outside of
<function>fetch*</function> functions and files outside the Nix store.
Depending on the operating system access to other resources are blocked
as well (ex. inter process communication is isolated on Linux); see <link
xlink:href="https://nixos.org/nix/manual/#description-45">build-use-sandbox</link>
in Nix manual for details.
</para>
<para>
Sandboxing is not enabled by default in Nix due to a small performance
hit on each build. In pull requests for <link
xlink:href="https://github.com/NixOS/nixpkgs/">nixpkgs</link> people
are asked to test builds with sandboxing enabled (see <literal>Tested
using sandboxing</literal> in the pull request template) because
in<link
xlink:href="https://nixos.org/hydra/">https://nixos.org/hydra/</link>
sandboxing is also used.
</para>
<para>
Depending if you use NixOS or other platforms you can use one of the
following methods to enable sandboxing <emphasis role="bold">before</emphasis> building the package:
<itemizedlist>
<listitem>
<para>
<emphasis role="bold">Globally enable sandboxing on NixOS</emphasis>:
add the following to
<filename>configuration.nix</filename>
<screen>nix.useSandbox = true;</screen>
</para>
</listitem>
<listitem>
<para>
<emphasis role="bold">Globally enable sandboxing on non-NixOS platforms</emphasis>:
add the following to: <filename>/etc/nix/nix.conf</filename>
<screen>build-use-sandbox = true</screen>
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Built on platform(s)</title>
<para>
Many Nix packages are designed to run on multiple
platforms. As such, it's important to let the maintainer know which
platforms your changes have been tested on. It's not always practical to
test a change on all platforms, and is not required for a pull request to
be merged. Only check the systems you tested the build on in this
section.
</para>
</section>
<section>
<title>Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)</title>
<para>
Packages with automated tests are much more likely to be merged in a
timely fashion because it doesn't require as much manual testing by the
maintainer to verify the functionality of the package. If there are
existing tests for the package, they should be run to verify your changes
do not break the tests. Tests only apply to packages with NixOS modules
defined and can only be run on Linux. For more details on writing and
running tests, see the <link
xlink:href="https://nixos.org/nixos/manual/index.html#sec-nixos-tests">section
in the NixOS manual</link>.
</para>
</section>
<section>
<title>Tested compilation of all pkgs that depend on this change using <command>nox-review</command></title>
<para>
If you are updating a package's version, you can use nox to make sure all
packages that depend on the updated package still compile correctly. This
can be done using the nox utility. The <command>nox-review</command>
utility can look for and build all dependencies either based on
uncommited changes with the <literal>wip</literal> option or specifying a
github pull request number.
</para>
<para>
review uncommitted changes:
<screen>nix-shell -p nox --run nox-review wip</screen>
</para>
<para>
review changes from pull request number 12345:
<screen>nix-shell -p nox --run nox-review pr 12345</screen>
</para>
</section>
<section>
<title>Tested execution of all binary files (usually in <filename>./result/bin/</filename>)</title>
<para>
It's important to test any executables generated by a build when you
change or create a package in nixpkgs. This can be done by looking in
<filename>./result/bin</filename> and running any files in there, or at a
minimum, the main executable for the package. For example, if you make a change
to <package>texlive</package>, you probably would only check the binaries
associated with the change you made rather than testing all of them.
</para>
</section>
<section>
<title>Meets nixpkgs contribution standards</title>
<para>
The last checkbox is fits <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/.github/CONTRIBUTING.md">CONTRIBUTING.md</link>.
The contributing document has detailed information on standards the Nix
community has for commit messages, reviews, licensing of contributions
you make to the project, etc... Everyone should read and understand the
standards the community has for contributing before submitting a pull
request.
</para>
</section>
</section>
<section>
<title>Hotfixing pull requests</title>

View File

@ -1,11 +1,11 @@
{ lib }:
# Operations on attribute sets.
let
inherit (builtins) head tail length;
inherit (import ./trivial.nix) and or;
inherit (import ./default.nix) fold;
inherit (import ./strings.nix) concatStringsSep;
inherit (import ./lists.nix) concatMap concatLists all deepSeqList;
inherit (lib.trivial) and or;
inherit (lib.strings) concatStringsSep;
inherit (lib.lists) fold concatMap concatLists all deepSeqList;
in
rec {

View File

@ -1,7 +1,7 @@
{ lib }:
let
lib = import ./default.nix;
inherit (builtins) attrNames isFunction;
inherit (builtins) attrNames;
in
@ -36,7 +36,7 @@ rec {
overrideDerivation = drv: f:
let
newDrv = derivation (drv.drvAttrs // (f drv));
in addPassthru newDrv (
in lib.flip (extendDerivation true) newDrv (
{ meta = drv.meta or {};
passthru = if drv ? passthru then drv.passthru else {};
}
@ -72,7 +72,7 @@ rec {
makeOverridable = f: origArgs:
let
ff = f origArgs;
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
in
if builtins.isAttrs ff then (ff // {
override = newArgs: makeOverridable f (overrideWith newArgs);
@ -81,7 +81,7 @@ rec {
${if ff ? overrideAttrs then "overrideAttrs" else null} = fdrv:
makeOverridable (args: (f args).overrideAttrs fdrv) origArgs;
})
else if builtins.isFunction ff then {
else if lib.isFunction ff then {
override = newArgs: makeOverridable f (overrideWith newArgs);
__functor = self: ff;
overrideDerivation = throw "overrideDerivation not yet supported for functors";
@ -112,8 +112,8 @@ rec {
*/
callPackageWith = autoArgs: fn: args:
let
f = if builtins.isFunction fn then fn else import fn;
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
f = if lib.isFunction fn then fn else import fn;
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
in makeOverridable f (auto // args);
@ -122,8 +122,8 @@ rec {
individual attributes. */
callPackagesWith = autoArgs: fn: args:
let
f = if builtins.isFunction fn then fn else import fn;
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
f = if lib.isFunction fn then fn else import fn;
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
origArgs = auto // args;
pkgs = f origArgs;
mkAttrOverridable = name: pkg: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
@ -131,8 +131,8 @@ rec {
/* Add attributes to each output of a derivation without changing
the derivation itself. */
addPassthru = drv: passthru:
the derivation itself and check a given condition when evaluating. */
extendDerivation = condition: passthru: drv:
let
outputs = drv.outputs or [ "out" ];
@ -142,13 +142,18 @@ rec {
outputToAttrListElement = outputName:
{ name = outputName;
value = commonAttrs // {
inherit (drv.${outputName}) outPath drvPath type outputName;
inherit (drv.${outputName}) type outputName;
drvPath = assert condition; drv.${outputName}.drvPath;
outPath = assert condition; drv.${outputName}.outPath;
};
};
outputsList = map outputToAttrListElement outputs;
in commonAttrs // { outputUnspecified = true; };
in commonAttrs // {
outputUnspecified = true;
drvPath = assert condition; drv.drvPath;
outPath = assert condition; drv.outPath;
};
/* Strip a derivation of all non-essential attributes, returning
only those needed by hydra-eval-jobs. Also strictly evaluate the

View File

@ -1,9 +1,11 @@
let lib = import ./default.nix;
{ lib }:
inherit (builtins) trace attrNamesToStr isAttrs isFunction isList isInt
let
inherit (builtins) trace attrNamesToStr isAttrs isList isInt
isString isBool head substring attrNames;
inherit (lib) all id mapAttrsFlatten elem;
inherit (lib) all id mapAttrsFlatten elem isFunction;
in

View File

@ -5,58 +5,128 @@
*/
let
# often used, or depending on very little
trivial = import ./trivial.nix;
fixedPoints = import ./fixed-points.nix;
callLibs = file: import file { inherit lib; };
# datatypes
attrsets = import ./attrsets.nix;
lists = import ./lists.nix;
strings = import ./strings.nix;
stringsWithDeps = import ./strings-with-deps.nix;
lib = rec {
# packaging
customisation = import ./customisation.nix;
maintainers = import ./maintainers.nix;
meta = import ./meta.nix;
sources = import ./sources.nix;
# often used, or depending on very little
trivial = callLibs ./trivial.nix;
fixedPoints = callLibs ./fixed-points.nix;
# module system
modules = import ./modules.nix;
options = import ./options.nix;
types = import ./types.nix;
# datatypes
attrsets = callLibs ./attrsets.nix;
lists = callLibs ./lists.nix;
strings = callLibs ./strings.nix;
stringsWithDeps = callLibs ./strings-with-deps.nix;
# constants
licenses = import ./licenses.nix;
systems = import ./systems;
# packaging
customisation = callLibs ./customisation.nix;
maintainers = import ../maintainers/maintainer-list.nix;
meta = callLibs ./meta.nix;
sources = callLibs ./sources.nix;
versions = callLibs ./versions.nix;
# misc
debug = import ./debug.nix;
generators = import ./generators.nix;
misc = import ./deprecated.nix;
# module system
modules = callLibs ./modules.nix;
options = callLibs ./options.nix;
types = callLibs ./types.nix;
# domain-specific
sandbox = import ./sandbox.nix;
fetchers = import ./fetchers.nix;
# constants
licenses = callLibs ./licenses.nix;
systems = callLibs ./systems;
# Eval-time filesystem handling
filesystem = import ./filesystem.nix;
# misc
debug = callLibs ./debug.nix;
in
{ inherit trivial fixedPoints
attrsets lists strings stringsWithDeps
customisation maintainers meta sources
modules options types
licenses systems
debug generators misc
sandbox fetchers filesystem;
generators = callLibs ./generators.nix;
misc = callLibs ./deprecated.nix;
# domain-specific
fetchers = callLibs ./fetchers.nix;
# Eval-time filesystem handling
filesystem = callLibs ./filesystem.nix;
# back-compat aliases
platforms = systems.doubles;
}
# !!! don't include everything at top-level; perhaps only the most
# commonly used functions.
// trivial // fixedPoints
// lists // strings // stringsWithDeps // attrsets // sources
// options // types // meta // debug // misc // modules
// customisation
platforms = systems.forMeta;
inherit (builtins) add addErrorContext attrNames
concatLists deepSeq elem elemAt filter genericClosure genList
getAttr hasAttr head isAttrs isBool isInt isList
isString length lessThan listToAttrs pathExists readFile
replaceStrings seq stringLength sub substring tail;
inherit (trivial) id const concat or and boolToString mergeAttrs
flip mapNullable inNixShell min max importJSON warn info
nixpkgsVersion mod compare splitByAndCompare
functionArgs setFunctionArgs isFunction;
inherit (fixedPoints) fix fix' extends composeExtensions
makeExtensible makeExtensibleWithCustomName;
inherit (attrsets) attrByPath hasAttrByPath setAttrByPath
getAttrFromPath attrVals attrValues catAttrs filterAttrs
filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond
genAttrs isDerivation toDerivation optionalAttrs
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
recursiveUpdate matchAttrs overrideExisting getOutput getBin
getLib getDev chooseDevOutputs zipWithNames zip;
inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
concatMap flatten remove findSingle findFirst any all count
optional optionals toList range partition zipListsWith zipLists
reverseList listDfs toposort sort compareLists take drop sublist
last init crossLists unique intersectLists subtractLists
mutuallyExclusive;
inherit (strings) concatStrings concatMapStrings concatImapStrings
intersperse concatStringsSep concatMapStringsSep
concatImapStringsSep makeSearchPath makeSearchPathOutput
makeLibraryPath makeBinPath makePerlPath optionalString
hasPrefix hasSuffix stringToCharacters stringAsChars escape
escapeShellArg escapeShellArgs replaceChars lowerChars upperChars
toLower toUpper addContextFrom splitString removePrefix
removeSuffix versionOlder versionAtLeast getVersion nameFromURL
enableFeature fixedWidthString fixedWidthNumber isStorePath
toInt readPathsFromFile fileContents;
inherit (stringsWithDeps) textClosureList textClosureMap
noDepEntry fullDepEntry packEntry stringAfter;
inherit (customisation) overrideDerivation makeOverridable
callPackageWith callPackagesWith extendDerivation
hydraJob makeScope;
inherit (meta) addMetaAttrs dontDistribute setName updateName
appendToName mapDerivationAttrset lowPrio lowPrioSet hiPrio
hiPrioSet;
inherit (sources) pathType pathIsDirectory cleanSourceFilter
cleanSource sourceByRegex sourceFilesBySuffices
commitIdFromGitRepo cleanSourceWith pathHasContext canCleanSource;
inherit (modules) evalModules closeModules unifyModuleSyntax
applyIfFunction unpackSubmodule packSubmodule mergeModules
mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
pushDownProperties dischargeProperties filterOverrides
sortProperties fixupOptionType mkIf mkAssert mkMerge mkOverride
mkOptionDefault mkDefault mkForce mkVMOverride mkStrict
mkFixStrictness mkOrder mkBefore mkAfter mkAliasDefinitions
mkAliasAndWrapDefinitions fixMergeModules mkRemovedOptionModule
mkRenamedOptionModule mkMergedOptionModule mkChangedOptionModule
mkAliasOptionModule doRename filterModules;
inherit (options) isOption mkEnableOption mkSinkUndeclaredOptions
mergeDefaultOption mergeOneOption mergeEqualOption getValues
getFiles optionAttrSetToDocList optionAttrSetToDocList'
scrubOptionValue literalExample showOption showFiles
unknownModule mkOption;
inherit (types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType;
inherit (debug) addErrorContextToAttrs traceIf traceVal
traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq
traceValSeqN traceShowVal traceShowValMarked
showVal traceCall traceCall2 traceCall3 traceValIfNot runTests
testAllTrue strict traceCallXml attrNamesToStr;
inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs
defaultOverridableDelayableArgs composedArgsAndFun
maybeAttrNullable maybeAttr ifEnable checkFlag getValue
checkReqs uniqList uniqListExt condConcat lazyGenericClosure
innerModifySumArgs modifySumArgs innerClosePropagation
closePropagation mapAttrsFlatten nvs setAttr setAttrMerge
mergeAttrsWithFunc mergeAttrsConcatenateValues
mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults
mergeAttrsByFuncDefaultsClean mergeAttrBy
prepareDerivationArgs nixType imap overridableDelayableArgs;
};
in lib

View File

@ -1,11 +1,12 @@
let lib = import ./default.nix;
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
{ lib }:
let
inherit (builtins) head tail isList isAttrs isInt attrNames;
in
with import ./lists.nix;
with import ./attrsets.nix;
with import ./strings.nix;
with lib.lists;
with lib.attrsets;
with lib.strings;
rec {
@ -52,7 +53,7 @@ rec {
f: # the function applied to the arguments
initial: # you pass attrs, the functions below are passing a function taking the fix argument
let
takeFixed = if isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
takeFixed = if lib.isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
tidy = args:
let # apply all functions given in "applyPreTidy" in sequence
applyPreTidyFun = fold ( n: a: x: n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
@ -62,7 +63,7 @@ rec {
let args = takeFixed fixed;
mergeFun = args.${n};
in if isAttrs x then (mergeFun args x)
else assert isFunction x;
else assert lib.isFunction x;
mergeFun args (x ( args // { inherit fixed; }));
in overridableDelayableArgs f newArgs;
in
@ -309,48 +310,6 @@ rec {
mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"];
# merge attrs based on version key into mkDerivation args, see mergeAttrBy to learn about smart merge defaults
#
# This function is best explained by an example:
#
# {version ? "2.x"}:
#
# mkDerivation (mergeAttrsByVersion "package-name" version
# { # version specific settings
# "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool]; };
# "2.x" = { src = ..; };
# }
# { // shared settings
# buildInputs = [ common build inputs ];
# meta = { .. }
# }
# )
#
# Please note that e.g. Eelco Dolstra usually prefers having one file for
# each version. On the other hand there are valuable additional design goals
# - readability
# - do it once only
# - try to avoid duplication
#
# Marc Weber and Michael Raskin sometimes prefer keeping older
# versions around for testing and regression tests - as long as its cheap to
# do so.
#
# Very often it just happens that the "shared" code is the bigger part.
# Then using this function might be appropriate.
#
# Be aware that its easy to cause recompilations in all versions when using
# this function - also if derivations get too complex splitting into multiple
# files is the way to go.
#
# See misc.nix -> versionedDerivation
# discussion: nixpkgs: pull/310
mergeAttrsByVersion = name: version: attrsByVersion: base:
mergeAttrsByFuncDefaultsClean [ { name = "${name}-${version}"; }
base
(maybeAttr version (throw "bad version ${version} for ${name}") attrsByVersion)
];
# sane defaults (same name as attr name so that inherit can be used)
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
listToAttrs (map (n: nameValuePair n lib.concat)
@ -415,7 +374,7 @@ rec {
if isAttrs x then
if x ? outPath then "derivation"
else "attrs"
else if isFunction x then "function"
else if lib.isFunction x then "function"
else if isList x then "list"
else if x == true then "bool"
else if x == false then "bool"

View File

@ -1,4 +1,5 @@
# snippets that can be shared by multiple fetchers (pkgs/build-support)
{ lib }:
{
proxyImpureEnvVars = [

View File

@ -1,3 +1,4 @@
{ lib }:
{ # haskellPathsInDir : Path -> Map String Path
# A map of all haskell packages defined in the given path,
# identified by having a cabal file with the same name as the

View File

@ -1,3 +1,4 @@
{ ... }:
rec {
# Compute the fixed point of the given function `f`, which is usually an
# attribute set that expects its final, non-recursive representation as an

View File

@ -7,12 +7,15 @@
* Tests can be found in ./tests.nix
* Documentation in the manual, #sec-generators
*/
with import ./trivial.nix;
{ lib }:
with (lib).trivial;
let
libStr = import ./strings.nix;
libAttr = import ./attrsets.nix;
libStr = lib.strings;
libAttr = lib.attrsets;
flipMapAttrs = flip libAttr.mapAttrs;
inherit (lib) isFunction;
in
rec {
@ -21,11 +24,15 @@ rec {
* character sep. If sep appears in k, it is escaped.
* Helper for synaxes with different separators.
*
* mkKeyValueDefault ":" "f:oo" "bar"
* mkValueString specifies how values should be formatted.
*
* mkKeyValueDefault {} ":" "f:oo" "bar"
* > "f\:oo:bar"
*/
mkKeyValueDefault = sep: k: v:
"${libStr.escape [sep] k}${sep}${toString v}";
mkKeyValueDefault = {
mkValueString ? toString
}: sep: k: v:
"${libStr.escape [sep] k}${sep}${mkValueString v}";
/* Generate a key-value-style config file from an attrset.
@ -33,7 +40,7 @@ rec {
* mkKeyValue is the same as in toINI.
*/
toKeyValue = {
mkKeyValue ? mkKeyValueDefault "="
mkKeyValue ? mkKeyValueDefault {} "="
}: attrs:
let mkLine = k: v: mkKeyValue k v + "\n";
in libStr.concatStrings (libAttr.mapAttrsToList mkLine attrs);
@ -63,7 +70,7 @@ rec {
# apply transformations (e.g. escapes) to section names
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
# format a setting line from key and value
mkKeyValue ? mkKeyValueDefault "="
mkKeyValue ? mkKeyValueDefault {} "="
}: attrsOfAttrs:
let
# map function to string for each key val
@ -105,7 +112,7 @@ rec {
else if isString v then "\"" + v + "\""
else if null == v then "null"
else if isFunction v then
let fna = functionArgs v;
let fna = lib.functionArgs v;
showFnas = concatStringsSep "," (libAttr.mapAttrsToList
(name: hasDefVal: if hasDefVal then "(${name})" else name)
fna);
@ -125,6 +132,6 @@ rec {
(name: value:
"${toPretty args name} = ${toPretty args value};") v)
+ " }"
else "toPretty: should never happen (v = ${v})";
else abort "toPretty: should never happen (v = ${v})";
}

View File

@ -1,9 +1,8 @@
{ lib }:
let
lib = import ./default.nix;
spdx = lic: lic // {
url = "http://spdx.org/licenses/${lic.spdxId}";
url = "http://spdx.org/licenses/${lic.spdxId}.html";
};
in
@ -16,7 +15,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
afl21 = spdx {
spdxId = "AFL-2.1";
fullName = "Academic Free License";
fullName = "Academic Free License v2.1";
};
afl3 = spdx {
spdxId = "AFL-3.0";
fullName = "Academic Free License v3.0";
};
agpl3 = spdx {
@ -75,6 +79,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = ''Beerware License'';
};
bsd0 = spdx {
spdxId = "0BSD";
fullName = "BSD Zero Clause License";
};
bsd2 = spdx {
spdxId = "BSD-2-Clause";
fullName = ''BSD 2-clause "Simplified" License'';
@ -90,6 +99,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = ''BSD 4-clause "Original" or "Old" License'';
};
clArtistic = spdx {
spdxId = "ClArtistic";
fullName = "Clarified Artistic License";
};
cc0 = spdx {
spdxId = "CC0-1.0";
fullName = "Creative Commons Zero v1.0 Universal";
@ -165,6 +179,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "CeCILL-C Free Software License Agreement";
};
cpal10 = spdx {
spdxId = "CPAL-1.0";
fullName = "Common Public Attribution License 1.0";
};
cpl10 = spdx {
spdxId = "CPL-1.0";
fullName = "Common Public License 1.0";
@ -175,6 +194,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "DOC License";
};
eapl = {
fullName = "EPSON AVASYS PUBLIC LICENSE";
url = http://avasys.jp/hp/menu000000700/hpg000000603.htm;
free = false;
};
efl10 = spdx {
spdxId = "EFL-1.0";
fullName = "Eiffel Forum License v1.0";
@ -190,6 +215,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Eclipse Public License 1.0";
};
epl20 = spdx {
spdxId = "EPL-2.0";
fullName = "Eclipse Public License 2.0";
};
epson = {
fullName = "Seiko Epson Corporation Software License Agreement for Linux";
url = https://download.ebz.epson.net/dsc/du/02/eula/global/LINUX_EN.html;
@ -198,7 +228,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
eupl11 = spdx {
spdxId = "EUPL-1.1";
fullname = "European Union Public License 1.1";
fullName = "European Union Public License 1.1";
};
fdl12 = spdx {
@ -211,6 +241,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "GNU Free Documentation License v1.3";
};
ffsl = {
fullName = "Floodgap Free Software License";
url = http://www.floodgap.com/software/ffsl/license.html;
free = false;
};
free = {
fullName = "Unspecified free software license";
};
@ -271,6 +307,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
};
hpnd = spdx {
spdxId = "HPND";
fullName = "Historic Permission Notice and Disclaimer";
};
# Intel's license, seems free
iasl = {
fullName = "iASL";
@ -282,9 +323,16 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Independent JPEG Group License";
};
inria = {
fullName = "INRIA Non-Commercial License Agreement";
inria-compcert = {
fullName = "INRIA Non-Commercial License Agreement for the CompCert verified compiler";
url = "http://compcert.inria.fr/doc/LICENSE";
free = false;
};
inria-icesl = {
fullName = "INRIA Non-Commercial License Agreement for IceSL";
url = "http://shapeforge.loria.fr/icesl/EULA_IceSL_binary.pdf";
free = false;
};
ipa = spdx {
@ -363,7 +411,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
};
miros = {
fullname = "MirOS License";
fullName = "MirOS License";
url = https://opensource.org/licenses/MirOS;
};
@ -408,7 +456,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
url = "https://raw.githubusercontent.com/raboof/notion/master/LICENSE";
fullName = "Notion modified LGPL";
};
nposl3 = spdx {
spdxId = "NPOSL-3.0";
fullName = "Non-Profit Open Software License 3.0";
};
ofl = spdx {
spdxId = "OFL-1.1";
fullName = "SIL Open Font License 1.1";
@ -424,6 +477,16 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "OpenSSL License";
};
osl21 = spdx {
spdxId = "OSL-2.1";
fullName = "Open Software License 2.1";
};
osl3 = spdx {
spdxId = "OSL-3.0";
fullName = "Open Software License 3.0";
};
php301 = spdx {
spdxId = "PHP-3.01";
fullName = "PHP License v3.01";
@ -434,6 +497,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "PostgreSQL License";
};
postman = {
fullName = "Postman EULA";
url = https://www.getpostman.com/licenses/postman_base_app;
free = false;
};
psfl = spdx {
spdxId = "Python-2.0";
fullName = "Python Software Foundation License version 2";
@ -521,6 +590,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Vovida Software License v1.0";
};
watcom = spdx {
spdxId = "Watcom-1.0";
fullName = "Sybase Open Watcom Public License 1.0";
};
w3c = spdx {
spdxId = "W3C";
fullName = "W3C Software Notice and License";
@ -546,14 +620,13 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "zlib License";
};
zpt20 = spdx { # FIXME: why zpt* instead of zpl*
zpl20 = spdx {
spdxId = "ZPL-2.0";
fullName = "Zope Public License 2.0";
};
zpt21 = spdx {
zpl21 = spdx {
spdxId = "ZPL-2.1";
fullName = "Zope Public License 2.1";
};
}

View File

@ -1,6 +1,6 @@
# General list operations.
with import ./trivial.nix;
{ lib }:
with lib.trivial;
rec {
@ -385,6 +385,30 @@ rec {
if len < 2 then list
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
/* Compare two lists element-by-element.
Example:
compareLists compare [] []
=> 0
compareLists compare [] [ "a" ]
=> -1
compareLists compare [ "a" ] []
=> 1
compareLists compare [ "a" "b" ] [ "a" "c" ]
=> 1
*/
compareLists = cmp: a: b:
if a == []
then if b == []
then 0
else -1
else if b == []
then 1
else let rel = cmp (head a) (head b); in
if rel == 0
then compareLists cmp (tail a) (tail b)
else rel;
/* Return the first (at most) N elements of a list.
Example:
@ -440,8 +464,12 @@ rec {
init = list: assert list != []; take (length list - 1) list;
/* FIXME(zimbatm) Not used anywhere
*/
/* return the image of the cross product of some lists by a function
Example:
crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
=> [ "13" "14" "23" "24" ]
*/
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];

View File

@ -1,634 +0,0 @@
/* List of NixOS maintainers. The format is:
handle = "Real Name <address@example.org>";
where <handle> is preferred to be your GitHub username (so it's easy
to ping a package @<handle>), and <Real Name> is your real name, not
a pseudonym. Please keep the list alphabetically sorted. */
{
a1russell = "Adam Russell <adamlr6+pub@gmail.com>";
aaronschif = "Aaron Schif <aaronschif@gmail.com>";
abaldeau = "Andreas Baldeau <andreas@baldeau.net>";
abbradar = "Nikolay Amiantov <ab@fmap.me>";
abigailbuccaneer = "Abigail Bunyan <abigailbuccaneer@gmail.com>";
aboseley = "Adam Boseley <adam.boseley@gmail.com>";
abuibrahim = "Ruslan Babayev <ruslan@babayev.com>";
acowley = "Anthony Cowley <acowley@gmail.com>";
adelbertc = "Adelbert Chang <adelbertc@gmail.com>";
adev = "Adrien Devresse <adev@adev.name>";
adisbladis = "Adam Hose <adis@blad.is>";
Adjective-Object = "Maxwell Huang-Hobbs <mhuan13@gmail.com>";
adnelson = "Allen Nelson <ithinkican@gmail.com>";
adolfogc = "Adolfo E. García Castro <adolfo.garcia.cr@gmail.com>";
aespinosa = "Allan Espinosa <allan.espinosa@outlook.com>";
aflatter = "Alexander Flatter <flatter@fastmail.fm>";
afldcr = "James Alexander Feldman-Crough <alex@fldcr.com>";
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
afranchuk = "Alex Franchuk <alex.franchuk@gmail.com>";
aherrmann = "Andreas Herrmann <andreash87@gmx.ch>";
ahmedtd = "Taahir Ahmed <ahmed.taahir@gmail.com>";
ak = "Alexander Kjeldaas <ak@formalprivacy.com>";
akaWolf = "Artjom Vejsel <akawolf0@gmail.com>";
akc = "Anders Claesson <akc@akc.is>";
algorith = "Dries Van Daele <dries_van_daele@telenet.be>";
alibabzo = "Alistair Bill <alistair.bill@gmail.com>";
all = "Nix Committers <nix-commits@lists.science.uu.nl>";
ambrop72 = "Ambroz Bizjak <ambrop7@gmail.com>";
amiddelk = "Arie Middelkoop <amiddelk@gmail.com>";
amiloradovsky = "Andrew Miloradovsky <miloradovsky@gmail.com>";
amorsillo = "Andrew Morsillo <andrew.morsillo@gmail.com>";
AndersonTorres = "Anderson Torres <torres.anderson.85@gmail.com>";
anderspapitto = "Anders Papitto <anderspapitto@gmail.com>";
andres = "Andres Loeh <ksnixos@andres-loeh.de>";
andrewrk = "Andrew Kelley <superjoe30@gmail.com>";
andsild = "Anders Sildnes <andsild@gmail.com>";
aneeshusa = "Aneesh Agrawal <aneeshusa@gmail.com>";
ankhers = "Justin Wood <justin.k.wood@gmail.com>";
antono = "Antono Vasiljev <self@antono.info>";
apeschar = "Albert Peschar <albert@peschar.net>";
apeyroux = "Alexandre Peyroux <alex@px.io>";
ardumont = "Antoine R. Dumont <eniotna.t@gmail.com>";
aristid = "Aristid Breitkreuz <aristidb@gmail.com>";
arobyn = "Alexei Robyn <shados@shados.net>";
artuuge = "Artur E. Ruuge <artuuge@gmail.com>";
ashalkhakov = "Artyom Shalkhakov <artyom.shalkhakov@gmail.com>";
aske = "Kirill Boltaev <aske@fmap.me>";
asppsa = "Alastair Pharo <asppsa@gmail.com>";
astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>";
asymmetric = "Lorenzo Manacorda <lorenzo@mailbox.org>";
aszlig = "aszlig <aszlig@redmoonstudios.org>";
auntie = "Jonathan Glines <auntieNeo@gmail.com>";
avnik = "Alexander V. Nikolaev <avn@avnik.info>";
aycanirican = "Aycan iRiCAN <iricanaycan@gmail.com>";
bachp = "Pascal Bach <pascal.bach@nextrem.ch>";
badi = "Badi' Abdul-Wahid <abdulwahidc@gmail.com>";
balajisivaraman = "Balaji Sivaraman<sivaraman.balaji@gmail.com>";
barrucadu = "Michael Walker <mike@barrucadu.co.uk>";
basvandijk = "Bas van Dijk <v.dijk.bas@gmail.com>";
Baughn = "Svein Ove Aas <sveina@gmail.com>";
bcarrell = "Brandon Carrell <brandoncarrell@gmail.com>";
bcdarwin = "Ben Darwin <bcdarwin@gmail.com>";
bdimcheff = "Brandon Dimcheff <brandon@dimcheff.com>";
benley = "Benjamin Staffin <benley@gmail.com>";
bennofs = "Benno Fünfstück <benno.fuenfstueck@gmail.com>";
benwbooth = "Ben Booth <benwbooth@gmail.com>";
berdario = "Dario Bertini <berdario@gmail.com>";
bergey = "Daniel Bergey <bergey@teallabs.org>";
bhipple = "Benjamin Hipple <bhipple@protonmail.com>";
bjg = "Brian Gough <bjg@gnu.org>";
bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>";
bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>";
bobakker = "Bo Bakker <bobakk3r@gmail.com>";
bobvanderlinden = "Bob van der Linden <bobvanderlinden@gmail.com>";
bodil = "Bodil Stokke <nix@bodil.org>";
boothead = "Ben Ford <ben@perurbis.com>";
bosu = "Boris Sukholitko <boriss@gmail.com>";
bradediger = "Brad Ediger <brad@bradediger.com>";
bramd = "Bram Duvigneau <bram@bramd.nl>";
bstrik = "Berno Strik <dutchman55@gmx.com>";
bzizou = "Bruno Bzeznik <Bruno@bzizou.net>";
c0dehero = "CodeHero <codehero@nerdpol.ch>";
calrama = "Moritz Maxeiner <moritz@ucworks.org>";
calvertvl = "Victor Calvert <calvertvl@gmail.com>";
campadrenalin = "Philip Horger <campadrenalin@gmail.com>";
canndrew = "Andrew Cann <shum@canndrew.org>";
carlsverre = "Carl Sverre <accounts@carlsverre.com>";
cdepillabout = "Dennis Gosnell <cdep.illabout@gmail.com>";
cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>";
changlinli = "Changlin Li <mail@changlinli.com>";
chaoflow = "Florian Friesdorf <flo@chaoflow.net>";
chattered = "Phil Scott <me@philscotted.com>";
choochootrain = "Hurshal Patel <hurshal@imap.cc>";
chris-martin = "Chris Martin <ch.martin@gmail.com>";
chrisjefferson = "Christopher Jefferson <chris@bubblescope.net>";
christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>";
ciil = "Simon Lackerbauer <simon@lackerbauer.com>";
ckampka = "Christian Kampka <christian@kampka.net>";
cko = "Christine Koppelt <christine.koppelt@gmail.com>";
cleverca22 = "Michael Bishop <cleverca22@gmail.com>";
cmcdragonkai = "Roger Qiu <roger.qiu@matrix.ai>";
cmfwyp = "cmfwyp <cmfwyp@riseup.net>";
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
codsl = "codsl <codsl@riseup.net>";
codyopel = "Cody Opel <codyopel@gmail.com>";
colemickens = "Cole Mickens <cole.mickens@gmail.com>";
colescott = "Cole Scott <colescottsf@gmail.com>";
copumpkin = "Dan Peebles <pumpkingod@gmail.com>";
corngood = "David McFarland <corngood@gmail.com>";
coroa = "Jonas Hörsch <jonas@chaoflow.net>";
couchemar = "Andrey Pavlov <couchemar@yandex.ru>";
cpages = "Carles Pagès <page@ruiec.cat>";
cransom = "Casey Ransom <cransom@hubns.net>";
cryptix = "Henry Bubert <cryptix@riseup.net>";
CrystalGamma = "Jona Stubbe <nixos@crystalgamma.de>";
cstrahan = "Charles Strahan <charles@cstrahan.com>";
cwoac = "Oliver Matthews <oliver@codersoffortune.net>";
DamienCassou = "Damien Cassou <damien@cassou.me>";
danbst = "Danylo Hlynskyi <abcz2.uprola@gmail.com>";
dancek = "Hannu Hartikainen <hannu.hartikainen@gmail.com>";
danielfullmer = "Daniel Fullmer <danielrf12@gmail.com>";
dasuxullebt = "Christoph-Simon Senjak <christoph.senjak@googlemail.com>";
davidak = "David Kleuker <post@davidak.de>";
davidrusu = "David Rusu <davidrusu.me@gmail.com>";
davorb = "Davor Babic <davor@davor.se>";
dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>";
dbrock = "Daniel Brockman <daniel@brockman.se>";
deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>";
demin-dmitriy = "Dmitriy Demin <demindf@gmail.com>";
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
dermetfan = "Robin Stumm <serverkorken@gmail.com>";
DerTim1 = "Tim Digel <tim.digel@active-group.de>";
desiderius = "Didier J. Devroye <didier@devroye.name>";
devhell = "devhell <\"^\"@regexmail.net>";
dezgeg = "Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>";
dfoxfranke = "Daniel Fox Franke <dfoxfranke@gmail.com>";
dgonyeo = "Derek Gonyeo <derek@gonyeo.com>";
dipinhora = "Dipin Hora <dipinhora+github@gmail.com>";
disassembler = "Samuel Leathers <disasm@gmail.com>";
dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>";
DmitryTsygankov = "Dmitry Tsygankov <dmitry.tsygankov@gmail.com>";
dmjio = "David Johnson <djohnson.m@gmail.com>";
dochang = "Desmond O. Chang <dochang@gmail.com>";
domenkozar = "Domen Kozar <domen@dev.si>";
dotlambda = "Robert Schütz <rschuetz17@gmail.com>";
doublec = "Chris Double <chris.double@double.co.nz>";
dpaetzel = "David Pätzel <david.a.paetzel@gmail.com>";
drets = "Dmytro Rets <dmitryrets@gmail.com>";
drewkett = "Andrew Burkett <burkett.andrew@gmail.com>";
dsferruzza = "David Sferruzza <david.sferruzza@gmail.com>";
dtzWill = "Will Dietz <nix@wdtz.org>";
dywedir = "Vladyslav M. <dywedir@protonmail.ch>";
e-user = "Alexander Kahl <nixos@sodosopa.io>";
ebzzry = "Rommel Martinez <ebzzry@gmail.com>";
edanaher = "Evan Danaher <nixos@edanaher.net>";
edef = "edef <edef@edef.eu>";
ederoyd46 = "Matthew Brown <matt@ederoyd.co.uk>";
eduarrrd = "Eduard Bachmakov <e.bachmakov@gmail.com>";
edwtjo = "Edward Tjörnhammar <ed@cflags.cc>";
eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
ehegnes = "Eric Hegnes <eric.hegnes@gmail.com>";
ehmry = "Emery Hemingway <emery@vfemail.net>";
eikek = "Eike Kettner <eike.kettner@posteo.de>";
ekleog = "Leo Gaspard <leo@gaspard.io>";
elasticdog = "Aaron Bull Schaefer <aaron@elasticdog.com>";
eleanor = "Dejan Lukan <dejan@proteansec.com>";
elijahcaine = "Elijah Caine <elijahcainemv@gmail.com>";
elitak = "Eric Litak <elitak@gmail.com>";
ellis = "Ellis Whitehead <nixos@ellisw.net>";
eperuffo = "Emanuele Peruffo <info@emanueleperuffo.com>";
epitrochoid = "Mabry Cervin <mpcervin@uncg.edu>";
ericbmerritt = "Eric Merritt <eric@afiniate.com>";
ericsagnes = "Eric Sagnes <eric.sagnes@gmail.com>";
erikryb = "Erik Rybakken <erik.rybakken@math.ntnu.no>";
ertes = "Ertugrul Söylemez <esz@posteo.de>";
ethercrow = "Dmitry Ivanov <ethercrow@gmail.com>";
exi = "Reno Reckling <nixos@reckling.org>";
exlevan = "Alexey Levan <exlevan@gmail.com>";
expipiplus1 = "Joe Hermaszewski <nix@monoid.al>";
fadenb = "Tristan Helmich <tristan.helmich+nixos@gmail.com>";
fare = "Francois-Rene Rideau <fahree@gmail.com>";
falsifian = "James Cook <james.cook@utoronto.ca>";
florianjacob = "Florian Jacob <projects+nixos@florianjacob.de>";
flosse = "Markus Kohlhase <mail@markus-kohlhase.de>";
fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>";
fmthoma = "Franz Thoma <f.m.thoma@googlemail.com>";
forkk = "Andrew Okin <forkk@forkk.net>";
fornever = "Friedrich von Never <friedrich@fornever.me>";
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
fps = "Florian Paul Schmidt <mista.tapas@gmx.net>";
fridh = "Frederik Rietdijk <fridh@fridh.nl>";
frlan = "Frank Lanitz <frank@frank.uvena.de>";
fro_ozen = "fro_ozen <fro_ozen@gmx.de>";
ftrvxmtrx = "Siarhei Zirukin <ftrvxmtrx@gmail.com>";
funfunctor = "Edward O'Callaghan <eocallaghan@alterapraxis.com>";
fuuzetsu = "Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>";
fuzzy-id = "Thomas Bach <hacking+nixos@babibo.de>";
fxfactorial = "Edgar Aroutiounian <edgar.factorial@gmail.com>";
gal_bolle = "Florent Becker <florent.becker@ens-lyon.org>";
garbas = "Rok Garbas <rok@garbas.si>";
garrison = "Jim Garrison <jim@garrison.cc>";
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
gebner = "Gabriel Ebner <gebner@gebner.org>";
georgewhewell = "George Whewell <georgerw@gmail.com>";
gilligan = "Tobias Pflug <tobias.pflug@gmail.com>";
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
gleber = "Gleb Peregud <gleber.p@gmail.com>";
globin = "Robin Gloster <mail@glob.in>";
gnidorah = "Alex Ivanov <yourbestfriend@opmbx.org>";
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
Gonzih = "Max Gonzih <gonzih@gmail.com>";
goodrone = "Andrew Trachenko <goodrone@gmail.com>";
gpyh = "Yacine Hmito <yacine.hmito@gmail.com>";
grahamc = "Graham Christensen <graham@grahamc.com>";
grburst = "Julius Elias <grburst@openmailbox.org>";
gridaphobe = "Eric Seidel <eric@seidel.io>";
guibert = "David Guibert <david.guibert@gmail.com>";
guillaumekoenig = "Guillaume Koenig <guillaume.edward.koenig@gmail.com>";
guyonvarch = "Joris Guyonvarch <joris@guyonvarch.me>";
hakuch = "Jesse Haber-Kucharsky <hakuch@gmail.com>";
havvy = "Ryan Scheel <ryan.havvy@gmail.com>";
hbunke = "Hendrik Bunke <bunke.hendrik@gmail.com>";
hce = "Hans-Christian Esperer <hc@hcesperer.org>";
hectorj = "Hector Jusforgues <hector.jusforgues+nixos@gmail.com>";
heel = "Sergii Paryzhskyi <parizhskiy@gmail.com>";
henrytill = "Henry Till <henrytill@gmail.com>";
hhm = "hhm <heehooman+nixpkgs@gmail.com>";
hinton = "Tom Hinton <t@larkery.com>";
hodapp = "Chris Hodapp <hodapp87@gmail.com>";
hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>";
htr = "Hugo Tavares Reis <hugo@linux.com>";
iand675 = "Ian Duncan <ian@iankduncan.com>";
ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>";
igsha = "Igor Sharonov <igor.sharonov@gmail.com>";
ikervagyok = "Balázs Lengyel <ikervagyok@gmail.com>";
infinisil = "Silvan Mosberger <infinisil@icloud.com";
ivan-tkatchev = "Ivan Tkatchev <tkatchev@gmail.com>";
j-keck = "Jürgen Keck <jhyphenkeck@gmail.com>";
jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>";
jammerful = "jammerful <jammerful@gmail.com>";
jansol = "Jan Solanti <jan.solanti@paivola.fi>";
javaguirre = "Javier Aguirre <contacto@javaguirre.net>";
jb55 = "William Casarin <jb55@jb55.com>";
jbedo = "Justin Bedő <cu@cua0.org>";
jcumming = "Jack Cummings <jack@mudshark.org>";
jdagilliland = "Jason Gilliland <jdagilliland@gmail.com>";
jefdaj = "Jeffrey David Johnson <jefdaj@gmail.com>";
jensbin = "Jens Binkert <jensbin@protonmail.com>";
jerith666 = "Matt McHenry <github@matt.mchenryfamily.org>";
jfb = "James Felix Black <james@yamtime.com>";
jfrankenau = "Johannes Frankenau <johannes@frankenau.net>";
jgeerds = "Jascha Geerds <jascha@jgeerds.name>";
jgertm = "Tim Jaeger <jger.tm@gmail.com>";
jgillich = "Jakob Gillich <jakob@gillich.me>";
jhhuh = "Ji-Haeng Huh <jhhuh.note@gmail.com>";
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
jlesquembre = "José Luis Lafuente <jl@lafuente.me>";
jluttine = "Jaakko Luttinen <jaakko.luttinen@iki.fi>";
joachifm = "Joachim Fasting <joachifm@fastmail.fm>";
joamaki = "Jussi Maki <joamaki@gmail.com>";
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
joelteon = "Joel Taylor <me@joelt.io>";
johbo = "Johannes Bornhold <johannes@bornhold.name>";
johnramsden = "John Ramsden <johnramsden@riseup.net>";
joko = "Ioannis Koutras <ioannis.koutras@gmail.com>";
jonafato = "Jon Banafato <jon@jonafato.com>";
jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>";
jpierre03 = "Jean-Pierre PRUNARET <nix@prunetwork.fr>";
jpotier = "Martin Potier <jpo.contributes.to.nixos@marvid.fr>";
jraygauthier = "Raymond Gauthier <jraygauthier@gmail.com>";
jtojnar = "Jan Tojnar <jtojnar@gmail.com>";
juliendehos = "Julien Dehos <dehos@lisic.univ-littoral.fr>";
jwiegley = "John Wiegley <johnw@newartisans.com>";
jwilberding = "Jordan Wilberding <jwilberding@afiniate.com>";
jzellner = "Jeff Zellner <jeffz@eml.cc>";
kaiha = "Kai Harries <kai.harries@gmail.com>";
kamilchm = "Kamil Chmielewski <kamil.chm@gmail.com>";
kampfschlaefer = "Arnold Krille <arnold@arnoldarts.de>";
kentjames = "James Kent <jameschristopherkent@gmail.com";
kevincox = "Kevin Cox <kevincox@kevincox.ca>";
khumba = "Bryan Gardiner <bog@khumba.net>";
KibaFox = "Kiba Fox <kiba.fox@foxypossibilities.com>";
kierdavis = "Kier Davis <kierdavis@gmail.com>";
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
knedlsepp = "Josef Kemetmüller <josef.kemetmueller@gmail.com>";
koral = "Koral <koral@mailoo.org>";
kovirobi = "Kovacsics Robert <kovirobi@gmail.com>";
kragniz = "Louis Taylor <louis@kragniz.eu>";
kristoff3r = "Kristoffer Søholm <k.soeholm@gmail.com>";
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
lassulus = "Lassulus <lassulus@gmail.com>";
layus = "Guillaume Maudoux <layus.on@gmail.com>";
ldesgoui = "Lucas Desgouilles <ldesgoui@gmail.com>";
league = "Christopher League <league@contrapunctus.net>";
lebastr = "Alexander Lebedev <lebastr@gmail.com>";
leemachin = "Lee Machin <me@mrl.ee>";
leenaars = "Michiel Leenaars <ml.software@leenaa.rs>";
leonardoce = "Leonardo Cecchi <leonardo.cecchi@gmail.com>";
lethalman = "Luca Bruno <lucabru@src.gnome.org>";
lewo = "Antoine Eiche <lewo@abesis.fr>";
lheckemann = "Linus Heckemann <git@sphalerite.org>";
lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>";
lihop = "Leroy Hopson <nixos@leroy.geek.nz>";
linquize = "Linquize <linquize@yahoo.com.hk>";
linus = "Linus Arver <linusarver@gmail.com>";
lnl7 = "Daiderd Jordan <daiderd@gmail.com>";
loskutov = "Ignat Loskutov <ignat.loskutov@gmail.com>";
lovek323 = "Jason O'Conal <jason@oconal.id.au>";
lowfatcomputing = "Andreas Wagner <andreas.wagner@lowfatcomputing.org>";
lsix = "Lancelot SIX <lsix@lancelotsix.com>";
lucas8 = "Luc Chabassier <luc.linux@mailoo.org>";
ludo = "Ludovic Courtès <ludo@gnu.org>";
lufia = "Kyohei Kadota <lufia@lufia.org>";
luispedro = "Luis Pedro Coelho <luis@luispedro.org>";
lukego = "Luke Gorrie <luke@snabb.co>";
lw = "Sergey Sofeychuk <lw@fmap.me>";
lyt = "Tim Liou <wheatdoge@gmail.com>";
m3tti = "Mathaeus Sander <mathaeus.peter.sander@gmail.com>";
ma27 = "Maximilian Bosch <maximilian@mbosch.me>";
madjar = "Georges Dubus <georges.dubus@compiletoi.net>";
magnetophon = "Bart Brouns <bart@magnetophon.nl>";
mahe = "Matthias Herrmann <matthias.mh.herrmann@gmail.com>";
makefu = "Felix Richter <makefu@syntax-fehler.de>";
malyn = "Michael Alyn Miller <malyn@strangeGizmo.com>";
manveru = "Michael Fellinger <m.fellinger@gmail.com>";
marcweber = "Marc Weber <marco-oweber@gmx.de>";
markus1189 = "Markus Hauck <markus1189@gmail.com>";
markWot = "Markus Wotringer <markus@wotringer.de>";
martijnvermaat = "Martijn Vermaat <martijn@vermaat.name>";
martingms = "Martin Gammelsæter <martin@mg.am>";
matejc = "Matej Cotman <cotman.matej@gmail.com>";
mathnerd314 = "Mathnerd314 <mathnerd314.gph+hs@gmail.com>";
matthewbauer = "Matthew Bauer <mjbauer95@gmail.com>";
matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>";
maurer = "Matthew Maurer <matthew.r.maurer+nix@gmail.com>";
mbakke = "Marius Bakke <mbakke@fastmail.com>";
mbbx6spp = "Susan Potter <me@susanpotter.net>";
mbe = "Brandon Edens <brandonedens@gmail.com>";
mboes = "Mathieu Boespflug <mboes@tweag.net>";
mbrgm = "Marius Bergmann <marius@yeai.de>";
mcmtroffaes = "Matthias C. M. Troffaes <matthias.troffaes@gmail.com>";
mdaiter = "Matthew S. Daiter <mdaiter8121@gmail.com>";
meditans = "Carlo Nucera <meditans@gmail.com>";
meisternu = "Matt Miemiec <meister@krutt.org>";
metabar = "Celine Mercier <softs@metabarcoding.org>";
mguentner = "Maximilian Güntner <code@klandest.in>";
mic92 = "Jörg Thalheim <joerg@thalheim.io>";
michaelpj = "Michael Peyton Jones <michaelpj@gmail.com>";
michalrus = "Michal Rus <m@michalrus.com>";
michelk = "Michel Kuhlmann <michel@kuhlmanns.info>";
midchildan = "midchildan <midchildan+nix@gmail.com>";
mikefaille = "Michaël Faille <michael@faille.io>";
miltador = "Vasiliy Solovey <miltador@yandex.ua>";
mimadrid = "Miguel Madrid <mimadrid@ucm.es>";
mingchuan = "Ming Chuan <ming@culpring.com>";
mirdhyn = "Merlin Gaillard <mirdhyn@gmail.com>";
mirrexagon = "Andrew Abbott <mirrexagon@mirrexagon.com>";
mjanczyk = "Marcin Janczyk <m@dragonvr.pl>";
mlieberman85 = "Michael Lieberman <mlieberman85@gmail.com>";
modulistic = "Pablo Costa <modulistic@gmail.com>";
mog = "Matthew O'Gorman <mog-lists@rldn.net>";
montag451 = "montag451 <montag451@laposte.net>";
moosingin3space = "Nathan Moos <moosingin3space@gmail.com>";
moretea = "Maarten Hoogendoorn <maarten@moretea.nl>";
mornfall = "Petr Ročkai <me@mornfall.net>";
MostAwesomeDude = "Corbin Simpson <cds@corbinsimpson.com>";
mounium = "Katona László <muoniurn@gmail.com>";
MP2E = "Cray Elliott <MP2E@archlinux.us>";
mpscholten = "Marc Scholten <marc@mpscholten.de>";
mpsyco = "Francis St-Amour <fr.st-amour@gmail.com>";
msackman = "Matthew Sackman <matthew@wellquite.org>";
mschristiansen = "Mikkel Christiansen <mikkel@rheosystems.com>";
msteen = "Matthijs Steen <emailmatthijs@gmail.com>";
mt-caret = "Masayuki Takeda <mtakeda.enigsol@gmail.com>";
mtreskin = "Max Treskin <zerthurd@gmail.com>";
mudri = "James Wood <lamudri@gmail.com>";
muflax = "Stefan Dorn <mail@muflax.com>";
myrl = "Myrl Hex <myrl.0xf@gmail.com>";
namore = "Roman Naumann <namor@hemio.de>";
nand0p = "Fernando Jose Pando <nando@hex7.com>";
Nate-Devv = "Nathan Moore <natedevv@gmail.com>";
nathan-gs = "Nathan Bijnens <nathan@nathan.gs>";
nckx = "Tobias Geerinckx-Rice <github@tobias.gr>";
ndowens = "Nathan Owens <ndowens04@gmail.com>";
neeasade = "Nathan Isom <nathanisom27@gmail.com>";
nequissimus = "Tim Steinbach <tim@nequissimus.com>";
nfjinjing = "Jinjing Wang <nfjinjing@gmail.com>";
nh2 = "Niklas Hambüchen <mail@nh2.me>";
nhooyr = "Anmol Sethi <anmol@aubble.com>";
nickhu = "Nick Hu <me@nickhu.co.uk>";
nicknovitski = "Nick Novitski <nixpkgs@nicknovitski.com>";
nico202 = "Nicolò Balzarotti <anothersms@gmail.com>";
NikolaMandic = "Ratko Mladic <nikola@mandic.email>";
nixy = "Andrew R. M. <andrewmiller237@gmail.com>";
nocoolnametom = "Tom Doggett <nocoolnametom@gmail.com>";
notthemessiah = "Brian Cohen <brian.cohen.88@gmail.com>";
np = "Nicolas Pouillard <np.nix@nicolaspouillard.fr>";
nslqqq = "Nikita Mikhailov <nslqqq@gmail.com>";
nthorne = "Niklas Thörne <notrupertthorne@gmail.com>";
obadz = "obadz <obadz-nixos@obadz.com>";
ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
odi = "Oliver Dunkl <oliver.dunkl@gmail.com>";
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
oida = "oida <oida@posteo.de>";
okasu = "Okasu <oka.sux@gmail.com>";
olcai = "Erik Timan <dev@timan.info>";
olejorgenb = "Ole Jørgen Brønner <olejorgenb@yahoo.no>";
olynch = "Owen Lynch <owen@olynch.me>";
orbekk = "KJ Ørbekk <kjetil.orbekk@gmail.com>";
orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
orivej = "Orivej Desh <orivej@gmx.fr>";
osener = "Ozan Sener <ozan@ozansener.com>";
otwieracz = "Slawomir Gonet <slawek@otwiera.cz>";
oxij = "Jan Malakhovski <oxij@oxij.org>";
paholg = "Paho Lurie-Gregg <paho@paholg.com>";
pakhfn = "Fedor Pakhomov <pakhfn@gmail.com>";
palo = "Ingolf Wanger <palipalo9@googlemail.com>";
panaeon = "Vitalii Voloshyn <vitalii.voloshyn@gmail.com";
paperdigits = "Mica Semrick <mica@silentumbrella.com>";
pashev = "Igor Pashev <pashev.igor@gmail.com>";
patternspandemic = "Brad Christensen <patternspandemic@live.com>";
pawelpacana = "Paweł Pacana <pawel.pacana@gmail.com>";
pbogdan = "Piotr Bogdan <ppbogdan@gmail.com>";
periklis = "theopompos@gmail.com";
pesterhazy = "Paulus Esterhazy <pesterhazy@gmail.com>";
peterhoeg = "Peter Hoeg <peter@hoeg.com>";
peti = "Peter Simons <simons@cryp.to>";
philandstuff = "Philip Potter <philip.g.potter@gmail.com>";
phile314 = "Philipp Hausmann <nix@314.ch>";
Phlogistique = "Noé Rubinstein <noe.rubinstein@gmail.com>";
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
phunehehe = "Hoang Xuan Phu <phunehehe@gmail.com>";
pierrer = "Pierre Radermecker <pierrer@pi3r.be>";
pierron = "Nicolas B. Pierron <nixos@nbp.name>";
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
pjbarnoy = "Perry Barnoy <pjbarnoy@gmail.com>";
pjones = "Peter Jones <pjones@devalot.com>";
pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>";
plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>";
plumps = "Maksim Bronsky <maks.bronsky@web.de";
pmahoney = "Patrick Mahoney <pat@polycrystal.org>";
pmiddend = "Philipp Middendorf <pmidden@secure.mailbox.org>";
polyrod = "Maurizio Di Pietro <dc1mdp@gmail.com>";
pradeepchhetri = "Pradeep Chhetri <pradeep.chhetri89@gmail.com>";
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
primeos = "Michael Weiss <dev.primeos@gmail.com>";
profpatsch = "Profpatsch <mail@profpatsch.de>";
proglodyte = "Proglodyte <proglodyte23@gmail.com>";
pshendry = "Paul Hendry <paul@pshendry.com>";
psibi = "Sibi <sibi@psibi.in>";
pstn = "Philipp Steinpaß <philipp@xndr.de>";
pSub = "Pascal Wittmann <mail@pascal-wittmann.de>";
puffnfresh = "Brian McKenna <brian@brianmckenna.org>";
pxc = "Patrick Callahan <patrick.callahan@latitudeengineering.com>";
qknight = "Joachim Schiele <js@lastlog.de>";
ragge = "Ragnar Dahlen <r.dahlen@gmail.com>";
ralith = "Benjamin Saunders <ben.e.saunders@gmail.com>";
ramkromberg = "Ram Kromberg <ramkromberg@mail.com>";
rardiol = "Ricardo Ardissone <ricardo.ardissone@gmail.com>";
rasendubi = "Alexey Shmalko <rasen.dubi@gmail.com>";
raskin = "Michael Raskin <7c6f434c@mail.ru>";
rbasso = "Rafael Basso <rbasso@sharpgeeks.net>";
redbaron = "Maxim Ivanov <ivanov.maxim@gmail.com>";
redvers = "Redvers Davies <red@infect.me>";
refnil = "Martin Lavoie <broemartino@gmail.com>";
regnat = "Théophane Hufschmitt <regnat@regnat.ovh>";
relrod = "Ricky Elrod <ricky@elrod.me>";
renzo = "Renzo Carbonara <renzocarbonara@gmail.com>";
retrry = "Tadas Barzdžius <retrry@gmail.com>";
rht = "rht <rhtbot@protonmail.com>";
rick68 = "Wei-Ming Yang <rick68@gmail.com>";
rickynils = "Rickard Nilsson <rickynils@gmail.com>";
ris = "Robert Scott <code@humanleg.org.uk>";
rlupton20 = "Richard Lupton <richard.lupton@gmail.com>";
rnhmjoj = "Michele Guerini Rocco <micheleguerinirocco@me.com>";
rob = "Rob Vermaas <rob.vermaas@gmail.com>";
robberer = "Longrin Wischnewski <robberer@freakmail.de>";
robbinch = "Robbin C. <robbinch33@gmail.com>";
roberth = "Robert Hensing <nixpkgs@roberthensing.nl>";
robgssp = "Rob Glossop <robgssp@gmail.com>";
roblabla = "Robin Lambertz <robinlambertz+dev@gmail.com>";
roconnor = "Russell O'Connor <roconnor@theorem.ca>";
romildo = "José Romildo Malaquias <malaquias@gmail.com>";
rongcuid = "Rongcui Dong <rongcuid@outlook.com>";
rszibele = "Richard Szibele <richard@szibele.com>";
rtreffer = "Rene Treffer <treffer+nixos@measite.de>";
rushmorem = "Rushmore Mushambi <rushmore@webenchanter.com>";
rvl = "Rodney Lorrimar <dev+nix@rodney.id.au>";
rvlander = "Gaëtan André <rvlander@gaetanandre.eu>";
rvolosatovs = "Roman Volosatovs <rvolosatovs@riseup.net";
ryanartecona = "Ryan Artecona <ryanartecona@gmail.com>";
ryansydnor = "Ryan Sydnor <ryan.t.sydnor@gmail.com>";
ryantm = "Ryan Mulligan <ryan@ryantm.com>";
rycee = "Robert Helgesson <robert@rycee.net>";
ryneeverett = "Ryne Everett <ryneeverett@gmail.com>";
rzetterberg = "Richard Zetterberg <richard.zetterberg@gmail.com>";
s1lvester = "Markus Silvester <s1lvester@bockhacker.me>";
samuelrivas = "Samuel Rivas <samuelrivas@gmail.com>";
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
sargon = "Daniel Ehlers <danielehlers@mindeye.net>";
schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>";
schneefux = "schneefux <schneefux+nixos_pkg@schneefux.xyz>";
schristo = "Scott Christopher <schristopher@konputa.com>";
scolobb = "Sergiu Ivanov <sivanov@colimite.fr>";
sepi = "Raffael Mancini <raffael@mancini.lu>";
seppeljordan = "Sebastian Jordan <sebastian.jordan.mail@googlemail.com>";
shanemikel = "Shane Pearlman <shanemikel1@gmail.com>";
shawndellysse = "Shawn Dellysse <sdellysse@gmail.com>";
sheenobu = "Sheena Artrip <sheena.artrip@gmail.com>";
sheganinans = "Aistis Raulinaitis <sheganinans@gmail.com>";
shell = "Shell Turner <cam.turn@gmail.com>";
shlevy = "Shea Levy <shea@shealevy.com>";
siddharthist = "Langston Barrett <langston.barrett@gmail.com>";
sigma = "Yann Hodique <yann.hodique@gmail.com>";
simonvandel = "Simon Vandel Sillesen <simon.vandel@gmail.com>";
sjagoe = "Simon Jagoe <simon@simonjagoe.com>";
sjmackenzie = "Stewart Mackenzie <setori88@gmail.com>";
sjourdois = "Stéphane kwisatz Jourdois <sjourdois@gmail.com>";
skeidel = "Sven Keidel <svenkeidel@gmail.com>";
skrzyp = "Jakub Skrzypnik <jot.skrzyp@gmail.com>";
sleexyz = "Sean Lee <freshdried@gmail.com>";
smironov = "Sergey Mironov <grrwlf@gmail.com>";
snyh = "Xia Bin <snyh@snyh.org>";
solson = "Scott Olson <scott@solson.me>";
spacefrogg = "Michael Raitza <spacefrogg-nixos@meterriblecrew.net>";
spencerjanssen = "Spencer Janssen <spencerjanssen@gmail.com>";
spinus = "Tomasz Czyż <tomasz.czyz@gmail.com>";
sprock = "Roger Mason <rmason@mun.ca>";
spwhitt = "Spencer Whitt <sw@swhitt.me>";
srhb = "Sarah Brofeldt <sbrofeldt@gmail.com>";
SShrike = "Severen Redwood <severen@shrike.me>";
stephenmw = "Stephen Weinberg <stephen@q5comm.com>";
sternenseemann = "Lukas Epple <post@lukasepple.de>";
stesie = "Stefan Siegl <stesie@brokenpipe.de>";
steveej = "Stefan Junker <mail@stefanjunker.de>";
SuprDewd = "Bjarki Ágúst Guðmundsson <suprdewd@gmail.com>";
swarren83 = "Shawn Warren <shawn.w.warren@gmail.com>";
swflint = "Samuel W. Flint <swflint@flintfam.org>";
swistak35 = "Rafał Łasocha <me@swistak35.com>";
szczyp = "Szczyp <qb@szczyp.com>";
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
taeer = "Taeer Bar-Yam <taeer@necsi.edu>";
tailhook = "Paul Colomiets <paul@colomiets.name>";
takikawa = "Asumu Takikawa <asumu@igalia.com>";
taktoa = "Remy Goldschmidt <taktoa@gmail.com>";
taku0 = "Takuo Yonezawa <mxxouy6x3m_github@tatapa.org>";
tari = "Peter Marheine <peter@taricorp.net>";
tavyc = "Octavian Cerna <octavian.cerna@gmail.com>";
teh = "Tom Hunger <tehunger@gmail.com>";
telotortium = "Robert Irelan <rirelan@gmail.com>";
thall = "Niclas Thall <niclas.thall@gmail.com>";
thammers = "Tobias Hammerschmidt <jawr@gmx.de>";
the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>";
theuni = "Christian Theune <ct@flyingcircus.io>";
thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
timbertson = "Tim Cuthbertson <tim@gfxmonk.net>";
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
tohl = "Tomas Hlavaty <tom@logand.com>";
tokudan = "Daniel Frank <git@danielfrank.net>";
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
tomsmeets = "Tom Smeets <tom@tsmeets.nl>";
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
trevorj = "Trevor Joynson <nix@trevor.joynson.io>";
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
tstrobel = "Thomas Strobel <4ZKTUB6TEP74PYJOPWIR013S2AV29YUBW5F9ZH2F4D5UMJUJ6S@hash.domains>";
ttuegel = "Thomas Tuegel <ttuegel@mailbox.org>";
tv = "Tomislav Viljetić <tv@shackspace.de>";
tvestelind = "Tomas Vestelind <tomas.vestelind@fripost.org>";
tvorog = "Marsel Zaripov <marszaripov@gmail.com>";
tweber = "Thorsten Weber <tw+nixpkgs@360vier.de>";
twey = "James Twey Kay <twey@twey.co.uk>";
uralbash = "Svintsov Dmitry <root@uralbash.ru>";
utdemir = "Utku Demir <me@utdemir.com>";
#urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; inactive since 2012
uwap = "uwap <me@uwap.name>";
vaibhavsagar = "Vaibhav Sagar <vaibhavsagar@gmail.com>";
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
vanzef = "Ivan Solyankin <vanzef@gmail.com>";
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
vdemeester = "Vincent Demeester <vincent@sbr.pm>";
veprbl = "Dmitry Kalinkin <veprbl@gmail.com>";
vifino = "Adrian Pistol <vifino@tty.sh>";
viric = "Lluís Batlle i Rossell <viric@viric.name>";
vizanto = "Danny Wilson <danny@prime.vc>";
vklquevs = "vklquevs <vklquevs@gmail.com>";
vlstill = "Vladimír Štill <xstill@fi.muni.cz>";
vmandela = "Venkateswara Rao Mandela <venkat.mandela@gmail.com>";
vmchale = "Vanessa McHale <tmchale@wisc.edu>";
valeriangalliat = "Valérian Galliat <val@codejam.info>";
volhovm = "Mikhail Volkhov <volhovm.cs@gmail.com>";
volth = "Jaroslavas Pocepko <jaroslavas@volth.com>";
vozz = "Oliver Hunt <oliver.huntuk@gmail.com>";
vrthra = "Rahul Gopinath <rahul@gopinath.org>";
vyp = "vyp <elisp.vim@gmail.com>";
wedens = "wedens <kirill.wedens@gmail.com>";
willtim = "Tim Philip Williams <tim.williams.public@gmail.com>";
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
wjlroe = "William Roe <willroe@gmail.com>";
wkennington = "William A. Kennington III <william@wkennington.com>";
wmertens = "Wout Mertens <Wout.Mertens@gmail.com>";
womfoo = "Kranium Gikos Mendoza <kranium@gikos.net>";
wscott = "Wayne Scott <wsc9tt@gmail.com>";
wyvie = "Elijah Rum <elijahrum@gmail.com>";
xnwdd = "Guillermo NWDD <nwdd+nixos@no.team>";
xvapx = "Marti Serra <marti.serra.coscollano@gmail.com>";
xwvvvvwx = "David Terry <davidterry@posteo.de>";
yarr = "Dmitry V. <savraz@gmail.com>";
yochai = "Yochai <yochai@titat.info>";
yorickvp = "Yorick van Pelt <yorickvanpelt@gmail.com>";
yuriaisaka = "Yuri Aisaka <yuri.aisaka+nix@gmail.com>";
yurrriq = "Eric Bailey <eric@ericb.me>";
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
zagy = "Christian Zagrodnick <cz@flyingcircus.io>";
zalakain = "Unai Zalakain <contact@unaizalakain.info>";
zarelit = "David Costa <david@zarel.net>";
zauberpony = "Elmar Athmer <elmar@athmer.org>";
zef = "Zef Hemel <zef@zef.me>";
zimbatm = "zimbatm <zimbatm@zimbatm.com>";
zohl = "Al Zohali <zohl@fmap.me>";
zoomulator = "Kim Simmons <zoomulator@gmail.com>";
zraexy = "David Mell <zraexy@gmail.com>";
zx2c4 = "Jason A. Donenfeld <Jason@zx2c4.com>";
}

View File

@ -1,8 +1,7 @@
/* Some functions for manipulating meta attributes, as well as the
name attribute. */
let lib = import ./default.nix;
in
{ lib }:
rec {
@ -68,4 +67,23 @@ rec {
*/
hiPrioSet = set: mapDerivationAttrset hiPrio set;
/* Check to see if a platform is matched by the given `meta.platforms`
element.
A `meta.platform` pattern is either
1. (legacy) a system string.
2. (modern) a pattern for the platform `parsed` field.
We can inject these into a patten for the whole of a structured platform,
and then match that.
*/
platformMatch = platform: elem: let
pattern =
if builtins.isString elem
then { system = elem; }
else { parsed = elem; };
in lib.matchAttrs pattern platform;
}

View File

@ -1,2 +1,2 @@
# Expose the minimum required version for evaluating Nixpkgs
"1.10"
"1.11"

View File

@ -1,10 +1,12 @@
with import ./lists.nix;
with import ./strings.nix;
with import ./trivial.nix;
with import ./attrsets.nix;
with import ./options.nix;
with import ./debug.nix;
with import ./types.nix;
{ lib }:
with lib.lists;
with lib.strings;
with lib.trivial;
with lib.attrsets;
with lib.options;
with lib.debug;
with lib.types;
rec {
@ -153,7 +155,7 @@ rec {
# a module will resolve strictly the attributes used as argument but
# not their values. The values are forwarding the result of the
# evaluation of the option.
requiredArgs = builtins.attrNames (builtins.functionArgs f);
requiredArgs = builtins.attrNames (lib.functionArgs f);
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
extraArgs = builtins.listToAttrs (map (name: {
inherit name;
@ -336,7 +338,7 @@ rec {
# Type-check the remaining definitions, and merge them.
mergedValue = foldl' (res: def:
if type.check def.value then res
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.description}.")
else throw "The option value `${showOption loc}' in `${def.file}' is not of type `${type.description}'.")
(type.merge loc defsFinal) defsFinal;
isDefined = defsFinal != [];

View File

@ -1,11 +1,10 @@
# Nixpkgs/NixOS option handling.
{ lib }:
let lib = import ./default.nix; in
with import ./trivial.nix;
with import ./lists.nix;
with import ./attrsets.nix;
with import ./strings.nix;
with lib.trivial;
with lib.lists;
with lib.attrsets;
with lib.strings;
rec {
@ -15,6 +14,7 @@ rec {
, defaultText ? null # Textual representation of the default, for in the manual.
, example ? null # Example value used in the manual.
, description ? null # String describing the option.
, relatedPackages ? null # Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix).
, type ? null # Option type, providing type-checking and value merging.
, apply ? null # Function that converts the option value to something else.
, internal ? null # Whether the option is for NixOS developers only.
@ -77,7 +77,6 @@ rec {
getValues = map (x: x.value);
getFiles = map (x: x.file);
# Generate documentation template from the list of option declaration like
# the set generated with filterOptionSets.
optionAttrSetToDocList = optionAttrSetToDocList' [];
@ -86,6 +85,7 @@ rec {
concatMap (opt:
let
docOption = rec {
loc = opt.loc;
name = showOption opt.loc;
description = opt.description or (throw "Option `${name}' has no description.");
declarations = filter (x: x != unknownModule) opt.declarations;
@ -94,9 +94,10 @@ rec {
readOnly = opt.readOnly or false;
type = opt.type.description or null;
}
// (if opt ? example then { example = scrubOptionValue opt.example; } else {})
// (if opt ? default then { default = scrubOptionValue opt.default; } else {})
// (if opt ? defaultText then { default = opt.defaultText; } else {});
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; }
// optionalAttrs (opt ? relatedPackages && opt.relatedPackages != null) { inherit (opt) relatedPackages; };
subOptions =
let ss = opt.type.getSubOptions opt.loc;

View File

@ -1,47 +0,0 @@
with import ./strings.nix;
/* Helpers for creating lisp S-exprs for the Apple sandbox
lib.sandbox.allowFileRead [ "/usr/bin/file" ];
# => "(allow file-read* (literal \"/usr/bin/file\"))";
lib.sandbox.allowFileRead {
literal = [ "/usr/bin/file" ];
subpath = [ "/usr/lib/system" ];
}
# => "(allow file-read* (literal \"/usr/bin/file\") (subpath \"/usr/lib/system\"))"
*/
let
sexp = tokens: "(" + builtins.concatStringsSep " " tokens + ")";
generateFileList = files:
if builtins.isList files
then concatMapStringsSep " " (x: sexp [ "literal" ''"${x}"'' ]) files
else if builtins.isString files
then generateFileList [ files ]
else concatStringsSep " " (
(map (x: sexp [ "literal" ''"${x}"'' ]) (files.literal or [])) ++
(map (x: sexp [ "subpath" ''"${x}"'' ]) (files.subpath or []))
);
applyToFiles = f: act: files: f "${act} ${generateFileList files}";
genActions = actionName: let
action = feature: sexp [ actionName feature ];
self = {
"${actionName}" = action;
"${actionName}File" = applyToFiles action "file*";
"${actionName}FileRead" = applyToFiles action "file-read*";
"${actionName}FileReadMetadata" = applyToFiles action "file-read-metadata";
"${actionName}DirectoryList" = self."${actionName}FileReadMetadata";
"${actionName}FileWrite" = applyToFiles action "file-write*";
"${actionName}FileWriteMetadata" = applyToFiles action "file-write-metadata";
};
in self;
in
genActions "allow" // genActions "deny" // {
importProfile = derivation: ''
(import "${derivation}")
'';
}

View File

@ -1,6 +1,5 @@
# Functions for copying sources to the Nix store.
let lib = import ./default.nix; in
{ lib }:
rec {
@ -15,8 +14,11 @@ rec {
cleanSourceFilter = name: type: let baseName = baseNameOf (toString name); in ! (
# Filter out Subversion and CVS directories.
(type == "directory" && (baseName == ".git" || baseName == ".svn" || baseName == "CVS" || baseName == ".hg")) ||
# Filter out backup files.
# Filter out editor backup / swap files.
lib.hasSuffix "~" baseName ||
builtins.match "^\\.sw[a-z]$" baseName != null ||
builtins.match "^\\..*\\.sw[a-z]$" baseName != null ||
# Filter out generates files.
lib.hasSuffix ".o" baseName ||
lib.hasSuffix ".so" baseName ||
@ -24,14 +26,35 @@ rec {
(type == "symlink" && lib.hasPrefix "result" baseName)
);
cleanSource = builtins.filterSource cleanSourceFilter;
cleanSource = src: cleanSourceWith { filter = cleanSourceFilter; inherit src; };
# Like `builtins.filterSource`, except it will compose with itself,
# allowing you to chain multiple calls together without any
# intermediate copies being put in the nix store.
#
# lib.cleanSourceWith f (lib.cleanSourceWith g ./.) # Succeeds!
# builtins.filterSource f (builtins.filterSource g ./.) # Fails!
cleanSourceWith = { filter, src }:
let
isFiltered = src ? _isLibCleanSourceWith;
origSrc = if isFiltered then src.origSrc else src;
filter' = if isFiltered then name: type: filter name type && src.filter name type else filter;
in {
inherit origSrc;
filter = filter';
outPath = builtins.filterSource filter' origSrc;
_isLibCleanSourceWith = true;
};
# Filter sources by a list of regular expressions.
#
# E.g. `src = sourceByRegex ./my-subproject [".*\.py$" "^database.sql$"]`
sourceByRegex = src: regexes: builtins.filterSource (path: type:
let relPath = lib.removePrefix (toString src + "/") (toString path);
in lib.any (re: builtins.match re relPath != null) regexes) src;
sourceByRegex = src: regexes: cleanSourceWith {
filter = (path: type:
let relPath = lib.removePrefix (toString src + "/") (toString path);
in lib.any (re: builtins.match re relPath != null) regexes);
inherit src;
};
# Get all files ending with the specified suffices from the given
# directory or its descendants. E.g. `sourceFilesBySuffices ./dir
@ -40,7 +63,7 @@ rec {
let filter = name: type:
let base = baseNameOf (toString name);
in type == "directory" || lib.any (ext: lib.hasSuffix ext base) exts;
in builtins.filterSource filter path;
in cleanSourceWith { inherit filter; src = path; };
# Get the commit id of a git repo
@ -70,4 +93,8 @@ rec {
else lib.head matchRef
else throw ("Not a .git directory: " + path);
in lib.flip readCommitFromFile "HEAD";
pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir);
canCleanSource = src: src ? _isLibCleanSourceWith || !(pathHasContext (toString src));
}

View File

@ -1,3 +1,4 @@
{ lib }:
/*
Usage:
@ -40,9 +41,9 @@ Usage:
[1] maybe this behaviour should be removed to keep things simple (?)
*/
with import ./lists.nix;
with import ./attrsets.nix;
with import ./strings.nix;
with lib.lists;
with lib.attrsets;
with lib.strings;
rec {

View File

@ -1,6 +1,6 @@
/* String manipulation functions. */
let lib = import ./default.nix;
{ lib }:
let
inherit (builtins) length;
@ -219,6 +219,14 @@ rec {
*/
escapeShellArgs = concatMapStringsSep " " escapeShellArg;
/* Turn a string into a Nix expression representing that string
Example:
escapeNixString "hello\${}\n"
=> "\"hello\\\${}\\n\""
*/
escapeNixString = s: escape ["$"] (builtins.toJSON s);
/* Obsolete - use replaceStrings instead. */
replaceChars = builtins.replaceStrings or (
del: new: s:
@ -429,6 +437,13 @@ rec {
*/
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
/* Check whether a value can be coerced to a string */
isCoercibleToString = x:
builtins.elem (builtins.typeOf x) [ "path" "string" "null" "int" "float" "bool" ] ||
(builtins.isList x && lib.all isCoercibleToString x) ||
x ? outPath ||
x ? __toString;
/* Check whether a value is a store path.
Example:
@ -442,7 +457,7 @@ rec {
=> false
*/
isStorePath = x:
builtins.isString x
isCoercibleToString x
&& builtins.substring 0 1 (toString x) == "/"
&& dirOf (builtins.toPath x) == builtins.storeDir;

View File

@ -1,11 +1,13 @@
let inherit (import ../attrsets.nix) mapAttrs; in
{ lib }:
let inherit (lib.attrsets) mapAttrs; in
rec {
doubles = import ./doubles.nix;
parse = import ./parse.nix;
inspect = import ./inspect.nix;
platforms = import ./platforms.nix;
examples = import ./examples.nix;
doubles = import ./doubles.nix { inherit lib; };
forMeta = import ./for-meta.nix { inherit lib; };
parse = import ./parse.nix { inherit lib; };
inspect = import ./inspect.nix { inherit lib; };
platforms = import ./platforms.nix { inherit lib; };
examples = import ./examples.nix { inherit lib; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary.
@ -22,13 +24,28 @@ rec {
config = parse.tripleFromSystem final.parsed;
# Just a guess, based on `system`
platform = platforms.selectBySystem final.system;
# Derived meta-data
libc =
/**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt"
else if final.isLinux then "glibc"
/**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt"
else if final.isMusl then "musl"
else if final.isAndroid then "bionic"
else if final.isLinux /* default */ then "glibc"
# TODO(@Ericson2314) think more about other operating systems
else "native/impure";
else "native/impure";
extensions = {
sharedLibrary =
/**/ if final.isDarwin then ".dylib"
else if final.isWindows then ".dll"
else ".so";
executable =
/**/ if final.isWindows then ".exe"
else "";
};
# Misc boolean options
useAndroidPrebuilt = false;
} // mapAttrs (n: v: v final.parsed) inspect.predicates
// args;
in final;
in assert final.useAndroidPrebuilt -> final.isAndroid;
final;
}

View File

@ -1,14 +1,15 @@
{ lib }:
let
lists = import ../lists.nix;
parse = import ./parse.nix;
inherit (import ./inspect.nix) predicates;
inherit (import ../attrsets.nix) matchAttrs;
inherit (lib) lists;
inherit (lib.systems) parse;
inherit (lib.systems.inspect) predicates;
inherit (lib.attrsets) matchAttrs;
all = [
"aarch64-linux"
"armv5tel-linux" "armv6l-linux" "armv7l-linux"
"mips64el-linux"
"mipsel-linux"
"i686-cygwin" "i686-freebsd" "i686-linux" "i686-netbsd" "i686-openbsd"
@ -23,19 +24,20 @@ let
in rec {
inherit all;
allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
none = [];
arm = filterDoubles predicates.isArm32;
arm = filterDoubles predicates.isArm;
aarch64 = filterDoubles predicates.isAarch64;
x86 = filterDoubles predicates.isx86;
i686 = filterDoubles predicates.isi686;
mips = filterDoubles predicates.isMips;
x86_64 = filterDoubles predicates.isx86_64;
mips = filterDoubles predicates.isMips;
cygwin = filterDoubles predicates.isCygwin;
darwin = filterDoubles predicates.isDarwin;
freebsd = filterDoubles predicates.isFreeBSD;
# Should be better, but MinGW is unclear, and HURD is bit-rotted.
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; });
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; });
illumos = filterDoubles predicates.isSunOS;
linux = filterDoubles predicates.isLinux;
netbsd = filterDoubles predicates.isNetBSD;

View File

@ -1,8 +1,8 @@
# These can be passed to nixpkgs as either the `localSystem` or
# `crossSystem`. They are put here for user convenience, but also used by cross
# tests and linux cross stdenv building, so handle with care!
let platforms = import ./platforms.nix; in
{ lib }:
let platforms = import ./platforms.nix { inherit lib; }; in
rec {
#
@ -11,84 +11,78 @@ rec {
sheevaplug = rec {
config = "armv5tel-unknown-linux-gnueabi";
bigEndian = false;
arch = "armv5tel";
float = "soft";
withTLS = true;
libc = "glibc";
platform = platforms.sheevaplug;
openssl.system = "linux-generic32";
inherit (platform) gcc;
};
raspberryPi = rec {
config = "armv6l-unknown-linux-gnueabihf";
bigEndian = false;
arch = "armv6l";
float = "hard";
fpu = "vfp";
withTLS = true;
libc = "glibc";
platform = platforms.raspberrypi;
openssl.system = "linux-generic32";
inherit (platform) gcc;
};
armv7l-hf-multiplatform = rec {
config = "arm-unknown-linux-gnueabihf";
bigEndian = false;
arch = "armv7-a";
float = "hard";
fpu = "vfpv3-d16";
withTLS = true;
libc = "glibc";
platform = platforms.armv7l-hf-multiplatform;
openssl.system = "linux-generic32";
inherit (platform) gcc;
};
aarch64-multiplatform = rec {
config = "aarch64-unknown-linux-gnu";
bigEndian = false;
arch = "aarch64";
withTLS = true;
libc = "glibc";
platform = platforms.aarch64-multiplatform;
inherit (platform) gcc;
};
aarch64-android-prebuilt = rec {
config = "aarch64-unknown-linux-android";
arch = "aarch64";
platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true;
};
scaleway-c1 = armv7l-hf-multiplatform // rec {
platform = platforms.scaleway-c1;
inherit (platform) gcc;
inherit (gcc) fpu;
inherit (platform.gcc) fpu;
};
pogoplug4 = rec {
arch = "armv5tel";
config = "armv5tel-softfloat-linux-gnueabi";
config = "armv5tel-unknown-linux-gnueabi";
float = "soft";
platform = platforms.pogoplug4;
inherit (platform) gcc;
libc = "glibc";
withTLS = true;
openssl.system = "linux-generic32";
};
fuloongminipc = rec {
config = "mips64el-unknown-linux-gnu";
bigEndian = false;
config = "mipsel-unknown-linux-gnu";
arch = "mips";
float = "hard";
withTLS = true;
libc = "glibc";
platform = platforms.fuloong2f_n32;
openssl.system = "linux-generic32";
inherit (platform) gcc;
};
muslpi = raspberryPi // {
config = "armv6l-unknown-linux-musleabihf";
};
aarch64-multiplatform-musl = aarch64-multiplatform // {
config = "aarch64-unknown-linux-musl";
};
musl64 = { config = "x86_64-unknown-linux-musl"; };
musl32 = { config = "i686-unknown-linux-musl"; };
riscv = bits: {
config = "riscv${bits}-unknown-linux-gnu";
platform = platforms.riscv-multiplatform bits;
};
riscv64 = riscv "64";
riscv32 = riscv "32";
#
# Darwin
#

30
lib/systems/for-meta.nix Normal file
View File

@ -0,0 +1,30 @@
{ lib }:
let
inherit (lib.systems) parse;
inherit (lib.systems.inspect) patterns;
in rec {
all = [ {} ]; # `{}` matches anything
none = [];
arm = [ patterns.isArm ];
aarch64 = [ patterns.isAarch64 ];
x86 = [ patterns.isx86 ];
i686 = [ patterns.isi686 ];
x86_64 = [ patterns.isx86_64 ];
mips = [ patterns.isMips ];
cygwin = [ patterns.isCygwin ];
darwin = [ patterns.isDarwin ];
freebsd = [ patterns.isFreeBSD ];
# Should be better, but MinGW is unclear, and HURD is bit-rotted.
gnu = [ { kernel = parse.kernels.linux; abi = parse.abis.gnu; } ];
illumos = [ patterns.isSunOS ];
linux = [ patterns.isLinux ];
netbsd = [ patterns.isNetBSD ];
openbsd = [ patterns.isOpenBSD ];
unix = patterns.isUnix; # Actually a list
windows = [ patterns.isWindows ];
inherit (lib.systems.doubles) mesaPlatforms;
}

View File

@ -1,43 +1,55 @@
with import ./parse.nix;
with import ../attrsets.nix;
with import ../lists.nix;
{ lib }:
with import ./parse.nix { inherit lib; };
with lib.attrsets;
with lib.lists;
rec {
patterns = rec {
"32bit" = { cpu = { bits = 32; }; };
"64bit" = { cpu = { bits = 64; }; };
i686 = { cpu = cpuTypes.i686; };
x86_64 = { cpu = cpuTypes.x86_64; };
PowerPC = { cpu = cpuTypes.powerpc; };
x86 = { cpu = { family = "x86"; }; };
Arm = { cpu = { family = "arm"; }; };
Mips = { cpu = { family = "mips"; }; };
BigEndian = { cpu = { significantByte = significantBytes.bigEndian; }; };
LittleEndian = { cpu = { significantByte = significantBytes.littleEndian; }; };
isi686 = { cpu = cpuTypes.i686; };
isx86_64 = { cpu = cpuTypes.x86_64; };
isPowerPC = { cpu = cpuTypes.powerpc; };
isx86 = { cpu = { family = "x86"; }; };
isArm = { cpu = { family = "arm"; }; };
isAarch64 = { cpu = { family = "aarch64"; }; };
isMips = { cpu = { family = "mips"; }; };
isRiscV = { cpu = { family = "riscv"; }; };
isWasm = { cpu = { family = "wasm"; }; };
BSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; };
Unix = [ BSD Darwin Linux SunOS Hurd Cygwin ];
is32bit = { cpu = { bits = 32; }; };
is64bit = { cpu = { bits = 64; }; };
isBigEndian = { cpu = { significantByte = significantBytes.bigEndian; }; };
isLittleEndian = { cpu = { significantByte = significantBytes.littleEndian; }; };
Darwin = { kernel = kernels.darwin; };
Linux = { kernel = kernels.linux; };
SunOS = { kernel = kernels.solaris; };
FreeBSD = { kernel = kernels.freebsd; };
Hurd = { kernel = kernels.hurd; };
NetBSD = { kernel = kernels.netbsd; };
OpenBSD = { kernel = kernels.openbsd; };
Windows = { kernel = kernels.windows; };
Cygwin = { kernel = kernels.windows; abi = abis.cygnus; };
MinGW = { kernel = kernels.windows; abi = abis.gnu; };
isBSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; };
isDarwin = { kernel = { families = { inherit (kernelFamilies) darwin; }; }; };
isUnix = [ isBSD isDarwin isLinux isSunOS isHurd isCygwin ];
Arm32 = recursiveUpdate Arm patterns."32bit";
Arm64 = recursiveUpdate Arm patterns."64bit";
isMacOS = { kernel = kernels.macos; };
isiOS = { kernel = kernels.ios; };
isLinux = { kernel = kernels.linux; };
isSunOS = { kernel = kernels.solaris; };
isFreeBSD = { kernel = kernels.freebsd; };
isHurd = { kernel = kernels.hurd; };
isNetBSD = { kernel = kernels.netbsd; };
isOpenBSD = { kernel = kernels.openbsd; };
isWindows = { kernel = kernels.windows; };
isCygwin = { kernel = kernels.windows; abi = abis.cygnus; };
isMinGW = { kernel = kernels.windows; abi = abis.gnu; };
isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ];
isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];
isKexecable = map (family: { kernel = kernels.linux; cpu.family = family; })
[ "x86" "arm" "aarch64" "mips" ];
isEfi = map (family: { cpu.family = family; })
[ "x86" "arm" "aarch64" ];
isSeccomputable = map (family: { kernel = kernels.linux; cpu.family = family; })
[ "x86" "arm" "aarch64" "mips" ];
};
matchAnyAttrs = patterns:
if builtins.isList patterns then attrs: any (pattern: matchAttrs pattern attrs) patterns
else matchAttrs patterns;
predicates = mapAttrs'
(name: value: nameValuePair ("is" + name) (matchAnyAttrs value))
patterns;
predicates = mapAttrs (_: matchAnyAttrs) patterns;
}

View File

@ -4,59 +4,116 @@
# http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html especially
# Triple::normalize. Parsing should essentially act as a more conservative
# version of that last function.
with import ../lists.nix;
with import ../types.nix;
with import ../attrsets.nix;
with (import ./inspect.nix).predicates;
#
# Most of the types below come in "open" and "closed" pairs. The open ones
# specify what information we need to know about systems in general, and the
# closed ones are sub-types representing the whitelist of systems we support in
# practice.
#
# Code in the remainder of nixpkgs shouldn't rely on the closed ones in
# e.g. exhaustive cases. Its more a sanity check to make sure nobody defines
# systems that overlap with existing ones and won't notice something amiss.
#
{ lib }:
with lib.lists;
with lib.types;
with lib.attrsets;
with (import ./inspect.nix { inherit lib; }).predicates;
let
lib = import ../default.nix;
setTypesAssert = type: pred:
inherit (lib.options) mergeOneOption;
setTypes = type:
mapAttrs (name: value:
assert pred value;
setType type ({ inherit name; } // value));
setTypes = type: setTypesAssert type (_: true);
assert type.check value;
setType type.name ({ inherit name; } // value));
in
rec {
isSignificantByte = isType "significant-byte";
significantBytes = setTypes "significant-byte" {
################################################################################
types.openSignifiantByte = mkOptionType {
name = "significant-byte";
description = "Endianness";
merge = mergeOneOption;
};
types.significantByte = enum (attrValues significantBytes);
significantBytes = setTypes types.openSignifiantByte {
bigEndian = {};
littleEndian = {};
};
isCpuType = isType "cpu-type";
cpuTypes = with significantBytes; setTypesAssert "cpu-type"
(x: elem x.bits [8 16 32 64 128]
&& (if 8 < x.bits
then isSignificantByte x.significantByte
else !(x ? significantByte)))
{
################################################################################
# Reasonable power of 2
types.bitWidth = enum [ 8 16 32 64 128 ];
################################################################################
types.openCpuType = mkOptionType {
name = "cpu-type";
description = "instruction set architecture name and information";
merge = mergeOneOption;
check = x: types.bitWidth.check x.bits
&& (if 8 < x.bits
then types.significantByte.check x.significantByte
else !(x ? significantByte));
};
types.cpuType = enum (attrValues cpuTypes);
cpuTypes = with significantBytes; setTypes types.openCpuType {
arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "aarch64"; };
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; };
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; };
mips64el = { bits = 32; significantByte = littleEndian; family = "mips"; };
mips = { bits = 32; significantByte = bigEndian; family = "mips"; };
mipsel = { bits = 32; significantByte = littleEndian; family = "mips"; };
mips64 = { bits = 64; significantByte = bigEndian; family = "mips"; };
mips64el = { bits = 64; significantByte = littleEndian; family = "mips"; };
powerpc = { bits = 32; significantByte = bigEndian; family = "power"; };
riscv32 = { bits = 32; significantByte = littleEndian; family = "riscv"; };
riscv64 = { bits = 64; significantByte = littleEndian; family = "riscv"; };
wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; };
wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; };
};
isVendor = isType "vendor";
vendors = setTypes "vendor" {
################################################################################
types.openVendor = mkOptionType {
name = "vendor";
description = "vendor for the platform";
merge = mergeOneOption;
};
types.vendor = enum (attrValues vendors);
vendors = setTypes types.openVendor {
apple = {};
pc = {};
unknown = {};
};
isExecFormat = isType "exec-format";
execFormats = setTypes "exec-format" {
################################################################################
types.openExecFormat = mkOptionType {
name = "exec-format";
description = "executable container used by the kernel";
merge = mergeOneOption;
};
types.execFormat = enum (attrValues execFormats);
execFormats = setTypes types.openExecFormat {
aout = {}; # a.out
elf = {};
macho = {};
@ -65,16 +122,38 @@ rec {
unknown = {};
};
isKernelFamily = isType "kernel-family";
kernelFamilies = setTypes "kernel-family" {
bsd = {};
################################################################################
types.openKernelFamily = mkOptionType {
name = "exec-format";
description = "executable container used by the kernel";
merge = mergeOneOption;
};
isKernel = x: isType "kernel" x;
kernels = with execFormats; with kernelFamilies; setTypesAssert "kernel"
(x: isExecFormat x.execFormat && all isKernelFamily (attrValues x.families))
{
darwin = { execFormat = macho; families = { }; };
types.kernelFamily = enum (attrValues kernelFamilies);
kernelFamilies = setTypes types.openKernelFamily {
bsd = {};
darwin = {};
};
################################################################################
types.openKernel = mkOptionType {
name = "kernel";
description = "kernel name and information";
merge = mergeOneOption;
check = x: types.execFormat.check x.execFormat
&& all types.kernelFamily.check (attrValues x.families);
};
types.kernel = enum (attrValues kernels);
kernels = with execFormats; with kernelFamilies; setTypes types.openKernel {
# TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as
# the nnormalized name for macOS.
macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
ios = { execFormat = macho; families = { inherit darwin; }; };
freebsd = { execFormat = elf; families = { inherit bsd; }; };
hurd = { execFormat = elf; families = { }; };
linux = { execFormat = elf; families = { }; };
@ -84,14 +163,28 @@ rec {
solaris = { execFormat = elf; families = { }; };
windows = { execFormat = pe; families = { }; };
} // { # aliases
# 'darwin' is the kernel for all of them. We choose macOS by default.
darwin = kernels.macos;
# TODO(@Ericson2314): Handle these Darwin version suffixes more generally.
darwin10 = kernels.darwin;
darwin14 = kernels.darwin;
darwin10 = kernels.macos;
darwin14 = kernels.macos;
watchos = kernels.ios;
tvos = kernels.ios;
win32 = kernels.windows;
};
isAbi = isType "abi";
abis = setTypes "abi" {
################################################################################
types.openAbi = mkOptionType {
name = "abi";
description = "binary interface for compiled code and syscalls";
merge = mergeOneOption;
};
types.abi = enum (attrValues abis);
abis = setTypes types.openAbi {
android = {};
cygnus = {};
gnu = {};
msvc = {};
@ -99,16 +192,31 @@ rec {
androideabi = {};
gnueabi = {};
gnueabihf = {};
musleabi = {};
musleabihf = {};
musl = {};
unknown = {};
};
################################################################################
types.system = mkOptionType {
name = "system";
description = "fully parsed representation of llvm- or nix-style platform tuple";
merge = mergeOneOption;
check = { cpu, vendor, kernel, abi }:
types.cpuType.check cpu
&& types.vendor.check vendor
&& types.kernel.check kernel
&& types.abi.check abi;
};
isSystem = isType "system";
mkSystem = { cpu, vendor, kernel, abi }:
assert isCpuType cpu && isVendor vendor && isKernel kernel && isAbi abi;
setType "system" {
inherit cpu vendor kernel abi;
};
mkSystem = components:
assert types.system.check components;
setType "system" components;
mkSkeletonFromList = l: {
"2" = # We only do 2-part hacks for things Nix already supports
@ -163,12 +271,14 @@ rec {
mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
doubleFromSystem = { cpu, vendor, kernel, abi, ... }:
if abi == abis.cygnus
then "${cpu.name}-cygwin"
/**/ if abi == abis.cygnus then "${cpu.name}-cygwin"
else if kernel.families ? darwin then "${cpu.name}-darwin"
else "${cpu.name}-${kernel.name}";
tripleFromSystem = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys; let
optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
in "${cpu.name}-${vendor.name}-${kernel.name}${optAbi}";
################################################################################
}

View File

@ -1,8 +1,7 @@
{ lib }:
rec {
pcBase = {
name = "pc";
uboot = null;
kernelHeadersBaseConfig = "defconfig";
kernelBaseConfig = "defconfig";
# Build whatever possible as a module, if not stated in the extra config.
kernelAutoModules = true;
@ -30,7 +29,6 @@ rec {
};
kernelMajor = "2.6";
kernelHeadersBaseConfig = "multi_v5_defconfig";
kernelBaseConfig = "multi_v5_defconfig";
kernelArch = "arm";
kernelAutoModules = false;
@ -49,15 +47,11 @@ rec {
kernelTarget = "uImage";
# TODO reenable once manual-config's config actually builds a .dtb and this is checked to be working
#kernelDTB = true;
# XXX can be anything non-null, pkgs actually only cares if it is set or not
uboot = "pogoplug4";
};
sheevaplug = {
name = "sheevaplug";
kernelMajor = "2.6";
kernelHeadersBaseConfig = "multi_v5_defconfig";
kernelBaseConfig = "multi_v5_defconfig";
kernelArch = "arm";
kernelAutoModules = false;
@ -161,9 +155,6 @@ rec {
'';
kernelMakeFlags = [ "LOADADDR=0x0200000" ];
kernelTarget = "uImage";
uboot = "sheevaplug";
# Only for uboot = uboot :
ubootConfig = "sheevaplug_config";
kernelDTB = true; # Beyond 3.10
gcc = {
arch = "armv5te";
@ -174,7 +165,6 @@ rec {
raspberrypi = {
name = "raspberrypi";
kernelMajor = "2.6";
kernelHeadersBaseConfig = "bcm2835_defconfig";
kernelBaseConfig = "bcmrpi_defconfig";
kernelDTB = true;
kernelArch = "arm";
@ -250,7 +240,6 @@ rec {
LATENCYTOP y
'';
kernelTarget = "zImage";
uboot = null;
gcc = {
arch = "armv6";
fpu = "vfp";
@ -341,7 +330,6 @@ rec {
XEN? n
'';
kernelTarget = "zImage";
uboot = null;
};
scaleway-c1 = armv7l-hf-multiplatform // {
@ -355,7 +343,6 @@ rec {
utilite = {
name = "utilite";
kernelMajor = "2.6";
kernelHeadersBaseConfig = "multi_v7_defconfig";
kernelBaseConfig = "multi_v7_defconfig";
kernelArch = "arm";
kernelAutoModules = false;
@ -373,7 +360,6 @@ rec {
kernelMakeFlags = [ "LOADADDR=0x10800000" ];
kernelTarget = "uImage";
kernelDTB = true;
uboot = true; #XXX: any non-null value here is needed so that mkimage is present to build kernelTarget uImage
gcc = {
cpu = "cortex-a9";
fpu = "neon";
@ -388,13 +374,11 @@ rec {
# patch.
kernelBaseConfig = "guruplug_defconfig";
#kernelHeadersBaseConfig = "guruplug_defconfig";
};
fuloong2f_n32 = {
name = "fuloong2f_n32";
kernelMajor = "2.6";
kernelHeadersBaseConfig = "fuloong2e_defconfig";
kernelBaseConfig = "lemote2f_defconfig";
kernelArch = "mips";
kernelAutoModules = false;
@ -463,7 +447,6 @@ rec {
FTRACE n
'';
kernelTarget = "vmlinux";
uboot = null;
gcc = {
arch = "loongson2f";
abi = "n32";
@ -472,25 +455,27 @@ rec {
beaglebone = armv7l-hf-multiplatform // {
name = "beaglebone";
kernelBaseConfig = "omap2plus_defconfig";
kernelBaseConfig = "bb.org_defconfig";
kernelAutoModules = false;
kernelExtraConfig = ""; # TBD kernel config
kernelTarget = "zImage";
uboot = null;
};
armv7l-hf-multiplatform = {
name = "armv7l-hf-multiplatform";
kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
kernelHeadersBaseConfig = "multi_v7_defconfig";
kernelBaseConfig = "multi_v7_defconfig";
kernelArch = "arm";
kernelDTB = true;
kernelAutoModules = true;
kernelPreferBuiltin = true;
uboot = null;
kernelTarget = "zImage";
kernelExtraConfig = ''
# Serial port for Raspberry Pi 3. Upstream forgot to add it to the ARMv7 defconfig.
SERIAL_8250_BCM2835AUX y
SERIAL_8250_EXTENDED y
SERIAL_8250_SHARE_IRQ y
# Fix broken sunxi-sid nvmem driver.
TI_CPTS y
@ -524,7 +509,6 @@ rec {
aarch64-multiplatform = {
name = "aarch64-multiplatform";
kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
kernelHeadersBaseConfig = "defconfig";
kernelBaseConfig = "defconfig";
kernelArch = "arm64";
kernelDTB = true;
@ -543,14 +527,33 @@ rec {
# Cavium ThunderX stuff.
PCI_HOST_THUNDER_ECAM y
# Nvidia Tegra stuff.
PCI_TEGRA y
# The default (=y) forces us to have the XHCI firmware available in initrd,
# which our initrd builder can't currently do easily.
USB_XHCI_TEGRA m
'';
uboot = null;
kernelTarget = "Image";
gcc = {
arch = "armv8-a";
};
};
riscv-multiplatform = bits: {
name = "riscv-multiplatform";
kernelArch = "riscv";
bfdEmulation = "elf${bits}lriscv";
kernelTarget = "vmlinux";
kernelAutoModules = true;
kernelBaseConfig = "defconfig";
kernelExtraConfig = ''
FTRACE n
SERIAL_OF_PLATFORM y
'';
};
selectBySystem = system: {
"i686-linux" = pc32;
"x86_64-linux" = pc64;
@ -558,6 +561,6 @@ rec {
"armv6l-linux" = raspberrypi;
"armv7l-linux" = armv7l-hf-multiplatform;
"aarch64-linux" = aarch64-multiplatform;
"mips64el-linux" = fuloong2f_n32;
"mipsel-linux" = fuloong2f_n32;
}.${system} or pcBase;
}

View File

@ -93,6 +93,7 @@ runTests {
"${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11";
in {
storePath = isStorePath goodPath;
storePathDerivation = isStorePath (import ../.. {}).hello;
storePathAppendix = isStorePath
"${goodPath}/bin/python";
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
@ -106,6 +107,7 @@ runTests {
};
expected = {
storePath = true;
storePathDerivation = true;
storePathAppendix = false;
nonAbsolute = false;
asPath = true;
@ -201,7 +203,7 @@ runTests {
# in alphabetical order
testMkKeyValueDefault = {
expr = generators.mkKeyValueDefault ":" "f:oo" "bar";
expr = generators.mkKeyValueDefault {} ":" "f:oo" "bar";
expected = ''f\:oo:bar'';
};

View File

@ -61,6 +61,16 @@ checkConfigError() {
checkConfigOutput "false" config.enable ./declare-enable.nix
checkConfigError 'The option .* defined in .* does not exist.' config.enable ./define-enable.nix
# Check integer types.
# unsigned
checkConfigOutput "42" config.value ./declare-int-unsigned-value.nix ./define-value-int-positive.nix
checkConfigError 'The option value .* in .* is not of type.*unsigned integer.*' config.value ./declare-int-unsigned-value.nix ./define-value-int-negative.nix
# positive
checkConfigError 'The option value .* in .* is not of type.*positive integer.*' config.value ./declare-int-positive-value.nix ./define-value-int-zero.nix
# between
checkConfigOutput "42" config.value ./declare-int-between-value.nix ./define-value-int-positive.nix
checkConfigError 'The option value .* in .* is not of type.*between.*-21 and 43.*inclusive.*' config.value ./declare-int-between-value.nix ./define-value-int-negative.nix
# Check mkForce without submodules.
set -- config.enable ./declare-enable.nix ./define-enable.nix
checkConfigOutput "true" "$@"
@ -126,7 +136,7 @@ checkConfigOutput "true" "$@" ./define-module-check.nix
# Check coerced value.
checkConfigOutput "\"42\"" config.value ./declare-coerced-value.nix
checkConfigOutput "\"24\"" config.value ./declare-coerced-value.nix ./define-value-string.nix
checkConfigError 'The option value .* in .* is not a string or integer.' config.value ./declare-coerced-value.nix ./define-value-list.nix
checkConfigError 'The option value .* in .* is not.*string or signed integer.*' config.value ./declare-coerced-value.nix ./define-value-list.nix
cat <<EOF
====== module tests ======

View File

@ -0,0 +1,9 @@
{ lib, ... }:
{
options = {
value = lib.mkOption {
type = lib.types.ints.between (-21) 43;
};
};
}

View File

@ -0,0 +1,9 @@
{ lib, ... }:
{
options = {
value = lib.mkOption {
type = lib.types.ints.positive;
};
};
}

View File

@ -0,0 +1,9 @@
{ lib, ... }:
{
options = {
value = lib.mkOption {
type = lib.types.ints.unsigned;
};
};
}

View File

@ -0,0 +1,3 @@
{
value = -23;
}

View File

@ -0,0 +1,3 @@
{
value = 42;
}

View File

@ -0,0 +1,3 @@
{
value = 0;
}

View File

@ -13,7 +13,6 @@ pkgs.stdenv.mkDerivation {
export NIX_DB_DIR=$TEST_ROOT/db
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
@ -21,7 +20,7 @@ pkgs.stdenv.mkDerivation {
nix-store --init
cd ${pkgs.path}/lib/tests
./modules.sh
bash ./modules.sh
[[ "$(nix-instantiate --eval --strict misc.nix)" == "[ ]" ]]

View File

@ -16,7 +16,7 @@ in with lib.systems.doubles; lib.runTests {
arm = assertTrue (mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7l-linux" ]);
i686 = assertTrue (mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" ]);
mips = assertTrue (mseteq mips [ "mips64el-linux" ]);
mips = assertTrue (mseteq mips [ "mipsel-linux" ]);
x86_64 = assertTrue (mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" ]);
cygwin = assertTrue (mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ]);
@ -24,7 +24,7 @@ in with lib.systems.doubles; lib.runTests {
freebsd = assertTrue (mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ]);
gnu = assertTrue (mseteq gnu (linux /* ++ hurd ++ kfreebsd ++ ... */));
illumos = assertTrue (mseteq illumos [ "x86_64-solaris" ]);
linux = assertTrue (mseteq linux [ "i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "mips64el-linux" ]);
linux = assertTrue (mseteq linux [ "i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "mipsel-linux" ]);
netbsd = assertTrue (mseteq netbsd [ "i686-netbsd" "x86_64-netbsd" ]);
openbsd = assertTrue (mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ]);
unix = assertTrue (mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos));

View File

@ -1,3 +1,4 @@
{ lib }:
rec {
/* The identity function
@ -51,11 +52,11 @@ rec {
# Pull in some builtins not included elsewhere.
inherit (builtins)
pathExists readFile isBool isFunction
pathExists readFile isBool
isInt add sub lessThan
seq deepSeq genericClosure;
inherit (import ./strings.nix) fileContents;
inherit (lib.strings) fileContents;
# Return the Nixpkgs version number.
nixpkgsVersion =
@ -70,6 +71,52 @@ rec {
min = x: y: if x < y then x else y;
max = x: y: if x > y then x else y;
/* Integer modulus
Example:
mod 11 10
=> 1
mod 1 10
=> 1
*/
mod = base: int: base - (int * (builtins.div base int));
/* C-style comparisons
a < b, compare a b => -1
a == b, compare a b => 0
a > b, compare a b => 1
*/
compare = a: b:
if a < b
then -1
else if a > b
then 1
else 0;
/* Split type into two subtypes by predicate `p`, take all elements
of the first subtype to be less than all the elements of the
second subtype, compare elements of a single subtype with `yes`
and `no` respectively.
Example:
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
cmp "a" "z" => -1
cmp "fooa" "fooz" => -1
cmp "f" "a" => 1
cmp "fooa" "a" => -1
# while
compare "fooa" "a" => 1
*/
splitByAndCompare = p: yes: no: a: b:
if p a
then if p b then yes a b else -1
else if p b then 1 else no a b;
/* Reads a JSON file. */
importJSON = path:
builtins.fromJSON (builtins.readFile path);
@ -88,4 +135,29 @@ rec {
*/
warn = msg: builtins.trace "WARNING: ${msg}";
info = msg: builtins.trace "INFO: ${msg}";
# | Add metadata about expected function arguments to a function.
# The metadata should match the format given by
# builtins.functionArgs, i.e. a set from expected argument to a bool
# representing whether that argument has a default or not.
# setFunctionArgs : (a → b) → Map String Bool → (a → b)
#
# This function is necessary because you can't dynamically create a
# function of the { a, b ? foo, ... }: format, but some facilities
# like callPackage expect to be able to query expected arguments.
setFunctionArgs = f: args:
{ # TODO: Should we add call-time "type" checking like built in?
__functor = self: f;
__functionArgs = args;
};
# | Extract the expected function arguments from a function.
# This works both with nix-native { a, b ? foo, ... }: style
# functions and functions with args set with 'setFunctionArgs'. It
# has the same return type and semantics as builtins.functionArgs.
# setFunctionArgs : (a → b) → Map String Bool.
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
isFunction = f: builtins.isFunction f ||
(f ? __functor && isFunction (f.__functor f));
}

View File

@ -1,15 +1,16 @@
# Definitions related to run-time type checking. Used in particular
# to type-check NixOS configurations.
{ lib }:
with lib.lists;
with lib.attrsets;
with lib.options;
with lib.trivial;
with lib.strings;
let
with import ./lists.nix;
with import ./attrsets.nix;
with import ./options.nix;
with import ./trivial.nix;
with import ./strings.nix;
let inherit (import ./modules.nix) mergeDefinitions filterOverrides; in
inherit (lib.modules) mergeDefinitions filterOverrides;
outer_types =
rec {
isType = type: x: (x._type or "") == type;
setType = typeName: value: value // {
@ -95,7 +96,6 @@ rec {
# When adding new types don't forget to document them in
# nixos/doc/manual/development/option-types.xml!
types = rec {
unspecified = mkOptionType {
name = "unspecified";
};
@ -108,11 +108,64 @@ rec {
};
int = mkOptionType rec {
name = "int";
description = "integer";
check = isInt;
merge = mergeOneOption;
};
name = "int";
description = "signed integer";
check = isInt;
merge = mergeOneOption;
};
# Specialized subdomains of int
ints =
let
betweenDesc = lowest: highest:
"${toString lowest} and ${toString highest} (both inclusive)";
between = lowest: highest: assert lowest <= highest;
addCheck int (x: x >= lowest && x <= highest) // {
name = "intBetween";
description = "integer between ${betweenDesc lowest highest}";
};
ign = lowest: highest: name: docStart:
between lowest highest // {
inherit name;
description = docStart + "; between ${betweenDesc lowest highest}";
};
unsign = bit: range: ign 0 (range - 1)
"unsignedInt${toString bit}" "${toString bit} bit unsigned integer";
sign = bit: range: ign (0 - (range / 2)) (range / 2 - 1)
"signedInt${toString bit}" "${toString bit} bit signed integer";
in rec {
/* An int with a fixed range.
*
* Example:
* (ints.between 0 100).check (-1)
* => false
* (ints.between 0 100).check (101)
* => false
* (ints.between 0 0).check 0
* => true
*/
inherit between;
unsigned = addCheck types.int (x: x >= 0) // {
name = "unsignedInt";
description = "unsigned integer, meaning >=0";
};
positive = addCheck types.int (x: x > 0) // {
name = "positiveInt";
description = "positive integer, meaning >0";
};
u8 = unsign 8 256;
u16 = unsign 16 65536;
# the biggest int a 64-bit Nix accepts is 2^63 - 1 (9223372036854775808), for a 32-bit Nix it is 2^31 - 1 (2147483647)
# the smallest int a 64-bit Nix accepts is -2^63 (-9223372036854775807), for a 32-bit Nix it is -2^31 (-2147483648)
# u32 = unsign 32 4294967296;
# u64 = unsign 64 18446744073709551616;
s8 = sign 8 256;
s16 = sign 16 65536;
# s32 = sign 32 4294967296;
};
str = mkOptionType {
name = "str";
@ -121,6 +174,13 @@ rec {
merge = mergeOneOption;
};
strMatching = pattern: mkOptionType {
name = "strMatching ${escapeNixString pattern}";
description = "string matching the pattern ${pattern}";
check = x: str.check x && builtins.match pattern x != null;
inherit (str) merge;
};
# Merge multiple definitions by concatenating them (with the given
# separator between the values).
separatedString = sep: mkOptionType rec {
@ -172,7 +232,7 @@ rec {
};
# drop this in the future:
list = builtins.trace "`types.list' is deprecated; use `types.listOf' instead" types.listOf;
list = builtins.trace "`types.list` is deprecated; use `types.listOf` instead" types.listOf;
listOf = elemType: mkOptionType rec {
name = "listOf";
@ -189,13 +249,17 @@ rec {
).optionalValue
) def.value
else
throw "The option value `${showOption loc}' in `${def.file}' is not a list.") defs)));
throw "The option value `${showOption loc}` in `${def.file}` is not a list.") defs)));
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
getSubModules = elemType.getSubModules;
substSubModules = m: listOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
};
nonEmptyListOf = elemType:
let list = addCheck (types.listOf elemType) (l: l != []);
in list // { description = "non-empty " + list.description; };
attrsOf = elemType: mkOptionType rec {
name = "attrsOf";
description = "attribute set of ${elemType.description}s";
@ -240,25 +304,6 @@ rec {
functor = (defaultFunctor name) // { wrapped = elemType; };
};
# List or element of ...
loeOf = elemType: mkOptionType rec {
name = "loeOf";
description = "element or list of ${elemType.description}s";
check = x: isList x || elemType.check x;
merge = loc: defs:
let
defs' = filterOverrides defs;
res = (head defs').value;
in
if isList res then concatLists (getValues defs')
else if lessThan 1 (length defs') then
throw "The option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
else if !isString res then
throw "The option `${showOption loc}' does not have a string value, in ${showFiles (getFiles defs)}."
else res;
functor = (defaultFunctor name) // { wrapped = elemType; };
};
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
uniq = elemType: mkOptionType rec {
name = "uniq";
@ -279,7 +324,7 @@ rec {
let nrNulls = count (def: def.value == null) defs; in
if nrNulls == length defs then null
else if nrNulls != 0 then
throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}."
throw "The option `${showOption loc}` is defined both null and not null, in ${showFiles (getFiles defs)}."
else elemType.merge loc defs;
getSubOptions = elemType.getSubOptions;
getSubModules = elemType.getSubModules;
@ -291,7 +336,7 @@ rec {
submodule = opts:
let
opts' = toList opts;
inherit (import ./modules.nix) evalModules;
inherit (lib.modules) evalModules;
in
mkOptionType rec {
name = "submodule";
@ -307,8 +352,17 @@ rec {
}).config;
getSubOptions = prefix: (evalModules
{ modules = opts'; inherit prefix;
# FIXME: hack to get shit to evaluate.
args = { name = ""; }; }).options;
# This is a work-around due to the fact that some sub-modules,
# such as the one included in an attribute set, expects a "args"
# attribute to be given to the sub-module. As the option
# evaluation does not have any specific attribute name, we
# provide a default one for the documentation.
#
# This is mandatory as some option declaration might use the
# "name" attribute given as argument of the submodule and use it
# as the default of option declarations.
args.name = "&lt;name&gt;";
}).options;
getSubModules = opts';
substSubModules = m: submodule m;
functor = (defaultFunctor name) // {
@ -395,5 +449,6 @@ rec {
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };
};
};
}
in outer_types // outer_types.types

47
lib/versions.nix Normal file
View File

@ -0,0 +1,47 @@
/* Version string functions. */
{ lib }:
let
splitVersion = builtins.splitVersion or (lib.splitString ".");
in
rec {
/* Get the major version string from a string.
Example:
major "1.2.3"
=> "1"
*/
major = v: builtins.elemAt (splitVersion v) 0;
/* Get the minor version string from a string.
Example:
minor "1.2.3"
=> "2"
*/
minor = v: builtins.elemAt (splitVersion v) 1;
/* Get the patch version string from a string.
Example:
patch "1.2.3"
=> "3"
*/
patch = v: builtins.elemAt (splitVersion v) 2;
/* Get string of the first two parts (major and minor)
of a version string.
Example:
majorMinor "1.2.3"
=> "1.2"
*/
majorMinor = v:
builtins.concatStringsSep "."
(lib.take 2 (splitVersion v));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,66 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq parallel
# Example how to work with the `lib.maintainers` attrset.
# Can be used to check whether all user handles are still valid.
set -e
# nixpkgs='<nixpkgs>'
# if [ -n "$1" ]; then
function checkCommits {
local user="$1"
local tmp=$(mktemp)
curl --silent -w "%{http_code}" \
"https://github.com/NixOS/nixpkgs/commits?author=$user" \
> "$tmp"
# the last line of tmp contains the http status
local status=$(tail -n1 "$tmp")
local ret=
case $status in
200) if <"$tmp" grep -i "no commits found" > /dev/null; then
ret=1
else
ret=0
fi
;;
# because of githubs hard request limits, this can take some time
429) sleep 2
printf "."
checkCommits "$user"
ret=$?
;;
*) printf "BAD STATUS: $(tail -n1 $tmp) for %s\n" "$user"; ret=1
ret=1
;;
esac
rm "$tmp"
return $ret
}
export -f checkCommits
function checkUser {
local user="$1"
local status=
status="$(curl --silent --head "https://github.com/${user}" | grep Status)"
# checks whether a user handle can be found on github
if [[ "$status" =~ 404 ]]; then
printf "%s\t\t\t\t%s\n" "$status" "$user"
# checks whether the user handle has any nixpkgs commits
elif checkCommits "$user"; then
printf "OK!\t\t\t\t%s\n" "$user"
else
printf "No Commits!\t\t\t%s\n" "$user"
fi
}
export -f checkUser
# output the maintainers set as json
# and filter out the github username of each maintainer (if it exists)
# then check some at the same time
nix-instantiate -A lib.maintainers --eval --strict --json \
| jq -r '.[]|.github|select(.)' \
| parallel -j5 checkUser
# parallel -j100 checkUser ::: "eelco" "profpatsch" "Profpatsch" "a"

View File

@ -1,5 +1,5 @@
#! /usr/bin/env nix-shell
#! nix-shell -i perl -p perl perlPackages.NetAmazonS3 perlPackages.FileSlurp nixUnstable
#! nix-shell -i perl -p perl perlPackages.NetAmazonS3 perlPackages.FileSlurp nixUnstable nixUnstable.perl-bindings
# This command uploads tarballs to tarballs.nixos.org, the
# content-addressed cache used by fetchurl as a fallback for when
@ -59,6 +59,7 @@ my $s3 = Net::Amazon::S3->new(
{ aws_access_key_id => $aws_access_key_id,
aws_secret_access_key => $aws_secret_access_key,
retry => 1,
host => "s3-eu-west-1.amazonaws.com",
});
my $bucket = $s3->bucket("nixpkgs-tarballs") or die;

View File

@ -4,11 +4,13 @@
# Usage $0 debian-patches.txt debian-patches.nix
# An example input and output files can be found in applications/graphics/xara/
DEB_URL=http://patch-tracker.debian.org/patch/series/dl
DEB_URL=https://sources.debian.org/data/main
declare -a deb_patches
mapfile -t deb_patches < $1
prefix="${DEB_URL}/${deb_patches[0]}"
# First letter
deb_prefix="${deb_patches[0]:0:1}"
prefix="${DEB_URL}/${deb_prefix}/${deb_patches[0]}/debian/patches"
if [[ -n "$2" ]]; then
exec 1> $2

View File

@ -21,7 +21,7 @@ find . -type f | while read src; do
# Sanitize file name
filename=$(basename "$src" | tr '@' '_')
nameVersion="${filename%.tar.*}"
name=$(echo "$nameVersion" | sed -e 's,-[[:digit:]].*,,' | sed -e 's,-opensource-src$,,')
name=$(echo "$nameVersion" | sed -e 's,-[[:digit:]].*,,' | sed -e 's,-opensource-src$,,' | sed -e 's,-everywhere-src$,,')
version=$(echo "$nameVersion" | sed -e 's,^\([[:alpha:]][[:alnum:]]*-\)\+,,')
echo "$name,$version,$src,$filename" >>$csv
done

View File

@ -1,194 +0,0 @@
#!/usr/bin/env bash
set -o pipefail
GNOME_FTP=ftp.gnome.org/pub/GNOME/sources
# projects that don't follow the GNOME major versioning, or that we don't want to
# programmatically update
NO_GNOME_MAJOR="ghex gtkhtml gdm"
usage() {
echo "Usage: $0 gnome_dir <show project>|<update project>|<update-all> [major.minor]" >&2
echo "gnome_dir is for example pkgs/desktops/gnome-3/3.18" >&2
exit 0
}
if [ "$#" -lt 2 ]; then
usage
fi
GNOME_TOP=$1
shift
action=$1
# curl -l ftp://... doesn't work from my office in HSE, and I don't want to have
# any conversations with sysadmin. Somehow lftp works.
if [ "$FTP_CLIENT" = "lftp" ]; then
ls_ftp() {
lftp -c "open $1; cls"
}
else
ls_ftp() {
curl -s -l "$1"/
}
fi
find_project() {
exec find "$GNOME_TOP" -mindepth 2 -maxdepth 2 -type d "$@"
}
show_project() {
local project=$1
local majorVersion=$2
local version=
if [ -z "$majorVersion" ]; then
echo "Looking for available versions..." >&2
local available_baseversions=$(ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n)
if [ "$?" -ne 0 ]; then
echo "Project $project not found" >&2
return 1
fi
echo -e "The following versions are available:\n ${available_baseversions[@]}" >&2
echo -en "Choose one of them: " >&2
read majorVersion
fi
if echo "$majorVersion" | grep -q "[0-9]\+\.[0-9]\+\.[0-9]\+"; then
# not a major version
version=$majorVersion
majorVersion=$(echo "$majorVersion" | cut -d '.' -f 1,2)
fi
local FTPDIR=${GNOME_FTP}/${project}/${majorVersion}
#version=`curl -l ${FTPDIR}/ 2>/dev/null | grep LATEST-IS | sed -e s/LATEST-IS-//`
# gnome's LATEST-IS is broken. Do not trust it.
if [ -z "$version" ]; then
local files=$(ls_ftp "${FTPDIR}")
declare -A versions
for f in $files; do
case $f in
(LATEST-IS-*|*.news|*.changes|*.sha256sum|*.diff*):
;;
($project-*.*.9*.tar.*):
tmp=${f#$project-}
tmp=${tmp%.tar*}
echo "Ignored unstable version ${tmp}" >&2
;;
($project-*.tar.*):
tmp=${f#$project-}
tmp=${tmp%.tar*}
versions[${tmp}]=1
;;
(*):
echo "UNKNOWN FILE $f" >&2
;;
esac
done
echo "Found versions ${!versions[@]}" >&2
version=$(echo ${!versions[@]} | sed -e 's/ /\n/g' | sort -t. -k1,1n -k 2,2n -k 3,3n | tail -n1)
if [ -z "$version" ]; then
echo "No version available for major $majorVersion" >&2
return 1
fi
echo "Latest version is: ${version}" >&2
fi
local name=${project}-${version}
echo "Fetching .sha256 file" >&2
local sha256out=$(curl -s -f http://"${FTPDIR}"/"${name}".sha256sum)
if [ "$?" -ne "0" ]; then
echo "Version not found" >&2
return 1
fi
extensions=( "xz" "bz2" "gz" )
echo "Choosing archive extension (known are ${extensions[@]})..." >&2
for ext in ${extensions[@]}; do
if echo -e "$sha256out" | grep -q "\\.tar\\.${ext}$"; then
ext_pref=$ext
sha256=$(echo -e "$sha256out" | grep "\\.tar\\.${ext}$" | cut -f1 -d\ )
break
fi
done
echo "Chosen ${ext_pref}, hash is ${sha256}" >&2
echo "# Autogenerated by maintainers/scripts/gnome.sh update
fetchurl: {
name = \"${project}-${version}\";
src = fetchurl {
url = mirror://gnome/sources/${project}/${majorVersion}/${project}-${version}.tar.${ext_pref};
sha256 = \"${sha256}\";
};
}"
return 0
}
update_project() {
local project=$1
local majorVersion=$2
# find project in nixpkgs tree
projectPath=$(find_project -name "$project" -print)
if [ -z "$projectPath" ]; then
echo "Project $project not found under $GNOME_TOP"
exit 1
fi
src=$(show_project "$project" "$majorVersion")
if [ "$?" -eq "0" ]; then
echo "Updating $projectPath/src.nix" >&2
echo -e "$src" > "$projectPath"/src.nix
fi
return 0
}
if [ "$action" = "update-all" ]; then
majorVersion=$2
if [ -z "$majorVersion" ]; then
echo "No major version specified" >&2
usage
fi
# find projects
projects=$(find_project -exec basename '{}' \;)
for project in $projects; do
if echo "$NO_GNOME_MAJOR"|grep -q $project; then
echo "Skipping $project"
else
echo "= Updating $project to $majorVersion" >&2
update_project "$project" "$majorVersion"
echo >&2
fi
done
else
project=$2
majorVersion=$3
if [ -z "$project" ]; then
echo "No project specified, exiting" >&2
usage
fi
if [ "$action" = show ]; then
show_project "$project" "$majorVersion"
elif [ "$action" = update ]; then
update_project "$project" "$majorVersion"
else
echo "Unknown action $action" >&2
usage
fi
fi

View File

@ -13,10 +13,8 @@ from pyquery import PyQuery as pq
maintainers_json = subprocess.check_output([
'nix-instantiate',
'lib/maintainers.nix',
'--eval',
'--json'])
'nix-instantiate', '-E', 'import ./maintainers/maintainer-list.nix {}', '--eval', '--json'
])
maintainers = json.loads(maintainers_json)
MAINTAINERS = {v: k for k, v in maintainers.iteritems()}
@ -31,25 +29,28 @@ EVAL_FILE = {
def get_maintainers(attr_name):
nixname = attr_name.split('.')
meta_json = subprocess.check_output([
'nix-instantiate',
'--eval',
'--strict',
'-A',
'.'.join(nixname[1:]) + '.meta',
EVAL_FILE[nixname[0]],
'--json'])
meta = json.loads(meta_json)
if meta.get('maintainers'):
return [MAINTAINERS[name] for name in meta['maintainers'] if MAINTAINERS.get(name)]
try:
nixname = attr_name.split('.')
meta_json = subprocess.check_output([
'nix-instantiate',
'--eval',
'--strict',
'-A',
'.'.join(nixname[1:]) + '.meta',
EVAL_FILE[nixname[0]],
'--json'])
meta = json.loads(meta_json)
if meta.get('maintainers'):
return [MAINTAINERS[name] for name in meta['maintainers'] if MAINTAINERS.get(name)]
except:
return []
@click.command()
@click.option(
'--jobset',
default="nixos/release-17.03",
help='Hydra project like nixos/release-17.03')
default="nixos/release-17.09",
help='Hydra project like nixos/release-17.09')
def cli(jobset):
"""
Given a Hydra project, inspect latest evaluation

View File

@ -1,9 +1,16 @@
#!/usr/bin/env bash
set -e
# --print: avoid dependency on environment
optPrint=
if [ "$1" == "--print" ]; then
optPrint=true
shift
fi
if [ "$#" != 1 ] && [ "$#" != 2 ]; then
cat <<-EOF
Usage: $0 commit-spec [commit-spec]
Usage: $0 [--print] commit-spec [commit-spec]
You need to be in a git-controlled nixpkgs tree.
The current state of the tree will be used if the second commit is missing.
EOF
@ -113,3 +120,8 @@ newPkgs "${tree[1]}" "${tree[2]}" '--argstr system "x86_64-linux"' > "$newlist"
sed -n 's/\([^. ]*\.\)*\([^. ]*\) .*$/\2/p' < "$newlist" \
| sort | uniq -c
if [ -n "$optPrint" ]; then
echo
cat "$newlist"
fi

View File

@ -1,82 +0,0 @@
#! /usr/bin/env bash
set -e
while test -n "$1"; do
# tell Travis to use folding
echo -en "travis_fold:start:$1\r"
case $1 in
nixpkgs-verify)
echo "=== Verifying that nixpkgs evaluates..."
nix-env --file $TRAVIS_BUILD_DIR --query --available --json > /dev/null
;;
nixos-options)
echo "=== Checking NixOS options"
nix-build $TRAVIS_BUILD_DIR/nixos/release.nix --attr options --show-trace
;;
nixos-manual)
echo "=== Checking NixOS manuals"
nix-build $TRAVIS_BUILD_DIR/nixos/release.nix --attr manual --show-trace
;;
nixpkgs-manual)
echo "=== Checking nixpkgs manuals"
nix-build $TRAVIS_BUILD_DIR/pkgs/top-level/release.nix --attr manual --show-trace
;;
nixpkgs-tarball)
echo "=== Checking nixpkgs tarball creation"
nix-build $TRAVIS_BUILD_DIR/pkgs/top-level/release.nix --attr tarball --show-trace
;;
nixpkgs-unstable)
echo "=== Checking nixpkgs unstable job"
nix-instantiate $TRAVIS_BUILD_DIR/pkgs/top-level/release.nix --attr unstable --show-trace
;;
nixpkgs-lint)
echo "=== Checking nixpkgs lint"
nix-shell --packages nixpkgs-lint --run "nixpkgs-lint -f $TRAVIS_BUILD_DIR"
;;
nox)
echo "=== Fetching Nox from binary cache"
# build nox silently so it's not in the log
nix-build "<nixpkgs>" -A nox -A stdenv
;;
pr)
if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
echo "=== No pull request found"
else
echo "=== Building pull request #$TRAVIS_PULL_REQUEST"
token=""
if [ -n "$GITHUB_TOKEN" ]; then
token="--token $GITHUB_TOKEN"
fi
nix-shell --packages nox --run "nox-review pr --slug $TRAVIS_REPO_SLUG $token $TRAVIS_PULL_REQUEST"
fi
;;
*)
echo "Skipping unknown option $1"
;;
esac
echo -en "travis_fold:end:$1\r"
shift
done

View File

@ -1,5 +1,5 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p 'python3.withPackages(ps: with ps; [ requests toolz ])'
#! nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ packaging requests toolz ])" -p git
"""
Update a Python package expression by passing in the `.nix` file, or the directory containing it.
@ -18,6 +18,12 @@ import os
import re
import requests
import toolz
from concurrent.futures import ThreadPoolExecutor as Pool
from packaging.version import Version as _Version
from packaging.version import InvalidVersion
from packaging.specifiers import SpecifierSet
import collections
import subprocess
INDEX = "https://pypi.io/pypi"
"""url of PyPI"""
@ -25,10 +31,30 @@ INDEX = "https://pypi.io/pypi"
EXTENSIONS = ['tar.gz', 'tar.bz2', 'tar', 'zip', '.whl']
"""Permitted file extensions. These are evaluated from left to right and the first occurance is returned."""
PRERELEASES = False
import logging
logging.basicConfig(level=logging.INFO)
class Version(_Version, collections.abc.Sequence):
def __init__(self, version):
super().__init__(version)
# We cannot use `str(Version(0.04.21))` because that becomes `0.4.21`
# https://github.com/avian2/unidecode/issues/13#issuecomment-354538882
self.raw_version = version
def __getitem__(self, i):
return self._version.release[i]
def __len__(self):
return len(self._version.release)
def __iter__(self):
yield from self._version.release
def _get_values(attribute, text):
"""Match attribute in text and return all matches.
@ -81,13 +107,59 @@ def _fetch_page(url):
else:
raise ValueError("request for {} failed".format(url))
def _get_latest_version_pypi(package, extension):
SEMVER = {
'major' : 0,
'minor' : 1,
'patch' : 2,
}
def _determine_latest_version(current_version, target, versions):
"""Determine latest version, given `target`.
"""
current_version = Version(current_version)
def _parse_versions(versions):
for v in versions:
try:
yield Version(v)
except InvalidVersion:
pass
versions = _parse_versions(versions)
index = SEMVER[target]
ceiling = list(current_version[0:index])
if len(ceiling) == 0:
ceiling = None
else:
ceiling[-1]+=1
ceiling = Version(".".join(map(str, ceiling)))
# We do not want prereleases
versions = SpecifierSet(prereleases=PRERELEASES).filter(versions)
if ceiling is not None:
versions = SpecifierSet(f"<{ceiling}").filter(versions)
return (max(sorted(versions))).raw_version
def _get_latest_version_pypi(package, extension, current_version, target):
"""Get latest version and hash from PyPI."""
url = "{}/{}/json".format(INDEX, package)
json = _fetch_page(url)
version = json['info']['version']
for release in json['releases'][version]:
versions = json['releases'].keys()
version = _determine_latest_version(current_version, target, versions)
try:
releases = json['releases'][version]
except KeyError as e:
raise KeyError('Could not find version {} for {}'.format(version, package)) from e
for release in releases:
if release['filename'].endswith(extension):
# TODO: In case of wheel we need to do further checks!
sha256 = release['digests']['sha256']
@ -97,7 +169,7 @@ def _get_latest_version_pypi(package, extension):
return version, sha256
def _get_latest_version_github(package, extension):
def _get_latest_version_github(package, extension, current_version, target):
raise ValueError("updating from GitHub is not yet supported.")
@ -140,9 +212,9 @@ def _determine_extension(text, fetcher):
"""
if fetcher == 'fetchPypi':
try:
format = _get_unique_value('format', text)
src_format = _get_unique_value('format', text)
except ValueError as e:
format = None # format was not given
src_format = None # format was not given
try:
extension = _get_unique_value('extension', text)
@ -150,9 +222,11 @@ def _determine_extension(text, fetcher):
extension = None # extension was not given
if extension is None:
if format is None:
format = 'setuptools'
extension = FORMATS[format]
if src_format is None:
src_format = 'setuptools'
elif src_format == 'flit':
raise ValueError("Don't know how to update a Flit package.")
extension = FORMATS[src_format]
elif fetcher == 'fetchurl':
url = _get_unique_value('url', text)
@ -166,9 +240,7 @@ def _determine_extension(text, fetcher):
return extension
def _update_package(path):
def _update_package(path, target):
# Read the expression
with open(path, 'r') as f:
@ -185,11 +257,13 @@ def _update_package(path):
extension = _determine_extension(text, fetcher)
new_version, new_sha256 = _get_latest_version_pypi(pname, extension)
new_version, new_sha256 = FETCHERS[fetcher](pname, extension, version, target)
if new_version == version:
logging.info("Path {}: no update available for {}.".format(path, pname))
return False
elif new_version <= version:
raise ValueError("downgrade for {}.".format(pname))
if not new_sha256:
raise ValueError("no file available for {}.".format(pname))
@ -201,10 +275,19 @@ def _update_package(path):
logging.info("Path {}: updated {} from {} to {}".format(path, pname, version, new_version))
return True
result = {
'path' : path,
'target': target,
'pname': pname,
'old_version' : version,
'new_version' : new_version,
#'fetcher' : fetcher,
}
return result
def _update(path):
def _update(path, target):
# We need to read and modify a Nix expression.
if os.path.isdir(path):
@ -221,23 +304,58 @@ def _update(path):
return False
try:
return _update_package(path)
return _update_package(path, target)
except ValueError as e:
logging.warning("Path {}: {}".format(path, e))
return False
def _commit(path, pname, old_version, new_version, **kwargs):
"""Commit result.
"""
msg = f'python: {pname}: {old_version} -> {new_version}'
try:
subprocess.check_call(['git', 'add', path])
subprocess.check_call(['git', 'commit', '-m', msg])
except subprocess.CalledProcessError as e:
subprocess.check_call(['git', 'checkout', path])
raise subprocess.CalledProcessError(f'Could not commit {path}') from e
return True
def main():
parser = argparse.ArgumentParser()
parser.add_argument('package', type=str, nargs='+')
parser.add_argument('--target', type=str, choices=SEMVER.keys(), default='major')
parser.add_argument('--commit', action='store_true', help='Create a commit for each package update')
args = parser.parse_args()
target = args.target
packages = map(os.path.abspath, args.package)
packages = list(map(os.path.abspath, args.package))
logging.info("Updating packages...")
# Use threads to update packages concurrently
with Pool() as p:
results = list(p.map(lambda pkg: _update(pkg, target), packages))
logging.info("Finished updating packages.")
# Commits are created sequentially.
if args.commit:
logging.info("Committing updates...")
list(map(lambda x: _commit(**x), filter(bool, results)))
logging.info("Finished committing updates")
count = sum(map(bool, results))
logging.info("{} package(s) updated".format(count))
count = list(map(_update, packages))
logging.info("{} package(s) updated".format(sum(count)))
if __name__ == '__main__':
main()
main()

View File

@ -1,37 +1,51 @@
{ package ? null
, maintainer ? null
, path ? null
}:
# TODO: add assert statements
let
/* Remove duplicate elements from the list based on some extracted value. O(n^2) complexity.
*/
nubOn = f: list:
if list == [] then
[]
else
let
x = pkgs.lib.head list;
xs = pkgs.lib.filter (p: f x != f p) (pkgs.lib.drop 1 list);
in
[x] ++ nubOn f xs;
pkgs = import ./../../default.nix { };
packagesWith = cond: return: set:
pkgs.lib.flatten
(pkgs.lib.mapAttrsToList
(name: pkg:
let
result = builtins.tryEval (
if pkgs.lib.isDerivation pkg && cond name pkg
then [(return name pkg)]
else if pkg.recurseForDerivations or false || pkg.recurseForRelease or false
then packagesWith cond return pkg
nubOn (pkg: pkg.updateScript)
(pkgs.lib.flatten
(pkgs.lib.mapAttrsToList
(name: pkg:
let
result = builtins.tryEval (
if pkgs.lib.isDerivation pkg && cond name pkg
then [(return name pkg)]
else if pkg.recurseForDerivations or false || pkg.recurseForRelease or false
then packagesWith cond return pkg
else []
);
in
if result.success then result.value
else []
);
in
if result.success then result.value
else []
)
set
)
set
);
packagesWithUpdateScriptAndMaintainer = maintainer':
let
maintainer =
if ! builtins.hasAttr maintainer' pkgs.lib.maintainers then
builtins.throw "Maintainer with name `${maintainer'} does not exist in `lib/maintainers.nix`."
builtins.throw "Maintainer with name `${maintainer'} does not exist in `maintainers/maintainer-list.nix`."
else
builtins.getAttr maintainer' pkgs.lib.maintainers;
in
@ -47,6 +61,14 @@ let
(name: pkg: pkg)
pkgs;
packagesWithUpdateScript = path:
let
attrSet = pkgs.lib.attrByPath (pkgs.lib.splitString "." path) null pkgs;
in
packagesWith (name: pkg: builtins.hasAttr "updateScript" pkg)
(name: pkg: pkg)
attrSet;
packageByName = name:
let
package = pkgs.lib.attrByPath (pkgs.lib.splitString "." name) null pkgs;
@ -54,7 +76,7 @@ let
if package == null then
builtins.throw "Package with an attribute name `${name}` does not exists."
else if ! builtins.hasAttr "updateScript" package then
builtins.throw "Package with an attribute name `${name}` does have an `passthru.updateScript` defined."
builtins.throw "Package with an attribute name `${name}` does not have a `passthru.updateScript` attribute defined."
else
package;
@ -63,6 +85,8 @@ let
[ (packageByName package) ]
else if maintainer != null then
packagesWithUpdateScriptAndMaintainer maintainer
else if path != null then
packagesWithUpdateScript path
else
builtins.throw "No arguments provided.\n\n${helpText}";
@ -76,7 +100,11 @@ let
% nix-shell maintainers/scripts/update.nix --argstr package garbas
to run update script for specific package.
to run update script for specific package, or
% nix-shell maintainers/scripts/update.nix --argstr path gnome3
to run update script for all package under an attribute path.
'';
runUpdateScript = package: ''

View File

@ -10,7 +10,7 @@ git_data="$(echo "$raw_git_log" | grep 'Author:' |
# Name - nick - email correspondence from log and from maintainer list
# Also there are a few manual entries
maintainers="$(cat "$(dirname "$0")/../../lib/maintainers.nix" |
maintainers="$(cat "$(dirname "$0")/../maintainer-list.nix" |
grep '=' | sed -re 's/\\"/''/g;
s/[ ]*([^ =]*)[ ]*=[ ]*" *(.*[^ ]) *[<](.*)[>] *".*/\1\t\2\t\3/')"
git_lines="$( ( echo "$git_data";

View File

@ -9,8 +9,6 @@ let
modules = [ configuration ];
};
inherit (eval) pkgs;
# This is for `nixos-rebuild build-vm'.
vmConfig = (import ./lib/eval-config.nix {
inherit system;
@ -30,7 +28,7 @@ let
in
{
inherit (eval) config options;
inherit (eval) pkgs config options;
system = eval.config.system.build.toplevel;

View File

@ -16,7 +16,7 @@ containers.database =
{ config =
{ config, pkgs, ... }:
{ services.postgresql.enable = true;
services.postgresql.package = pkgs.postgresql92;
services.postgresql.package = pkgs.postgresql96;
};
};
</programlisting>

View File

@ -23,10 +23,23 @@ networking.firewall.allowedTCPPorts = [ 80 443 ];
</programlisting>
Note that TCP port 22 (ssh) is opened automatically if the SSH daemon
is enabled (<option>services.openssh.enable = true</option>). UDP
is enabled (<option>services.openssh.enable = true</option>). UDP
ports can be opened through
<option>networking.firewall.allowedUDPPorts</option>. Also of
interest is
<option>networking.firewall.allowedUDPPorts</option>.</para>
<para>To open ranges of TCP ports:
<programlisting>
networking.firewall.allowedTCPPortRanges = [
{ from = 4000; to = 4007; }
{ from = 8000; to = 8010; }
];
</programlisting>
Similarly, UDP port ranges can be opened through
<option>networking.firewall.allowedUDPPortRanges</option>.</para>
<para>Also of interest is
<programlisting>
networking.firewall.allowPing = true;

View File

@ -12,7 +12,7 @@ interfaces. However, you can configure an interface manually as
follows:
<programlisting>
networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
</programlisting>
Typically youll also want to set a default gateway and set of name

View File

@ -26,7 +26,7 @@ boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true;
DHCPv6. You can configure an interface manually:
<programlisting>
networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ];
networking.interfaces.eth0.ipv6.addresses = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ];
</programlisting>
</para>

View File

@ -113,7 +113,8 @@ manual</link> for the rest.</para>
</row>
<row>
<entry><literal>assert 1 + 1 == 2; "yes!"</literal></entry>
<entry>Assertion check (evaluates to <literal>"yes!"</literal>)</entry>
<entry>Assertion check (evaluates to <literal>"yes!"</literal>). See <xref
linkend="sec-assertions"/> for using assertions in modules</entry>
</row>
<row>
<entry><literal>let x = "foo"; y = "bar"; in x + y</literal></entry>

View File

@ -12,7 +12,7 @@ management. In the declarative style, users are specified in
states that a user account named <literal>alice</literal> shall exist:
<programlisting>
users.extraUsers.alice =
users.users.alice =
{ isNormalUser = true;
home = "/home/alice";
description = "Alice Foobar";
@ -34,7 +34,7 @@ to set a password, which is retained across invocations of
<para>If you set users.mutableUsers to false, then the contents of /etc/passwd
and /etc/group will be congruent to your NixOS configuration. For instance,
if you remove a user from users.extraUsers and run nixos-rebuild, the user
if you remove a user from users.users and run nixos-rebuild, the user
account will cease to exist. Also, imperative commands for managing users
and groups, such as useradd, are no longer available. Passwords may still be
assigned by setting the user's <literal>hashedPassword</literal> option. A
@ -54,7 +54,7 @@ to the user specification.</para>
group named <literal>students</literal> shall exist:
<programlisting>
users.extraGroups.students.gid = 1000;
users.groups.students.gid = 1000;
</programlisting>
As with users, the group ID (gid) is optional and will be assigned
@ -68,8 +68,8 @@ account named <literal>alice</literal>:
<screen>
# useradd -m alice</screen>
To make all nix tools available to this new user use `su - USER` which
opens a login shell (==shell that loads the profile) for given user.
To make all nix tools available to this new user use `su - USER` which
opens a login shell (==shell that loads the profile) for given user.
This will create the ~/.nix-defexpr symlink. So run:
<screen>

View File

@ -115,13 +115,14 @@ hardware.opengl.driSupport32Bit = true;
<para>Support for Synaptics touchpads (found in many laptops such as
the Dell Latitude series) can be enabled as follows:
<programlisting>
services.xserver.synaptics.enable = true;
services.xserver.libinput.enable = true;
</programlisting>
The driver has many options (see <xref linkend="ch-options"/>). For
instance, the following enables two-finger scrolling:
instance, the following disables tap-to-click behavior:
<programlisting>
services.xserver.synaptics.twoFingerScroll = true;
services.xserver.libinput.tapping = false;
</programlisting>
Note: the use of <literal>services.xserver.synaptics</literal> is deprecated since NixOS 17.09.
</para>
</simplesect>
@ -129,7 +130,7 @@ services.xserver.synaptics.twoFingerScroll = true;
<simplesect><title>GTK/Qt themes</title>
<para>GTK themes can be installed either to user profile or system-wide (via
<literal>system.environmentPackages</literal>). To make Qt 5 applications look similar
<literal>environment.systemPackages</literal>). To make Qt 5 applications look similar
to GTK2 ones, you can install <literal>qt5.qtbase.gtk</literal> package into your
system environment. It should work for all Qt 5 library versions.
</para>

View File

@ -35,18 +35,7 @@ services.compton = {
To install them manually (system wide), put them into your
<literal>environment.systemPackages</literal>.
</para>
<para>
NixOSs default <emphasis>display manager</emphasis> is SLiM.
(DM is the program that provides a graphical login prompt
and manages the X server.)
You can, for example, select KDEs
<command>sddm</command> instead:
<programlisting>
services.xserver.displayManager.sddm.enable = true;
</programlisting>
</para>
<simplesect>
<title>Thunar Volume Support</title>

View File

@ -6,22 +6,52 @@ let
lib = pkgs.lib;
# Remove invisible and internal options.
optionsList = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
# Replace functions by the string <function>
substFunction = x:
if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
else if builtins.isList x then map substFunction x
else if builtins.isFunction x then "<function>"
else if lib.isFunction x then "<function>"
else x;
# Clean up declaration sites to not refer to the NixOS source tree.
optionsList' = lib.flip map optionsList (opt: opt // {
# Generate DocBook documentation for a list of packages. This is
# what `relatedPackages` option of `mkOption` from
# ../../../lib/options.nix influences.
#
# Each element of `relatedPackages` can be either
# - a string: that will be interpreted as an attribute name from `pkgs`,
# - a list: that will be interpreted as an attribute path from `pkgs`,
# - an attrset: that can specify `name`, `path`, `package`, `comment`
# (either of `name`, `path` is required, the rest are optional).
genRelatedPackages = packages:
let
unpack = p: if lib.isString p then { name = p; }
else if lib.isList p then { path = p; }
else p;
describe = args:
let
name = args.name or (lib.concatStringsSep "." args.path);
path = args.path or [ args.name ];
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
in "<listitem>"
+ "<para><literal>pkgs.${name} (${package.meta.name})</literal>"
+ lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"
+ ": ${package.meta.description or "???"}.</para>"
+ lib.optionalString (args ? comment) "\n<para>${args.comment}</para>"
# Lots of `longDescription's break DocBook, so we just wrap them into <programlisting>
+ lib.optionalString (package.meta ? longDescription) "\n<programlisting>${package.meta.longDescription}</programlisting>"
+ "</listitem>";
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
optionsListDesc = lib.flip map optionsListVisible (opt: opt // {
# Clean up declaration sites to not refer to the NixOS source tree.
declarations = map stripAnyPrefixes opt.declarations;
}
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; });
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
// lib.optionalAttrs (opt ? relatedPackages) { relatedPackages = genRelatedPackages opt.relatedPackages; });
# We need to strip references to /nix/store/* from options,
# including any `extraSources` if some modules came from elsewhere,
@ -32,8 +62,21 @@ let
prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
# Custom "less" that pushes up all the things ending in ".enable*"
# and ".package*"
optionLess = a: b:
let
ise = lib.hasPrefix "enable";
isp = lib.hasPrefix "package";
cmp = lib.splitByAndCompare ise lib.compare
(lib.splitByAndCompare isp lib.compare lib.compare);
in lib.compareLists cmp a.loc b.loc < 0;
# Customly sort option list for the man page.
optionsList = lib.sort optionLess optionsListDesc;
# Convert the list of options into an XML file.
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList');
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
optionsDocBook = runCommand "options-db.xml" {} ''
optionsXML=${optionsXML}
@ -44,7 +87,7 @@ let
echo "for hints about the offending path)."
exit 1
fi
${libxslt.bin}/bin/xsltproc \
${buildPackages.libxslt.bin}/bin/xsltproc \
--stringparam revision '${revision}' \
-o $out ${./options-to-docbook.xsl} $optionsXML
'';
@ -96,7 +139,7 @@ let
manual-combined = runCommand "nixos-manual-combined"
{ inherit sources;
buildInputs = [ libxml2 libxslt ];
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
meta.description = "The NixOS manual as plain docbook XML";
}
''
@ -106,13 +149,43 @@ let
xmllint --xinclude --noxincludenode \
--output ./man-pages-combined.xml ./man-pages.xml
xmllint --debug --noout --nonet \
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
manual-combined.xml
xmllint --debug --noout --nonet \
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
man-pages-combined.xml
# outputs the context of an xmllint error output
# LEN lines around the failing line are printed
function context {
# length of context
local LEN=6
# lines to print before error line
local BEFORE=4
# xmllint output lines are:
# file.xml:1234: there was an error on line 1234
while IFS=':' read -r file line rest; do
echo
if [[ -n "$rest" ]]; then
echo "$file:$line:$rest"
local FROM=$(($line>$BEFORE ? $line - $BEFORE : 1))
# number lines & filter context
nl --body-numbering=a "$file" | sed -n "$FROM,+$LEN p"
else
if [[ -n "$line" ]]; then
echo "$file:$line"
else
echo "$file"
fi
fi
done
}
function lintrng {
xmllint --debug --noout --nonet \
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
"$1" \
2>&1 | context 1>&2
# ^ redirect assumes xmllint doesnt print to stdout
}
lintrng manual-combined.xml
lintrng man-pages-combined.xml
mkdir $out
cp manual-combined.xml $out/
@ -121,7 +194,7 @@ let
olinkDB = runCommand "manual-olinkdb"
{ inherit sources;
buildInputs = [ libxml2 libxslt ];
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
}
''
xsltproc \
@ -161,7 +234,7 @@ in rec {
mkdir -p $dst
cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
(builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList'))))
(builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList))))
} $dst/options.json
mkdir -p $out/nix-support
@ -171,7 +244,7 @@ in rec {
# Generate the NixOS manual.
manual = runCommand "nixos-manual"
{ inherit sources;
buildInputs = [ libxml2 libxslt ];
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
meta.description = "The NixOS manual in HTML format";
allowedReferences = ["out"];
}
@ -199,7 +272,7 @@ in rec {
manualEpub = runCommand "nixos-manual-epub"
{ inherit sources;
buildInputs = [ libxml2 libxslt zip ];
buildInputs = [ libxml2.bin libxslt.bin zip ];
}
''
# Generate the epub manual.
@ -229,7 +302,7 @@ in rec {
# Generate the NixOS manpages.
manpages = runCommand "nixos-manpages"
{ inherit sources;
buildInputs = [ libxml2 libxslt ];
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
allowedReferences = ["out"];
}
''

View File

@ -0,0 +1,80 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-assertions">
<title>Warnings and Assertions</title>
<para>
When configuration problems are detectable in a module, it is a good
idea to write an assertion or warning. Doing so provides clear
feedback to the user and prevents errors after the build.
</para>
<para>
Although Nix has the <literal>abort</literal> and
<literal>builtins.trace</literal> <link xlink:href="https://nixos.org/nix/manual/#ssec-builtins">functions</link> to perform such tasks,
they are not ideally suited for NixOS modules. Instead of these
functions, you can declare your warnings and assertions using the
NixOS module system.
</para>
<section>
<title>Warnings</title>
<para>
This is an example of using <literal>warnings</literal>.
</para>
<programlisting>
<![CDATA[
{ config, lib, ... }:
{
config = lib.mkIf config.services.foo.enable {
warnings =
if config.services.foo.bar
then [ ''You have enabled the bar feature of the foo service.
This is known to cause some specific problems in certain situations.
'' ]
else [];
}
}
]]>
</programlisting>
</section>
<section>
<title>Assertions</title>
<para>
This example, extracted from the
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-17.09/nixos/modules/services/logging/syslogd.nix">
<literal>syslogd</literal> module
</link> shows how to use <literal>assertions</literal>. Since there
can only be one active syslog daemon at a time, an assertion is useful to
prevent such a broken system from being built.
</para>
<programlisting>
<![CDATA[
{ config, lib, ... }:
{
config = lib.mkIf config.services.syslogd.enable {
assertions =
[ { assertion = !config.services.rsyslogd.enable;
message = "rsyslogd conflicts with syslogd";
}
];
}
}
]]>
</programlisting>
</section>
</section>

View File

@ -22,6 +22,15 @@ options = {
};
</programlisting>
The attribute names within the <replaceable>name</replaceable>
attribute path must be camel cased in general but should, as an
exception, match the
<link
xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming">
package attribute name</link> when referencing a Nixpkgs package. For
example, the option <varname>services.nix-serve.bindAddress</varname>
references the <varname>nix-serve</varname> Nixpkgs package.
</para>
<para>The function <varname>mkOption</varname> accepts the following arguments.
@ -137,8 +146,8 @@ services.xserver.displayManager.enable = mkOption {
};</screen></example>
<example xml:id='ex-option-declaration-eot-backend-sddm'><title>Extending
<literal>services.foo.backend</literal> in the <literal>sddm</literal>
module</title>
<literal>services.xserver.displayManager.enable</literal> in the
<literal>sddm</literal> module</title>
<screen>
services.xserver.displayManager.enable = mkOption {
type = with types; nullOr (enum [ "sddm" ]);

View File

@ -22,10 +22,6 @@
<listitem><para>A boolean, its values can be <literal>true</literal> or
<literal>false</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>types.int</varname></term>
<listitem><para>An integer.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>types.path</varname></term>
<listitem><para>A filesystem path, defined as anything that when coerced to
@ -39,7 +35,59 @@
</varlistentry>
</variablelist>
<para>String related types:</para>
<para>Integer-related types:</para>
<variablelist>
<varlistentry>
<term><varname>types.int</varname></term>
<listitem><para>A signed integer.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.ints.{s8, s16, s32}</varname>
</term>
<listitem>
<para>Signed integers with a fixed length (8, 16 or 32 bits).
They go from
<inlineequation><mathphrase>2<superscript>n</superscript>/2</mathphrase>
</inlineequation> to <inlineequation>
<mathphrase>2<superscript>n</superscript>/21</mathphrase>
</inlineequation>
respectively (e.g. <literal>128</literal> to <literal>127</literal>
for 8 bits).
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.ints.unsigned</varname>
</term>
<listitem><para>An unsigned integer (that is >= 0).
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.ints.{u8, u16, u32}</varname>
</term>
<listitem>
<para>Unsigned integers with a fixed length (8, 16 or 32 bits).
They go from
<inlineequation><mathphrase>0</mathphrase></inlineequation> to <inlineequation>
<mathphrase>2<superscript>n</superscript>1</mathphrase>
</inlineequation>
respectively (e.g. <literal>0</literal> to <literal>255</literal>
for 8 bits).
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.ints.positive</varname>
</term>
<listitem><para>A positive integer (that is > 0).
</para></listitem>
</varlistentry>
</variablelist>
<para>String-related types:</para>
<variablelist>
<varlistentry>
@ -62,13 +110,19 @@
<listitem><para>A string. Multiple definitions are concatenated with a
collon <literal>":"</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>types.strMatching</varname></term>
<listitem><para>A string matching a specific regular expression. Multiple
definitions cannot be merged. The regular expression is processed using
<literal>builtins.match</literal>.</para></listitem>
</varlistentry>
</variablelist>
</section>
<section><title>Value Types</title>
<para>Value types are type that take a value parameter.</para>
<para>Value types are types that take a value parameter.</para>
<variablelist>
<varlistentry>
@ -84,6 +138,17 @@
<replaceable>sep</replaceable>, e.g. <literal>types.separatedString
"|"</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.ints.between</varname>
<replaceable>lowest</replaceable>
<replaceable>highest</replaceable>
</term>
<listitem><para>An integer between <replaceable>lowest</replaceable>
and <replaceable>highest</replaceable> (both inclusive).
Useful for creating types like <literal>types.port</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>types.submodule</varname> <replaceable>o</replaceable></term>
<listitem><para>A set of sub options <replaceable>o</replaceable>.
@ -157,27 +222,26 @@
<section xml:id='section-option-types-submodule'><title>Submodule</title>
<para>Submodule is a very powerful type that defines a set of sub-options that
are handled like a separate module.
It is especially interesting when used with composed types like
<literal>attrsOf</literal> or <literal>listOf</literal>.</para>
<para><literal>submodule</literal> is a very powerful type that defines a set
of sub-options that are handled like a separate module.</para>
<para>The submodule type take a parameter <replaceable>o</replaceable>, that
should be a set, or a function returning a set with an
<literal>options</literal> key defining the sub-options.
The option set can be defined directly (<xref linkend='ex-submodule-direct'
/>) or as reference (<xref linkend='ex-submodule-reference' />).</para>
<para>It takes a parameter <replaceable>o</replaceable>, that should be a set,
or a function returning a set with an <literal>options</literal> key
defining the sub-options.
Submodule option definitions are type-checked accordingly to the
<literal>options</literal> declarations.
Of course, you can nest submodule option definitons for even higher
modularity.</para>
<para>Submodule option definitions are type-checked accordingly to the options
declarations. It is possible to declare submodule options inside a submodule
sub-options for even higher modularity.</para>
<para>The option set can be defined directly
(<xref linkend='ex-submodule-direct' />) or as reference
(<xref linkend='ex-submodule-reference' />).</para>
<example xml:id='ex-submodule-direct'><title>Directly defined submodule</title>
<screen>
options.mod = mkOption {
name = "mod";
description = "submodule example";
type = with types; listOf (submodule {
type = with types; submodule {
options = {
foo = mkOption {
type = int;
@ -186,10 +250,10 @@ options.mod = mkOption {
type = str;
};
};
});
};
};</screen></example>
<example xml:id='ex-submodule-reference'><title>Submodule defined as a
<example xml:id='ex-submodule-reference'><title>Submodule defined as a
reference</title>
<screen>
let
@ -206,15 +270,19 @@ let
in
options.mod = mkOption {
description = "submodule example";
type = with types; listOf (submodule modOptions);
type = with types; submodule modOptions;
};</screen></example>
<section><title>Composed with <literal>listOf</literal></title>
<para>The <literal>submodule</literal> type is especially interesting when
used with composed types like <literal>attrsOf</literal> or
<literal>listOf</literal>.
When composed with <literal>listOf</literal>
(<xref linkend='ex-submodule-listof-declaration' />),
<literal>submodule</literal> allows multiple definitions of the submodule
option set (<xref linkend='ex-submodule-listof-definition' />).</para>
<para>When composed with <literal>listOf</literal>, submodule allows multiple
definitions of the submodule option set.</para>
<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list
<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list
of submodules</title>
<screen>
options.mod = mkOption {
@ -239,13 +307,11 @@ config.mod = [
{ foo = 2; bar = "two"; }
];</screen></example>
</section>
<section><title>Composed with <literal>attrsOf</literal></title>
<para>When composed with <literal>attrsOf</literal>, submodule allows multiple
named definitions of the submodule option set.</para>
<para>When composed with <literal>attrsOf</literal>
(<xref linkend='ex-submodule-attrsof-declaration' />),
<literal>submodule</literal> allows multiple named definitions of the
submodule option set (<xref linkend='ex-submodule-attrsof-definition' />).
</para>
<example xml:id='ex-submodule-attrsof-declaration'><title>Declaration of
attribute sets of submodules</title>
@ -270,7 +336,6 @@ options.mod = mkOption {
config.mod.one = { foo = 1; bar = "one"; };
config.mod.two = { foo = 2; bar = "two"; };</screen></example>
</section>
</section>
<section><title>Extending types</title>

Some files were not shown because too many files have changed in this diff Show More