mirror of
https://github.com/CHN-beta/nixpkgs.git
synced 2026-01-13 11:30:35 +08:00
Compare commits
7 Commits
v192
...
backups/st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
448be29a21 | ||
|
|
28ad00775f | ||
|
|
ef94f7d4e9 | ||
|
|
552f7b4ec8 | ||
|
|
98644029cf | ||
|
|
8afe8cfff0 | ||
|
|
d76f7de2da |
18
.gitignore
vendored
18
.gitignore
vendored
@@ -1,18 +0,0 @@
|
||||
*~
|
||||
,*
|
||||
.*.swp
|
||||
.*.swo
|
||||
result
|
||||
result-*
|
||||
/doc/NEWS.html
|
||||
/doc/NEWS.txt
|
||||
/doc/manual.html
|
||||
/doc/manual.pdf
|
||||
.version-suffix
|
||||
|
||||
.DS_Store
|
||||
|
||||
/pkgs/applications/kde-apps-*/tmp/
|
||||
/pkgs/development/libraries/kde-frameworks-*/tmp/
|
||||
/pkgs/development/libraries/qt-5/*/tmp/
|
||||
/pkgs/desktops/plasma-*/tmp/
|
||||
@@ -1,6 +0,0 @@
|
||||
language: python
|
||||
python: "3.4"
|
||||
sudo: required
|
||||
before_install: ./maintainers/scripts/travis-nox-review-pr.sh nix
|
||||
install: ./maintainers/scripts/travis-nox-review-pr.sh nox
|
||||
script: ./maintainers/scripts/travis-nox-review-pr.sh build
|
||||
@@ -1,12 +0,0 @@
|
||||
# How to contribute
|
||||
|
||||
## Opening issues
|
||||
|
||||
* Make sure you have a [GitHub account](https://github.com/signup/free)
|
||||
* [Submit an issue](https://github.com/NixOS/nixpkgs/issues) - assuming one does not already exist.
|
||||
* Clearly describe the issue including steps to reproduce when it is a bug.
|
||||
* Include information what version of nixpkgs and Nix are you using (nixos-version or git revision).
|
||||
|
||||
## Submitting changes
|
||||
|
||||
See the nixpkgs manual for details on how to [Submit changes to nixpkgs](http://hydra.nixos.org/job/nixpkgs/trunk/manual/latest/download-by-type/doc/manual#chap-submitting-changes).
|
||||
44
README.md
44
README.md
@@ -1,44 +0,0 @@
|
||||
[<img src="http://nixos.org/logo/nixos-hires.png" width="500px" alt="logo" />](https://nixos.org/nixos)
|
||||
|
||||
[](https://travis-ci.org/NixOS/nixpkgs)
|
||||
[](http://www.issuestats.com/github/nixos/nixpkgs)
|
||||
[](http://www.issuestats.com/github/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/)
|
||||
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:
|
||||
|
||||
```
|
||||
% git remote add channels git://github.com/NixOS/nixpkgs-channels.git
|
||||
```
|
||||
|
||||
For stability and maximum binary package support, it is recommended to maintain
|
||||
custom changes on top of one of the channels, e.g. `nixos-14.12` for the latest
|
||||
release and `nixos-unstable` for the latest successful build of master:
|
||||
|
||||
```
|
||||
% git remote update channels
|
||||
% git rebase channels/nixos-14.12
|
||||
```
|
||||
|
||||
For pull-requests, please rebase onto nixpkgs `master`.
|
||||
|
||||
[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/)
|
||||
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
|
||||
* [Continuous package builds for 14.12 release](https://hydra.nixos.org/jobset/nixos/release-14.12)
|
||||
* [Continuous package builds for 15.09 release](https://hydra.nixos.org/jobset/nixos/release-15.09)
|
||||
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
|
||||
* [Tests for 14.12 release](https://hydra.nixos.org/job/nixos/release-14.12/tested#tabs-constituents)
|
||||
* [Tests for 15.09 release](https://hydra.nixos.org/job/nixos/release-15.09/tested#tabs-constituents)
|
||||
|
||||
Communication:
|
||||
|
||||
* [Mailing list](http://lists.science.uu.nl/mailman/listinfo/nix-dev)
|
||||
* [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)
|
||||
@@ -1,7 +1 @@
|
||||
if ! builtins ? nixVersion || builtins.compareVersions "1.8" builtins.nixVersion == 1 then
|
||||
|
||||
abort "This version of Nixpkgs requires Nix >= 1.8, please upgrade! See https://nixos.org/wiki/How_to_update_when_nix_is_too_old_to_evaluate_nixpkgs"
|
||||
|
||||
else
|
||||
|
||||
import ./pkgs/top-level/all-packages.nix
|
||||
import ./pkgs/top-level/all-packages.nix
|
||||
|
||||
41
doc/Makefile
Normal file
41
doc/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
# You may need to override this.
|
||||
docbookxsl = $(HOME)/.nix-profile/xml/xsl/docbook
|
||||
dblatex = dblatex
|
||||
|
||||
XMLLINT = xmllint --catalogs
|
||||
XSLTPROC = xsltproc --catalogs \
|
||||
--param section.autolabel 1 \
|
||||
--param section.label.includes.component.label 1 \
|
||||
--param html.stylesheet \'style.css\' \
|
||||
--param xref.with.number.and.title 1 \
|
||||
--param toc.section.depth 3 \
|
||||
--param admon.style \'\' \
|
||||
--param callout.graphics.extension \'.gif\'
|
||||
|
||||
NEWS_OPTS = \
|
||||
--stringparam generate.toc "article nop" \
|
||||
--stringparam section.autolabel.max.depth 0 \
|
||||
--stringparam header.rule 0
|
||||
|
||||
all: NEWS.html NEWS.txt manual.html manual.pdf
|
||||
|
||||
NEWS.html: release-notes.xml
|
||||
$(XSLTPROC) --nonet --xinclude --output $@ $(NEWS_OPTS) \
|
||||
$(docbookxsl)/html/docbook.xsl release-notes.xml
|
||||
|
||||
NEWS.txt: release-notes.xml
|
||||
$(XSLTPROC) --nonet --xinclude quote-literals.xsl release-notes.xml | \
|
||||
$(XSLTPROC) --nonet --output $@.tmp.html $(NEWS_OPTS) \
|
||||
$(docbookxsl)/html/docbook.xsl -
|
||||
LANG=en_US w3m -dump $@.tmp.html > $@
|
||||
rm $@.tmp.html
|
||||
|
||||
manual.html: *.xml
|
||||
$(XSLTPROC) --nonet --xinclude --output manual.html \
|
||||
$(docbookxsl)/html/docbook.xsl manual.xml
|
||||
|
||||
manual.pdf: *.xml
|
||||
$(dblatex) \
|
||||
-P doc.collab.show=0 \
|
||||
-P latex.output.revhistory=0 \
|
||||
manual.xml
|
||||
@@ -5,7 +5,7 @@
|
||||
<title>Coding conventions</title>
|
||||
|
||||
|
||||
<section xml:id="sec-syntax"><title>Syntax</title>
|
||||
<section><title>Syntax</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
@@ -169,8 +169,8 @@ stdenv.mkDerivation { ...
|
||||
args: with args; <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
|
||||
or
|
||||
|
||||
or
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, fetchurl, perl, ... }: <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
@@ -207,7 +207,7 @@ args.stdenv.mkDerivation (args // {
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-package-naming"><title>Package naming</title>
|
||||
<section><title>Package naming</title>
|
||||
|
||||
<para>In Nixpkgs, there are generally three different names associated with a package:
|
||||
|
||||
@@ -235,7 +235,12 @@ Most of the time, these are the same. For instance, the package
|
||||
bound to the variable name <varname>e2fsprogs</varname> in
|
||||
<filename>all-packages.nix</filename>, and the Nix expression is in
|
||||
<filename>pkgs/os-specific/linux/e2fsprogs/default.nix</filename>.
|
||||
</para>
|
||||
However, identifiers in the Nix language don’t allow certain
|
||||
characters (e.g. dashes), so sometimes a different variable name
|
||||
should be used. For instance, the
|
||||
<literal>module-init-tools</literal> package is bound to the
|
||||
<literal>module_init_tools</literal> variable in
|
||||
<filename>all-packages.nix</filename>.</para>
|
||||
|
||||
<para>There are a few naming guidelines:
|
||||
|
||||
@@ -256,26 +261,17 @@ bound to the variable name <varname>e2fsprogs</varname> in
|
||||
a package named <literal>hello-svn</literal> by
|
||||
<command>nix-env</command>.</para></listitem>
|
||||
|
||||
<listitem><para>If package is fetched from git's commit then
|
||||
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 add <literal>"git"</literal> to the name - e.g.,
|
||||
<literal>"pkgname-git-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 changed to
|
||||
underscores in variable names, rather than to camel case — e.g.,
|
||||
<varname>module_init_tools</varname> instead of
|
||||
<varname>moduleInitTools</varname>.</para></listitem>
|
||||
|
||||
<listitem><para>If there are multiple versions of a package, this
|
||||
should be reflected in the variable names in
|
||||
<filename>all-packages.nix</filename>,
|
||||
e.g. <varname>json-c-0-9</varname> and <varname>json-c-0-11</varname>.
|
||||
e.g. <varname>hello_0_3</varname> and <varname>hello_0_4</varname>.
|
||||
If there is an obvious “default” version, make an attribute like
|
||||
<literal>json-c = json-c-0-9;</literal>.
|
||||
See also <xref linkend="sec-versioning" /></para></listitem>
|
||||
<literal>hello = hello_0_4;</literal>.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
@@ -292,7 +288,7 @@ dashes between words — not in camel case. For instance, it should be
|
||||
<filename>allPackages.nix</filename> or
|
||||
<filename>AllPackages.nix</filename>.</para>
|
||||
|
||||
<section xml:id="sec-hierarchy"><title>Hierarchy</title>
|
||||
<section><title>Hierachy</title>
|
||||
|
||||
<para>Each package should be stored in its own directory somewhere in
|
||||
the <filename>pkgs/</filename> tree, i.e. in
|
||||
@@ -451,17 +447,12 @@ splitting up an existing category.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>desktop environment</emphasis>:</term>
|
||||
<term>If it’s a <emphasis>desktop environment</emphasis>
|
||||
(including <emphasis>window managers</emphasis>):</term>
|
||||
<listitem>
|
||||
<para><filename>desktops</filename> (e.g. <filename>kde</filename>, <filename>gnome</filename>, <filename>enlightenment</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s 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>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s an <emphasis>application</emphasis>:</term>
|
||||
<listitem>
|
||||
@@ -576,7 +567,7 @@ splitting up an existing category.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-versioning"><title>Versioning</title>
|
||||
<section><title>Versioning</title>
|
||||
|
||||
<para>Because every version of a package in Nixpkgs creates a
|
||||
potential maintenance burden, old versions of a package should not be
|
||||
@@ -609,57 +600,6 @@ evaluate correctly.</para>
|
||||
</section>
|
||||
|
||||
</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
|
||||
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.
|
||||
</para>
|
||||
<para>You can find many source fetch helpers in <literal>pkgs/build-support/fetch*</literal>.
|
||||
</para>
|
||||
<para>In the file <literal>pkgs/top-level/all-packages.nix</literal> you can
|
||||
find fetch helpers, these have names on the form
|
||||
<literal>fetchFrom*</literal>. The intention of these are to provide
|
||||
snapshot fetches but using the same api as some of the version controlled
|
||||
fetchers from <literal>pkgs/build-support/</literal>. As an example going
|
||||
from bad to good:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Uses <literal>git://</literal> which won't be proxied.
|
||||
<programlisting>
|
||||
src = fetchgit {
|
||||
url = "git://github.com/NixOS/nix.git";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>This is ok, but an archive fetch will still be faster.
|
||||
<programlisting>
|
||||
src = fetchgit {
|
||||
url = "https://github.com/NixOS/nix.git";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "1cw5fszffl5pkpa6s6wjnkiv6lm5k618s32sp60kvmvpy7a2v9kg";
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Fetches a snapshot archive and you get the rev you want.
|
||||
<programlisting>
|
||||
src = fetchFromGitHub {
|
||||
owner = "NixOS";
|
||||
repo = "nix";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "04yri911rj9j19qqqn6m82266fl05pz98inasni0vxr1cf1gdgv9";
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-contributing">
|
||||
|
||||
<title>Contributing to this documentation</title>
|
||||
|
||||
<para>The DocBook sources of the Nixpkgs manual are in the <filename
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/tree/master/doc">doc</filename>
|
||||
subdirectory of the Nixpkgs repository. If you make modifications to
|
||||
the manual, it's important to build it before committing. You can do that as follows:
|
||||
|
||||
<screen>
|
||||
$ cd /path/to/nixpkgs
|
||||
$ nix-build doc
|
||||
</screen>
|
||||
|
||||
If the build succeeds, the manual will be in
|
||||
<filename>./result/share/doc/nixpkgs/manual.html</filename>.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,45 +0,0 @@
|
||||
with import ./.. { };
|
||||
with lib;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-manual";
|
||||
|
||||
sources = sourceFilesBySuffices ./. [".xml"];
|
||||
|
||||
buildInputs = [ libxml2 libxslt ];
|
||||
|
||||
xsltFlags = ''
|
||||
--param section.autolabel 1
|
||||
--param section.label.includes.component.label 1
|
||||
--param html.stylesheet 'style.css'
|
||||
--param xref.with.number.and.title 1
|
||||
--param toc.section.depth 3
|
||||
--param admon.style '''
|
||||
--param callout.graphics.extension '.gif'
|
||||
'';
|
||||
|
||||
buildCommand = ''
|
||||
ln -s $sources/*.xml . # */
|
||||
|
||||
echo ${nixpkgsVersion} > .version
|
||||
|
||||
xmllint --noout --nonet --xinclude --noxincludenode \
|
||||
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
|
||||
manual.xml
|
||||
|
||||
dst=$out/share/doc/nixpkgs
|
||||
mkdir -p $dst
|
||||
xsltproc $xsltFlags --nonet --xinclude \
|
||||
--output $dst/manual.html \
|
||||
${docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \
|
||||
./manual.xml
|
||||
|
||||
cp ${./style.css} $dst/style.css
|
||||
|
||||
mkdir -p $dst/images/callouts
|
||||
cp ${docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/images/callouts/
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-functions">
|
||||
|
||||
<title>Functions reference</title>
|
||||
|
||||
<para>
|
||||
The nixpkgs repository has several utility functions to manipulate Nix expressions.
|
||||
</para>
|
||||
|
||||
<section xml:id="sec-pkgs-overridePackages">
|
||||
<title>pkgs.overridePackages</title>
|
||||
|
||||
<para>
|
||||
This function inside the nixpkgs expression (<varname>pkgs</varname>)
|
||||
can be used to override the set of packages itself.
|
||||
</para>
|
||||
<para>
|
||||
Warning: this function is expensive and must not be used from within
|
||||
the nixpkgs repository.
|
||||
</para>
|
||||
<para>
|
||||
Example usage:
|
||||
|
||||
<programlisting>let
|
||||
pkgs = import <nixpkgs> {};
|
||||
newpkgs = pkgs.overridePackages (self: super: {
|
||||
foo = super.foo.override { ... };
|
||||
};
|
||||
in ...</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The resulting <varname>newpkgs</varname> will have the new <varname>foo</varname>
|
||||
expression, and all other expressions depending on <varname>foo</varname> will also
|
||||
use the new <varname>foo</varname> expression.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The behavior of this function is similar to <link
|
||||
linkend="sec-modify-via-packageOverrides">config.packageOverrides</link>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <varname>self</varname> parameter refers to the final package set with the
|
||||
applied overrides. Using this parameter may lead to infinite recursion if not
|
||||
used consciously.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <varname>super</varname> parameter refers to the old package set.
|
||||
It's equivalent to <varname>pkgs</varname> in the above example.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-pkg-override">
|
||||
<title><pkg>.override</title>
|
||||
|
||||
<para>
|
||||
The function <varname>override</varname> is usually available for all the
|
||||
derivations in the nixpkgs expression (<varname>pkgs</varname>).
|
||||
</para>
|
||||
<para>
|
||||
It is used to override the arguments passed to a function.
|
||||
</para>
|
||||
<para>
|
||||
Example usages:
|
||||
|
||||
<programlisting>pkgs.foo.override { arg1 = val1; arg2 = val2; ... }</programlisting>
|
||||
<programlisting>pkgs.overridePackages (self: super: {
|
||||
foo = super.foo.override { barSupport = true ; };
|
||||
})</programlisting>
|
||||
<programlisting>mypkg = pkgs.callPackage ./mypkg.nix {
|
||||
mydep = pkgs.mydep.override { ... };
|
||||
})</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the first example, <varname>pkgs.foo</varname> is the result of a function call
|
||||
with some default arguments, usually a derivation.
|
||||
Using <varname>pkgs.foo.override</varname> will call the same function with
|
||||
the given new arguments.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-pkg-overrideDerivation">
|
||||
<title><pkg>.overrideDerivation</title>
|
||||
|
||||
<para>
|
||||
The function <varname>overrideDerivation</varname> is usually available for all the
|
||||
derivations in the nixpkgs expression (<varname>pkgs</varname>).
|
||||
</para>
|
||||
<para>
|
||||
It is used to create a new derivation by overriding the attributes of
|
||||
the original derivation according to the given function.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example usage:
|
||||
|
||||
<programlisting>mySed = pkgs.gnused.overrideDerivation (oldAttrs: {
|
||||
name = "sed-4.2.2-pre";
|
||||
src = fetchurl {
|
||||
url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
|
||||
sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
|
||||
};
|
||||
patches = [];
|
||||
});</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the above example, the name, src and patches of the derivation
|
||||
will be overridden, while all other attributes will be retained from the
|
||||
original derivation.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The argument <varname>oldAttrs</varname> is used to refer to the attribute set of
|
||||
the original derivation.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-lib-makeOverridable">
|
||||
<title>lib.makeOverridable</title>
|
||||
|
||||
<para>
|
||||
The function <varname>lib.makeOverridable</varname> is used make the result
|
||||
of a function easily customizable. This utility only makes sense for functions
|
||||
that accept an argument set and return an attribute set.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example usage:
|
||||
|
||||
<programlisting>f = { a, b }: { result = a+b; }
|
||||
c = lib.makeOverridable f { a = 1; b = 2; }</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The variable <varname>c</varname> is the value of the <varname>f</varname> function
|
||||
applied with some default arguments. Hence the value of <varname>c.result</varname>
|
||||
is <literal>3</literal>, in this example.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The variable <varname>c</varname> however also has some additional functions, like
|
||||
<link linkend="sec-pkg-override">c.override</link> which can be used to
|
||||
override the default arguments. In this example the value of
|
||||
<varname>(c.override { a = 4; }).result</varname> is 6.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-fhs-environments">
|
||||
<title>buildFHSChrootEnv/buildFHSUserEnv</title>
|
||||
|
||||
<para>
|
||||
<function>buildFHSChrootEnv</function> and
|
||||
<function>buildFHSUserEnv</function> provide a way to build and run
|
||||
FHS-compatible lightweight sandboxes. They get their own isolated root with
|
||||
binded <filename>/nix/store</filename>, so their footprint in terms of disk
|
||||
space needed is quite small. This allows one to run software which is hard or
|
||||
unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions,
|
||||
games distributed as tarballs, software with integrity checking and/or external
|
||||
self-updated binaries.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildFHSChrootEnv</function> allows to create persistent
|
||||
environments, which can be constructed, deconstructed and entered by
|
||||
multiple users at once. A downside is that it requires
|
||||
<literal>root</literal> access for both those who create and destroy and
|
||||
those who enter it. It can be useful to create environments for daemons that
|
||||
one can enter and observe.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildFHSUserEnv</function> uses Linux namespaces feature to create
|
||||
temporary lightweight environments which are destroyed after all child
|
||||
processes exit. It does not require root access, and can be useful to create
|
||||
sandboxes and wrap applications.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Those functions both rely on <function>buildFHSEnv</function>, which creates
|
||||
an actual directory structure given a list of necessary packages and extra
|
||||
build commands.
|
||||
<function>buildFHSChrootEnv</function> and <function>buildFHSUserEnv</function>
|
||||
both accept those arguments which are passed to
|
||||
<function>buildFHSEnv</function>:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><literal>name</literal></term>
|
||||
|
||||
<listitem><para>Environment name.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>targetPkgs</literal></term>
|
||||
|
||||
<listitem><para>Packages to be installed for the main host's architecture
|
||||
(i.e. x86_64 on x86_64 installations).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>multiPkgs</literal></term>
|
||||
|
||||
<listitem><para>Packages to be installed for all architectures supported by
|
||||
a host (i.e. i686 and x86_64 on x86_64 installations).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>extraBuildCommands</literal></term>
|
||||
|
||||
<listitem><para>Additional commands to be executed for finalizing the
|
||||
directory structure.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>extraBuildCommandsMulti</literal></term>
|
||||
|
||||
<listitem><para>Like <literal>extraBuildCommandsMulti</literal>, but
|
||||
executed only on multilib architectures.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
||||
Additionally, <function>buildFHSUserEnv</function> accepts
|
||||
<literal>runScript</literal> parameter, which is a command that would be
|
||||
executed inside the sandbox and passed all the command line arguments. It
|
||||
default to <literal>bash</literal>.
|
||||
One can create a simple environment using a <literal>shell.nix</literal>
|
||||
like that:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
|
||||
(pkgs.buildFHSUserEnv {
|
||||
name = "simple-x11-env";
|
||||
targetPkgs = pkgs: (with pkgs;
|
||||
[ udev
|
||||
alsaLib
|
||||
]) ++ (with pkgs.xlibs;
|
||||
[ libX11
|
||||
libXcursor
|
||||
libXrandr
|
||||
]);
|
||||
multiPkgs = pkgs: (with pkgs;
|
||||
[ udev
|
||||
alsaLib
|
||||
]) ++ (with [];
|
||||
runScript = "bash";
|
||||
}).env
|
||||
]]></programlisting>
|
||||
|
||||
<para>
|
||||
Running <literal>nix-shell</literal> would then drop you into a shell with
|
||||
these libraries and binaries available. You can use this to run
|
||||
closed-source applications which expect FHS structure without hassles:
|
||||
simply change <literal>runScript</literal> to the application path,
|
||||
e.g. <filename>./bin/start.sh</filename> -- relative paths are supported.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -1,829 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="users-guide-to-the-haskell-infrastructure">
|
||||
|
||||
<title>User's Guide to the Haskell Infrastructure</title>
|
||||
|
||||
<section xml:id="how-to-install-haskell-packages">
|
||||
<title>How to install Haskell packages</title>
|
||||
<para>
|
||||
Nixpkgs distributes build instructions for all Haskell packages
|
||||
registered on
|
||||
<link xlink:href="http://hackage.haskell.org/">Hackage</link>, but
|
||||
strangely enough normal Nix package lookups don't seem to discover
|
||||
any of them:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -qa cabal-install
|
||||
error: selector ‘cabal-install’ matches no derivations
|
||||
|
||||
$ nix-env -i ghc
|
||||
error: selector ‘ghc’ matches no derivations
|
||||
</programlisting>
|
||||
<para>
|
||||
The Haskell package set is not registered in the top-level namespace
|
||||
because it is <emphasis>huge</emphasis>. If all Haskell packages
|
||||
were visible to these commands, then name-based search/install
|
||||
operations would be much slower than they are now. We avoided that
|
||||
by keeping all Haskell-related packages in a separate attribute set
|
||||
called <literal>haskellPackages</literal>, which the following
|
||||
command will list:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages
|
||||
haskellPackages.a50 a50-0.5
|
||||
haskellPackages.abacate haskell-abacate-0.0.0.0
|
||||
haskellPackages.abcBridge haskell-abcBridge-0.12
|
||||
haskellPackages.afv afv-0.1.1
|
||||
haskellPackages.alex alex-3.1.4
|
||||
haskellPackages.Allure Allure-0.4.101.1
|
||||
haskellPackages.alms alms-0.6.7
|
||||
[... some 8000 entries omitted ...]
|
||||
</programlisting>
|
||||
<para>
|
||||
To install any of those packages into your profile, refer to them by
|
||||
their attribute path (first column):
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -f "<nixpkgs>" -iA haskellPackages.Allure ...
|
||||
</programlisting>
|
||||
<para>
|
||||
The attribute path of any Haskell packages corresponds to the name
|
||||
of that particular package on Hackage: the package
|
||||
<literal>cabal-install</literal> has the attribute
|
||||
<literal>haskellPackages.cabal-install</literal>, and so on.
|
||||
(Actually, this convention causes trouble with packages like
|
||||
<literal>3dmodels</literal> and <literal>4Blocks</literal>, because
|
||||
these names are invalid identifiers in the Nix language. The issue
|
||||
of how to deal with these rare corner cases is currently
|
||||
unresolved.)
|
||||
</para>
|
||||
<para>
|
||||
Haskell packages who's Nix name (second column) begins with a
|
||||
<literal>haskell-</literal> prefix are packages that provide a
|
||||
library whereas packages without that prefix provide just
|
||||
executables. Libraries may provide executables too, though: the
|
||||
package <literal>haskell-pandoc</literal>, for example, installs
|
||||
both a library and an application. You can install and use Haskell
|
||||
executables just like any other program in Nixpkgs, but using
|
||||
Haskell libraries for development is a bit trickier and we'll
|
||||
address that subject in great detail in section
|
||||
<link linkend="how-to-create-a-development-environment">How to
|
||||
create a development environment</link>.
|
||||
</para>
|
||||
<para>
|
||||
Attribute paths are deterministic inside of Nixpkgs, but the path
|
||||
necessary to reach Nixpkgs varies from system to system. We dodged
|
||||
that problem by giving <literal>nix-env</literal> an explicit
|
||||
<literal>-f "<nixpkgs>"</literal> parameter, but if
|
||||
you call <literal>nix-env</literal> without that flag, then chances
|
||||
are the invocation fails:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -iA haskellPackages.cabal-install
|
||||
error: attribute ‘haskellPackages’ in selection path
|
||||
‘haskellPackages.cabal-install’ not found
|
||||
</programlisting>
|
||||
<para>
|
||||
On NixOS, for example, Nixpkgs does <emphasis>not</emphasis> exist
|
||||
in the top-level namespace by default. To figure out the proper
|
||||
attribute path, it's easiest to query for the path of a well-known
|
||||
Nixpkgs package, i.e.:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -qaP coreutils
|
||||
nixos.coreutils coreutils-8.23
|
||||
</programlisting>
|
||||
<para>
|
||||
If your system responds like that (most NixOS installations will),
|
||||
then the attribute path to <literal>haskellPackages</literal> is
|
||||
<literal>nixos.haskellPackages</literal>. Thus, if you want to
|
||||
use <literal>nix-env</literal> without giving an explicit
|
||||
<literal>-f</literal> flag, then that's the way to do it:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -qaP -A nixos.haskellPackages
|
||||
$ nix-env -iA nixos.haskellPackages.cabal-install
|
||||
</programlisting>
|
||||
<para>
|
||||
Our current default compiler is GHC 7.10.x and the
|
||||
<literal>haskellPackages</literal> set contains packages built with
|
||||
that particular version. Nixpkgs contains the latest major release
|
||||
of every GHC since 6.10.4, however, and there is a whole family of
|
||||
package sets available that defines Hackage packages built with each
|
||||
of those compilers, too:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc6123
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc763
|
||||
</programlisting>
|
||||
<para>
|
||||
The name <literal>haskellPackages</literal> is really just a synonym
|
||||
for <literal>haskell.packages.ghc7102</literal>, because we prefer
|
||||
that package set internally and recommend it to our users as their
|
||||
default choice, but ultimately you are free to compile your Haskell
|
||||
packages with any GHC version you please. The following command
|
||||
displays the complete list of available compilers:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler
|
||||
haskell.compiler.ghc6104 ghc-6.10.4
|
||||
haskell.compiler.ghc6123 ghc-6.12.3
|
||||
haskell.compiler.ghc704 ghc-7.0.4
|
||||
haskell.compiler.ghc722 ghc-7.2.2
|
||||
haskell.compiler.ghc742 ghc-7.4.2
|
||||
haskell.compiler.ghc763 ghc-7.6.3
|
||||
haskell.compiler.ghc784 ghc-7.8.4
|
||||
haskell.compiler.ghc7102 ghc-7.10.2
|
||||
haskell.compiler.ghcHEAD ghc-7.11.20150402
|
||||
haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704
|
||||
haskell.compiler.ghcjs ghcjs-0.1.0
|
||||
haskell.compiler.jhc jhc-0.8.2
|
||||
haskell.compiler.uhc uhc-1.1.9.0
|
||||
</programlisting>
|
||||
<para>
|
||||
We have no package sets for <literal>jhc</literal> or
|
||||
<literal>uhc</literal> yet, unfortunately, but for every version of
|
||||
GHC listed above, there exists a package set based on that compiler.
|
||||
Also, the attributes <literal>haskell.compiler.ghcXYC</literal> and
|
||||
<literal>haskell.packages.ghcXYC.ghc</literal> are synonymous for
|
||||
the sake of convenience.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="how-to-create-a-development-environment">
|
||||
<title>How to create a development environment</title>
|
||||
<section xml:id="how-to-install-a-compiler">
|
||||
<title>How to install a compiler</title>
|
||||
<para>
|
||||
A simple development environment consists of a Haskell compiler
|
||||
and the tool <literal>cabal-install</literal>, and we saw in
|
||||
section <link linkend="how-to-install-haskell-packages">How to
|
||||
install Haskell packages</link> how you can install those programs
|
||||
into your user profile:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install
|
||||
</programlisting>
|
||||
<para>
|
||||
Instead of the default package set
|
||||
<literal>haskellPackages</literal>, you can also use the more
|
||||
precise name <literal>haskell.compiler.ghc7102</literal>, which
|
||||
has the advantage that it refers to the same GHC version
|
||||
regardless of what Nixpkgs considers "default" at any
|
||||
given time.
|
||||
</para>
|
||||
<para>
|
||||
Once you've made those tools available in
|
||||
<literal>$PATH</literal>, it's possible to build Hackage packages
|
||||
the same way people without access to Nix do it all the time:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal get lens-4.11 && cd lens-4.11
|
||||
$ cabal install -j --dependencies-only
|
||||
$ cabal configure
|
||||
$ cabal build
|
||||
</programlisting>
|
||||
<para>
|
||||
If you enjoy working with Cabal sandboxes, then that's entirely
|
||||
possible too: just execute the command
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal sandbox init
|
||||
</programlisting>
|
||||
<para>
|
||||
before installing the required dependencies.
|
||||
</para>
|
||||
<para>
|
||||
The <literal>nix-shell</literal> utility makes it easy to switch
|
||||
to a different compiler version; just enter the Nix shell
|
||||
environment with the command
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-shell -p haskell.compiler.ghc784
|
||||
</programlisting>
|
||||
<para>
|
||||
to bring GHC 7.8.4 into <literal>$PATH</literal>. Re-running
|
||||
<literal>cabal configure</literal> switches your build to use that
|
||||
compiler instead. If you're working on a project that doesn't
|
||||
depend on any additional system libraries outside of GHC, then
|
||||
it's sufficient even to run the <literal>cabal configure</literal>
|
||||
command inside of the shell:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-shell -p haskell.compiler.ghc784 --command "cabal configure"
|
||||
</programlisting>
|
||||
<para>
|
||||
Afterwards, all other commands like <literal>cabal build</literal>
|
||||
work just fine in any shell environment, because the configure
|
||||
phase recorded the absolute paths to all required tools like GHC
|
||||
in its build configuration inside of the <literal>dist/</literal>
|
||||
directory. Please note, however, that
|
||||
<literal>nix-collect-garbage</literal> can break such an
|
||||
environment because the Nix store paths created by
|
||||
<literal>nix-shell</literal> aren't "alive" anymore once
|
||||
<literal>nix-shell</literal> has terminated. If you find that your
|
||||
Haskell builds no longer work after garbage collection, then
|
||||
you'll have to re-run <literal>cabal configure</literal> inside of
|
||||
a new <literal>nix-shell</literal> environment.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="how-to-install-a-compiler-with-libraries">
|
||||
<title>How to install a compiler with libraries</title>
|
||||
<para>
|
||||
GHC expects to find all installed libraries inside of its own
|
||||
<literal>lib</literal> directory. This approach works fine on
|
||||
traditional Unix systems, but it doesn't work for Nix, because
|
||||
GHC's store path is immutable once it's built. We cannot install
|
||||
additional libraries into that location. As a consequence, our
|
||||
copies of GHC don't know any packages except their own core
|
||||
libraries, like <literal>base</literal>,
|
||||
<literal>containers</literal>, <literal>Cabal</literal>, etc.
|
||||
</para>
|
||||
<para>
|
||||
We can register additional libraries to GHC, however, using a
|
||||
special build function called <literal>ghcWithPackages</literal>.
|
||||
That function expects one argument: a function that maps from an
|
||||
attribute set of Haskell packages to a list of packages, which
|
||||
determines the libraries known to that particular version of GHC.
|
||||
For example, the Nix expression
|
||||
<literal>ghcWithPackages (pkgs: [pkgs.mtl])</literal> generates a
|
||||
copy of GHC that has the <literal>mtl</literal> library registered
|
||||
in addition to its normal core packages:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: [pkgs.mtl])"
|
||||
|
||||
[nix-shell:~]$ ghc-pkg list mtl
|
||||
/nix/store/zy79...-ghc-7.10.2/lib/ghc-7.10.2/package.conf.d:
|
||||
mtl-2.2.1
|
||||
</programlisting>
|
||||
<para>
|
||||
This function allows users to define their own development
|
||||
environment by means of an override. After adding the following
|
||||
snippet to <literal>~/.nixpkgs/config.nix</literal>,
|
||||
</para>
|
||||
<programlisting>
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
myHaskellEnv = self.haskell.packages.ghc7102.ghcWithPackages
|
||||
(haskellPackages: with haskellPackages; [
|
||||
# libraries
|
||||
arrows async cgi criterion
|
||||
# tools
|
||||
cabal-install haskintex
|
||||
]);
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
it's possible to install that compiler with
|
||||
<literal>nix-env -f "<nixpkgs>" -iA myHaskellEnv</literal>.
|
||||
If you'd like to switch that development environment to a
|
||||
different version of GHC, just replace the
|
||||
<literal>ghc7102</literal> bit in the previous definition with the
|
||||
appropriate name. Of course, it's also possible to define any
|
||||
number of these development environments! (You can't install two
|
||||
of them into the same profile at the same time, though, because
|
||||
that would result in file conflicts.)
|
||||
</para>
|
||||
<para>
|
||||
The generated <literal>ghc</literal> program is a wrapper script
|
||||
that re-directs the real GHC executable to use a new
|
||||
<literal>lib</literal> directory --- one that we specifically
|
||||
constructed to contain all those packages the user requested:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cat $(type -p ghc)
|
||||
#! /nix/store/xlxj...-bash-4.3-p33/bin/bash -e
|
||||
export NIX_GHC=/nix/store/19sm...-ghc-7.10.2/bin/ghc
|
||||
export NIX_GHCPKG=/nix/store/19sm...-ghc-7.10.2/bin/ghc-pkg
|
||||
export NIX_GHC_DOCDIR=/nix/store/19sm...-ghc-7.10.2/share/doc/ghc/html
|
||||
export NIX_GHC_LIBDIR=/nix/store/19sm...-ghc-7.10.2/lib/ghc-7.10.2
|
||||
exec /nix/store/j50p...-ghc-7.10.2/bin/ghc "-B$NIX_GHC_LIBDIR" "$@"
|
||||
</programlisting>
|
||||
<para>
|
||||
The variables <literal>$NIX_GHC</literal>,
|
||||
<literal>$NIX_GHCPKG</literal>, etc. point to the
|
||||
<emphasis>new</emphasis> store path
|
||||
<literal>ghcWithPackages</literal> constructed specifically for
|
||||
this environment. The last line of the wrapper script then
|
||||
executes the real <literal>ghc</literal>, but passes the path to
|
||||
the new <literal>lib</literal> directory using GHC's
|
||||
<literal>-B</literal> flag.
|
||||
</para>
|
||||
<para>
|
||||
The purpose of those environment variables is to work around an
|
||||
impurity in the popular
|
||||
<link xlink:href="http://hackage.haskell.org/package/ghc-paths">ghc-paths</link>
|
||||
library. That library promises to give its users access to GHC's
|
||||
installation paths. Only, the library can't possible know that
|
||||
path when it's compiled, because the path GHC considers its own is
|
||||
determined only much later, when the user configures it through
|
||||
<literal>ghcWithPackages</literal>. So we
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/ghc-paths-nix.patch">patched
|
||||
ghc-paths</link> to return the paths found in those environment
|
||||
variables at run-time rather than trying to guess them at
|
||||
compile-time.
|
||||
</para>
|
||||
<para>
|
||||
To make sure that mechanism works properly all the time, we
|
||||
recommend that you set those variables to meaningful values in
|
||||
your shell environment, too, i.e. by adding the following code to
|
||||
your <literal>~/.bashrc</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
if type >/dev/null 2>&1 -p ghc; then
|
||||
eval "$(egrep ^export "$(type -p ghc)")"
|
||||
fi
|
||||
</programlisting>
|
||||
<para>
|
||||
If you are certain that you'll use only one GHC environment which
|
||||
is located in your user profile, then you can use the following
|
||||
code, too, which has the advantage that it doesn't contain any
|
||||
paths from the Nix store, i.e. those settings always remain valid
|
||||
even if a <literal>nix-env -u</literal> operation updates the GHC
|
||||
environment in your profile:
|
||||
</para>
|
||||
<programlisting>
|
||||
if [ -e ~/.nix-profile/bin/ghc ]; then
|
||||
export NIX_GHC="$HOME/.nix-profile/bin/ghc"
|
||||
export NIX_GHCPKG="$HOME/.nix-profile/bin/ghc-pkg"
|
||||
export NIX_GHC_DOCDIR="$HOME/.nix-profile/share/doc/ghc/html"
|
||||
export NIX_GHC_LIBDIR="$HOME/.nix-profile/lib/ghc-$($NIX_GHC --numeric-version)"
|
||||
fi
|
||||
</programlisting>
|
||||
</section>
|
||||
<section xml:id="how-to-create-ad-hoc-environments-for-nix-shell">
|
||||
<title>How to create ad hoc environments for
|
||||
<literal>nix-shell</literal></title>
|
||||
<para>
|
||||
The easiest way to create an ad hoc development environment is to
|
||||
run <literal>nix-shell</literal> with the appropriate GHC
|
||||
environment given on the command-line:
|
||||
</para>
|
||||
<programlisting>
|
||||
nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [mtl pandoc])"
|
||||
</programlisting>
|
||||
<para>
|
||||
For more sophisticated use-cases, however, it's more convenient to
|
||||
save the desired configuration in a file called
|
||||
<literal>shell.nix</literal> that looks like this:
|
||||
</para>
|
||||
<programlisting>
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
let
|
||||
inherit (nixpkgs) pkgs;
|
||||
ghc = pkgs.haskell.packages.${compiler}.ghcWithPackages (ps: with ps; [
|
||||
monad-par mtl
|
||||
]);
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "my-haskell-env-0";
|
||||
buildInputs = [ ghc ];
|
||||
shellHook = "eval $(egrep ^export ${ghc}/bin/ghc)";
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Now run <literal>nix-shell</literal> --- or even
|
||||
<literal>nix-shell --pure</literal> --- to enter a shell
|
||||
environment that has the appropriate compiler in
|
||||
<literal>$PATH</literal>. If you use <literal>--pure</literal>,
|
||||
then add all other packages that your development environment
|
||||
needs into the <literal>buildInputs</literal> attribute. If you'd
|
||||
like to switch to a different compiler version, then pass an
|
||||
appropriate <literal>compiler</literal> argument to the
|
||||
expression, i.e.
|
||||
<literal>nix-shell --argstr compiler ghc784</literal>.
|
||||
</para>
|
||||
<para>
|
||||
If you need such an environment because you'd like to compile a
|
||||
Hackage package outside of Nix --- i.e. because you're hacking on
|
||||
the latest version from Git ---, then the package set provides
|
||||
suitable nix-shell environments for you already! Every Haskell
|
||||
package has an <literal>env</literal> attribute that provides a
|
||||
shell environment suitable for compiling that particular package.
|
||||
If you'd like to hack the <literal>lens</literal> library, for
|
||||
example, then you just have to check out the source code and enter
|
||||
the appropriate environment:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal get lens-4.11 && cd lens-4.11
|
||||
Downloading lens-4.11...
|
||||
Unpacking to lens-4.11/
|
||||
|
||||
$ nix-shell "<nixpkgs>" -A haskellPackages.lens.env
|
||||
[nix-shell:/tmp/lens-4.11]$
|
||||
</programlisting>
|
||||
<para>
|
||||
At point, you can run <literal>cabal configure</literal>,
|
||||
<literal>cabal build</literal>, and all the other development
|
||||
commands. Note that you need <literal>cabal-install</literal>
|
||||
installed in your <literal>$PATH</literal> already to use it here
|
||||
--- the <literal>nix-shell</literal> environment does not provide
|
||||
it.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="how-to-create-nix-builds-for-your-own-private-haskell-packages">
|
||||
<title>How to create Nix builds for your own private Haskell
|
||||
packages</title>
|
||||
<para>
|
||||
If your own Haskell packages have build instructions for Cabal, then
|
||||
you can convert those automatically into build instructions for Nix
|
||||
using the <literal>cabal2nix</literal> utility, which you can
|
||||
install into your profile by running
|
||||
<literal>nix-env -i cabal2nix</literal>.
|
||||
</para>
|
||||
<section xml:id="how-to-build-a-stand-alone-project">
|
||||
<title>How to build a stand-alone project</title>
|
||||
<para>
|
||||
For example, let's assume that you're working on a private project
|
||||
called <literal>foo</literal>. To generate a Nix build expression
|
||||
for it, change into the project's top-level directory and run the
|
||||
command:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal2nix . >foo.nix
|
||||
</programlisting>
|
||||
<para>
|
||||
Then write the following snippet into a file called
|
||||
<literal>default.nix</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
nixpkgs.pkgs.haskell.packages.${compiler}.callPackage ./foo.nix { }
|
||||
</programlisting>
|
||||
<para>
|
||||
Finally, store the following code in a file called
|
||||
<literal>shell.nix</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
(import ./default.nix { inherit nixpkgs compiler; }).env
|
||||
</programlisting>
|
||||
<para>
|
||||
At this point, you can run <literal>nix-build</literal> to have
|
||||
Nix compile your project and install it into a Nix store path. The
|
||||
local directory will contain a symlink called
|
||||
<literal>result</literal> after <literal>nix-build</literal>
|
||||
returns that points into that location. Of course, passing the
|
||||
flag <literal>--argstr compiler ghc763</literal> allows switching
|
||||
the build to any version of GHC currently supported.
|
||||
</para>
|
||||
<para>
|
||||
Furthermore, you can call <literal>nix-shell</literal> to enter an
|
||||
interactive development environment in which you can use
|
||||
<literal>cabal configure</literal> and
|
||||
<literal>cabal build</literal> to develop your code. That
|
||||
environment will automatically contain a proper GHC derivation
|
||||
with all the required libraries registered as well as all the
|
||||
system-level libraries your package might need.
|
||||
</para>
|
||||
<para>
|
||||
If your package does not depend on any system-level libraries,
|
||||
then it's sufficient to run
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-shell --command "cabal configure"
|
||||
</programlisting>
|
||||
<para>
|
||||
once to set up your build. <literal>cabal-install</literal>
|
||||
determines the absolute paths to all resources required for the
|
||||
build and writes them into a config file in the
|
||||
<literal>dist/</literal> directory. Once that's done, you can run
|
||||
<literal>cabal build</literal> and any other command for that
|
||||
project even outside of the <literal>nix-shell</literal>
|
||||
environment. This feature is particularly nice for those of us who
|
||||
like to edit their code with an IDE, like Emacs'
|
||||
<literal>haskell-mode</literal>, because it's not necessary to
|
||||
start Emacs inside of nix-shell just to make it find out the
|
||||
necessary settings for building the project;
|
||||
<literal>cabal-install</literal> has already done that for us.
|
||||
</para>
|
||||
<para>
|
||||
If you want to do some quick-and-dirty hacking and don't want to
|
||||
bother setting up a <literal>default.nix</literal> and
|
||||
<literal>shell.nix</literal> file manually, then you can use the
|
||||
<literal>--shell</literal> flag offered by
|
||||
<literal>cabal2nix</literal> to have it generate a stand-alone
|
||||
<literal>nix-shell</literal> environment for you. With that
|
||||
feature, running
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal2nix --shell . >shell.nix
|
||||
$ nix-shell --command "cabal configure"
|
||||
</programlisting>
|
||||
<para>
|
||||
is usually enough to set up a build environment for any given
|
||||
Haskell package. You can even use that generated file to run
|
||||
<literal>nix-build</literal>, too:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-build shell.nix
|
||||
</programlisting>
|
||||
</section>
|
||||
<section xml:id="how-to-build-projects-that-depend-on-each-other">
|
||||
<title>How to build projects that depend on each other</title>
|
||||
<para>
|
||||
If you have multiple private Haskell packages that depend on each
|
||||
other, then you'll have to register those packages in the Nixpkgs
|
||||
set to make them visible for the dependency resolution performed
|
||||
by <literal>callPackage</literal>. First of all, change into each
|
||||
of your projects top-level directories and generate a
|
||||
<literal>default.nix</literal> file with
|
||||
<literal>cabal2nix</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cd ~/src/foo && cabal2nix . >default.nix
|
||||
$ cd ~/src/bar && cabal2nix . >default.nix
|
||||
</programlisting>
|
||||
<para>
|
||||
Then edit your <literal>~/.nixpkgs/config.nix</literal> file to
|
||||
register those builds in the default Haskell package set:
|
||||
</para>
|
||||
<programlisting>
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
haskellPackages = super.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
foo = self.callPackage ../src/foo {};
|
||||
bar = self.callPackage ../src/bar {};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Once that's accomplished,
|
||||
<literal>nix-env -f "<nixpkgs>" -qA haskellPackages</literal>
|
||||
will show your packages like any other package from Hackage, and
|
||||
you can build them
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-build "<nixpkgs>" -A haskellPackages.foo
|
||||
</programlisting>
|
||||
<para>
|
||||
or enter an interactive shell environment suitable for building
|
||||
them:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-shell "<nixpkgs>" -A haskellPackages.bar.env
|
||||
</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="miscellaneous-topics">
|
||||
<title>Miscellaneous Topics</title>
|
||||
<section xml:id="how-to-build-with-profiling-enabled">
|
||||
<title>How to build with profiling enabled</title>
|
||||
<para>
|
||||
Every Haskell package set takes a function called
|
||||
<literal>overrides</literal> that you can use to manipulate the
|
||||
package as much as you please. One useful application of this
|
||||
feature is to replace the default <literal>mkDerivation</literal>
|
||||
function with one that enables library profiling for all packages.
|
||||
To accomplish that, add configure the following snippet in your
|
||||
<literal>~/.nixpkgs/config.nix</literal> file:
|
||||
</para>
|
||||
<programlisting>
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
profiledHaskellPackages = self.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
mkDerivation = args: super.mkDerivation (args // {
|
||||
enableLibraryProfiling = true;
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Then, replace instances of <literal>haskellPackages</literal> in the
|
||||
<literal>cabal2nix</literal>-generated <literal>default.nix</literal>
|
||||
or <literal>shell.nix</literal> files with
|
||||
<literal>profiledHaskellPackages</literal>.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="how-to-override-package-versions-in-a-compiler-specific-package-set">
|
||||
<title>How to override package versions in a compiler-specific
|
||||
package set</title>
|
||||
<para>
|
||||
Nixpkgs provides the latest version of
|
||||
<link xlink:href="http://hackage.haskell.org/package/ghc-events"><literal>ghc-events</literal></link>,
|
||||
which is 0.4.4.0 at the time of this writing. This is fine for
|
||||
users of GHC 7.10.x, but GHC 7.8.4 cannot compile that binary.
|
||||
Now, one way to solve that problem is to register an older version
|
||||
of <literal>ghc-events</literal> in the 7.8.x-specific package
|
||||
set. The first step is to generate Nix build instructions with
|
||||
<literal>cabal2nix</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal2nix cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix
|
||||
</programlisting>
|
||||
<para>
|
||||
Then add the override in <literal>~/.nixpkgs/config.nix</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
haskell = super.haskell // {
|
||||
packages = super.haskell.packages // {
|
||||
ghc784 = super.haskell.packages.ghc784.override {
|
||||
overrides = self: super: {
|
||||
ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
This code is a little crazy, no doubt, but it's necessary because
|
||||
the intuitive version
|
||||
</para>
|
||||
<programlisting>
|
||||
haskell.packages.ghc784 = super.haskell.packages.ghc784.override {
|
||||
overrides = self: super: {
|
||||
ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {};
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
doesn't do what we want it to: that code replaces the
|
||||
<literal>haskell</literal> package set in Nixpkgs with one that
|
||||
contains only one entry,<literal>packages</literal>, which
|
||||
contains only one entry <literal>ghc784</literal>. This override
|
||||
loses the <literal>haskell.compiler</literal> set, and it loses
|
||||
the <literal>haskell.packages.ghcXYZ</literal> sets for all
|
||||
compilers but GHC 7.8.4. To avoid that problem, we have to perform
|
||||
the convoluted little dance from above, iterating over each step
|
||||
in hierarchy.
|
||||
</para>
|
||||
<para>
|
||||
Once it's accomplished, however, we can install a variant of
|
||||
<literal>ghc-events</literal> that's compiled with GHC 7.8.4:
|
||||
</para>
|
||||
<programlisting>
|
||||
nix-env -f "<nixpkgs>" -iA haskell.packages.ghc784.ghc-events
|
||||
</programlisting>
|
||||
<para>
|
||||
Unfortunately, it turns out that this build fails again while
|
||||
executing the test suite! Apparently, the release archive on
|
||||
Hackage is missing some data files that the test suite requires,
|
||||
so we cannot run it. We accomplish that by re-generating the Nix
|
||||
expression with the <literal>--no-check</literal> flag:
|
||||
</para>
|
||||
<programlisting>
|
||||
$ cabal2nix --no-check cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix
|
||||
</programlisting>
|
||||
<para>
|
||||
Now the builds succeeds.
|
||||
</para>
|
||||
<para>
|
||||
Of course, in the concrete example of
|
||||
<literal>ghc-events</literal> this whole exercise is not an ideal
|
||||
solution, because <literal>ghc-events</literal> can analyze the
|
||||
output emitted by any version of GHC later than 6.12 regardless of
|
||||
the compiler version that was used to build the `ghc-events'
|
||||
executable, so strictly speaking there's no reason to prefer one
|
||||
built with GHC 7.8.x in the first place. However, for users who
|
||||
cannot use GHC 7.10.x at all for some reason, the approach of
|
||||
downgrading to an older version might be useful.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="how-to-recover-from-ghcs-infamous-non-deterministic-library-id-bug">
|
||||
<title>How to recover from GHC's infamous non-deterministic library
|
||||
ID bug</title>
|
||||
<para>
|
||||
GHC and distributed build farms don't get along well:
|
||||
</para>
|
||||
<programlisting>
|
||||
https://ghc.haskell.org/trac/ghc/ticket/4012
|
||||
</programlisting>
|
||||
<para>
|
||||
When you see an error like this one
|
||||
</para>
|
||||
<programlisting>
|
||||
package foo-0.7.1.0 is broken due to missing package
|
||||
text-1.2.0.4-98506efb1b9ada233bb5c2b2db516d91
|
||||
</programlisting>
|
||||
<para>
|
||||
then you have to download and re-install <literal>foo</literal>
|
||||
and all its dependents from scratch:
|
||||
</para>
|
||||
<programlisting>
|
||||
# nix-store -q --referrers /nix/store/*-haskell-text-1.2.0.4 \
|
||||
| xargs -L 1 nix-store --repair-path --option binary-caches http://hydra.nixos.org
|
||||
</programlisting>
|
||||
<para>
|
||||
If you're using additional Hydra servers other than
|
||||
<literal>hydra.nixos.org</literal>, then it 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:
|
||||
</para>
|
||||
<programlisting>
|
||||
rm /nix/var/nix/binary-cache-v3.sqlite
|
||||
rm /nix/var/nix/manifests/*
|
||||
rm /nix/var/nix/channel-cache/*
|
||||
</programlisting>
|
||||
</section>
|
||||
<section xml:id="builds-on-darwin-fail-with-math.h-not-found">
|
||||
<title>Builds on Darwin fail with <literal>math.h</literal> not
|
||||
found</title>
|
||||
<para>
|
||||
Users of GHC on Darwin have occasionally reported that builds
|
||||
fail, because the compiler complains about a missing include file:
|
||||
</para>
|
||||
<programlisting>
|
||||
fatal error: 'math.h' file not found
|
||||
</programlisting>
|
||||
<para>
|
||||
The issue has been discussed at length in
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/6390">ticket
|
||||
6390</link>, and so far no good solution has been proposed. As a
|
||||
work-around, users who run into this problem can configure the
|
||||
environment variables
|
||||
</para>
|
||||
<programlisting>
|
||||
export NIX_CFLAGS_COMPILE="-idirafter /usr/include"
|
||||
export NIX_CFLAGS_LINK="-L/usr/lib"
|
||||
</programlisting>
|
||||
<para>
|
||||
in their <literal>~/.bashrc</literal> file to avoid the compiler
|
||||
error.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section xml:id="other-resources">
|
||||
<title>Other resources</title>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
The Youtube video
|
||||
<link xlink:href="https://www.youtube.com/watch?v=BsBhi_r-OeE">Nix
|
||||
Loves Haskell</link> provides an introduction into Haskell NG
|
||||
aimed at beginners. The slides are available at
|
||||
http://cryp.to/nixos-meetup-3-slides.pdf and also -- in a form
|
||||
ready for cut & paste -- at
|
||||
https://github.com/NixOS/cabal2nix/blob/master/doc/nixos-meetup-3-slides.md.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Another Youtube video is
|
||||
<link xlink:href="https://www.youtube.com/watch?v=mQd3s57n_2Y">Escaping
|
||||
Cabal Hell with Nix</link>, which discusses the subject of
|
||||
Haskell development with Nix but also provides a basic
|
||||
introduction to Nix as well, i.e. it's suitable for viewers with
|
||||
almost no prior Nix experience.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Oliver Charles wrote a very nice
|
||||
<link xlink:href="http://wiki.ocharles.org.uk/Nix">Tutorial how to
|
||||
develop Haskell packages with Nix</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <emphasis>Journey into the Haskell NG
|
||||
infrastructure</emphasis> series of postings describe the new
|
||||
Haskell infrastructure in great detail:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015591.html">Part
|
||||
1</link> explains the differences between the old and the
|
||||
new code and gives instructions how to migrate to the new
|
||||
setup.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015608.html">Part
|
||||
2</link> looks in-depth at how to tweak and configure your
|
||||
setup by means of overrides.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-April/016912.html">Part
|
||||
3</link> describes the infrastructure that keeps the
|
||||
Haskell package set in Nixpkgs up-to-date.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -7,13 +7,13 @@
|
||||
<para>This manual tells you how to write packages for the Nix Packages
|
||||
collection (Nixpkgs). Thus it’s for packagers and developers who want
|
||||
to add packages to Nixpkgs. End users are kindly referred to the
|
||||
<link xlink:href="http://hydra.nixos.org/job/nix/trunk/tarball/latest/download-by-type/doc/manual">Nix
|
||||
<link xlink:href="http://nixos.org/releases/nix/unstable/manual/">Nix
|
||||
manual</link>.</para>
|
||||
|
||||
<para>This manual does not describe the syntax and semantics of the
|
||||
Nix expression language, which are given in the Nix manual in the
|
||||
<link
|
||||
xlink:href="http://hydra.nixos.org/job/nix/trunk/tarball/latest/download-by-type/doc/manual/#chap-writing-nix-expressions">chapter
|
||||
xlink:href="http://nixos.org/releases/nix/unstable/manual/#chap-writing-nix-expressions">chapter
|
||||
on writing Nix expressions</link>. It only describes the facilities
|
||||
provided by Nixpkgs to make writing packages easier, such as the
|
||||
standard build environment (<literal>stdenv</literal>).</para>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-language-support">
|
||||
@@ -14,15 +13,15 @@ in Nixpkgs to easily build packages for other programming languages,
|
||||
such as Perl or Haskell. These are described in this chapter.</para>
|
||||
|
||||
|
||||
<section xml:id="sec-language-perl"><title>Perl</title>
|
||||
<section xml:id="ssec-language-perl"><title>Perl</title>
|
||||
|
||||
<para>Nixpkgs provides a function <varname>buildPerlPackage</varname>,
|
||||
a generic package builder function for any Perl package that has a
|
||||
standard <varname>Makefile.PL</varname>. It’s implemented in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/perl-modules/generic"><filename>pkgs/development/perl-modules/generic</filename></link>.</para>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/development/perl-modules/generic"><filename>pkgs/development/perl-modules/generic</filename></link>.</para>
|
||||
|
||||
<para>Perl packages from CPAN are defined in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>,
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/top-level/perl-packages.nix"><filename>pkgs/perl-packages.nix</filename></link>,
|
||||
rather than <filename>pkgs/all-packages.nix</filename>. Most Perl
|
||||
packages are so straight-forward to build that they are defined here
|
||||
directly, rather than having a separate function for each package
|
||||
@@ -109,22 +108,22 @@ a <varname>preConfigure</varname> hook to generate a configuration
|
||||
file used by <filename>Makefile.PL</filename>:
|
||||
|
||||
<programlisting>
|
||||
{ buildPerlPackage, fetchurl, db }:
|
||||
{buildPerlPackage, fetchurl, db4}:
|
||||
|
||||
buildPerlPackage rec {
|
||||
name = "BerkeleyDB-0.36";
|
||||
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://cpan/authors/id/P/PM/PMQS/${name}.tar.gz";
|
||||
sha256 = "07xf50riarb60l1h6m2dqmql8q5dij619712fsgw7ach04d8g3z1";
|
||||
};
|
||||
|
||||
preConfigure = ''
|
||||
echo "LIB = ${db}/lib" > config.in
|
||||
echo "INCLUDE = ${db}/include" >> config.in
|
||||
echo "LIB = ${db4}/lib" > config.in
|
||||
echo "INCLUDE = ${db4}/include" >> config.in
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
@@ -152,836 +151,51 @@ ClassC3Componentised = buildPerlPackage rec {
|
||||
|
||||
</para>
|
||||
|
||||
<section xml:id="ssec-generation-from-CPAN"><title>Generation from CPAN</title>
|
||||
|
||||
<para>Nix expressions for Perl packages can be generated (almost)
|
||||
automatically from CPAN. This is done by the program
|
||||
<command>nix-generate-from-cpan</command>, which can be installed
|
||||
as follows:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-env -i nix-generate-from-cpan
|
||||
</screen>
|
||||
|
||||
<para>This program takes a Perl module name, looks it up on CPAN,
|
||||
fetches and unpacks the corresponding package, and prints a Nix
|
||||
expression on standard output. For example:
|
||||
|
||||
<screen>
|
||||
$ nix-generate-from-cpan XML::Simple
|
||||
XMLSimple = buildPerlPackage {
|
||||
name = "XML-Simple-2.20";
|
||||
src = fetchurl {
|
||||
url = mirror://cpan/authors/id/G/GR/GRANTM/XML-Simple-2.20.tar.gz;
|
||||
sha256 = "5cff13d0802792da1eb45895ce1be461903d98ec97c9c953bc8406af7294434a";
|
||||
};
|
||||
propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ];
|
||||
meta = {
|
||||
description = "Easily read/write XML (esp config files)";
|
||||
license = "perl";
|
||||
};
|
||||
};
|
||||
</screen>
|
||||
|
||||
The output can be pasted into
|
||||
<filename>pkgs/top-level/perl-packages.nix</filename> or wherever else
|
||||
you need it.</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-python"><title>Python</title>
|
||||
|
||||
<para>
|
||||
Currently supported interpreters are <varname>python26</varname>, <varname>python27</varname>,
|
||||
<varname>python32</varname>, <varname>python33</varname>, <varname>python34</varname>
|
||||
and <varname>pypy</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python</varname> is an alias of <varname>python27</varname> and <varname>python3</varname> is an alias of <varname>python34</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python26</varname> and <varname>python27</varname> do not include modules that require
|
||||
external dependencies (to reduce dependency bloat). Following modules need to be added as
|
||||
<varname>buildInput</varname> explicitly:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><varname>python.modules.bsddb</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.curses</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.curses_panel</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.crypt</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.gdbm</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.sqlite3</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.tkinter</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.readline</varname></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For convenience <varname>python27Full</varname> and <varname>python26Full</varname>
|
||||
are provided with all modules included.</para>
|
||||
<section><title>Python</title>
|
||||
|
||||
<para>
|
||||
Python packages that
|
||||
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link> or <literal>distutils</literal>,
|
||||
can be built using the <varname>buildPythonPackage</varname> function as documented below.
|
||||
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link>,
|
||||
which many Python packages do nowadays, can be built very simply using
|
||||
the <varname>buildPythonPackage</varname> function. This function is
|
||||
implemented
|
||||
in <link xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/development/python-modules/generic/default.nix"><filename>pkgs/development/python-modules/generic/default.nix</filename></link>
|
||||
and works similarly to <varname>buildPerlPackage</varname>. (See
|
||||
<xref linkend="ssec-language-perl"/> for details.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
All packages depending on any Python interpreter get appended <varname>$out/${python.libPrefix}/site-packages</varname>
|
||||
to <literal>$PYTHONPATH</literal> if such directory exists.
|
||||
</para>
|
||||
Python packages that use <varname>buildPythonPackage</varname> are
|
||||
defined
|
||||
in <link xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>.
|
||||
Most of them are simple. For example:
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
Useful attributes on interpreters packages:
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>libPrefix</varname></term>
|
||||
<listitem><para>
|
||||
Name of the folder in <literal>${python}/lib/</literal> for corresponding interpreter.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>interpreter</varname></term>
|
||||
<listitem><para>
|
||||
Alias for <literal>${python}/bin/${executable}.</literal>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>buildEnv</varname></term>
|
||||
<listitem><para>
|
||||
Function to build python interpreter environments with extra packages bundled together.
|
||||
See <xref linkend="ssec-python-build-env" /> for usage and documentation.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>sitePackages</varname></term>
|
||||
<listitem><para>
|
||||
Alias for <literal>lib/${libPrefix}/site-packages</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>executable</varname></term>
|
||||
<listitem><para>
|
||||
Name of the interpreter executable, ie <literal>python3.4</literal>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
<section xml:id="ssec-build-python-package"><title><varname>buildPythonPackage</varname> function</title>
|
||||
|
||||
<para>
|
||||
The function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix">
|
||||
<filename>pkgs/development/python-modules/generic/default.nix</filename></link>.
|
||||
Example usage:
|
||||
|
||||
<programlisting language="nix">
|
||||
<programlisting>
|
||||
twisted = buildPythonPackage {
|
||||
name = "twisted-8.1.0";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
src = fetchurl {
|
||||
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
|
||||
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ self.ZopeInterface ];
|
||||
propagatedBuildInputs = [ pkgs.ZopeInterface ];
|
||||
|
||||
meta = {
|
||||
homepage = http://twistedmatrix.com/;
|
||||
description = "Twisted, an event-driven networking engine written in Python";
|
||||
license = stdenv.lib.licenses.mit;
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
Most of Python packages that use <varname>buildPythonPackage</varname> are defined
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
|
||||
and generated for each python interpreter separately into attribute sets <varname>python26Packages</varname>,
|
||||
<varname>python27Packages</varname>, <varname>python32Packages</varname>, <varname>python33Packages</varname>,
|
||||
<varname>python34Packages</varname> and <varname>pypyPackages</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildPythonPackage</function> mainly does four things:
|
||||
|
||||
<orderedlist>
|
||||
<listitem><para>
|
||||
In the <varname>configurePhase</varname>, it patches
|
||||
<literal>setup.py</literal> to always include setuptools before
|
||||
distutils for monkeypatching machinery to take place.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>buildPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py build ...</literal>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>installPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py install ...</literal>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>postFixup</varname> phase, <literal>wrapPythonPrograms</literal>
|
||||
bash function is called to wrap all programs in <filename>$out/bin/*</filename>
|
||||
directory to include <literal>$PYTHONPATH</literal> and <literal>$PATH</literal>
|
||||
environment variables.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>By default <varname>doCheck = true</varname> is set and tests are run with
|
||||
<literal>${python.interpreter} setup.py test</literal> command in <varname>checkPhase</varname>.</para>
|
||||
|
||||
<para>
|
||||
As in Perl, dependencies on other Python packages can be specified in the
|
||||
<varname>buildInputs</varname> and
|
||||
<varname>propagatedBuildInputs</varname> attributes. If something is
|
||||
exclusively a build-time dependency, use
|
||||
<varname>buildInputs</varname>; if it’s (also) a runtime dependency,
|
||||
use <varname>propagatedBuildInputs</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default <varname>meta.platforms</varname> is set to the same value
|
||||
as the interpreter unless overriden otherwise.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
<varname>buildPythonPackage</varname> parameters
|
||||
(all parameters from <varname>mkDerivation</varname> function are still supported)
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>namePrefix</varname></term>
|
||||
<listitem><para>
|
||||
Prepended text to <varname>${name}</varname> parameter.
|
||||
Defaults to <literal>"python3.3-"</literal> for Python 3.3, etc. Set it to
|
||||
<literal>""</literal>
|
||||
if you're packaging an application or a command line tool.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>disabled</varname></term>
|
||||
<listitem><para>
|
||||
If <varname>true</varname>, package is not build for
|
||||
particular python interpreter version. Grep around
|
||||
<filename>pkgs/top-level/python-packages.nix</filename>
|
||||
for examples.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>setupPyInstallFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py install</command> command.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>setupPyBuildFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py build</command> command.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>pythonPath</varname></term>
|
||||
<listitem><para>
|
||||
List of packages to be added into <literal>$PYTHONPATH</literal>.
|
||||
Packages in <varname>pythonPath</varname> are not propagated into user environment
|
||||
(contrary to <varname>propagatedBuildInputs</varname>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>preShellHook</varname></term>
|
||||
<listitem><para>
|
||||
Hook to execute commands before <varname>shellHook</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>postShellHook</varname></term>
|
||||
<listitem><para>
|
||||
Hook to execute commands after <varname>shellHook</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>distutilsExtraCfg</varname></term>
|
||||
<listitem><para>
|
||||
Extra lines passed to <varname>[easy_install]</varname> section of
|
||||
<filename>distutils.cfg</filename> (acts as global setup.cfg
|
||||
configuration).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>makeWrapperArgs</varname></term>
|
||||
<listitem><para>
|
||||
A list of strings. Arguments to be passed to
|
||||
<varname>makeWrapper</varname>, which wraps generated binaries. By
|
||||
default, the arguments to <varname>makeWrapper</varname> set
|
||||
<varname>PATH</varname> and <varname>PYTHONPATH</varname> environment
|
||||
variables before calling the binary. Additional arguments here can
|
||||
allow a developer to set environment variables which will be
|
||||
available when the binary is run. For example,
|
||||
<varname>makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-build-env"><title><function>python.buildEnv</function> function</title>
|
||||
<para>
|
||||
Create Python environments using low-level <function>pkgs.buildEnv</function> function. Example <filename>default.nix</filename>:
|
||||
|
||||
<programlisting language="nix">
|
||||
<![CDATA[with import <nixpkgs> {};
|
||||
|
||||
python.buildEnv.override {
|
||||
extraLibs = [ pkgs.pythonPackages.pyramid ];
|
||||
ignoreCollisions = true;
|
||||
}]]>
|
||||
</programlisting>
|
||||
|
||||
Running <command>nix-build</command> will create
|
||||
<filename>/nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env</filename>
|
||||
with wrapped binaries in <filename>bin/</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can also use <varname>env</varname> attribute to create local
|
||||
environments with needed packages installed (somewhat comparable to
|
||||
<literal>virtualenv</literal>). For example, with the following
|
||||
<filename>shell.nix</filename>:
|
||||
|
||||
<programlisting language="nix">
|
||||
<![CDATA[with import <nixpkgs> {};
|
||||
|
||||
(python3.buildEnv.override {
|
||||
extraLibs = with python3Packages;
|
||||
[ numpy
|
||||
requests
|
||||
];
|
||||
}).env]]>
|
||||
</programlisting>
|
||||
|
||||
Running <command>nix-shell</command> will drop you into a shell where
|
||||
<command>python</command> will have specified packages in its path.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
<function>python.buildEnv</function> arguments
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>extraLibs</varname></term>
|
||||
<listitem><para>
|
||||
List of packages installed inside the environment.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>postBuild</varname></term>
|
||||
<listitem><para>
|
||||
Shell command executed after the build of environment.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ignoreCollisions</varname></term>
|
||||
<listitem><para>
|
||||
Ignore file collisions inside the environment (default is <varname>false</varname>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-tools"><title>Tools</title>
|
||||
|
||||
<para>Packages inside nixpkgs are written by hand. However many tools
|
||||
exist in community to help save time. No tool is preferred at the moment.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>
|
||||
<link xlink:href="https://github.com/proger/python2nix">python2nix</link>
|
||||
by Vladimir Kirillov
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
<link xlink:href="https://github.com/garbas/pypi2nix">pypi2nix</link>
|
||||
by Rok Garbas
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
<link xlink:href="https://github.com/offlinehacker/pypi2nix">pypi2nix</link>
|
||||
by Jaka Hudoklin
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-development"><title>Development</title>
|
||||
|
||||
<para>
|
||||
To develop Python packages <function>buildPythonPackage</function> has
|
||||
additional logic inside <varname>shellPhase</varname> to run
|
||||
<command>${python.interpreter} setup.py develop</command> for the package.
|
||||
</para>
|
||||
|
||||
<warning><para><varname>shellPhase</varname> is executed only if <filename>setup.py</filename>
|
||||
exists.</para></warning>
|
||||
|
||||
<para>
|
||||
Given a <filename>default.nix</filename>:
|
||||
|
||||
<programlisting language="nix">
|
||||
<![CDATA[with import <nixpkgs> {};
|
||||
|
||||
buildPythonPackage {
|
||||
name = "myproject";
|
||||
|
||||
buildInputs = with pkgs.pythonPackages; [ pyramid ];
|
||||
|
||||
src = ./.;
|
||||
}]]>
|
||||
</programlisting>
|
||||
|
||||
Running <command>nix-shell</command> with no arguments should give you
|
||||
the environment in which the package would be build with
|
||||
<command>nix-build</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Shortcut to setup environments with C headers/libraries and python packages:
|
||||
|
||||
<programlisting language="bash">$ nix-shell -p pythonPackages.pyramid zlib libjpeg git</programlisting>
|
||||
</para>
|
||||
|
||||
<note><para>
|
||||
There is a boolean value <varname>lib.inNixShell</varname> set to
|
||||
<varname>true</varname> if nix-shell is invoked.
|
||||
</para></note>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-python-faq"><title>FAQ</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term>How to solve circular dependencies?</term>
|
||||
<listitem><para>
|
||||
If you have packages <varname>A</varname> and <varname>B</varname> that
|
||||
depend on each other, when packaging <varname>B</varname> override package
|
||||
<varname>A</varname> not to depend on <varname>B</varname> as input
|
||||
(and also the other way around).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>install_data / data_files</varname> problems resulting into <literal>error: could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc': Permission denied</literal></term>
|
||||
<listitem><para>
|
||||
<link xlink:href="https://bitbucket.org/pypa/setuptools/issue/130/install_data-doesnt-respect-prefix">
|
||||
Known bug in setuptools <varname>install_data</varname> does not respect --prefix</link>. Example of
|
||||
such package using the feature is <filename>pkgs/tools/X11/xpra/default.nix</filename>. As workaround
|
||||
install it as an extra <varname>preInstall</varname> step:
|
||||
|
||||
<programlisting>${python.interpreter} setup.py install_data --install-dir=$out --root=$out
|
||||
sed -i '/ = data_files/d' setup.py</programlisting>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Rationale of non-existent global site-packages</term>
|
||||
<listitem><para>
|
||||
There is no need to have global site-packages in Nix. Each package has isolated
|
||||
dependency tree and installing any python package will only populate <varname>$PATH</varname>
|
||||
inside user environment. See <xref linkend="ssec-python-build-env" /> to create self-contained
|
||||
interpreter with a set of packages.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-python-contrib"><title>Contributing guidelines</title>
|
||||
<para>
|
||||
Following rules are desired to be respected:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>
|
||||
Make sure package builds for all python interpreters. Use <varname>disabled</varname> argument to
|
||||
<function>buildPythonPackage</function> to set unsupported interpreters.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
If tests need to be disabled for a package, make sure you leave a comment about reasoning.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
Packages in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
|
||||
are sorted quasi-alphabetically to avoid merge conflicts.
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-language-ruby"><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>For example, to package sensu, we did:</para>
|
||||
|
||||
<screen>
|
||||
<![CDATA[$ cd pkgs/servers/monitoring
|
||||
$ mkdir sensu
|
||||
$ cat > Gemfile
|
||||
source 'https://rubygems.org'
|
||||
gem 'sensu'
|
||||
$ bundler package --path /tmp/vendor/bundle
|
||||
$ $(nix-build '<nixpkgs>' -A bundix)/bin/bundix
|
||||
$ cat > default.nix
|
||||
{ lib, bundlerEnv, ruby }:
|
||||
|
||||
bundlerEnv {
|
||||
name = "sensu-0.17.1";
|
||||
|
||||
inherit ruby;
|
||||
gemfile = ./Gemfile;
|
||||
lockfile = ./Gemfile.lock;
|
||||
gemset = ./gemset.nix;
|
||||
|
||||
meta = with lib; {
|
||||
description = "A monitoring framework that aims to be simple, malleable,
|
||||
and scalable.";
|
||||
homepage = http://sensuapp.org/;
|
||||
license = with licenses; mit;
|
||||
maintainers = with maintainers; [ theuni ];
|
||||
platforms = platforms.unix;
|
||||
};
|
||||
}]]>
|
||||
</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>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-language-go"><title>Go</title>
|
||||
|
||||
<para>The function <varname>buildGoPackage</varname> builds
|
||||
standard Go packages.
|
||||
</para>
|
||||
|
||||
<example xml:id='ex-buildGoPackage'><title>buildGoPackage</title>
|
||||
<programlisting>
|
||||
net = buildGoPackage rec {
|
||||
name = "go.net-${rev}";
|
||||
goPackagePath = "golang.org/x/net"; <co xml:id='ex-buildGoPackage-1' />
|
||||
subPackages = [ "ipv4" "ipv6" ]; <co xml:id='ex-buildGoPackage-2' />
|
||||
rev = "e0403b4e005";
|
||||
src = fetchFromGitHub {
|
||||
inherit rev;
|
||||
owner = "golang";
|
||||
repo = "net";
|
||||
sha256 = "1g7cjzw4g4301a3yqpbk8n1d4s97sfby2aysl275x04g0zh8jxqp";
|
||||
};
|
||||
goPackageAliases = [ "code.google.com/p/go.net" ]; <co xml:id='ex-buildGoPackage-3' />
|
||||
propagatedBuildInputs = [ goPackages.text ]; <co xml:id='ex-buildGoPackage-4' />
|
||||
buildFlags = "--tags release"; <co xml:id='ex-buildGoPackage-5' />
|
||||
disabled = isGo13;<co xml:id='ex-buildGoPackage-6' />
|
||||
};
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para><xref linkend='ex-buildGoPackage'/> is an example expression using buildGoPackage,
|
||||
the following arguments are of special significance to the function:
|
||||
|
||||
<calloutlist>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-1'>
|
||||
<para>
|
||||
<varname>goPackagePath</varname> specifies the package's canonical Go import path.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-2'>
|
||||
<para>
|
||||
<varname>subPackages</varname> limits the builder from building child packages that
|
||||
have not been listed. If <varname>subPackages</varname> is not specified, all child
|
||||
packages will be built.
|
||||
</para>
|
||||
<para>
|
||||
In this example only <literal>code.google.com/p/go.net/ipv4</literal> and
|
||||
<literal>code.google.com/p/go.net/ipv4</literal> will be built.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-3'>
|
||||
<para>
|
||||
<varname>goPackageAliases</varname> is a list of alternative import paths
|
||||
that are valid for this library.
|
||||
Packages that depend on this library will automatically rename
|
||||
import paths that match any of the aliases to <literal>goPackagePath</literal>.
|
||||
</para>
|
||||
<para>
|
||||
In this example imports will be renamed from
|
||||
<literal>code.google.com/p/go.net</literal> to
|
||||
<literal>golang.org/x/net</literal> in every package that depend on the
|
||||
<literal>go.net</literal> library.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-4'>
|
||||
<para>
|
||||
<varname>propagatedBuildInputs</varname> is where the dependencies of a Go library are
|
||||
listed. Only libraries should list <varname>propagatedBuildInputs</varname>. If a standalone
|
||||
program is being build instead, use <varname>buildInputs</varname>. If a library's tests require
|
||||
additional dependencies that are not propagated, they should be listed in <varname>buildInputs</varname>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-5'>
|
||||
<para>
|
||||
<varname>buildFlags</varname> is a list of flags passed to the go build command.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-buildGoPackage-6'>
|
||||
<para>
|
||||
If <varname>disabled</varname> is <literal>true</literal>,
|
||||
nix will refuse to build this package.
|
||||
</para>
|
||||
<para>
|
||||
In this example the package will not be built for go 1.3. The <literal>isGo13</literal>
|
||||
is an utility function that returns <literal>true</literal> if go used to build the
|
||||
package has version 1.3.x.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
</calloutlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Reusable Go libraries may be found in the <varname>goPackages</varname> set. You can test
|
||||
build a Go package as follows:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A goPackages.net
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may use Go packages installed into the active Nix profiles by adding
|
||||
the following to your ~/.bashrc:
|
||||
|
||||
<screen>
|
||||
for p in $NIX_PROFILES; do
|
||||
GOPATH="$p/share/go:$GOPATH"
|
||||
done
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>To extract dependency information from a Go package in automated way use <link xlink:href="https://github.com/cstrahan/go2nix">go2nix</link>.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-language-java"><title>Java</title>
|
||||
|
||||
<para>Ant-based Java packages are typically built from source as follows:
|
||||
|
||||
<programlisting>
|
||||
stdenv.mkDerivation {
|
||||
name = "...";
|
||||
src = fetchurl { ... };
|
||||
|
||||
buildInputs = [ jdk ant ];
|
||||
|
||||
buildPhase = "ant";
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
Note that <varname>jdk</varname> is an alias for the OpenJDK.</para>
|
||||
|
||||
<para>JAR files that are intended to be used by other packages should
|
||||
be installed in <filename>$out/share/java</filename>. The OpenJDK has
|
||||
a stdenv setup hook that adds any JARs in the
|
||||
<filename>share/java</filename> directories of the build inputs to the
|
||||
<envar>CLASSPATH</envar> environment variable. For instance, if the
|
||||
package <literal>libfoo</literal> installs a JAR named
|
||||
<filename>foo.jar</filename> in its <filename>share/java</filename>
|
||||
directory, and another package declares the attribute
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ jdk libfoo ];
|
||||
</programlisting>
|
||||
|
||||
then <envar>CLASSPATH</envar> will be set to
|
||||
<filename>/nix/store/...-libfoo/share/java/foo.jar</filename>.</para>
|
||||
|
||||
<para>Private JARs
|
||||
should be installed in a location like
|
||||
<filename>$out/share/<replaceable>package-name</replaceable></filename>.</para>
|
||||
|
||||
<para>If your Java package provides a program, you need to generate a
|
||||
wrapper script to run it using the OpenJRE. You can use
|
||||
<literal>makeWrapper</literal> for this:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ makeWrapper ];
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper ${jre}/bin/java $out/bin/foo \
|
||||
--add-flags "-cp $out/share/java/foo.jar org.foo.Main"
|
||||
'';
|
||||
</programlisting>
|
||||
|
||||
Note the use of <literal>jre</literal>, which is the part of the
|
||||
OpenJDK package that contains the Java Runtime Environment. By using
|
||||
<literal>${jre}/bin/java</literal> instead of
|
||||
<literal>${jdk}/bin/java</literal>, you prevent your package from
|
||||
depending on the JDK at runtime.</para>
|
||||
|
||||
<para>It is possible to use a different Java compiler than
|
||||
<command>javac</command> from the OpenJDK. For instance, to use the
|
||||
Eclipse Java Compiler:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ jre ant ecj ];
|
||||
</programlisting>
|
||||
|
||||
(Note that here you don’t need the full JDK as an input, but just the
|
||||
JRE.) The ECJ has a stdenv setup hook that sets some environment
|
||||
variables to cause Ant to use ECJ, but this doesn’t work with all Ant
|
||||
files. Similarly, you can use the GNU Java Compiler:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ gcj ant ];
|
||||
</programlisting>
|
||||
|
||||
Here, Ant will automatically use <command>gij</command> (the GNU Java
|
||||
Runtime) instead of the OpenJRE.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-language-lua"><title>Lua</title>
|
||||
|
||||
<para>
|
||||
Lua packages are built by the <varname>buildLuaPackage</varname> function. This function is
|
||||
implemented
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules/generic/default.nix">
|
||||
<filename>pkgs/development/lua-modules/generic/default.nix</filename></link>
|
||||
and works similarly to <varname>buildPerlPackage</varname>. (See
|
||||
<xref linkend="sec-language-perl"/> for details.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Lua packages are defined
|
||||
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/lua-packages.nix"><filename>pkgs/top-level/lua-packages.nix</filename></link>.
|
||||
Most of them are simple. For example:
|
||||
|
||||
<programlisting>
|
||||
fileSystem = buildLuaPackage {
|
||||
name = "filesystem-1.6.2";
|
||||
src = fetchurl {
|
||||
url = "https://github.com/keplerproject/luafilesystem/archive/v1_6_2.tar.gz";
|
||||
sha256 = "1n8qdwa20ypbrny99vhkmx8q04zd2jjycdb5196xdhgvqzk10abz";
|
||||
};
|
||||
meta = {
|
||||
homepage = "https://github.com/keplerproject/luafilesystem";
|
||||
hydraPlatforms = stdenv.lib.platforms.linux;
|
||||
maintainers = with maintainers; [ flosse ];
|
||||
license = "MIT";
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Though, more complicated package should be placed in a seperate file in
|
||||
<link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules"><filename>pkgs/development/lua-modules</filename></link>.
|
||||
</para>
|
||||
<para>
|
||||
Lua packages accept additional parameter <varname>disabled</varname>, which defines
|
||||
the condition of disabling package from luaPackages. For example, if package has
|
||||
<varname>disabled</varname> assigned to <literal>lua.luaversion != "5.1"</literal>,
|
||||
it will not be included in any luaPackages except lua51Packages, making it
|
||||
only be built for lua 5.1.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-language-coq"><title>Coq</title>
|
||||
<para>
|
||||
Coq libraries should be installed in
|
||||
<literal>$(out)/lib/coq/${coq.coq-version}/user-contrib/</literal>.
|
||||
Such directories are automatically added to the
|
||||
<literal>$COQPATH</literal> environment variable by the hook defined
|
||||
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
|
||||
<literal>coq.ocaml</literal> and <literal>coq.camlp5</literal>
|
||||
attributes.
|
||||
</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
|
||||
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";
|
||||
};
|
||||
|
||||
name = "coq-karatsuba";
|
||||
|
||||
buildInputs = [ coq ];
|
||||
|
||||
installFlags = "COQLIB=$(out)/lib/coq/${coq.coq-version}/";
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<!--
|
||||
<section><title>Haskell</title>
|
||||
|
||||
<para>TODO</para>
|
||||
@@ -989,12 +203,18 @@ stdenv.mkDerivation {
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Java</title>
|
||||
|
||||
<para>TODO; Java support needs lots of improvement</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>TeX / LaTeX</title>
|
||||
|
||||
<para>* Special support for building TeX documents</para>
|
||||
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -3,23 +3,37 @@
|
||||
|
||||
<info>
|
||||
|
||||
<title>Nixpkgs Contributors Guide</title>
|
||||
<title>Nixpkgs Manual</title>
|
||||
|
||||
<subtitle>Version <xi:include href=".version" parse="text" /></subtitle>
|
||||
<subtitle>Draft (Version <xi:include href="../VERSION"
|
||||
parse="text" />)</subtitle>
|
||||
|
||||
<author>
|
||||
<personname>
|
||||
<firstname>Eelco</firstname>
|
||||
<surname>Dolstra</surname>
|
||||
</personname>
|
||||
<affiliation>
|
||||
<orgname>Delft University of Technology</orgname>
|
||||
<orgdiv>Department of Software Technology</orgdiv>
|
||||
</affiliation>
|
||||
</author>
|
||||
|
||||
<copyright>
|
||||
<year>2008</year>
|
||||
<year>2009</year>
|
||||
<holder>Eelco Dolstra</holder>
|
||||
</copyright>
|
||||
|
||||
</info>
|
||||
|
||||
<xi:include href="introduction.xml" />
|
||||
<xi:include href="quick-start.xml" />
|
||||
<xi:include href="stdenv.xml" />
|
||||
<xi:include href="packageconfig.xml" />
|
||||
<xi:include href="functions.xml" />
|
||||
<xi:include href="meta.xml" />
|
||||
<xi:include href="language-support.xml" />
|
||||
<xi:include href="package-notes.xml" />
|
||||
<xi:include href="coding-conventions.xml" />
|
||||
<xi:include href="submitting-changes.xml" />
|
||||
<xi:include href="haskell-users-guide.xml" />
|
||||
<xi:include href="contributing.xml" />
|
||||
|
||||
|
||||
|
||||
</book>
|
||||
|
||||
249
doc/meta.xml
249
doc/meta.xml
@@ -17,9 +17,7 @@ meta = {
|
||||
It is fully customizable.
|
||||
'';
|
||||
homepage = http://www.gnu.org/software/hello/manual/;
|
||||
license = stdenv.lib.licenses.gpl3Plus;
|
||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||
platforms = stdenv.lib.platforms.all;
|
||||
license = "GPLv3+";
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
@@ -27,48 +25,22 @@ meta = {
|
||||
|
||||
<para>Meta-attributes are not passed to the builder of the package.
|
||||
Thus, a change to a meta-attribute doesn’t trigger a recompilation of
|
||||
the package. The value of a meta-attribute must be a string.</para>
|
||||
the package. The value of a meta-attribute must a string.</para>
|
||||
|
||||
<para>The meta-attributes of a package can be queried from the
|
||||
command-line using <command>nix-env</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa hello --meta --json
|
||||
{
|
||||
"hello": {
|
||||
"meta": {
|
||||
"description": "A program that produces a familiar, friendly greeting",
|
||||
"homepage": "http://www.gnu.org/software/hello/manual/",
|
||||
"license": {
|
||||
"fullName": "GNU General Public License version 3 or later",
|
||||
"shortName": "GPLv3+",
|
||||
"url": "http://www.fsf.org/licensing/licenses/gpl.html"
|
||||
},
|
||||
"longDescription": "GNU Hello is a program that prints \"Hello, world!\" when you run it.\nIt is fully customizable.\n",
|
||||
"maintainers": [
|
||||
"Ludovic Court\u00e8s <ludo@gnu.org>"
|
||||
],
|
||||
"platforms": [
|
||||
"i686-linux",
|
||||
"x86_64-linux",
|
||||
"armv5tel-linux",
|
||||
"armv7l-linux",
|
||||
"mips64el-linux",
|
||||
"x86_64-darwin",
|
||||
"i686-cygwin",
|
||||
"i686-freebsd",
|
||||
"x86_64-freebsd",
|
||||
"i686-openbsd",
|
||||
"x86_64-openbsd"
|
||||
],
|
||||
"position": "/home/user/dev/nixpkgs/pkgs/applications/misc/hello/ex-2/default.nix:14"
|
||||
},
|
||||
"name": "hello-2.9",
|
||||
"system": "x86_64-linux"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$ nix-env -qa hello --meta --xml
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<items>
|
||||
<item attrPath="hello" name="hello-2.3" system="i686-linux">
|
||||
<meta name="description" value="A program that produces a familiar, friendly greeting" />
|
||||
<meta name="homepage" value="http://www.gnu.org/software/hello/manual/" />
|
||||
<meta name="license" value="GPLv3+" />
|
||||
<meta name="longDescription" value="GNU Hello is a program that prints &quot;Hello, world!&quot; when you run it.&#xA;It is fully customizable.&#xA;" />
|
||||
</item>
|
||||
</items>
|
||||
</screen>
|
||||
|
||||
<command>nix-env</command> knows about the
|
||||
@@ -82,10 +54,10 @@ hello-2.3 A program that produces a familiar, friendly greeting
|
||||
</para>
|
||||
|
||||
|
||||
<section xml:id="sec-standard-meta-attributes"><title>Standard
|
||||
meta-attributes</title>
|
||||
<section><title>Standard meta-attributes</title>
|
||||
|
||||
<para>It is expected that each meta-attribute is one of the following:</para>
|
||||
<para>The following meta-attributes have a standard
|
||||
interpretation:</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
@@ -112,76 +84,28 @@ meta-attributes</title>
|
||||
package.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>version</varname></term>
|
||||
<listitem><para>Package version.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>branch</varname></term>
|
||||
<listitem><para>Release branch. Used to specify that a package is not
|
||||
going to receive updates that are not in this branch; for example, Linux
|
||||
kernel 3.0 is supposed to be updated to 3.0.X, not 3.1.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>homepage</varname></term>
|
||||
<listitem><para>The package’s homepage. Example:
|
||||
<literal>http://www.gnu.org/software/hello/manual/</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>downloadPage</varname></term>
|
||||
<listitem><para>The page where a link to the current version can be found. Example:
|
||||
<literal>http://ftp.gnu.org/gnu/hello/</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>license</varname></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The license, or licenses, for the package. One from the attribute set
|
||||
defined in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix">
|
||||
<filename>nixpkgs/lib/licenses.nix</filename></link>. At this moment
|
||||
using both a list of licenses and a single license is valid. If the
|
||||
license field is in the form of a list representation, then it means
|
||||
that parts of the package are licensed differently. Each license
|
||||
should preferably be referenced by their attribute. The non-list
|
||||
attribute value can also be a space delimited string representation of
|
||||
the contained attribute shortNames or spdxIds. The following are all valid
|
||||
examples:
|
||||
<itemizedlist>
|
||||
<listitem><para>Single license referenced by attribute (preferred)
|
||||
<literal>stdenv.lib.licenses.gpl3</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Single license referenced by its attribute shortName (frowned upon)
|
||||
<literal>"gpl3"</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Single license referenced by its attribute spdxId (frowned upon)
|
||||
<literal>"GPL-3.0"</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Multiple licenses referenced by attribute (preferred)
|
||||
<literal>with stdenv.lib.licenses; [ asl20 free ofl ]</literal>.
|
||||
</para></listitem>
|
||||
<listitem><para>Multiple licenses referenced as a space delimited string of attribute shortNames (frowned upon)
|
||||
<literal>"asl20 free ofl"</literal>.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
For details, see <xref linkend='sec-meta-license'/>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem><para>The license for the package. See below for the
|
||||
allowed values.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>maintainers</varname></term>
|
||||
<listitem><para>A list of names and e-mail addresses of the
|
||||
maintainers of this Nix expression. If
|
||||
you would like to be a maintainer of a package, you may want to add
|
||||
maintainers of this Nix expression, e.g. <literal>["Alice
|
||||
<alice@example.org>" "Bob <bob@example.com>"]</literal>. If
|
||||
you are the maintainer of multiple packages, 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>
|
||||
and write something like <literal>[ stdenv.lib.maintainers.alice
|
||||
stdenv.lib.maintainers.bob ]</literal>.</para></listitem>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/lib/maintainers.nix"><filename>pkgs/lib/maintainers.nix</filename></link>
|
||||
and write something like <literal>[stdenv.lib.maintainers.alice
|
||||
stdenv.lib.maintainers.bob]</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -194,62 +118,6 @@ meta-attributes</title>
|
||||
package).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>platforms</varname></term>
|
||||
<listitem><para>The list of Nix platform types on which the
|
||||
package is supported. Hydra builds packages according to the
|
||||
platform specified. If no platform is specified, the package does
|
||||
not have prebuilt binaries. An example is:
|
||||
|
||||
<programlisting>
|
||||
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>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>hydraPlatforms</varname></term>
|
||||
<listitem><para>The list of Nix platform types for which the Hydra
|
||||
instance at <literal>hydra.nixos.org</literal> will build the
|
||||
package. (Hydra is the Nix-based continuous build system.) It
|
||||
defaults to the value of <varname>meta.platforms</varname>. Thus,
|
||||
the only reason to set <varname>meta.hydraPlatforms</varname> is
|
||||
if you want <literal>hydra.nixos.org</literal> to build the
|
||||
package on a subset of <varname>meta.platforms</varname>, or not
|
||||
at all, e.g.
|
||||
|
||||
<programlisting>
|
||||
meta.platforms = stdenv.lib.platforms.linux;
|
||||
meta.hydraPlatforms = [];
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>broken</varname></term>
|
||||
<listitem><para>If set to <literal>true</literal>, the package is
|
||||
marked as “broken”, meaning that it won’t show up in
|
||||
<literal>nix-env -qa</literal>, and cannot be built or installed.
|
||||
Such packages should be removed from Nixpkgs eventually unless
|
||||
they are fixed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>updateWalker</varname></term>
|
||||
<listitem><para>If set to <literal>true</literal>, the package is
|
||||
tested to be updated correctly by the <literal>update-walker.sh</literal>
|
||||
script without additional settings. Such packages have
|
||||
<varname>meta.version</varname> set and their homepage (or
|
||||
the page specified by <varname>meta.downloadPage</varname>) contains
|
||||
a direct link to the package tarball.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
|
||||
@@ -258,23 +126,74 @@ meta.hydraPlatforms = [];
|
||||
|
||||
<section xml:id="sec-meta-license"><title>Licenses</title>
|
||||
|
||||
<para>The <varname>meta.license</varname> attribute should preferrably contain
|
||||
a value from <varname>stdenv.lib.licenses</varname> defined in
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/licenses.nix">
|
||||
<filename>nixpkgs/lib/licenses.nix</filename></link>,
|
||||
or in-place license description of the same format if the license is
|
||||
unlikely to be useful in another expression.
|
||||
<note><para>This is just a first attempt at standardising the license
|
||||
attribute.</para></note>
|
||||
|
||||
<para>The <varname>meta.license</varname> attribute must be one of the
|
||||
following:
|
||||
|
||||
A few generic options are available, although it's typically better
|
||||
to indicate the specific license:
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>GPL</varname></term>
|
||||
<listitem><para>GNU General Public License; version not
|
||||
specified.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>GPLv2</varname></term>
|
||||
<listitem><para>GNU General Public License, version
|
||||
2.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>GPLv2+</varname></term>
|
||||
<listitem><para>GNU General Public License, version
|
||||
2 or higher.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>GPLv3</varname></term>
|
||||
<listitem><para>GNU General Public License, version
|
||||
3.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>GPLv3+</varname></term>
|
||||
<listitem><para>GNU General Public License, version
|
||||
3 or higher.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>bsd</varname></term>
|
||||
<listitem><para>Catch-all for licenses that are essentially
|
||||
similar to <link
|
||||
xlink:href="http://www.gnu.org/licenses/license-list.html#ModifiedBSD">the
|
||||
original BSD license with the advertising clause removed</link>,
|
||||
i.e. permissive non-copyleft free software licenses. This
|
||||
includes the <link
|
||||
xlink:href="http://www.gnu.org/licenses/license-list.html#X11License">X11
|
||||
(“MIT”) License</link>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>free</varname></term>
|
||||
<listitem><para>Catch-all for free software licenses not listed
|
||||
above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>free-copyleft</varname></term>
|
||||
<listitem><para>Catch-all for free, copyleft software licenses not
|
||||
listed above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>free-non-copyleft</varname></term>
|
||||
<listitem><para>Catch-all for free, non-copyleft software licenses
|
||||
not listed above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>unfree-redistributable</varname></term>
|
||||
<listitem><para>Unfree package that can be redistributed in binary
|
||||
@@ -311,9 +230,9 @@ to indicate the specific license:
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
158
doc/outline.txt
Normal file
158
doc/outline.txt
Normal file
@@ -0,0 +1,158 @@
|
||||
- The standard environment
|
||||
|
||||
(Some of this can be moved from the Nix manual)
|
||||
|
||||
- Special attributes
|
||||
|
||||
- Generic builder
|
||||
|
||||
- Helper functions
|
||||
|
||||
- GCC / ld wrapper (+ env vars)
|
||||
|
||||
- Phases (+ how to add phases) and hooks
|
||||
|
||||
- Override functions for stdenv
|
||||
|
||||
- Overriding GCC
|
||||
|
||||
- Overriding the setup script
|
||||
|
||||
- Predefined override functions in all-packages.nix: static binary
|
||||
stdenv, dietlibc stdenv
|
||||
|
||||
- Stdenv bootstrap; how to update the Linux bootstrap binaries
|
||||
|
||||
- Specific platform notes (Linux, Native, Cygwin, Mingw)
|
||||
|
||||
|
||||
- Support for specific languages
|
||||
|
||||
- Perl
|
||||
|
||||
- Generic Perl builder
|
||||
|
||||
- Python
|
||||
|
||||
- Wrapper generation
|
||||
|
||||
- Haskell
|
||||
|
||||
- TODO
|
||||
|
||||
- Java
|
||||
|
||||
- TODO; Java needs lots of improvement
|
||||
|
||||
- TeX/LaTeX
|
||||
|
||||
- Special support for building TeX documents
|
||||
|
||||
|
||||
- Special kinds of applications
|
||||
|
||||
- OpenGL apps
|
||||
|
||||
- Binary-only apps
|
||||
|
||||
- Linux kernel modules
|
||||
|
||||
- Mozilla plugins/extensions
|
||||
|
||||
- X apps
|
||||
|
||||
- KDE apps
|
||||
|
||||
- GConf-based apps
|
||||
|
||||
- Programs that need wrappers
|
||||
|
||||
- makeWrapper etc.
|
||||
|
||||
- Initial ramdisks
|
||||
|
||||
|
||||
- Library functions
|
||||
|
||||
- i.e. in lib/default.nix
|
||||
|
||||
|
||||
- Specific package notes
|
||||
|
||||
- Linux kernel; how to update; feature tests
|
||||
|
||||
- X.org; how to update
|
||||
|
||||
- Gnome; how to update
|
||||
|
||||
- GCC?
|
||||
|
||||
- GHC?
|
||||
|
||||
- ...
|
||||
|
||||
|
||||
- Meta attributes
|
||||
|
||||
- License attr; possible values
|
||||
|
||||
|
||||
- Virtual machine support (for the build farm)
|
||||
|
||||
- vmtools
|
||||
|
||||
- KVM notes
|
||||
|
||||
- Performing a build in a VM
|
||||
|
||||
- In the host FS
|
||||
|
||||
- In a disk image
|
||||
|
||||
- RPM builds
|
||||
|
||||
- RPM image creation
|
||||
|
||||
- Deb builds
|
||||
|
||||
- Deb image creation
|
||||
|
||||
- Debugging VM builds
|
||||
|
||||
|
||||
- Guidelines for Nixpkgs contributions
|
||||
|
||||
- File naming conventions
|
||||
|
||||
- Versioning of packages
|
||||
|
||||
- Tree organisation
|
||||
|
||||
- Variable naming
|
||||
|
||||
- Layout / indentations style
|
||||
|
||||
- Output FS hierarchy (e.g. $out/share/man instead of $out/man)
|
||||
|
||||
|
||||
- Misc
|
||||
|
||||
- Building outside of the Nixpkgs tree
|
||||
|
||||
- Config options
|
||||
|
||||
- Downloading stuff
|
||||
|
||||
- fetchurl
|
||||
|
||||
- mirror:// scheme
|
||||
|
||||
- fetchsvn
|
||||
|
||||
- fetchcvs
|
||||
|
||||
- fetchdarcs
|
||||
|
||||
|
||||
- Appendix: Nixpkgs config options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-package-notes">
|
||||
xml:id="chap-introduction">
|
||||
|
||||
<title>Package Notes</title>
|
||||
|
||||
@@ -16,7 +16,7 @@ Linux kernel or X.org.</para>
|
||||
<title>Linux kernel</title>
|
||||
|
||||
<para>The Nix expressions to build the Linux kernel are in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/linux/kernel"><filename>pkgs/os-specific/linux/kernel</filename></link>.</para>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/os-specific/linux/kernel"><filename>pkgs/os-specific/linux/kernel</filename></link>.</para>
|
||||
|
||||
<para>The function that builds the kernel has an argument
|
||||
<varname>kernelPatches</varname> which should be a list of
|
||||
@@ -49,7 +49,7 @@ modulesTree = [kernel]
|
||||
<orderedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Copy the old Nix expression
|
||||
<para>Copy (<command>svn cp</command>) the old Nix expression
|
||||
(e.g. <filename>linux-2.6.21.nix</filename>) to the new one
|
||||
(e.g. <filename>linux-2.6.22.nix</filename>) and update it.</para>
|
||||
</listitem>
|
||||
@@ -69,7 +69,7 @@ modulesTree = [kernel]
|
||||
<orderedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Make an copy from the old
|
||||
<para>Make an <command>svn copy</command> from the old
|
||||
config (e.g. <filename>config-2.6.21-i686-smp</filename>) to
|
||||
the new one
|
||||
(e.g. <filename>config-2.6.22-i686-smp</filename>).</para>
|
||||
@@ -105,6 +105,16 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Make sure that
|
||||
<literal>CONFIG_FB_TILEBLITTING</literal> is <emphasis>not
|
||||
set</emphasis> (otherwise <command>fbsplash</command> won't
|
||||
work). This option has a tendency to be enabled as a
|
||||
side-effect of other options. If it is, investigate why
|
||||
(there's probably another option that forces it to be on)
|
||||
and fix it.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Copy <filename>.config</filename> over the new config
|
||||
file (e.g. <filename>config-2.6.22-i686-smp</filename>).</para>
|
||||
@@ -127,9 +137,22 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
kernel modules and kernel-dependent packages listed in the
|
||||
<varname>kernelPackagesFor</varname> function in
|
||||
<filename>all-packages.nix</filename> (such as the NVIDIA drivers,
|
||||
AUFS, etc.). If the updated packages aren’t backwards compatible
|
||||
with older kernels, you may need to keep the older versions
|
||||
around.</para>
|
||||
AUFS, splashutils, etc.). If the updated packages aren’t
|
||||
backwards compatible with older kernels, you need to keep the
|
||||
older versions and use some conditionals. For example, new
|
||||
kernels require splashutils 1.5 while old kernel require 1.3, so
|
||||
<varname>kernelPackagesFor</varname> says:
|
||||
|
||||
<programlisting>
|
||||
splashutils =
|
||||
if kernel.features ? fbSplash then splashutils_13 else
|
||||
if kernel.features ? fbConDecor then splashutils_15 else
|
||||
null;
|
||||
|
||||
splashutils_13 = ...;
|
||||
splashutils_15 = ...;</programlisting>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</orderedlist>
|
||||
@@ -141,7 +164,7 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-xorg">
|
||||
<section>
|
||||
|
||||
<title>X.org</title>
|
||||
|
||||
@@ -201,169 +224,19 @@ you should modify
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<!--
|
||||
<section>
|
||||
<title>Gnome</title>
|
||||
<para>* Expression is auto-generated</para>
|
||||
<para>* How to update</para>
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<!--
|
||||
<section>
|
||||
<title>GCC</title>
|
||||
<para>…</para>
|
||||
</section>
|
||||
-->
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-eclipse">
|
||||
|
||||
<title>Eclipse</title>
|
||||
|
||||
<para>
|
||||
The Nix expressions related to the Eclipse platform and IDE are in
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/eclipse"><filename>pkgs/applications/editors/eclipse</filename></link>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Nixpkgs provides a number of packages that will install Eclipse in
|
||||
its various forms, these range from the bare-bones Eclipse
|
||||
Platform to the more fully featured Eclipse SDK or Scala-IDE
|
||||
packages and multiple version are often available. It is possible
|
||||
to list available Eclipse packages by issuing the command:
|
||||
|
||||
<screen>
|
||||
$ nix-env -f '<nixpkgs>' -qaP -A eclipses --description
|
||||
</screen>
|
||||
|
||||
Once an Eclipse variant is installed it can be run using the
|
||||
<command>eclipse</command> command, as expected. From within
|
||||
Eclipse it is then possible to install plugins in the usual manner
|
||||
by either manually specifying an Eclipse update site or by
|
||||
installing the Marketplace Client plugin and using it to discover
|
||||
and install other plugins. This installation method provides an
|
||||
Eclipse installation that closely resemble a manually installed
|
||||
Eclipse.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you prefer to install plugins in a more declarative manner then
|
||||
Nixpkgs also offer a number of Eclipse plugins that can be
|
||||
installed in an <emphasis>Eclipse environment</emphasis>. This
|
||||
type of environment is created using the function
|
||||
<varname>eclipseWithPlugins</varname> found inside the
|
||||
<varname>nixpkgs.eclipses</varname> attribute set. This function
|
||||
takes as argument <literal>{ eclipse, plugins ? [], jvmArgs ? []
|
||||
}</literal> where <varname>eclipse</varname> is a one of the
|
||||
Eclipse packages described above, <varname>plugins</varname> is a
|
||||
list of plugin derivations, and <varname>jvmArgs</varname> is a
|
||||
list of arguments given to the JVM running the Eclipse. For
|
||||
example, say you wish to install the latest Eclipse Platform with
|
||||
the popular Eclipse Color Theme plugin and also allow Eclipse to
|
||||
use more RAM. You could then add
|
||||
|
||||
<screen>
|
||||
packageOverrides = pkgs: {
|
||||
myEclipse = with pkgs.eclipses; eclipseWithPlugins {
|
||||
eclipse = eclipse-platform;
|
||||
jvmArgs = [ "-Xmx2048m" ];
|
||||
plugins = [ plugins.color-theme ];
|
||||
};
|
||||
}
|
||||
</screen>
|
||||
|
||||
to your Nixpkgs configuration
|
||||
(<filename>~/.nixpkgs/config.nix</filename>) and install it by
|
||||
running <command>nix-env -f '<nixpkgs>' -iA
|
||||
myEclipse</command> and afterward run Eclipse as usual. It is
|
||||
possible to find out which plugins are available for installation
|
||||
using <varname>eclipseWithPlugins</varname> by running
|
||||
|
||||
<screen>
|
||||
$ nix-env -f '<nixpkgs>' -qaP -A eclipses.plugins --description
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If there is a need to install plugins that are not available in
|
||||
Nixpkgs then it may be possible to define these plugins outside
|
||||
Nixpkgs using the <varname>buildEclipseUpdateSite</varname> and
|
||||
<varname>buildEclipsePlugin</varname> functions found in the
|
||||
<varname>nixpkgs.eclipses.plugins</varname> attribute set. Use the
|
||||
<varname>buildEclipseUpdateSite</varname> function to install a
|
||||
plugin distributed as an Eclipse update site. This function takes
|
||||
<literal>{ name, src }</literal> as argument where
|
||||
<literal>src</literal> indicates the Eclipse update site archive.
|
||||
All Eclipse features and plugins within the downloaded update site
|
||||
will be installed. When an update site archive is not available
|
||||
then the <varname>buildEclipsePlugin</varname> function can be
|
||||
used to install a plugin that consists of a pair of feature and
|
||||
plugin JARs. This function takes an argument <literal>{ name,
|
||||
srcFeature, srcPlugin }</literal> where
|
||||
<literal>srcFeature</literal> and <literal>srcPlugin</literal> are
|
||||
the feature and plugin JARs, respectively.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Expanding the previous example with two plugins using the above
|
||||
functions we have
|
||||
<screen>
|
||||
packageOverrides = pkgs: {
|
||||
myEclipse = with pkgs.eclipses; eclipseWithPlugins {
|
||||
eclipse = eclipse-platform;
|
||||
jvmArgs = [ "-Xmx2048m" ];
|
||||
plugins = [
|
||||
plugins.color-theme
|
||||
(plugins.buildEclipsePlugin {
|
||||
name = "myplugin1-1.0";
|
||||
srcFeature = fetchurl {
|
||||
url = "http://…/features/myplugin1.jar";
|
||||
sha256 = "123…";
|
||||
};
|
||||
srcPlugin = fetchurl {
|
||||
url = "http://…/plugins/myplugin1.jar";
|
||||
sha256 = "123…";
|
||||
};
|
||||
});
|
||||
(plugins.buildEclipseUpdateSite {
|
||||
name = "myplugin2-1.0";
|
||||
src = fetchurl {
|
||||
stripRoot = false;
|
||||
url = "http://…/myplugin2.zip";
|
||||
sha256 = "123…";
|
||||
};
|
||||
});
|
||||
];
|
||||
};
|
||||
}
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-elm">
|
||||
|
||||
<title>Elm</title>
|
||||
|
||||
<para>
|
||||
The Nix expressions for Elm reside in
|
||||
<filename>pkgs/development/compilers/elm</filename>. They are generated
|
||||
automatically by <command>update-elm.rb</command> script. One should
|
||||
specify versions of Elm packages inside the script, clear the
|
||||
<filename>packages</filename> directory and run the script from inside it.
|
||||
<literal>elm-reactor</literal> is special because it also has Elm package
|
||||
dependencies. The process is not automated very much for now -- you should
|
||||
get the <literal>elm-reactor</literal> source tree (e.g. with
|
||||
<command>nix-shell</command>) and run <command>elm2nix.rb</command> inside
|
||||
it. Place the resulting <filename>package.nix</filename> file into
|
||||
<filename>packages/elm-reactor-elm.nix</filename>.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-packageconfig">
|
||||
|
||||
<title><filename>~/.nixpkgs/config.nix</filename>: global configuration</title>
|
||||
|
||||
<para>
|
||||
Nix packages can be configured to allow or deny certain options.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To apply the configuration edit <filename>~/.nixpkgs/config.nix</filename>
|
||||
and set it like
|
||||
<programlisting>{
|
||||
allowUnfree = true;
|
||||
}</programlisting>
|
||||
and will allow the Nix package manager to install unfree licensed packages.
|
||||
|
||||
The configuration as listed also applies to NixOS under <option>nixpkgs.config</option> set.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Allow installing of packages that are distributed under unfree license by setting
|
||||
<programlisting>allowUnfree = true;</programlisting>
|
||||
or deny them by setting it to <literal>false</literal>.
|
||||
</para>
|
||||
<para>
|
||||
Same can be achieved by setting the environment variable:
|
||||
<programlisting>$ export NIXPKGS_ALLOW_UNFREE=1</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Whenever unfree packages are not allowed, single packages can
|
||||
still be allowed by a predicate function that accepts package
|
||||
as an argument and should return a boolean:
|
||||
<programlisting>allowUnfreePredicate = (pkg: ...);</programlisting>
|
||||
|
||||
Example to allow flash player only:
|
||||
<programlisting>allowUnfreePredicate = (pkg: pkgs.lib.hasPrefix "flashplayer-" pkg.name);</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Whenever unfree packages are not allowed, packages can still be
|
||||
whitelisted by their license:
|
||||
<programlisting>whitelistedLicenses = with stdenv.lib.licenses; [ amd wtfpl ];</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
In addition to whitelisting licenses which are denied by the
|
||||
<literal>allowUnfree</literal> setting, you can also explicitely
|
||||
deny installation of packages which have a certain license:
|
||||
<programlisting>blacklistedLicenses = with stdenv.lib.licenses; [ agpl3 gpl3 ];</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
A complete list of licenses can be found in the file
|
||||
<filename>lib/licenses.nix</filename> of the nix package tree.
|
||||
</para>
|
||||
|
||||
<section xml:id="sec-modify-via-packageOverrides"><title>Modify
|
||||
packages via <literal>packageOverrides</literal></title>
|
||||
|
||||
<para>
|
||||
|
||||
You can define a function called <varname>packageOverrides</varname>
|
||||
in your local <filename>~/.nixpkgs/config</filename> to overide nix
|
||||
packages. It must be a function that takes pkgs as an argument and
|
||||
return modified set of packages.
|
||||
|
||||
<programlisting>{
|
||||
packageOverrides = pkgs: rec {
|
||||
foo = pkgs.foo.override { ... };
|
||||
};
|
||||
}</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -12,7 +12,7 @@
|
||||
<para>Checkout the Nixpkgs source tree:
|
||||
|
||||
<screen>
|
||||
$ git clone git://github.com/NixOS/nixpkgs.git
|
||||
$ svn checkout https://svn.nixos.org/repos/nix/nixpkgs/trunk nixpkgs
|
||||
$ cd nixpkgs</screen>
|
||||
|
||||
</para>
|
||||
@@ -29,7 +29,7 @@ $ cd nixpkgs</screen>
|
||||
organisation. Create a directory for your package, e.g.
|
||||
|
||||
<screen>
|
||||
$ mkdir pkgs/development/libraries/libfoo</screen>
|
||||
$ svn mkdir pkgs/development/libraries/libfoo</screen>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
@@ -44,7 +44,7 @@ $ mkdir pkgs/development/libraries/libfoo</screen>
|
||||
|
||||
<screen>
|
||||
$ emacs pkgs/development/libraries/libfoo/default.nix
|
||||
$ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
$ svn add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
|
||||
</para>
|
||||
|
||||
@@ -54,31 +54,31 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>GNU Hello: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/hello/ex-2/default.nix"><filename>pkgs/applications/misc/hello/ex-2/default.nix</filename></link>.
|
||||
Trivial package, which specifies some <varname>meta</varname>
|
||||
attributes which is good practice.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>GNU cpio: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/archivers/cpio/default.nix"><filename>pkgs/tools/archivers/cpio/default.nix</filename></link>.
|
||||
Also a simple package. The generic builder in
|
||||
<varname>stdenv</varname> does everything for you. It has
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/tools/archivers/cpio/default.nix"><filename>pkgs/tools/archivers/cpio/default.nix</filename></link>.
|
||||
The simplest possible package. The generic builder in
|
||||
<varname>stdenv</varname> does everything for you. It has
|
||||
no dependencies beyond <varname>stdenv</varname>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>GNU Hello: <link
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/applications/misc/hello/ex-2/default.nix"><filename>pkgs/applications/misc/hello/ex-2/default.nix</filename></link>.
|
||||
Also trivial, but it specifies some <varname>meta</varname>
|
||||
attributes which is good practice.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>GNU Multiple Precision arithmetic library (GMP): <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/gmp/5.1.x.nix"><filename>pkgs/development/libraries/gmp/5.1.x.nix</filename></link>.
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/development/libraries/gmp/default.nix"><filename>pkgs/development/libraries/gmp/default.nix</filename></link>.
|
||||
Also done by the generic builder, but has a dependency on
|
||||
<varname>m4</varname>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Pan, a GTK-based newsreader: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/newsreaders/pan/default.nix"><filename>pkgs/applications/networking/newsreaders/pan/default.nix</filename></link>.
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/applications/networking/newsreaders/pan/default.nix"><filename>pkgs/applications/networking/newsreaders/pan/default.nix</filename></link>.
|
||||
Has an optional dependency on <varname>gtkspell</varname>,
|
||||
which is only built if <varname>spellCheck</varname> is
|
||||
<literal>true</literal>.</para>
|
||||
@@ -86,30 +86,41 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
|
||||
<listitem>
|
||||
<para>Apache HTTPD: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/http/apache-httpd/2.4.nix"><filename>pkgs/servers/http/apache-httpd/2.4.nix</filename></link>.
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/servers/http/apache-httpd/default.nix"><filename>pkgs/servers/http/apache-httpd/default.nix</filename></link>.
|
||||
A bunch of optional features, variable substitutions in the
|
||||
configure flags, a post-install hook, and miscellaneous
|
||||
hackery.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>BitTorrent (wxPython-based): <link
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/tools/networking/p2p/bittorrent/default.nix"><filename>pkgs/tools/networking/p2p/bittorrent/default.nix</filename></link>.
|
||||
Uses an external <link
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/tools/networking/p2p/bittorrent/builder.sh">build
|
||||
script</link>, which can be useful if you have lots of code
|
||||
that you don’t want cluttering up the Nix expression. But
|
||||
external builders are mostly obsolete.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Thunderbird: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/mailreaders/thunderbird/default.nix"><filename>pkgs/applications/networking/mailreaders/thunderbird/default.nix</filename></link>.
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix"><filename>pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix</filename></link>.
|
||||
Lots of dependencies.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>JDiskReport, a Java utility: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/misc/jdiskreport/default.nix"><filename>pkgs/tools/misc/jdiskreport/default.nix</filename></link>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/tools/misc/jdiskreport/default.nix"><filename>pkgs/tools/misc/jdiskreport/default.nix</filename></link>
|
||||
(and the <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/misc/jdiskreport/builder.sh">builder</link>).
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/tools/misc/jdiskreport/builder.sh">builder</link>).
|
||||
Nixpkgs doesn’t have a decent <varname>stdenv</varname> for
|
||||
Java yet so this is pretty ad-hoc.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>XML::Simple, a Perl module: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>
|
||||
(search for the <varname>XMLSimple</varname> attribute).
|
||||
Most Perl modules are so simple to build that they are
|
||||
defined directly in <filename>perl-packages.nix</filename>;
|
||||
@@ -118,10 +129,10 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
|
||||
<listitem>
|
||||
<para>Adobe Reader: <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/adobe-reader/default.nix"><filename>pkgs/applications/misc/adobe-reader/default.nix</filename></link>.
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/applications/misc/adobe-reader/default.nix"><filename>pkgs/applications/misc/adobe-reader/default.nix</filename></link>.
|
||||
Shows how binary-only packages can be supported. In
|
||||
particular the <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/adobe-reader/builder.sh">builder</link>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/applications/misc/adobe-reader/builder.sh">builder</link>
|
||||
uses <command>patchelf</command> to set the RUNPATH and ELF
|
||||
interpreter of the executables so that the right libraries
|
||||
are found at runtime.</para>
|
||||
@@ -144,16 +155,15 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>You can use <command>nix-prefetch-url</command> (or similar nix-prefetch-git, etc)
|
||||
<para>You can use <command>nix-prefetch-url</command>
|
||||
<replaceable>url</replaceable> to get the SHA-256 hash of
|
||||
source distributions. There are similar commands as <command>nix-prefetch-git</command> and
|
||||
<command>nix-prefetch-hg</command> available in <literal>nix-prefetch-scripts</literal> package.</para>
|
||||
source distributions.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>A list of schemes for <literal>mirror://</literal>
|
||||
URLs can be found in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/fetchurl/mirrors.nix"><filename>pkgs/build-support/fetchurl/mirrors.nix</filename></link>.</para>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/build-support/fetchurl/mirrors.nix"><filename>pkgs/build-support/fetchurl/mirrors.nix</filename></link>.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
@@ -163,7 +173,7 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
<para>The exact syntax and semantics of the Nix expression
|
||||
language, including the built-in function, are described in the
|
||||
Nix manual in the <link
|
||||
xlink:href="http://hydra.nixos.org/job/nix/trunk/tarball/latest/download-by-type/doc/manual/#chap-writing-nix-expressions">chapter
|
||||
xlink:href="http://nixos.org/releases/nix/unstable/manual/#chap-writing-nix-expressions">chapter
|
||||
on writing Nix expressions</link>.</para>
|
||||
|
||||
</listitem>
|
||||
@@ -171,7 +181,7 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
<listitem>
|
||||
<para>Add a call to the function defined in the previous step to
|
||||
<link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/all-packages.nix"><filename>pkgs/top-level/all-packages.nix</filename></link>
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/top-level/all-packages.nix"><filename>pkgs/top-level/all-packages.nix</filename></link>
|
||||
with some descriptive name for the variable,
|
||||
e.g. <varname>libfoo</varname>.
|
||||
|
||||
@@ -186,8 +196,7 @@ $ emacs pkgs/top-level/all-packages.nix</screen>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>To test whether the package builds, run the following command
|
||||
from the root of the nixpkgs source tree:
|
||||
<para>Test whether the package builds:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A libfoo</screen>
|
||||
@@ -211,10 +220,18 @@ $ nix-env -f . -iA libfoo</screen>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Optionally commit the new package and open a pull request, or send a patch to
|
||||
<para>Optionally commit the new package (<command>svn
|
||||
ci</command>) or send a patch to
|
||||
<literal>nix-dev@cs.uu.nl</literal>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you want the TU Delft build farm to build binaries of the
|
||||
package and make them available in the <link
|
||||
xlink:href="http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable/"><literal>nixpkgs</literal>
|
||||
channel</link>, add it to <link
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/top-level/release.nix"><filename>pkgs/top-level/release.nix</filename></link>.</para>
|
||||
</listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
|
||||
44
doc/quote-literals.xsl
Normal file
44
doc/quote-literals.xsl
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xsl:stylesheet
|
||||
version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:str="http://exslt.org/strings"
|
||||
extension-element-prefixes="str">
|
||||
|
||||
<xsl:output method="xml"/>
|
||||
|
||||
<xsl:template match="function|command|literal|varname|filename|option|quote">`<xsl:apply-templates/>'</xsl:template>
|
||||
|
||||
<xsl:template match="token"><xsl:text> </xsl:text><xsl:apply-templates /><xsl:text>
|
||||
</xsl:text></xsl:template>
|
||||
|
||||
<xsl:template match="screen|programlisting">
|
||||
<screen><xsl:apply-templates select="str:split(., '
')" /></screen>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="section[following::section]">
|
||||
<section>
|
||||
<xsl:apply-templates />
|
||||
<screen><xsl:text>
|
||||
</xsl:text></screen>
|
||||
</section>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*">
|
||||
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
|
||||
<xsl:copy-of select="namespace::*" />
|
||||
<xsl:for-each select="@*">
|
||||
<xsl:attribute name="{name(.)}" namespace="{namespace-uri(.)}">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:attribute>
|
||||
</xsl:for-each>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="text()">
|
||||
<xsl:value-of select="translate(., '‘’“”—', concat("`'", '""-'))" />
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -5,21 +5,6 @@
|
||||
<title>Nixpkgs Release Notes</title>
|
||||
|
||||
|
||||
<section><title>Release 0.14 (June 4, 2012)</title>
|
||||
|
||||
<para>In preparation for the switch from Subversion to Git, this
|
||||
release is mainly the prevent the Nixpkgs version number from going
|
||||
backwards. (This would happen because prerelease version numbers
|
||||
produced for the Git repository are lower than those for the
|
||||
Subversion repository.)</para>
|
||||
|
||||
<para>Since the last release, there have been thousands of changes and
|
||||
new packages by numerous contributors. For details, see the commit
|
||||
logs.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Release 0.13 (February 5, 2010)</title>
|
||||
|
||||
<para>As always, there are many changes. Some of the most important
|
||||
@@ -95,7 +80,7 @@ worth listing:
|
||||
<listitem><para>Support for building derivations in a virtual
|
||||
machine, including RPM and Debian builds in automatically generated
|
||||
VM images. See
|
||||
<filename>pkgs/build-support/vm/default.nix</filename> for
|
||||
<filename>pkgs/build-support/vm.default.nix</filename> for
|
||||
details.</para></listitem>
|
||||
|
||||
<listitem><para>Improved support for building Haskell
|
||||
@@ -237,12 +222,12 @@ fetchurl {
|
||||
|
||||
<function>fetchurl</function> will first try to download this file
|
||||
from <link
|
||||
xlink:href="http://tarballs.nixos.org/sha1/eb72f55e4a8bf08e8c6ef227c0ade3d068ba1082"/>.
|
||||
xlink:href="http://nixos.org/tarballs/sha1/eb72f55e4a8bf08e8c6ef227c0ade3d068ba1082"/>.
|
||||
If that file doesn’t exist, it will try the original URL. In
|
||||
general, the “content-addressed” location is
|
||||
<replaceable>mirror</replaceable><literal>/</literal><replaceable>hash-type</replaceable><literal>/</literal><replaceable>hash</replaceable>.
|
||||
There is currently only one content-addressable mirror (<link
|
||||
xlink:href="http://tarballs.nixos.org"/>), but more can be
|
||||
xlink:href="http://nixos.org/tarballs"/>), but more can be
|
||||
specified in the <varname>hashedMirrors</varname> attribute in
|
||||
<filename>pkgs/build-support/fetchurl/mirrors.nix</filename>, or by
|
||||
setting the <envar>NIX_HASHED_MIRRORS</envar> environment variable
|
||||
@@ -446,7 +431,7 @@ xlink:href='http://nixos.org/releases/nix/nix-0.10/'>Nix
|
||||
<literal>stdenv</literal>; the formed changes the C compiler, and
|
||||
the latter adds additional packages to the front of
|
||||
<literal>stdenv</literal>’s initial <envar>PATH</envar>, allowing
|
||||
tools to be overridden.</para>
|
||||
tools to be overriden.</para>
|
||||
|
||||
<para>For instance, the package <varname>strategoxt</varname>
|
||||
doesn’t build with the GNU Make in <literal>stdenv</literal>
|
||||
|
||||
142
doc/stdenv.xml
142
doc/stdenv.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
<para>The standard build environment in the Nix Packages collection
|
||||
provides an environment for building Unix packages that does a lot of
|
||||
provides a environment for building Unix packages that does a lot of
|
||||
common build tasks automatically. In fact, for Unix packages that use
|
||||
the standard <literal>./configure; make; make install</literal> build
|
||||
interface, you don’t need to write a build script at all; the standard
|
||||
@@ -15,8 +15,7 @@ environment does everything automatically. If
|
||||
can easily customise or override the various build phases.</para>
|
||||
|
||||
|
||||
<section xml:id="sec-using-stdenv"><title>Using
|
||||
<literal>stdenv</literal></title>
|
||||
<section><title>Using <literal>stdenv</literal></title>
|
||||
|
||||
<para>To build a package with the standard environment, you use the
|
||||
function <varname>stdenv.mkDerivation</varname>, instead of the
|
||||
@@ -57,9 +56,9 @@ details.)</para>
|
||||
<para>Often it is necessary to override or modify some aspect of the
|
||||
build. To make this easier, the standard environment breaks the
|
||||
package build into a number of <emphasis>phases</emphasis>, all of
|
||||
which can be overridden or modified individually: unpacking the
|
||||
which can be overriden or modified individually: unpacking the
|
||||
sources, applying patches, configuring, building, and installing.
|
||||
(There are some others; see <xref linkend="sec-stdenv-phases"/>.)
|
||||
(There are some others; see <xref linkend="ssec-stdenv-phases"/>.)
|
||||
For instance, a package that doesn’t supply a makefile but instead has
|
||||
to be compiled “manually” could be handled like this:
|
||||
|
||||
@@ -71,7 +70,7 @@ stdenv.mkDerivation {
|
||||
gcc foo.c -o foo
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
ensureDir $out/bin
|
||||
cp foo $out/bin
|
||||
'';
|
||||
}</programlisting>
|
||||
@@ -113,7 +112,7 @@ buildPhase() {
|
||||
}
|
||||
|
||||
installPhase() {
|
||||
mkdir -p $out/bin
|
||||
ensureDir $out/bin
|
||||
cp foo $out/bin
|
||||
}
|
||||
|
||||
@@ -125,8 +124,7 @@ genericBuild
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-tools-of-stdenv"><title>Tools provided by
|
||||
<literal>stdenv</literal></title>
|
||||
<section><title>Tools provided by <literal>stdenv</literal></title>
|
||||
|
||||
<para>The standard environment provides the following packages:
|
||||
|
||||
@@ -152,8 +150,8 @@ genericBuild
|
||||
|
||||
<listitem><para>GNU <command>tar</command>.</para></listitem>
|
||||
|
||||
<listitem><para><command>gzip</command>, <command>bzip2</command>
|
||||
and <command>xz</command>.</para></listitem>
|
||||
<listitem><para><command>gzip</command> and
|
||||
<command>bzip2</command>.</para></listitem>
|
||||
|
||||
<listitem><para>GNU Make. It has been patched to provide
|
||||
<quote>nested</quote> output that can be fed into the
|
||||
@@ -227,7 +225,7 @@ genericBuild
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-stdenv-phases"><title>Phases</title>
|
||||
<section xml:id="ssec-stdenv-phases"><title>Phases</title>
|
||||
|
||||
<para>The generic builder has a number of <emphasis>phases</emphasis>.
|
||||
Package builds are split into phases to make it easier to override
|
||||
@@ -235,7 +233,7 @@ specific parts of the build (e.g., unpacking the sources or installing
|
||||
the binaries). Furthermore, it allows a nicer presentation of build
|
||||
logs in the Nix build farm.</para>
|
||||
|
||||
<para>Each phase can be overridden in its entirety either by setting
|
||||
<para>Each phase can be overriden in its entirety either by setting
|
||||
the environment variable
|
||||
<varname><replaceable>name</replaceable>Phase</varname> to a string
|
||||
containing some shell commands to be executed, or by redefining the
|
||||
@@ -245,8 +243,7 @@ is convenient to override a phase from the derivation, while the
|
||||
latter is convenient from a build script.</para>
|
||||
|
||||
|
||||
<section xml:id="ssec-controlling-phases"><title>Controlling
|
||||
phases</title>
|
||||
<section><title>Controlling phases</title>
|
||||
|
||||
<para>There are a number of variables that control what phases are
|
||||
executed and in what order:
|
||||
@@ -301,13 +298,6 @@ executed and in what order:
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>preFixupPhases</varname></term>
|
||||
<listitem>
|
||||
<para>Additional phases executed just before the fixup phase.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>preDistPhases</varname></term>
|
||||
<listitem>
|
||||
@@ -330,7 +320,7 @@ executed and in what order:
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-unpack-phase"><title>The unpack phase</title>
|
||||
<section><title>The unpack phase</title>
|
||||
|
||||
<para>The unpack phase is responsible for unpacking the source code of
|
||||
the package. The default implementation of
|
||||
@@ -344,11 +334,9 @@ It supports the following files by default:
|
||||
<term>Tar files</term>
|
||||
<listitem><para>These can optionally be compressed using
|
||||
<command>gzip</command> (<filename>.tar.gz</filename>,
|
||||
<filename>.tgz</filename> or <filename>.tar.Z</filename>),
|
||||
<filename>.tgz</filename> or <filename>.tar.Z</filename>) or
|
||||
<command>bzip2</command> (<filename>.tar.bz2</filename> or
|
||||
<filename>.tbz2</filename>) or <command>xz</command>
|
||||
(<filename>.tar.xz</filename> or
|
||||
<filename>.tar.lzma</filename>).</para></listitem>
|
||||
<filename>.tbz2</filename>).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -437,7 +425,7 @@ Additional file types can be supported by setting the
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-patch-phase"><title>The patch phase</title>
|
||||
<section><title>The patch phase</title>
|
||||
|
||||
<para>The patch phase applies the list of patches defined in the
|
||||
<varname>patches</varname> variable.</para>
|
||||
@@ -450,10 +438,9 @@ Additional file types can be supported by setting the
|
||||
<listitem><para>The list of patches. They must be in the format
|
||||
accepted by the <command>patch</command> command, and may
|
||||
optionally be compressed using <command>gzip</command>
|
||||
(<filename>.gz</filename>), <command>bzip2</command>
|
||||
(<filename>.bz2</filename>) or <command>xz</command>
|
||||
(<filename>.xz</filename>).</para></listitem>
|
||||
</varlistentry>
|
||||
(<filename>.gz</filename>) or <command>bzip2</command>
|
||||
(<filename>.bz2</filename>).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>patchFlags</varname></term>
|
||||
@@ -480,7 +467,7 @@ Additional file types can be supported by setting the
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-configure-phase"><title>The configure phase</title>
|
||||
<section><title>The configure phase</title>
|
||||
|
||||
<para>The configure phase prepares the source tree for building. The
|
||||
default <function>configurePhase</function> runs
|
||||
@@ -516,8 +503,8 @@ script) if it exists.</para>
|
||||
<term><varname>dontAddPrefix</varname></term>
|
||||
<listitem><para>By default, the flag
|
||||
<literal>--prefix=$prefix</literal> is added to the configure
|
||||
flags. If this is undesirable, set this variable to
|
||||
true.</para></listitem>
|
||||
flags. If this is undesirable, set this variable to a non-empty
|
||||
value.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -533,7 +520,8 @@ script) if it exists.</para>
|
||||
<listitem><para>By default, the flag
|
||||
<literal>--disable-dependency-tracking</literal> is added to the
|
||||
configure flags to speed up Automake-based builds. If this is
|
||||
undesirable, set this variable to true.</para></listitem>
|
||||
undesirable, set this variable to a non-empty
|
||||
value.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -546,16 +534,7 @@ script) if it exists.</para>
|
||||
variables in the Libtool script to prevent Libtool from using
|
||||
libraries in <filename>/usr/lib</filename> and
|
||||
such.</para></footnote>. If this is undesirable, set this
|
||||
variable to true.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontDisableStatic</varname></term>
|
||||
<listitem><para>By default, when the configure script has
|
||||
<option>--enable-static</option>, the option
|
||||
<option>--disable-static</option> is added to the configure flags.</para>
|
||||
<para>If this is undesirable, set this variable to
|
||||
true.</para></listitem>
|
||||
variable to a non-empty value.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -576,7 +555,7 @@ script) if it exists.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="build-phase"><title>The build phase</title>
|
||||
<section><title>The build phase</title>
|
||||
|
||||
<para>The build phase is responsible for actually building the package
|
||||
(e.g. compiling it). The default <function>buildPhase</function>
|
||||
@@ -589,11 +568,6 @@ nothing.</para>
|
||||
<variablelist>
|
||||
<title>Variables controlling the build phase</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontBuild</varname></term>
|
||||
<listitem><para>Set to true to skip the build phase.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>makefile</varname></term>
|
||||
<listitem><para>The file name of the Makefile.</para></listitem>
|
||||
@@ -660,7 +634,7 @@ called, respectively.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-check-phase"><title>The check phase</title>
|
||||
<section><title>The check phase</title>
|
||||
|
||||
<para>The check phase checks whether the package was built correctly
|
||||
by running its test suite. The default
|
||||
@@ -720,7 +694,7 @@ doCheck = true;</programlisting>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-install-phase"><title>The install phase</title>
|
||||
<section><title>The install phase</title>
|
||||
|
||||
<para>The install phase is responsible for installing the package in
|
||||
the Nix store under <envar>out</envar>. The default
|
||||
@@ -729,7 +703,7 @@ the Nix store under <envar>out</envar>. The default
|
||||
install</command>.</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables controlling the install phase</title>
|
||||
<title>Variables controlling the check phase</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>makeFlags</varname> /
|
||||
@@ -775,7 +749,7 @@ installTargets = "install-bin install-doc";</programlisting>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-fixup-phase"><title>The fixup phase</title>
|
||||
<section><title>The fixup phase</title>
|
||||
|
||||
<para>The fixup phase performs some (Nix-specific) post-processing
|
||||
actions on the files installed under <filename>$out</filename> by the
|
||||
@@ -808,7 +782,7 @@ following:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables controlling the fixup phase</title>
|
||||
<title>Variables controlling the check phase</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontStrip</varname></term>
|
||||
@@ -816,12 +790,6 @@ following:
|
||||
stripped. By default, they are.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>dontMoveSbin</varname></term>
|
||||
<listitem><para>If set, files in <filename>$out/sbin</filename> are not moved
|
||||
to <filename>$out/bin</filename>. By default, they are.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>stripAllList</varname></term>
|
||||
<listitem><para>List of directories to search for libraries and
|
||||
@@ -904,15 +872,14 @@ following:
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-distribution-phase"><title>The distribution
|
||||
phase</title>
|
||||
<section><title>The distribution phase</title>
|
||||
|
||||
<para>The distribution phase is intended to produce a source
|
||||
distribution of the package. The default
|
||||
<function>distPhase</function> first calls <command>make
|
||||
dist</command>, then it copies the resulting source tarballs to
|
||||
<filename>$out/tarballs/</filename>. This phase is only executed if
|
||||
the attribute <varname>doDist</varname> is set.</para>
|
||||
the attribute <varname>doDist</varname> is not set.</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables controlling the distribution phase</title>
|
||||
@@ -972,6 +939,14 @@ functions.</para>
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry xml:id='fun-ensureDir'>
|
||||
<term><function>ensureDir</function> <replaceable>args</replaceable></term>
|
||||
<listitem><para>Creates the specified directories, including all
|
||||
necessary parent directories, if they do not already
|
||||
exist.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id='fun-substitute'>
|
||||
<term><function>substitute</function>
|
||||
<replaceable>infile</replaceable>
|
||||
@@ -1087,16 +1062,7 @@ echo @foo@
|
||||
That is, no substitution is performed for undefined variables.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id='fun-substituteAllInPlace'>
|
||||
<term><function>substituteAllInPlace</function>
|
||||
<replaceable>file</replaceable></term>
|
||||
<listitem><para>Like <function>substituteAll</function>, but performs
|
||||
the substitutions in place on the file
|
||||
<replaceable>file</replaceable>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
|
||||
<varlistentry xml:id='fun-stripHash'>
|
||||
<term><function>stripHash</function>
|
||||
<replaceable>path</replaceable></term>
|
||||
@@ -1138,9 +1104,12 @@ echo @foo@
|
||||
<varlistentry>
|
||||
<term>Python</term>
|
||||
<listitem><para>Adds the
|
||||
<filename>lib/${python.libPrefix}/site-packages</filename> subdirectory of
|
||||
<filename>lib/python2.5/site-packages</filename> subdirectory of
|
||||
each build input to the <envar>PYTHONPATH</envar> environment
|
||||
variable.</para></listitem>
|
||||
variable.</para>
|
||||
|
||||
<note><para>This should be generalised: the Python version
|
||||
shouldn’t be hard-coded.</para></note></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -1181,27 +1150,12 @@ echo @foo@
|
||||
to Qt’s path.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>gdk-pixbuf</term>
|
||||
<listitem><para>Exports <envar>GDK_PIXBUF_MODULE_FILE</envar>
|
||||
environment variable the the builder. Add librsvg package
|
||||
to <varname>buildInputs</varname> to get svg support.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>GHC</term>
|
||||
<listitem><para>Creates a temporary package database and registers
|
||||
every Haskell build input in it (TODO: how?).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>GStreamer</term>
|
||||
<listitem><para>Adds the
|
||||
GStreamer plugins subdirectory of
|
||||
each build input to the <envar>GST_PLUGIN_SYSTEM_PATH_1_0</envar> or
|
||||
<envar>GST_PLUGIN_SYSTEM_PATH</envar> environment variable.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
@@ -1209,7 +1163,7 @@ echo @foo@
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-purity-in-nixpkgs"><title>Purity in Nixpkgs</title>
|
||||
<section><title>Purity in Nixpkgs</title>
|
||||
|
||||
<para>[measures taken to prevent dependencies on packages outside the
|
||||
store, and what you can do to prevent them]</para>
|
||||
|
||||
116
doc/style.css
116
doc/style.css
@@ -8,14 +8,15 @@
|
||||
|
||||
body
|
||||
{
|
||||
font-family: "Nimbus Sans L", sans-serif;
|
||||
font-family: sans-serif;
|
||||
background: white;
|
||||
margin: 2em 1em 2em 1em;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4
|
||||
h1,h2,h3
|
||||
{
|
||||
color: #005aa0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 /* title */
|
||||
@@ -45,11 +46,6 @@ h3 /* subsections */
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
div.simplesect h2
|
||||
{
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
div.appendix h3
|
||||
{
|
||||
font-size: 150%;
|
||||
@@ -74,13 +70,11 @@ div.refsection h3
|
||||
|
||||
div.example
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
border: 1px solid #6185a0;
|
||||
padding: 6px 6px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
background: #f4f4f8;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.example p.title
|
||||
@@ -88,11 +82,6 @@ div.example p.title
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
div.example pre
|
||||
{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Screen dumps:
|
||||
@@ -100,15 +89,14 @@ div.example pre
|
||||
|
||||
pre.screen, pre.programlisting
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
border: 1px solid #6185a0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
color: #600000;
|
||||
background: #f4f4f8;
|
||||
font-family: monospace;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
/* font-size: 90%; */
|
||||
}
|
||||
|
||||
div.example pre.programlisting
|
||||
@@ -125,15 +113,13 @@ div.example pre.programlisting
|
||||
|
||||
.note, .warning
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
border: 1px solid #6185a0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.3em 0.3em 0.3em 0.3em;
|
||||
background: #fffff5;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.note, div.warning
|
||||
@@ -145,6 +131,7 @@ div.note h3, div.warning h3
|
||||
{
|
||||
color: red;
|
||||
font-size: 100%;
|
||||
// margin: 0 0 0 0;
|
||||
padding-right: 0.5em;
|
||||
display: inline;
|
||||
}
|
||||
@@ -175,26 +162,20 @@ div.navfooter *
|
||||
Links colors and highlighting:
|
||||
***************************************************************************/
|
||||
|
||||
a { text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
a:link { color: #0048b3; }
|
||||
a:visited { color: #002a6a; }
|
||||
a:hover { background: #ffffcd; }
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Table of contents:
|
||||
***************************************************************************/
|
||||
|
||||
div.toc
|
||||
.toc
|
||||
{
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.toc dl
|
||||
{
|
||||
margin-top: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
@@ -227,29 +208,76 @@ div.glosslist dt
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.default
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.availability
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.varname
|
||||
{
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
span.command strong
|
||||
|
||||
div.informaltable table
|
||||
{
|
||||
font-weight: normal;
|
||||
border: 1px solid #6185a0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.informaltable td
|
||||
{
|
||||
border: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
div.informaltable td.default
|
||||
{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.informaltable th
|
||||
{
|
||||
text-align: left;
|
||||
color: #005aa0;
|
||||
border: 0;
|
||||
padding: 5px;
|
||||
background: #fffff5;
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
td.varname, td.tagname, td.paramname
|
||||
{
|
||||
font-weight: bold;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div.epigraph
|
||||
{
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table.productionset table.productionset
|
||||
{
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
strong.command
|
||||
{
|
||||
// font-family: monospace;
|
||||
// font-style: italic;
|
||||
// font-weight: normal;
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
div.calloutlist table
|
||||
div.calloutlist td
|
||||
{
|
||||
box-shadow: none;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.affiliation
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -1,283 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-submitting-changes">
|
||||
|
||||
<title>Submitting changes</title>
|
||||
|
||||
<section>
|
||||
<title>Making patches</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Read <link xlink:href="https://nixos.org/nixpkgs/manual/">Manual (How to write packages for Nix)</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Fork the repository on GitHub.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Create a branch for your future fix.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>You can make branch from a commit of your local <command>nixos-version</command>. That will help you to avoid additional local compilations. Because you will receive packages from binary cache.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>For example: <command>nixos-version</command> returns <command>15.05.git.0998212 (Dingo)</command>. So you can do:</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<screen>
|
||||
$ git checkout 0998212
|
||||
$ git checkout -b 'fix/pkg-name-update'
|
||||
</screen>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Please avoid working directly on the <command>master</command> branch.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Make commits of logical units.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>If you removed pkgs, made some major NixOS changes etc., write about them in <command>nixos/doc/manual/release-notes/rl-unstable.xml</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Check for unnecessary whitespace with <command>git diff --check</command> before committing.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Format the commit in a following way:</para>
|
||||
<programlisting>
|
||||
(pkg-name | service-name): (from -> to | init at version | refactor | etc)
|
||||
Additional information.
|
||||
</programlisting>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Examples:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nginx: init at 2.0.1</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>firefox: 3.0 -> 3.1.1</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>hydra service: add bazBaz option</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nginx service: refactor config generation</command>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Test your changes. If you work with
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>nixpkgs:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>update pkg ->
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nix-env -i pkg-name -f <path to your local nixpkgs folder></command>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>add pkg ->
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Make sure it's in <command>pkgs/top-level/all-packages.nix</command>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nix-env -i pkg-name -f <path to your local nixpkgs folder></command>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>If you don't want to install pkg in you profile</emphasis>.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>nix-build -A pkg-attribute-name <path to your local nixpkgs folder>/default.nix</command> and check results in the folder <command>result</command>. It will appear in the same directory where you did <command>nix-build</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you did <command>nix-env -i pkg-name</command> you can do <command>nix-env -e pkg-name</command> to uninstall it from your system.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>NixOS and its modules:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>You can add new module to your NixOS configuration file (usually it's <command>/etc/nixos/configuration.nix</command>).
|
||||
And do <command>sudo nixos-rebuild test -I nixpkgs=<path to your local nixpkgs folder> --fast</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you have commits <command>pkg-name: oh, forgot to insert whitespace</command>: squash commits in this case. Use <command>git rebase -i</command>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Rebase you branch against current <command>master</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Submitting changes</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Push your changes to your fork of nixpkgs.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Create pull request:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Write the title in format <command>(pkg-name | service): improvement</command>.
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>If you update the pkg, write versions <command>from -> to</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Write in comment if you have tested your patch. Do not rely much on <command>TravisCI</command>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you make an improvement, write about your motivation.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Notify maintainers of the package. For example add to the message: <command>cc @jagajaga @domenkozar</command>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Hotfixing pull requests</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Make the appropriate changes in you branch.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Don't create additional commits, do
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><command>git rebase -i</command></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<command>git push --force</command> to your branch.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Commit policy</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Commits must be sufficiently tested before being merged, both for the master and staging branches.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Hydra builds for master and staging should not be used as testing platform, it's a build farm for changes that have been already tested.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Master should only see non-breaking commits that do not cause mass rebuilds.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Staging should only see non-breaking mass-rebuild commits. That means it's not to be used for testing, and changes must have been well tested already. <link xlink:href="http://comments.gmane.org/gmane.linux.distributions.nixos/13447">Read policy here</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If staging is already in a broken state, please refrain from adding extra new breakages. Stabilize it for a few days, merge into master, then resume development on staging. <link xlink:href="http://hydra.nixos.org/jobset/nixpkgs/staging#tabs-evaluations">Keep an eye on the staging evaluations here</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>When changing the bootloader installation process, extra care must be taken. Grub installations cannot be rolled back, hence changes may break people's installations forever. For any non-trivial change to the bootloader please file a PR asking for review, especially from @edolstra.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
337
lib/attrsets.nix
337
lib/attrsets.nix
@@ -1,337 +0,0 @@
|
||||
# Operations on attribute sets.
|
||||
|
||||
with {
|
||||
inherit (builtins) head tail length;
|
||||
inherit (import ./trivial.nix) or;
|
||||
inherit (import ./default.nix) fold;
|
||||
inherit (import ./strings.nix) concatStringsSep;
|
||||
inherit (import ./lists.nix) concatMap concatLists all deepSeqList;
|
||||
};
|
||||
|
||||
rec {
|
||||
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr;
|
||||
|
||||
|
||||
/* Return an attribute from nested attribute sets. For instance
|
||||
["x" "y"] applied to some set e returns e.x.y, if it exists. The
|
||||
default value is returned otherwise. */
|
||||
attrByPath = attrPath: default: e:
|
||||
let attr = head attrPath;
|
||||
in
|
||||
if attrPath == [] then e
|
||||
else if e ? ${attr}
|
||||
then attrByPath (tail attrPath) default e.${attr}
|
||||
else default;
|
||||
|
||||
|
||||
/* Return nested attribute set in which an attribute is set. For instance
|
||||
["x" "y"] applied with some value v returns `x.y = v;' */
|
||||
setAttrByPath = attrPath: value:
|
||||
if attrPath == [] then value
|
||||
else listToAttrs
|
||||
[ { name = head attrPath; value = setAttrByPath (tail attrPath) value; } ];
|
||||
|
||||
|
||||
getAttrFromPath = attrPath: set:
|
||||
let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'";
|
||||
in attrByPath attrPath (abort errorMsg) set;
|
||||
|
||||
|
||||
/* Return the specified attributes from a set.
|
||||
|
||||
Example:
|
||||
attrVals ["a" "b" "c"] as
|
||||
=> [as.a as.b as.c]
|
||||
*/
|
||||
attrVals = nameList: set: map (x: set.${x}) nameList;
|
||||
|
||||
|
||||
/* Return the values of all attributes in the given set, sorted by
|
||||
attribute name.
|
||||
|
||||
Example:
|
||||
attrValues {c = 3; a = 1; b = 2;}
|
||||
=> [1 2 3]
|
||||
*/
|
||||
attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
|
||||
|
||||
|
||||
/* Collect each attribute named `attr' from a list of attribute
|
||||
sets. Sets that don't contain the named attribute are ignored.
|
||||
|
||||
Example:
|
||||
catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
|
||||
=> [1 2]
|
||||
*/
|
||||
catAttrs = builtins.catAttrs or
|
||||
(attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
|
||||
|
||||
|
||||
/* Filter an attribute set by removing all attributes for which the
|
||||
given predicate return false.
|
||||
|
||||
Example:
|
||||
filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
|
||||
=> { foo = 1; }
|
||||
*/
|
||||
filterAttrs = pred: set:
|
||||
listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
|
||||
|
||||
|
||||
/* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list:
|
||||
foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }]
|
||||
=> { a = [ 2 3 ]; }
|
||||
*/
|
||||
foldAttrs = op: nul: list_of_attrs:
|
||||
fold (n: a:
|
||||
fold (name: o:
|
||||
o // (listToAttrs [{inherit name; value = op n.${name} (a.${name} or nul); }])
|
||||
) a (attrNames n)
|
||||
) {} list_of_attrs;
|
||||
|
||||
|
||||
/* Recursively collect sets that verify a given predicate named `pred'
|
||||
from the set `attrs'. The recursion is stopped when the predicate is
|
||||
verified.
|
||||
|
||||
Type:
|
||||
collect ::
|
||||
(AttrSet -> Bool) -> AttrSet -> AttrSet
|
||||
|
||||
Example:
|
||||
collect isList { a = { b = ["b"]; }; c = [1]; }
|
||||
=> [["b"] [1]]
|
||||
|
||||
collect (x: x ? outPath)
|
||||
{ a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
|
||||
=> [{ outPath = "a/"; } { outPath = "b/"; }]
|
||||
*/
|
||||
collect = pred: attrs:
|
||||
if pred attrs then
|
||||
[ attrs ]
|
||||
else if isAttrs attrs then
|
||||
concatMap (collect pred) (attrValues attrs)
|
||||
else
|
||||
[];
|
||||
|
||||
|
||||
/* Utility function that creates a {name, value} pair as expected by
|
||||
builtins.listToAttrs. */
|
||||
nameValuePair = name: value: { inherit name value; };
|
||||
|
||||
|
||||
/* Apply a function to each element in an attribute set. The
|
||||
function takes two arguments --- the attribute name and its value
|
||||
--- and returns the new value for the attribute. The result is a
|
||||
new attribute set.
|
||||
|
||||
Example:
|
||||
mapAttrs (name: value: name + "-" + value)
|
||||
{ x = "foo"; y = "bar"; }
|
||||
=> { x = "x-foo"; y = "y-bar"; }
|
||||
*/
|
||||
mapAttrs = f: set:
|
||||
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set));
|
||||
|
||||
|
||||
/* Like `mapAttrs', but allows the name of each attribute to be
|
||||
changed in addition to the value. The applied function should
|
||||
return both the new name and value as a `nameValuePair'.
|
||||
|
||||
Example:
|
||||
mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
|
||||
{ x = "a"; y = "b"; }
|
||||
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
|
||||
*/
|
||||
mapAttrs' = f: set:
|
||||
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
||||
|
||||
|
||||
/* Call a function for each attribute in the given set and return
|
||||
the result in a list.
|
||||
|
||||
Example:
|
||||
mapAttrsToList (name: value: name + value)
|
||||
{ x = "a"; y = "b"; }
|
||||
=> [ "xa" "yb" ]
|
||||
*/
|
||||
mapAttrsToList = f: attrs:
|
||||
map (name: f name attrs.${name}) (attrNames attrs);
|
||||
|
||||
|
||||
/* Like `mapAttrs', except that it recursively applies itself to
|
||||
attribute sets. Also, the first argument of the argument
|
||||
function is a *list* of the names of the containing attributes.
|
||||
|
||||
Type:
|
||||
mapAttrsRecursive ::
|
||||
([String] -> a -> b) -> AttrSet -> AttrSet
|
||||
|
||||
Example:
|
||||
mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
|
||||
{ n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
|
||||
=> { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
|
||||
*/
|
||||
mapAttrsRecursive = mapAttrsRecursiveCond (as: true);
|
||||
|
||||
|
||||
/* Like `mapAttrsRecursive', but it takes an additional predicate
|
||||
function that tells it whether to recursive into an attribute
|
||||
set. If it returns false, `mapAttrsRecursiveCond' does not
|
||||
recurse, but does apply the map function. It is returns true, it
|
||||
does recurse, and does not apply the map function.
|
||||
|
||||
Type:
|
||||
mapAttrsRecursiveCond ::
|
||||
(AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
|
||||
|
||||
Example:
|
||||
# To prevent recursing into derivations (which are attribute
|
||||
# sets with the attribute "type" equal to "derivation"):
|
||||
mapAttrsRecursiveCond
|
||||
(as: !(as ? "type" && as.type == "derivation"))
|
||||
(x: ... do something ...)
|
||||
attrs
|
||||
*/
|
||||
mapAttrsRecursiveCond = cond: f: set:
|
||||
let
|
||||
recurse = path: set:
|
||||
let
|
||||
g =
|
||||
name: value:
|
||||
if isAttrs value && cond value
|
||||
then recurse (path ++ [name]) value
|
||||
else f (path ++ [name]) value;
|
||||
in mapAttrs g set;
|
||||
in recurse [] set;
|
||||
|
||||
|
||||
/* Generate an attribute set by mapping a function over a list of
|
||||
attribute names.
|
||||
|
||||
Example:
|
||||
genAttrs [ "foo" "bar" ] (name: "x_" + name)
|
||||
=> { foo = "x_foo"; bar = "x_bar"; }
|
||||
*/
|
||||
genAttrs = names: f:
|
||||
listToAttrs (map (n: nameValuePair n (f n)) names);
|
||||
|
||||
|
||||
/* Check whether the argument is a derivation. */
|
||||
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
|
||||
|
||||
|
||||
/* Convert a store path to a fake derivation. */
|
||||
toDerivation = path:
|
||||
let path' = builtins.storePath path; in
|
||||
{ type = "derivation";
|
||||
name = builtins.unsafeDiscardStringContext (builtins.substring 33 (-1) (baseNameOf path'));
|
||||
outPath = path';
|
||||
outputs = [ "out" ];
|
||||
};
|
||||
|
||||
|
||||
/* If the Boolean `cond' is true, return the attribute set `as',
|
||||
otherwise an empty attribute set. */
|
||||
optionalAttrs = cond: as: if cond then as else {};
|
||||
|
||||
|
||||
/* Merge sets of attributes and use the function f to merge attributes
|
||||
values. */
|
||||
zipAttrsWithNames = names: f: sets:
|
||||
listToAttrs (map (name: {
|
||||
inherit name;
|
||||
value = f name (catAttrs name sets);
|
||||
}) names);
|
||||
|
||||
# implentation note: Common names appear multiple times in the list of
|
||||
# names, hopefully this does not affect the system because the maximal
|
||||
# laziness avoid computing twice the same expression and listToAttrs does
|
||||
# not care about duplicated attribute names.
|
||||
zipAttrsWith = f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets;
|
||||
|
||||
zipAttrs = zipAttrsWith (name: values: values);
|
||||
|
||||
/* backward compatibility */
|
||||
zipWithNames = zipAttrsWithNames;
|
||||
zip = builtins.trace "lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith;
|
||||
|
||||
|
||||
/* Does the same as the update operator '//' except that attributes are
|
||||
merged until the given pedicate is verified. The predicate should
|
||||
accept 3 arguments which are the path to reach the attribute, a part of
|
||||
the first attribute set and a part of the second attribute set. When
|
||||
the predicate is verified, the value of the first attribute set is
|
||||
replaced by the value of the second attribute set.
|
||||
|
||||
Example:
|
||||
recursiveUpdateUntil (path: l: r: path == ["foo"]) {
|
||||
# first attribute set
|
||||
foo.bar = 1;
|
||||
foo.baz = 2;
|
||||
bar = 3;
|
||||
} {
|
||||
#second attribute set
|
||||
foo.bar = 1;
|
||||
foo.quz = 2;
|
||||
baz = 4;
|
||||
}
|
||||
|
||||
returns: {
|
||||
foo.bar = 1; # 'foo.*' from the second set
|
||||
foo.quz = 2; #
|
||||
bar = 3; # 'bar' from the first set
|
||||
baz = 4; # 'baz' from the second set
|
||||
}
|
||||
|
||||
*/
|
||||
recursiveUpdateUntil = pred: lhs: rhs:
|
||||
let f = attrPath:
|
||||
zipAttrsWith (n: values:
|
||||
if tail values == []
|
||||
|| pred attrPath (head (tail values)) (head values) then
|
||||
head values
|
||||
else
|
||||
f (attrPath ++ [n]) values
|
||||
);
|
||||
in f [] [rhs lhs];
|
||||
|
||||
/* A recursive variant of the update operator ‘//’. The recusion
|
||||
stops when one of the attribute values is not an attribute set,
|
||||
in which case the right hand side value takes precedence over the
|
||||
left hand side value.
|
||||
|
||||
Example:
|
||||
recursiveUpdate {
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.device = "/dev/hda";
|
||||
} {
|
||||
boot.loader.grub.device = "";
|
||||
}
|
||||
|
||||
returns: {
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.device = "";
|
||||
}
|
||||
|
||||
*/
|
||||
recursiveUpdate = lhs: rhs:
|
||||
recursiveUpdateUntil (path: lhs: rhs:
|
||||
!(isAttrs lhs && isAttrs rhs)
|
||||
) lhs rhs;
|
||||
|
||||
matchAttrs = pattern: attrs:
|
||||
fold or false (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
|
||||
let pat = head values; val = head (tail values); in
|
||||
if length values == 1 then false
|
||||
else if isAttrs pat then isAttrs val && matchAttrs head values
|
||||
else pat == val
|
||||
) [pattern attrs]));
|
||||
|
||||
# override only the attributes that are already present in the old set
|
||||
# useful for deep-overriding
|
||||
overrideExisting = old: new:
|
||||
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old));
|
||||
|
||||
deepSeqAttrs = x: y: deepSeqList (attrValues x) y;
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
{lib, pkgs} :
|
||||
let inherit (lib) nv nvs; in
|
||||
{
|
||||
|
||||
# composableDerivation basically mixes these features:
|
||||
# - fix function
|
||||
# - mergeAttrBy
|
||||
# - provides shortcuts for "options" such as "--enable-foo" and adding
|
||||
# buildInputs, see php example
|
||||
#
|
||||
# It predates styles which are common today, such as
|
||||
# * the config attr
|
||||
# * mkDerivation.override feature
|
||||
# * overrideDerivation (lib/customization.nix)
|
||||
#
|
||||
# Some of the most more important usage examples (which could be rewritten if it was important):
|
||||
# * php
|
||||
# * postgis
|
||||
# * vim_configurable
|
||||
#
|
||||
# A minimal example illustrating most features would look like this:
|
||||
# let base = composableDerivation { (fixed : let inherit (fixed.fixed) name in {
|
||||
# src = fetchurl {
|
||||
# }
|
||||
# buildInputs = [A];
|
||||
# preConfigre = "echo ${name}";
|
||||
# # attention, "name" attr is missing, thus you cannot instantiate "base".
|
||||
# }
|
||||
# in {
|
||||
# # These all add name attribute, thus you can instantiate those:
|
||||
# v1 = base.merge ({ name = "foo-add-B"; buildInputs = [B]; }); // B gets merged into buildInputs
|
||||
# v2 = base.merge ({ name = "mix-in-pre-configure-lines" preConfigre = ""; });
|
||||
# v3 = base.replace ({ name = "foo-no-A-only-B;" buildInputs = [B]; });
|
||||
# }
|
||||
#
|
||||
# So yes, you can think about it being something like nixos modules, and
|
||||
# you'd be merging "features" in one at a time using .merge or .replace
|
||||
# Thanks Shea for telling me that I rethink the documentation ..
|
||||
#
|
||||
# issues:
|
||||
# * its complicated to understand
|
||||
# * some "features" such as exact merge behaviour are burried in mergeAttrBy
|
||||
# and defaultOverridableDelayableArgs assuming the default behaviour does
|
||||
# the right thing in the common case
|
||||
# * Eelco once said using such fix style functions are slow to evaluate
|
||||
# * Too quick & dirty. Hard to understand for others. The benefit was that
|
||||
# you were able to create a kernel builder like base derivation and replace
|
||||
# / add patches the way you want without having to declare function arguments
|
||||
#
|
||||
# nice features:
|
||||
# declaring "optional featuers" is modular. For instance:
|
||||
# flags.curl = {
|
||||
# configureFlags = ["--with-curl=${curl}" "--with-curlwrappers"];
|
||||
# buildInputs = [curl openssl];
|
||||
# };
|
||||
# flags.other = { .. }
|
||||
# (Example taken from PHP)
|
||||
#
|
||||
# alternative styles / related features:
|
||||
# * Eg see function supporting building the kernel
|
||||
# * versionedDerivation (discussion about this is still going on - or ended)
|
||||
# * composedArgsAndFun
|
||||
# * mkDerivation.override
|
||||
# * overrideDerivation
|
||||
# * using { .., *Support ? false }: like configurable options.
|
||||
# To find those examples use grep
|
||||
#
|
||||
# To sum up: It exists for historical reasons - and for most commonly used
|
||||
# tasks the alternatives should be used
|
||||
#
|
||||
# If you have questions about this code ping Marc Weber.
|
||||
composableDerivation = {
|
||||
mkDerivation ? pkgs.stdenv.mkDerivation,
|
||||
|
||||
# list of functions to be applied before defaultOverridableDelayableArgs removes removeAttrs names
|
||||
# prepareDerivationArgs handles derivation configurations
|
||||
applyPreTidy ? [ lib.prepareDerivationArgs ],
|
||||
|
||||
# consider adding addtional elements by derivation.merge { removeAttrs = ["elem"]; };
|
||||
removeAttrs ? ["cfg" "flags"]
|
||||
|
||||
}: (lib.defaultOverridableDelayableArgs ( a: mkDerivation a)
|
||||
{
|
||||
inherit applyPreTidy removeAttrs;
|
||||
}).merge;
|
||||
|
||||
# some utility functions
|
||||
# use this function to generate flag attrs for prepareDerivationArgs
|
||||
# E nable D isable F eature
|
||||
edf = {name, feat ? name, enable ? {}, disable ? {} , value ? ""}:
|
||||
nvs name {
|
||||
set = {
|
||||
configureFlags = ["--enable-${feat}${if value == "" then "" else "="}${value}"];
|
||||
} // enable;
|
||||
unset = {
|
||||
configureFlags = ["--disable-${feat}"];
|
||||
} // disable;
|
||||
};
|
||||
|
||||
# same for --with and --without-
|
||||
# W ith or W ithout F eature
|
||||
wwf = {name, feat ? name, enable ? {}, disable ? {}, value ? ""}:
|
||||
nvs name {
|
||||
set = enable // {
|
||||
configureFlags = ["--with-${feat}${if value == "" then "" else "="}${value}"]
|
||||
++ lib.maybeAttr "configureFlags" [] enable;
|
||||
};
|
||||
unset = disable // {
|
||||
configureFlags = ["--without-${feat}"]
|
||||
++ lib.maybeAttr "configureFlags" [] disable;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
let
|
||||
|
||||
lib = import ./default.nix;
|
||||
inherit (builtins) attrNames isFunction;
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
|
||||
/* `overrideDerivation drv f' takes a derivation (i.e., the result
|
||||
of a call to the builtin function `derivation') and returns a new
|
||||
derivation in which the attributes of the original are overriden
|
||||
according to the function `f'. The function `f' is called with
|
||||
the original derivation attributes.
|
||||
|
||||
`overrideDerivation' allows certain "ad-hoc" customisation
|
||||
scenarios (e.g. in ~/.nixpkgs/config.nix). For instance, if you
|
||||
want to "patch" the derivation returned by a package function in
|
||||
Nixpkgs to build another version than what the function itself
|
||||
provides, you can do something like this:
|
||||
|
||||
mySed = overrideDerivation pkgs.gnused (oldAttrs: {
|
||||
name = "sed-4.2.2-pre";
|
||||
src = fetchurl {
|
||||
url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
|
||||
sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
|
||||
};
|
||||
patches = [];
|
||||
});
|
||||
|
||||
For another application, see build-support/vm, where this
|
||||
function is used to build arbitrary derivations inside a QEMU
|
||||
virtual machine.
|
||||
*/
|
||||
overrideDerivation = drv: f:
|
||||
let
|
||||
newDrv = derivation (drv.drvAttrs // (f drv));
|
||||
in addPassthru newDrv (
|
||||
{ meta = drv.meta or {};
|
||||
passthru = if drv ? passthru then drv.passthru else {};
|
||||
}
|
||||
//
|
||||
(drv.passthru or {})
|
||||
//
|
||||
(if (drv ? crossDrv && drv ? nativeDrv)
|
||||
then {
|
||||
crossDrv = overrideDerivation drv.crossDrv f;
|
||||
nativeDrv = overrideDerivation drv.nativeDrv f;
|
||||
}
|
||||
else { }));
|
||||
|
||||
|
||||
makeOverridable = f: origArgs:
|
||||
let
|
||||
ff = f origArgs;
|
||||
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
|
||||
in
|
||||
if builtins.isAttrs ff then (ff //
|
||||
{ override = newArgs: makeOverridable f (overrideWith newArgs);
|
||||
overrideDerivation = fdrv:
|
||||
makeOverridable (args: overrideDerivation (f args) fdrv) origArgs;
|
||||
})
|
||||
else if builtins.isFunction ff then
|
||||
{ override = newArgs: makeOverridable f (overrideWith newArgs);
|
||||
__functor = self: ff;
|
||||
overrideDerivation = throw "overrideDerivation not yet supported for functors";
|
||||
}
|
||||
else ff;
|
||||
|
||||
|
||||
/* Call the package function in the file `fn' with the required
|
||||
arguments automatically. The function is called with the
|
||||
arguments `args', but any missing arguments are obtained from
|
||||
`autoArgs'. This function is intended to be partially
|
||||
parameterised, e.g.,
|
||||
|
||||
callPackage = callPackageWith pkgs;
|
||||
pkgs = {
|
||||
libfoo = callPackage ./foo.nix { };
|
||||
libbar = callPackage ./bar.nix { };
|
||||
};
|
||||
|
||||
If the `libbar' function expects an argument named `libfoo', it is
|
||||
automatically passed as an argument. Overrides or missing
|
||||
arguments can be supplied in `args', e.g.
|
||||
|
||||
libbar = callPackage ./bar.nix {
|
||||
libfoo = null;
|
||||
enableX11 = true;
|
||||
};
|
||||
*/
|
||||
callPackageWith = autoArgs: fn: args:
|
||||
let
|
||||
f = if builtins.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
|
||||
in makeOverridable f (auto // args);
|
||||
|
||||
|
||||
/* Like callPackage, but for a function that returns an attribute
|
||||
set of derivations. The override function is added to the
|
||||
individual attributes. */
|
||||
callPackagesWith = autoArgs: fn: args:
|
||||
let
|
||||
f = if builtins.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
|
||||
finalArgs = auto // args;
|
||||
pkgs = f finalArgs;
|
||||
mkAttrOverridable = name: pkg: pkg // {
|
||||
override = newArgs: mkAttrOverridable name (f (finalArgs // newArgs)).${name};
|
||||
};
|
||||
in lib.mapAttrs mkAttrOverridable pkgs;
|
||||
|
||||
|
||||
/* Add attributes to each output of a derivation without changing
|
||||
the derivation itself. */
|
||||
addPassthru = drv: passthru:
|
||||
let
|
||||
outputs = drv.outputs or [ "out" ];
|
||||
|
||||
commonAttrs = drv // (builtins.listToAttrs outputsList) //
|
||||
({ all = map (x: x.value) outputsList; }) // passthru;
|
||||
|
||||
outputToAttrListElement = outputName:
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
inherit (drv.${outputName}) outPath drvPath type outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map outputToAttrListElement outputs;
|
||||
in commonAttrs.${drv.outputName};
|
||||
|
||||
|
||||
/* Strip a derivation of all non-essential attributes, returning
|
||||
only those needed by hydra-eval-jobs. Also strictly evaluate the
|
||||
result to ensure that there are no thunks kept alive to prevent
|
||||
garbage collection. */
|
||||
hydraJob = drv:
|
||||
let
|
||||
outputs = drv.outputs or ["out"];
|
||||
|
||||
commonAttrs =
|
||||
{ inherit (drv) name system meta; inherit outputs; }
|
||||
// lib.optionalAttrs (drv._hydraAggregate or false) {
|
||||
_hydraAggregate = true;
|
||||
constituents = map hydraJob (lib.flatten drv.constituents);
|
||||
}
|
||||
// (lib.listToAttrs outputsList);
|
||||
|
||||
makeOutput = outputName:
|
||||
let output = drv.${outputName}; in
|
||||
{ name = outputName;
|
||||
value = commonAttrs // {
|
||||
outPath = output.outPath;
|
||||
drvPath = output.drvPath;
|
||||
type = "derivation";
|
||||
inherit outputName;
|
||||
};
|
||||
};
|
||||
|
||||
outputsList = map makeOutput outputs;
|
||||
|
||||
drv' = (lib.head outputsList).value;
|
||||
in lib.deepSeq drv' drv';
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
let
|
||||
|
||||
trivial = import ./trivial.nix;
|
||||
lists = import ./lists.nix;
|
||||
strings = import ./strings.nix;
|
||||
stringsWithDeps = import ./strings-with-deps.nix;
|
||||
attrsets = import ./attrsets.nix;
|
||||
sources = import ./sources.nix;
|
||||
modules = import ./modules.nix;
|
||||
options = import ./options.nix;
|
||||
types = import ./types.nix;
|
||||
meta = import ./meta.nix;
|
||||
debug = import ./debug.nix;
|
||||
misc = import ./deprecated.nix;
|
||||
maintainers = import ./maintainers.nix;
|
||||
platforms = import ./platforms.nix;
|
||||
systems = import ./systems.nix;
|
||||
customisation = import ./customisation.nix;
|
||||
licenses = import ./licenses.nix;
|
||||
|
||||
in
|
||||
{ inherit trivial lists strings stringsWithDeps attrsets sources options
|
||||
modules types meta debug maintainers licenses platforms systems;
|
||||
}
|
||||
# !!! don't include everything at top-level; perhaps only the most
|
||||
# commonly used functions.
|
||||
// trivial // lists // strings // stringsWithDeps // attrsets // sources
|
||||
// options // types // meta // debug // misc // modules
|
||||
// systems
|
||||
// customisation
|
||||
@@ -1,423 +0,0 @@
|
||||
let lib = import ./default.nix;
|
||||
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
|
||||
|
||||
in
|
||||
|
||||
with import ./lists.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./strings.nix;
|
||||
|
||||
rec {
|
||||
|
||||
# returns default if env var is not set
|
||||
maybeEnv = name: default:
|
||||
let value = builtins.getEnv name; in
|
||||
if value == "" then default else value;
|
||||
|
||||
defaultMergeArg = x : y: if builtins.isAttrs y then
|
||||
y
|
||||
else
|
||||
(y x);
|
||||
defaultMerge = x: y: x // (defaultMergeArg x y);
|
||||
foldArgs = merger: f: init: x:
|
||||
let arg=(merger init (defaultMergeArg init x));
|
||||
# now add the function with composed args already applied to the final attrs
|
||||
base = (setAttrMerge "passthru" {} (f arg)
|
||||
( z : z // rec {
|
||||
function = foldArgs merger f arg;
|
||||
args = (lib.attrByPath ["passthru" "args"] {} z) // x;
|
||||
} ));
|
||||
withStdOverrides = base // {
|
||||
override = base.passthru.function;
|
||||
} ;
|
||||
in
|
||||
withStdOverrides;
|
||||
|
||||
|
||||
# predecessors: proposed replacement for applyAndFun (which has a bug cause it merges twice)
|
||||
# the naming "overridableDelayableArgs" tries to express that you can
|
||||
# - override attr values which have been supplied earlier
|
||||
# - use attr values before they have been supplied by accessing the fix point
|
||||
# name "fixed"
|
||||
# f: the (delayed overridden) arguments are applied to this
|
||||
#
|
||||
# initial: initial attrs arguments and settings. see defaultOverridableDelayableArgs
|
||||
#
|
||||
# returns: f applied to the arguments // special attributes attrs
|
||||
# a) merge: merge applied args with new args. Wether an argument is overridden depends on the merge settings
|
||||
# b) replace: this let's you replace and remove names no matter which merge function has been set
|
||||
#
|
||||
# examples: see test cases "res" below;
|
||||
overridableDelayableArgs =
|
||||
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
|
||||
tidy = args :
|
||||
let # apply all functions given in "applyPreTidy" in sequence
|
||||
applyPreTidyFun = fold ( n : a : x : n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
|
||||
in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr "removeAttrs" [] args) ); # tidy up args before applying them
|
||||
fun = n : x :
|
||||
let newArgs = fixed :
|
||||
let args = takeFixed fixed;
|
||||
mergeFun = args.${n};
|
||||
in if isAttrs x then (mergeFun args x)
|
||||
else assert isFunction x;
|
||||
mergeFun args (x ( args // { inherit fixed; }));
|
||||
in overridableDelayableArgs f newArgs;
|
||||
in
|
||||
(f (tidy (lib.fix takeFixed))) // {
|
||||
merge = fun "mergeFun";
|
||||
replace = fun "keepFun";
|
||||
};
|
||||
defaultOverridableDelayableArgs = f :
|
||||
let defaults = {
|
||||
mergeFun = mergeAttrByFunc; # default merge function. merge strategie (concatenate lists, strings) is given by mergeAttrBy
|
||||
keepFun = a : b : { inherit (a) removeAttrs mergeFun keepFun mergeAttrBy; } // b; # even when using replace preserve these values
|
||||
applyPreTidy = []; # list of functions applied to args before args are tidied up (usage case : prepareDerivationArgs)
|
||||
mergeAttrBy = mergeAttrBy // {
|
||||
applyPreTidy = a : b : a ++ b;
|
||||
removeAttrs = a : b: a ++ b;
|
||||
};
|
||||
removeAttrs = ["mergeFun" "keepFun" "mergeAttrBy" "removeAttrs" "fixed" ]; # before applying the arguments to the function make sure these names are gone
|
||||
};
|
||||
in (overridableDelayableArgs f defaults).merge;
|
||||
|
||||
|
||||
|
||||
# rec { # an example of how composedArgsAndFun can be used
|
||||
# a = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
|
||||
# # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
|
||||
# b = a.passthru.function { a = [ "3" ]; meta = { d2 = "bar2";}; };
|
||||
# # instead of passing/ overriding values you can use a merge function:
|
||||
# c = b.passthru.function ( x: { a = x.a ++ ["4"]; }); # consider using (maybeAttr "a" [] x)
|
||||
# }
|
||||
# result:
|
||||
# {
|
||||
# a = { a = ["2"]; meta = { d = "bar"; }; passthru = { function = .. }; };
|
||||
# b = { a = ["3"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
|
||||
# c = { a = ["3" "4"]; meta = { d2 = "bar2"; }; passthru = { function = .. }; };
|
||||
# # c2 is equal to c
|
||||
# }
|
||||
composedArgsAndFun = f: foldArgs defaultMerge f {};
|
||||
|
||||
|
||||
# shortcut for attrByPath ["name"] default attrs
|
||||
maybeAttrNullable = maybeAttr;
|
||||
|
||||
# shortcut for attrByPath ["name"] default attrs
|
||||
maybeAttr = name: default: attrs: attrs.${name} or default;
|
||||
|
||||
|
||||
# Return the second argument if the first one is true or the empty version
|
||||
# of the second argument.
|
||||
ifEnable = cond: val:
|
||||
if cond then val
|
||||
else if builtins.isList val then []
|
||||
else if builtins.isAttrs val then {}
|
||||
# else if builtins.isString val then ""
|
||||
else if val == true || val == false then false
|
||||
else null;
|
||||
|
||||
|
||||
# Return true only if there is an attribute and it is true.
|
||||
checkFlag = attrSet: name:
|
||||
if name == "true" then true else
|
||||
if name == "false" then false else
|
||||
if (elem name (attrByPath ["flags"] [] attrSet)) then true else
|
||||
attrByPath [name] false attrSet ;
|
||||
|
||||
|
||||
# Input : attrSet, [ [name default] ... ], name
|
||||
# Output : its value or default.
|
||||
getValue = attrSet: argList: name:
|
||||
( attrByPath [name] (if checkFlag attrSet name then true else
|
||||
if argList == [] then null else
|
||||
let x = builtins.head argList; in
|
||||
if (head x) == name then
|
||||
(head (tail x))
|
||||
else (getValue attrSet
|
||||
(tail argList) name)) attrSet );
|
||||
|
||||
|
||||
# Input : attrSet, [[name default] ...], [ [flagname reqs..] ... ]
|
||||
# Output : are reqs satisfied? It's asserted.
|
||||
checkReqs = attrSet : argList : condList :
|
||||
(
|
||||
fold lib.and true
|
||||
(map (x: let name = (head x) ; in
|
||||
|
||||
((checkFlag attrSet name) ->
|
||||
(fold lib.and true
|
||||
(map (y: let val=(getValue attrSet argList y); in
|
||||
(val!=null) && (val!=false))
|
||||
(tail x))))) condList)) ;
|
||||
|
||||
|
||||
# This function has O(n^2) performance.
|
||||
uniqList = {inputList, acc ? []} :
|
||||
let go = xs : acc :
|
||||
if xs == []
|
||||
then []
|
||||
else let x = head xs;
|
||||
y = if elem x acc then [] else [x];
|
||||
in y ++ go (tail xs) (y ++ acc);
|
||||
in go inputList acc;
|
||||
|
||||
uniqListExt = {inputList, outputList ? [],
|
||||
getter ? (x : x), compare ? (x: y: x==y)}:
|
||||
if inputList == [] then outputList else
|
||||
let x=head inputList;
|
||||
isX = y: (compare (getter y) (getter x));
|
||||
newOutputList = outputList ++
|
||||
(if any isX outputList then [] else [x]);
|
||||
in uniqListExt {outputList=newOutputList;
|
||||
inputList = (tail inputList);
|
||||
inherit getter compare;
|
||||
};
|
||||
|
||||
|
||||
|
||||
condConcat = name: list: checker:
|
||||
if list == [] then name else
|
||||
if checker (head list) then
|
||||
condConcat
|
||||
(name + (head (tail list)))
|
||||
(tail (tail list))
|
||||
checker
|
||||
else condConcat
|
||||
name (tail (tail list)) checker;
|
||||
|
||||
lazyGenericClosure = {startSet, operator}:
|
||||
let
|
||||
work = list: doneKeys: result:
|
||||
if list == [] then
|
||||
result
|
||||
else
|
||||
let x = head list; key = x.key; in
|
||||
if elem key doneKeys then
|
||||
work (tail list) doneKeys result
|
||||
else
|
||||
work (tail list ++ operator x) ([key] ++ doneKeys) ([x] ++ result);
|
||||
in
|
||||
work startSet [] [];
|
||||
|
||||
innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else
|
||||
innerModifySumArgs f x (a // b);
|
||||
modifySumArgs = f: x: innerModifySumArgs f x {};
|
||||
|
||||
|
||||
innerClosePropagation = acc : xs :
|
||||
if xs == []
|
||||
then acc
|
||||
else let y = head xs;
|
||||
ys = tail xs;
|
||||
in if ! isAttrs y
|
||||
then innerClosePropagation acc ys
|
||||
else let acc' = [y] ++ acc;
|
||||
in innerClosePropagation
|
||||
acc'
|
||||
(uniqList { inputList = (maybeAttrNullable "propagatedBuildInputs" [] y)
|
||||
++ (maybeAttrNullable "propagatedNativeBuildInputs" [] y)
|
||||
++ ys;
|
||||
acc = acc';
|
||||
}
|
||||
);
|
||||
|
||||
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
|
||||
|
||||
# calls a function (f attr value ) for each record item. returns a list
|
||||
mapAttrsFlatten = f : r : map (attr: f attr r.${attr}) (attrNames r);
|
||||
|
||||
# attribute set containing one attribute
|
||||
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
|
||||
# adds / replaces an attribute of an attribute set
|
||||
setAttr = set : name : v : set // (nvs name v);
|
||||
|
||||
# setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
|
||||
# setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; }
|
||||
# setAttrMerge "a" [] { } (x : x ++ [3]) -> { a = [ 3]; }
|
||||
setAttrMerge = name : default : attrs : f :
|
||||
setAttr attrs name (f (maybeAttr name default attrs));
|
||||
|
||||
# Using f = a : b = b the result is similar to //
|
||||
# merge attributes with custom function handling the case that the attribute
|
||||
# exists in both sets
|
||||
mergeAttrsWithFunc = f : set1 : set2 :
|
||||
fold (n: set : if set ? ${n}
|
||||
then setAttr set n (f set.${n} set2.${n})
|
||||
else set )
|
||||
(set2 // set1) (attrNames set2);
|
||||
|
||||
# merging two attribute set concatenating the values of same attribute names
|
||||
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
|
||||
mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : (toList a) ++ (toList b) );
|
||||
|
||||
# merges attributes using //, if a name exisits in both attributes
|
||||
# an error will be triggered unless its listed in mergeLists
|
||||
# so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
|
||||
# { buildInputs = [a b]; }
|
||||
# merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs?
|
||||
# in these cases the first buildPhase will override the second one
|
||||
# ! deprecated, use mergeAttrByFunc instead
|
||||
mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
|
||||
overrideSnd ? [ "buildPhase" ]
|
||||
} : attrs1 : attrs2 :
|
||||
fold (n: set :
|
||||
setAttr set n ( if set ? ${n}
|
||||
then # merge
|
||||
if elem n mergeLists # attribute contains list, merge them by concatenating
|
||||
then attrs2.${n} ++ attrs1.${n}
|
||||
else if elem n overrideSnd
|
||||
then attrs1.${n}
|
||||
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
|
||||
else attrs2.${n} # add attribute not existing in attr1
|
||||
)) attrs1 (attrNames attrs2);
|
||||
|
||||
|
||||
# example usage:
|
||||
# mergeAttrByFunc {
|
||||
# inherit mergeAttrBy; # defined below
|
||||
# buildInputs = [ a b ];
|
||||
# } {
|
||||
# buildInputs = [ c d ];
|
||||
# };
|
||||
# will result in
|
||||
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
|
||||
# is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
|
||||
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
|
||||
mergeAttrByFunc = x : y :
|
||||
let
|
||||
mergeAttrBy2 = { mergeAttrBy=lib.mergeAttrs; }
|
||||
// (maybeAttr "mergeAttrBy" {} x)
|
||||
// (maybeAttr "mergeAttrBy" {} y); in
|
||||
fold lib.mergeAttrs {} [
|
||||
x y
|
||||
(mapAttrs ( a : v : # merge special names using given functions
|
||||
if x ? ${a}
|
||||
then if y ? ${a}
|
||||
then v x.${a} y.${a} # both have attr, use merge func
|
||||
else x.${a} # only x has attr
|
||||
else y.${a} # only y has attr)
|
||||
) (removeAttrs mergeAttrBy2
|
||||
# don't merge attrs which are neither in x nor y
|
||||
(filter (a: ! x ? ${a} && ! y ? ${a})
|
||||
(attrNames mergeAttrBy2))
|
||||
)
|
||||
)
|
||||
];
|
||||
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)
|
||||
[ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ])
|
||||
// listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
|
||||
// listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
|
||||
;
|
||||
|
||||
# prepareDerivationArgs tries to make writing configurable derivations easier
|
||||
# example:
|
||||
# prepareDerivationArgs {
|
||||
# mergeAttrBy = {
|
||||
# myScript = x : y : x ++ "\n" ++ y;
|
||||
# };
|
||||
# cfg = {
|
||||
# readlineSupport = true;
|
||||
# };
|
||||
# flags = {
|
||||
# readline = {
|
||||
# set = {
|
||||
# configureFlags = [ "--with-compiler=${compiler}" ];
|
||||
# buildInputs = [ compiler ];
|
||||
# pass = { inherit compiler; READLINE=1; };
|
||||
# assertion = compiler.dllSupport;
|
||||
# myScript = "foo";
|
||||
# };
|
||||
# unset = { configureFlags = ["--without-compiler"]; };
|
||||
# };
|
||||
# };
|
||||
# src = ...
|
||||
# buildPhase = '' ... '';
|
||||
# name = ...
|
||||
# myScript = "bar";
|
||||
# };
|
||||
# if you don't have need for unset you can omit the surrounding set = { .. } attr
|
||||
# all attrs except flags cfg and mergeAttrBy will be merged with the
|
||||
# additional data from flags depending on config settings
|
||||
# It's used in composableDerivation in all-packages.nix. It's also used
|
||||
# heavily in the new python and libs implementation
|
||||
#
|
||||
# should we check for misspelled cfg options?
|
||||
# TODO use args.mergeFun here as well?
|
||||
prepareDerivationArgs = args:
|
||||
let args2 = { cfg = {}; flags = {}; } // args;
|
||||
flagName = name : "${name}Support";
|
||||
cfgWithDefaults = (listToAttrs (map (n : nameValuePair (flagName n) false) (attrNames args2.flags)))
|
||||
// args2.cfg;
|
||||
opts = attrValues (mapAttrs (a : v :
|
||||
let v2 = if v ? set || v ? unset then v else { set = v; };
|
||||
n = if cfgWithDefaults.${flagName a} then "set" else "unset";
|
||||
attr = maybeAttr n {} v2; in
|
||||
if (maybeAttr "assertion" true attr)
|
||||
then attr
|
||||
else throw "assertion of flag ${a} of derivation ${args.name} failed"
|
||||
) args2.flags );
|
||||
in removeAttrs
|
||||
(mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
|
||||
["flags" "cfg" "mergeAttrBy" ];
|
||||
|
||||
|
||||
nixType = x:
|
||||
if isAttrs x then
|
||||
if x ? outPath then "derivation"
|
||||
else "aattrs"
|
||||
else if isFunction x then "function"
|
||||
else if isList x then "list"
|
||||
else if x == true then "bool"
|
||||
else if x == false then "bool"
|
||||
else if x == null then "null"
|
||||
else if isInt x then "int"
|
||||
else "string";
|
||||
|
||||
}
|
||||
461
lib/licenses.nix
461
lib/licenses.nix
@@ -1,461 +0,0 @@
|
||||
let
|
||||
|
||||
lib = import ./default.nix;
|
||||
|
||||
spdx = lic: lic // {
|
||||
url = "http://spdx.org/licenses/${lic.spdxId}";
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||
/* License identifiers from spdx.org where possible.
|
||||
* If you cannot find your license here, then look for a similar license or
|
||||
* add it to this list. The URL mentioned above is a good source for inspiration.
|
||||
*/
|
||||
|
||||
afl21 = spdx {
|
||||
spdxId = "AFL-2.1";
|
||||
fullName = "Academic Free License";
|
||||
};
|
||||
|
||||
agpl3 = spdx {
|
||||
spdxId = "AGPL-3.0";
|
||||
fullName = "GNU Affero General Public License v3.0";
|
||||
};
|
||||
|
||||
agpl3Plus = {
|
||||
fullName = "GNU Affero General Public License v3.0 or later";
|
||||
inherit (agpl3) url;
|
||||
};
|
||||
|
||||
amazonsl = {
|
||||
fullName = "Amazon Software License";
|
||||
url = http://aws.amazon.com/asl/;
|
||||
free = false;
|
||||
};
|
||||
|
||||
amd = {
|
||||
fullName = "AMD License Agreement";
|
||||
url = http://developer.amd.com/amd-license-agreement/;
|
||||
};
|
||||
|
||||
apsl20 = spdx {
|
||||
spdxId = "APSL-2.0";
|
||||
fullName = "Apple Public Source License 2.0";
|
||||
};
|
||||
|
||||
artistic1 = spdx {
|
||||
spdxId = "Artistic-1.0";
|
||||
fullName = "Artistic License 1.0";
|
||||
};
|
||||
|
||||
artistic2 = spdx {
|
||||
spdxId = "Artistic-2.0";
|
||||
fullName = "Artistic License 2.0";
|
||||
};
|
||||
|
||||
asl20 = spdx {
|
||||
spdxId = "Apache-2.0";
|
||||
fullName = "Apache License 2.0";
|
||||
};
|
||||
|
||||
boost = spdx {
|
||||
spdxId = "BSL-1.0";
|
||||
fullName = "Boost Software License 1.0";
|
||||
};
|
||||
|
||||
bsd2 = spdx {
|
||||
spdxId = "BSD-2-Clause";
|
||||
fullName = ''BSD 2-clause "Simplified" License'';
|
||||
};
|
||||
|
||||
bsd3 = spdx {
|
||||
spdxId = "BSD-3-Clause";
|
||||
fullName = ''BSD 3-clause "New" or "Revised" License'';
|
||||
};
|
||||
|
||||
bsdOriginal = spdx {
|
||||
spdxId = "BSD-4-Clause";
|
||||
fullName = ''BSD 4-clause "Original" or "Old" License'';
|
||||
};
|
||||
|
||||
cc0 = spdx {
|
||||
spdxId = "CC0-1.0";
|
||||
fullName = "Creative Commons Zero v1.0 Universal";
|
||||
};
|
||||
|
||||
cc-by-sa-25 = spdx {
|
||||
spdxId = "CC-BY-SA-2.5";
|
||||
fullName = "Creative Commons Attribution Share Alike 2.5";
|
||||
};
|
||||
|
||||
cc-by-30 = spdx {
|
||||
spdxId = "CC-BY-3.0";
|
||||
fullName = "Creative Commons Attribution 3.0";
|
||||
};
|
||||
|
||||
cc-by-sa-30 = spdx {
|
||||
spdxId = "CC-BY-SA-3.0";
|
||||
fullName = "Creative Commons Attribution Share Alike 3.0";
|
||||
};
|
||||
|
||||
cc-by-40 = spdx {
|
||||
spdxId = "CC-BY-4.0";
|
||||
fullName = "Creative Commons Attribution 4.0";
|
||||
};
|
||||
|
||||
cc-by-sa-40 = spdx {
|
||||
spdxId = "CC-BY-SA-4.0";
|
||||
fullName = "Creative Commons Attribution Share Alike 4.0";
|
||||
};
|
||||
|
||||
cddl = spdx {
|
||||
spdxId = "CDDL-1.0";
|
||||
fullName = "Common Development and Distribution License 1.0";
|
||||
};
|
||||
|
||||
cecill20 = spdx {
|
||||
spdxId = "CECILL-2.0";
|
||||
fullName = "CeCILL Free Software License Agreement v2.0";
|
||||
};
|
||||
|
||||
cecill-b = spdx {
|
||||
spdxId = "CECILL-B";
|
||||
fullName = "CeCILL-B Free Software License Agreement";
|
||||
};
|
||||
|
||||
cecill-c = spdx {
|
||||
spdxId = "CECILL-C";
|
||||
fullName = "CeCILL-C Free Software License Agreement";
|
||||
};
|
||||
|
||||
cpl10 = spdx {
|
||||
spdxId = "CPL-1.0";
|
||||
fullName = "Common Public License 1.0";
|
||||
};
|
||||
|
||||
efl10 = spdx {
|
||||
spdxId = "EFL-1.0";
|
||||
fullName = "Eiffel Forum License v1.0";
|
||||
};
|
||||
|
||||
efl20 = spdx {
|
||||
spdxId = "EFL-2.0";
|
||||
fullName = "Eiffel Forum License v2.0";
|
||||
};
|
||||
|
||||
epl10 = spdx {
|
||||
spdxId = "EPL-1.0";
|
||||
fullName = "Eclipse Public License 1.0";
|
||||
};
|
||||
|
||||
fdl12 = spdx {
|
||||
spdxId = "GFDL-1.2";
|
||||
fullName = "GNU Free Documentation License v1.2";
|
||||
};
|
||||
|
||||
free = {
|
||||
fullName = "Unspecified free software license";
|
||||
};
|
||||
|
||||
gpl1 = spdx {
|
||||
spdxId = "GPL-1.0";
|
||||
fullName = "GNU General Public License v1.0 only";
|
||||
};
|
||||
|
||||
gpl1Plus = spdx {
|
||||
spdxId = "GPL-1.0+";
|
||||
fullName = "GNU General Public License v1.0 or later";
|
||||
};
|
||||
|
||||
gpl2 = spdx {
|
||||
spdxId = "GPL-2.0";
|
||||
fullName = "GNU General Public License v2.0 only";
|
||||
};
|
||||
|
||||
gpl2ClasspathPlus = {
|
||||
fullName = "GNU General Public License v2.0 or later (with Classpath exception)";
|
||||
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
|
||||
};
|
||||
|
||||
gpl2Oss = {
|
||||
fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)";
|
||||
url = http://www.mysql.com/about/legal/licensing/foss-exception;
|
||||
};
|
||||
|
||||
gpl2Plus = spdx {
|
||||
spdxId = "GPL-2.0+";
|
||||
fullName = "GNU General Public License v2.0 or later";
|
||||
};
|
||||
|
||||
gpl3 = spdx {
|
||||
spdxId = "GPL-3.0";
|
||||
fullName = "GNU General Public License v3.0 only";
|
||||
};
|
||||
|
||||
gpl3Plus = spdx {
|
||||
spdxId = "GPL-3.0+";
|
||||
fullName = "GNU General Public License v3.0 or later";
|
||||
};
|
||||
|
||||
gpl3ClasspathPlus = {
|
||||
fullName = "GNU General Public License v3.0 or later (with Classpath exception)";
|
||||
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
|
||||
};
|
||||
|
||||
# Intel's license, seems free
|
||||
iasl = {
|
||||
fullName = "iASL";
|
||||
url = http://www.calculate-linux.org/packages/licenses/iASL;
|
||||
};
|
||||
|
||||
ijg = spdx {
|
||||
spdxId = "IJG";
|
||||
fullName = "Independent JPEG Group License";
|
||||
};
|
||||
|
||||
inria = {
|
||||
fullName = "INRIA Non-Commercial License Agreement";
|
||||
url = "http://compcert.inria.fr/doc/LICENSE";
|
||||
};
|
||||
|
||||
ipa = spdx {
|
||||
spdxId = "IPA";
|
||||
fullName = "IPA Font License";
|
||||
};
|
||||
|
||||
ipl10 = spdx {
|
||||
spdxId = "IPL-1.0";
|
||||
fullName = "IBM Public License v1.0";
|
||||
};
|
||||
|
||||
isc = spdx {
|
||||
spdxId = "ISC";
|
||||
fullName = "ISC License";
|
||||
};
|
||||
|
||||
lgpl2 = spdx {
|
||||
spdxId = "LGPL-2.0";
|
||||
fullName = "GNU Library General Public License v2 only";
|
||||
};
|
||||
|
||||
lgpl2Plus = spdx {
|
||||
spdxId = "LGPL-2.0+";
|
||||
fullName = "GNU Library General Public License v2 or later";
|
||||
};
|
||||
|
||||
lgpl21 = spdx {
|
||||
spdxId = "LGPL-2.1";
|
||||
fullName = "GNU Library General Public License v2.1 only";
|
||||
};
|
||||
|
||||
lgpl21Plus = spdx {
|
||||
spdxId = "LGPL-2.1+";
|
||||
fullName = "GNU Library General Public License v2.1 or later";
|
||||
};
|
||||
|
||||
lgpl3 = spdx {
|
||||
spdxId = "LGPL-3.0";
|
||||
fullName = "GNU Lesser General Public License v3.0 only";
|
||||
};
|
||||
|
||||
lgpl3Plus = spdx {
|
||||
spdxId = "LGPL-3.0+";
|
||||
fullName = "GNU Lesser General Public License v3.0 or later";
|
||||
};
|
||||
|
||||
libpng = spdx {
|
||||
spdxId = "Libpng";
|
||||
fullName = "libpng License";
|
||||
};
|
||||
|
||||
libtiff = spdx {
|
||||
spdxId = "libtiff";
|
||||
fullName = "libtiff License";
|
||||
};
|
||||
|
||||
llgpl21 = {
|
||||
fullName = "Lisp LGPL; GNU Lesser General Public License version 2.1 with Franz Inc. preamble for clarification of LGPL terms in context of Lisp";
|
||||
url = http://opensource.franz.com/preamble.html;
|
||||
};
|
||||
|
||||
lppl12 = spdx {
|
||||
spdxId = "LPPL-1.2";
|
||||
fullName = "LaTeX Project Public License v1.2";
|
||||
};
|
||||
|
||||
lppl13c = spdx {
|
||||
spdxId = "LPPL-1.3c";
|
||||
fullName = "LaTeX Project Public License v1.3c";
|
||||
};
|
||||
|
||||
lpl-102 = spdx {
|
||||
spdxId = "LPL-1.02";
|
||||
fullName = "Lucent Public License v1.02";
|
||||
};
|
||||
|
||||
# spdx.org does not (yet) differentiate between the X11 and Expat versions
|
||||
# for details see http://en.wikipedia.org/wiki/MIT_License#Various_versions
|
||||
mit = spdx {
|
||||
spdxId = "MIT";
|
||||
fullName = "MIT License";
|
||||
};
|
||||
|
||||
mpl10 = spdx {
|
||||
spdxId = "MPL-1.0";
|
||||
fullName = "Mozilla Public License 1.0";
|
||||
};
|
||||
|
||||
mpl11 = spdx {
|
||||
spdxId = "MPL-1.1";
|
||||
fullName = "Mozilla Public License 1.1";
|
||||
};
|
||||
|
||||
mpl20 = spdx {
|
||||
spdxId = "MPL-2.0";
|
||||
fullName = "Mozilla Public License 2.0";
|
||||
};
|
||||
|
||||
msrla = {
|
||||
fullName = "Microsoft Research License Agreement";
|
||||
url = "http://research.microsoft.com/en-us/projects/pex/msr-la.txt";
|
||||
};
|
||||
|
||||
ncsa = spdx {
|
||||
spdxId = "NCSA";
|
||||
fullName = "University of Illinois/NCSA Open Source License";
|
||||
};
|
||||
|
||||
notion_lgpl = {
|
||||
url = "https://raw.githubusercontent.com/raboof/notion/master/LICENSE";
|
||||
fullName = "Notion modified LGPL";
|
||||
};
|
||||
|
||||
ofl = spdx {
|
||||
spdxId = "OFL-1.1";
|
||||
fullName = "SIL Open Font License 1.1";
|
||||
};
|
||||
|
||||
openldap = spdx {
|
||||
spdxId = "OLDAP-2.8";
|
||||
fullName = "Open LDAP Public License v2.8";
|
||||
};
|
||||
|
||||
openssl = spdx {
|
||||
spdxId = "OpenSSL";
|
||||
fullName = "OpenSSL License";
|
||||
};
|
||||
|
||||
php301 = spdx {
|
||||
spdxId = "PHP-3.01";
|
||||
fullName = "PHP License v3.01";
|
||||
};
|
||||
|
||||
postgresql = spdx {
|
||||
spdxId = "PostgreSQL";
|
||||
fullName = "PostgreSQL License";
|
||||
};
|
||||
|
||||
psfl = spdx {
|
||||
spdxId = "Python-2.0";
|
||||
fullName = "Python Software Foundation License version 2";
|
||||
#url = http://docs.python.org/license.html;
|
||||
};
|
||||
|
||||
publicDomain = {
|
||||
fullName = "Public Domain";
|
||||
};
|
||||
|
||||
qpl = spdx {
|
||||
spdxId = "QPL-1.0";
|
||||
fullName = "Q Public License 1.0";
|
||||
};
|
||||
|
||||
qwt = {
|
||||
fullName = "Qwt License, Version 1.0";
|
||||
url = http://qwt.sourceforge.net/qwtlicense.html;
|
||||
};
|
||||
|
||||
ruby = spdx {
|
||||
spdxId = "Ruby";
|
||||
fullName = "Ruby License";
|
||||
};
|
||||
|
||||
sgi-b-20 = spdx {
|
||||
spdxId = "SGI-B-2.0";
|
||||
fullName = "SGI Free Software License B v2.0";
|
||||
};
|
||||
|
||||
sleepycat = spdx {
|
||||
spdxId = "Sleepycat";
|
||||
fullName = "Sleepycat License";
|
||||
};
|
||||
|
||||
tcltk = spdx {
|
||||
spdxId = "TCL";
|
||||
fullName = "TCL/TK License";
|
||||
};
|
||||
|
||||
unfree = {
|
||||
fullName = "Unfree";
|
||||
free = false;
|
||||
};
|
||||
|
||||
unfreeRedistributable = {
|
||||
fullName = "Unfree redistributable";
|
||||
free = false;
|
||||
};
|
||||
|
||||
unfreeRedistributableFirmware = {
|
||||
fullName = "Unfree redistributable firmware";
|
||||
# Note: we currently consider these "free" for inclusion in the
|
||||
# channel and NixOS images.
|
||||
};
|
||||
|
||||
unlicense = spdx {
|
||||
spdxId = "Unlicense";
|
||||
fullName = "The Unlicense";
|
||||
};
|
||||
|
||||
vim = spdx {
|
||||
spdxId = "Vim";
|
||||
fullName = "Vim License";
|
||||
};
|
||||
|
||||
vsl10 = spdx {
|
||||
spdxId = "VSL-1.0";
|
||||
fullName = "Vovida Software License v1.0";
|
||||
};
|
||||
|
||||
w3c = spdx {
|
||||
spdxId = "W3C";
|
||||
fullName = "W3C Software Notice and License";
|
||||
};
|
||||
|
||||
wadalab = {
|
||||
fullName = "Wadalab Font License";
|
||||
url = https://fedoraproject.org/wiki/Licensing:Wadalab?rd=Licensing/Wadalab;
|
||||
};
|
||||
|
||||
wtfpl = spdx {
|
||||
spdxId = "WTFPL";
|
||||
fullName = "Do What The F*ck You Want To Public License";
|
||||
};
|
||||
|
||||
zlib = spdx {
|
||||
spdxId = "Zlib";
|
||||
fullName = "zlib License";
|
||||
};
|
||||
|
||||
zpt20 = spdx { # FIXME: why zpt* instead of zpl*
|
||||
spdxId = "ZPL-2.0";
|
||||
fullName = "Zope Public License 2.0";
|
||||
};
|
||||
|
||||
zpt21 = spdx {
|
||||
spdxId = "ZPL-2.1";
|
||||
fullName = "Zope Public License 2.1";
|
||||
};
|
||||
|
||||
}
|
||||
273
lib/lists.nix
273
lib/lists.nix
@@ -1,273 +0,0 @@
|
||||
# General list operations.
|
||||
|
||||
with import ./trivial.nix;
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) head tail length isList elemAt concatLists filter elem genList;
|
||||
|
||||
|
||||
# Create a list consisting of a single element. `singleton x' is
|
||||
# sometimes more convenient with respect to indentation than `[x]'
|
||||
# when x spans multiple lines.
|
||||
singleton = x: [x];
|
||||
|
||||
|
||||
# "Fold" a binary function `op' between successive elements of
|
||||
# `list' with `nul' as the starting value, i.e., `fold op nul [x_1
|
||||
# x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'. (This is
|
||||
# Haskell's foldr).
|
||||
fold = op: nul: list:
|
||||
let
|
||||
len = length list;
|
||||
fold' = n:
|
||||
if n == len
|
||||
then nul
|
||||
else op (elemAt list n) (fold' (n + 1));
|
||||
in fold' 0;
|
||||
|
||||
# Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul
|
||||
# x_1) x_2) ... x_n)'.
|
||||
foldl = op: nul: list:
|
||||
let
|
||||
len = length list;
|
||||
foldl' = n:
|
||||
if n == -1
|
||||
then nul
|
||||
else op (foldl' (n - 1)) (elemAt list n);
|
||||
in foldl' (length list - 1);
|
||||
|
||||
|
||||
# Strict version of foldl.
|
||||
foldl' = builtins.foldl' or foldl;
|
||||
|
||||
|
||||
# Map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
|
||||
# ["a-1" "b-2"]'. FIXME: why does this start to count at 1?
|
||||
imap =
|
||||
if builtins ? genList then
|
||||
f: list: genList (n: f (n + 1) (elemAt list n)) (length list)
|
||||
else
|
||||
f: list:
|
||||
let
|
||||
len = length list;
|
||||
imap' = n:
|
||||
if n == len
|
||||
then []
|
||||
else [ (f (n + 1) (elemAt list n)) ] ++ imap' (n + 1);
|
||||
in imap' 0;
|
||||
|
||||
|
||||
# Map and concatenate the result.
|
||||
concatMap = f: list: concatLists (map f list);
|
||||
|
||||
|
||||
# Flatten the argument into a single list; that is, nested lists are
|
||||
# spliced into the top-level lists. E.g., `flatten [1 [2 [3] 4] 5]
|
||||
# == [1 2 3 4 5]' and `flatten 1 == [1]'.
|
||||
flatten = x:
|
||||
if isList x
|
||||
then foldl' (x: y: x ++ (flatten y)) [] x
|
||||
else [x];
|
||||
|
||||
|
||||
# Remove elements equal to 'e' from a list. Useful for buildInputs.
|
||||
remove = e: filter (x: x != e);
|
||||
|
||||
|
||||
# Find the sole element in the list matching the specified
|
||||
# predicate, returns `default' if no such element exists, or
|
||||
# `multiple' if there are multiple matching elements.
|
||||
findSingle = pred: default: multiple: list:
|
||||
let found = filter pred list; len = length found;
|
||||
in if len == 0 then default
|
||||
else if len != 1 then multiple
|
||||
else head found;
|
||||
|
||||
|
||||
# Find the first element in the list matching the specified
|
||||
# predicate or returns `default' if no such element exists.
|
||||
findFirst = pred: default: list:
|
||||
let found = filter pred list;
|
||||
in if found == [] then default else head found;
|
||||
|
||||
|
||||
# Return true iff function `pred' returns true for at least element
|
||||
# of `list'.
|
||||
any = builtins.any or (pred: fold (x: y: if pred x then true else y) false);
|
||||
|
||||
|
||||
# Return true iff function `pred' returns true for all elements of
|
||||
# `list'.
|
||||
all = builtins.all or (pred: fold (x: y: if pred x then y else false) true);
|
||||
|
||||
|
||||
# Count how many times function `pred' returns true for the elements
|
||||
# of `list'.
|
||||
count = pred: foldl' (c: x: if pred x then c + 1 else c) 0;
|
||||
|
||||
|
||||
# Return a singleton list or an empty list, depending on a boolean
|
||||
# value. Useful when building lists with optional elements
|
||||
# (e.g. `++ optional (system == "i686-linux") flashplayer').
|
||||
optional = cond: elem: if cond then [elem] else [];
|
||||
|
||||
|
||||
# Return a list or an empty list, dependening on a boolean value.
|
||||
optionals = cond: elems: if cond then elems else [];
|
||||
|
||||
|
||||
# If argument is a list, return it; else, wrap it in a singleton
|
||||
# list. If you're using this, you should almost certainly
|
||||
# reconsider if there isn't a more "well-typed" approach.
|
||||
toList = x: if isList x then x else [x];
|
||||
|
||||
|
||||
# Return a list of integers from `first' up to and including `last'.
|
||||
range =
|
||||
if builtins ? genList then
|
||||
first: last:
|
||||
if first > last
|
||||
then []
|
||||
else genList (n: first + n) (last - first + 1)
|
||||
else
|
||||
first: last:
|
||||
if last < first
|
||||
then []
|
||||
else [first] ++ range (first + 1) last;
|
||||
|
||||
|
||||
# Partition the elements of a list in two lists, `right' and
|
||||
# `wrong', depending on the evaluation of a predicate.
|
||||
partition = pred:
|
||||
fold (h: t:
|
||||
if pred h
|
||||
then { right = [h] ++ t.right; wrong = t.wrong; }
|
||||
else { right = t.right; wrong = [h] ++ t.wrong; }
|
||||
) { right = []; wrong = []; };
|
||||
|
||||
|
||||
zipListsWith =
|
||||
if builtins ? genList then
|
||||
f: fst: snd: genList (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd))
|
||||
else
|
||||
f: fst: snd:
|
||||
let
|
||||
len = min (length fst) (length snd);
|
||||
zipListsWith' = n:
|
||||
if n != len then
|
||||
[ (f (elemAt fst n) (elemAt snd n)) ]
|
||||
++ zipListsWith' (n + 1)
|
||||
else [];
|
||||
in zipListsWith' 0;
|
||||
|
||||
zipLists = zipListsWith (fst: snd: { inherit fst snd; });
|
||||
|
||||
|
||||
# Reverse the order of the elements of a list.
|
||||
reverseList =
|
||||
if builtins ? genList then
|
||||
xs: let l = length xs; in genList (n: elemAt xs (l - n - 1)) l
|
||||
else
|
||||
fold (e: acc: acc ++ [ e ]) [];
|
||||
|
||||
|
||||
# Sort a list based on a comparator function which compares two
|
||||
# elements and returns true if the first argument is strictly below
|
||||
# the second argument. The returned list is sorted in an increasing
|
||||
# order. The implementation does a quick-sort.
|
||||
sort = builtins.sort or (
|
||||
strictLess: list:
|
||||
let
|
||||
len = length list;
|
||||
first = head list;
|
||||
pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (n + 1); in
|
||||
if n == len
|
||||
then acc
|
||||
else if strictLess first el
|
||||
then next { inherit left; right = [ el ] ++ right; }
|
||||
else
|
||||
next { left = [ el ] ++ left; inherit right; };
|
||||
pivot = pivot' 1 { left = []; right = []; };
|
||||
in
|
||||
if len < 2 then list
|
||||
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
|
||||
|
||||
|
||||
# Return the first (at most) N elements of a list.
|
||||
take =
|
||||
if builtins ? genList then
|
||||
count: sublist 0 count
|
||||
else
|
||||
count: list:
|
||||
let
|
||||
len = length list;
|
||||
take' = n:
|
||||
if n == len || n == count
|
||||
then []
|
||||
else
|
||||
[ (elemAt list n) ] ++ take' (n + 1);
|
||||
in take' 0;
|
||||
|
||||
|
||||
# Remove the first (at most) N elements of a list.
|
||||
drop =
|
||||
if builtins ? genList then
|
||||
count: list: sublist count (length list) list
|
||||
else
|
||||
count: list:
|
||||
let
|
||||
len = length list;
|
||||
drop' = n:
|
||||
if n == -1 || n < count
|
||||
then []
|
||||
else
|
||||
drop' (n - 1) ++ [ (elemAt list n) ];
|
||||
in drop' (len - 1);
|
||||
|
||||
|
||||
# Return a list consisting of at most ‘count’ elements of ‘list’,
|
||||
# starting at index ‘start’.
|
||||
sublist = start: count: list:
|
||||
let len = length list; in
|
||||
genList
|
||||
(n: elemAt list (n + start))
|
||||
(if start >= len then 0
|
||||
else if start + count > len then len - start
|
||||
else count);
|
||||
|
||||
|
||||
# Return the last element of a list.
|
||||
last = list:
|
||||
assert list != []; elemAt list (length list - 1);
|
||||
|
||||
|
||||
# Return all elements but the last
|
||||
init = list: assert list != []; take (length list - 1) list;
|
||||
|
||||
|
||||
deepSeqList = xs: y: if any (x: deepSeq x false) xs then y else y;
|
||||
|
||||
|
||||
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
||||
|
||||
|
||||
# Remove duplicate elements from the list. O(n^2) complexity.
|
||||
unique = list:
|
||||
if list == [] then
|
||||
[]
|
||||
else
|
||||
let
|
||||
x = head list;
|
||||
xs = unique (drop 1 list);
|
||||
in [x] ++ remove x xs;
|
||||
|
||||
|
||||
# Intersects list 'e' and another list. O(nm) complexity.
|
||||
intersectLists = e: filter (x: elem x e);
|
||||
|
||||
|
||||
# Subtracts list 'e' from another list. O(nm) complexity.
|
||||
subtractLists = e: filter (x: !(elem x e));
|
||||
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
/* -*- coding: utf-8; -*- */
|
||||
|
||||
{
|
||||
/* Add your name and email address here.
|
||||
Keep the list alphabetically sorted.
|
||||
Prefer the same attrname as your github username, please,
|
||||
so it's easy to ping a package @maintainer.
|
||||
*/
|
||||
|
||||
a1russell = "Adam Russell <adamlr6+pub@gmail.com>";
|
||||
abaldeau = "Andreas Baldeau <andreas@baldeau.net>";
|
||||
abbradar = "Nikolay Amiantov <ab@fmap.me>";
|
||||
adev = "Adrien Devresse <adev@adev.name>";
|
||||
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
|
||||
aflatter = "Alexander Flatter <flatter@fastmail.fm>";
|
||||
aherrmann = "Andreas Herrmann <andreash87@gmx.ch>";
|
||||
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>";
|
||||
all = "Nix Committers <nix-commits@lists.science.uu.nl>";
|
||||
amiddelk = "Arie Middelkoop <amiddelk@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>";
|
||||
antono = "Antono Vasiljev <self@antono.info>";
|
||||
ardumont = "Antoine R. Dumont <eniotna.t@gmail.com>";
|
||||
aristid = "Aristid Breitkreuz <aristidb@gmail.com>";
|
||||
arobyn = "Alexei Robyn <shados@shados.net>";
|
||||
asppsa = "Alastair Pharo <asppsa@gmail.com>";
|
||||
astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>";
|
||||
aszlig = "aszlig <aszlig@redmoonstudios.org>";
|
||||
auntie = "Jonathan Glines <auntieNeo@gmail.com>";
|
||||
avnik = "Alexander V. Nikolaev <avn@avnik.info>";
|
||||
aycanirican = "Aycan iRiCAN <iricanaycan@gmail.com>";
|
||||
badi = "Badi' Abdul-Wahid <abdulwahidc@gmail.com>";
|
||||
balajisivaraman = "Balaji Sivaraman<sivaraman.balaji@gmail.com>";
|
||||
bbenoist = "Baptist BENOIST <return_0@live.com>";
|
||||
bcarrell = "Brandon Carrell <brandoncarrell@gmail.com>";
|
||||
bcdarwin = "Ben Darwin <bcdarwin@gmail.com>";
|
||||
bdimcheff = "Brandon Dimcheff <brandon@dimcheff.com>";
|
||||
bennofs = "Benno Fünfstück <benno.fuenfstueck@gmail.com>";
|
||||
benley = "Benjamin Staffin <benley@gmail.com>";
|
||||
berdario = "Dario Bertini <berdario@gmail.com>";
|
||||
bergey = "Daniel Bergey <bergey@teallabs.org>";
|
||||
bjg = "Brian Gough <bjg@gnu.org>";
|
||||
bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>";
|
||||
bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>";
|
||||
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>";
|
||||
bramd = "Bram Duvigneau <bram@bramd.nl>";
|
||||
bstrik = "Berno Strik <dutchman55@gmx.com>";
|
||||
c0dehero = "CodeHero <codehero@nerdpol.ch>";
|
||||
calrama = "Moritz Maxeiner <moritz@ucworks.org>";
|
||||
campadrenalin = "Philip Horger <campadrenalin@gmail.com>";
|
||||
cdepillabout = "Dennis Gosnell <cdep.illabout@gmail.com>";
|
||||
cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>";
|
||||
chaoflow = "Florian Friesdorf <flo@chaoflow.net>";
|
||||
chattered = "Phil Scott <me@philscotted.com>";
|
||||
christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>";
|
||||
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
|
||||
codyopel = "Cody Opel <codyopel@gmail.com>";
|
||||
copumpkin = "Dan Peebles <pumpkingod@gmail.com>";
|
||||
coroa = "Jonas Hörsch <jonas@chaoflow.net>";
|
||||
couchemar = "Andrey Pavlov <couchemar@yandex.ru>";
|
||||
cstrahan = "Charles Strahan <charles.c.strahan@gmail.com>";
|
||||
cwoac = "Oliver Matthews <oliver@codersoffortune.net>";
|
||||
DamienCassou = "Damien Cassou <damien@cassou.me>";
|
||||
davidrusu = "David Rusu <davidrusu.me@gmail.com>";
|
||||
dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>";
|
||||
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
|
||||
deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>";
|
||||
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>";
|
||||
dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>";
|
||||
doublec = "Chris Double <chris.double@double.co.nz>";
|
||||
ebzzry = "Rommel Martinez <ebzzry@gmail.com>";
|
||||
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>";
|
||||
eikek = "Eike Kettner <eike.kettner@posteo.de>";
|
||||
ellis = "Ellis Whitehead <nixos@ellisw.net>";
|
||||
emery = "Emery Hemingway <emery@vfemail.net>";
|
||||
epitrochoid = "Mabry Cervin <mpcervin@uncg.edu>";
|
||||
ericbmerritt = "Eric Merritt <eric@afiniate.com>";
|
||||
ertes = "Ertugrul Söylemez <ertesx@gmx.de>";
|
||||
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
||||
falsifian = "James Cook <james.cook@utoronto.ca>";
|
||||
flosse = "Markus Kohlhase <mail@markus-kohlhase.de>";
|
||||
fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>";
|
||||
forkk = "Andrew Okin <forkk@forkk.net>";
|
||||
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
|
||||
fridh = "Frederik Rietdijk <fridh@fridh.nl>";
|
||||
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>";
|
||||
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>";
|
||||
gfxmonk = "Tim Cuthbertson <tim@gfxmonk.net>";
|
||||
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
|
||||
globin = "Robin Gloster <robin@glob.in>";
|
||||
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
|
||||
gridaphobe = "Eric Seidel <eric@seidel.io>";
|
||||
guibert = "David Guibert <david.guibert@gmail.com>";
|
||||
havvy = "Ryan Scheel <ryan.havvy@gmail.com>";
|
||||
hbunke = "Hendrik Bunke <bunke.hendrik@gmail.com>";
|
||||
henrytill = "Henry Till <henrytill@gmail.com>";
|
||||
hiberno = "Christian Lask <mail@elfsechsundzwanzig.de>";
|
||||
hinton = "Tom Hinton <t@larkery.com>";
|
||||
hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>";
|
||||
iand675 = "Ian Duncan <ian@iankduncan.com>";
|
||||
ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>";
|
||||
iElectric = "Domen Kozar <domen@dev.si>";
|
||||
ikervagyok = "Balázs Lengyel <ikervagyok@gmail.com>";
|
||||
iyzsong = "Song Wenwu <iyzsong@gmail.com>";
|
||||
j-keck = "Jürgen Keck <jhyphenkeck@gmail.com>";
|
||||
jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>";
|
||||
jb55 = "William Casarin <bill@casarin.me>";
|
||||
jcumming = "Jack Cummings <jack@mudshark.org>";
|
||||
jefdaj = "Jeffrey David Johnson <jefdaj@gmail.com>";
|
||||
jfb = "James Felix Black <james@yamtime.com>";
|
||||
jgeerds = "Jascha Geerds <jg@ekby.de>";
|
||||
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
|
||||
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>";
|
||||
jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>";
|
||||
jwiegley = "John Wiegley <johnw@newartisans.com>";
|
||||
jwilberding = "Jordan Wilberding <jwilberding@afiniate.com>";
|
||||
jzellner = "Jeff Zellner <jeffz@eml.cc>";
|
||||
kamilchm = "Kamil Chmielewski <kamil.chm@gmail.com>";
|
||||
khumba = "Bryan Gardiner <bog@khumba.net>";
|
||||
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
|
||||
koral = "Koral <koral@mailoo.org>";
|
||||
kovirobi = "Kovacsics Robert <kovirobi@gmail.com>";
|
||||
kragniz = "Louis Taylor <kragniz@gmail.com>";
|
||||
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
|
||||
lassulus = "Lassulus <lassulus@gmail.com>";
|
||||
layus = "Guillaume Maudoux <layus.on@gmail.com>";
|
||||
lebastr = "Alexander Lebedev <lebastr@gmail.com>";
|
||||
leonardoce = "Leonardo Cecchi <leonardo.cecchi@gmail.com>";
|
||||
lethalman = "Luca Bruno <lucabru@src.gnome.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>";
|
||||
lovek323 = "Jason O'Conal <jason@oconal.id.au>";
|
||||
lowfatcomputing = "Andreas Wagner <andreas.wagner@lowfatcomputing.org>";
|
||||
lsix = "Lancelot SIX <lsix@lancelotsix.com>";
|
||||
ludo = "Ludovic Courtès <ludo@gnu.org>";
|
||||
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>";
|
||||
maurer = "Matthew Maurer <matthew.r.maurer+nix@gmail.com>";
|
||||
matejc = "Matej Cotman <cotman.matej@gmail.com>";
|
||||
mathnerd314 = "Mathnerd314 <mathnerd314.gph+hs@gmail.com>";
|
||||
matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>";
|
||||
mbakke = "Marius Bakke <ymse@tuta.io>";
|
||||
meditans = "Carlo Nucera <meditans@gmail.com>";
|
||||
meisternu = "Matt Miemiec <meister@krutt.org>";
|
||||
michelk = "Michel Kuhlmann <michel@kuhlmanns.info>";
|
||||
mirdhyn = "Merlin Gaillard <mirdhyn@gmail.com>";
|
||||
mschristiansen = "Mikkel Christiansen <mikkel@rheosystems.com>";
|
||||
modulistic = "Pablo Costa <modulistic@gmail.com>";
|
||||
mornfall = "Petr Ročkai <me@mornfall.net>";
|
||||
MP2E = "Cray Elliott <MP2E@archlinux.us>";
|
||||
msackman = "Matthew Sackman <matthew@wellquite.org>";
|
||||
mtreskin = "Max Treskin <zerthurd@gmail.com>";
|
||||
mudri = "James Wood <lamudri@gmail.com>";
|
||||
muflax = "Stefan Dorn <mail@muflax.com>";
|
||||
nathan-gs = "Nathan Bijnens <nathan@nathan.gs>";
|
||||
nckx = "Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>";
|
||||
notthemessiah = "Brian Cohen <brian.cohen.88@gmail.com>";
|
||||
np = "Nicolas Pouillard <np.nix@nicolaspouillard.fr>";
|
||||
nslqqq = "Nikita Mikhailov <nslqqq@gmail.com>";
|
||||
obadz = "obadz <dav-nixos@odav.org>";
|
||||
ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
|
||||
odi = "Oliver Dunkl <oliver.dunkl@gmail.com>";
|
||||
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
|
||||
olcai = "Erik Timan <dev@timan.info>";
|
||||
orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
|
||||
osener = "Ozan Sener <ozan@ozansener.com>";
|
||||
page = "Carles Pagès <page@cubata.homelinux.net>";
|
||||
paholg = "Paho Lurie-Gregg <paho@paholg.com>";
|
||||
pakhfn = "Fedor Pakhomov <pakhfn@gmail.com>";
|
||||
pashev = "Igor Pashev <pashev.igor@gmail.com>";
|
||||
pesterhazy = "Paulus Esterhazy <pesterhazy@gmail.com>";
|
||||
phausmann = "Philipp Hausmann <nix@314.ch>";
|
||||
philandstuff = "Philip Potter <philip.g.potter@gmail.com>";
|
||||
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
|
||||
pierron = "Nicolas B. Pierron <nixos@nbp.name>";
|
||||
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
|
||||
pjones = "Peter Jones <pjones@devalot.com>";
|
||||
pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>";
|
||||
plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>";
|
||||
pmahoney = "Patrick Mahoney <pat@polycrystal.org>";
|
||||
pmiddend = "Philipp Middendorf <pmidden@secure.mailbox.org>";
|
||||
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
||||
psibi = "Sibi <sibi@psibi.in>";
|
||||
pSub = "Pascal Wittmann <mail@pascal-wittmann.de>";
|
||||
puffnfresh = "Brian McKenna <brian@brianmckenna.org>";
|
||||
qknight = "Joachim Schiele <js@lastlog.de>";
|
||||
ragge = "Ragnar Dahlen <r.dahlen@gmail.com>";
|
||||
raskin = "Michael Raskin <7c6f434c@mail.ru>";
|
||||
redbaron = "Maxim Ivanov <ivanov.maxim@gmail.com>";
|
||||
refnil = "Martin Lavoie <broemartino@gmail.com>";
|
||||
relrod = "Ricky Elrod <ricky@elrod.me>";
|
||||
renzo = "Renzo Carbonara <renzocarbonara@gmail.com>";
|
||||
rick68 = "Wei-Ming Yang <rick68@gmail.com>";
|
||||
rickynils = "Rickard Nilsson <rickynils@gmail.com>";
|
||||
rob = "Rob Vermaas <rob.vermaas@gmail.com>";
|
||||
robberer = "Longrin Wischnewski <robberer@freakmail.de>";
|
||||
robbinch = "Robbin C. <robbinch33@gmail.com>";
|
||||
roconnor = "Russell O'Connor <roconnor@theorem.ca>";
|
||||
roelof = "Roelof Wobben <rwobben@hotmail.com>";
|
||||
romildo = "José Romildo Malaquias <malaquias@gmail.com>";
|
||||
rszibele = "Richard Szibele <richard_szibele@hotmail.com>";
|
||||
rushmorem = "Rushmore Mushambi <rushmore@webenchanter.com>";
|
||||
rycee = "Robert Helgesson <robert@rycee.net>";
|
||||
samuelrivas = "Samuel Rivas <samuelrivas@gmail.com>";
|
||||
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
|
||||
schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>";
|
||||
schristo = "Scott Christopher <schristopher@konputa.com>";
|
||||
sepi = "Raffael Mancini <raffael@mancini.lu>";
|
||||
sheganinans = "Aistis Raulinaitis <sheganinans@gmail.com>";
|
||||
shell = "Shell Turner <cam.turn@gmail.com>";
|
||||
shlevy = "Shea Levy <shea@shealevy.com>";
|
||||
simons = "Peter Simons <simons@cryp.to>";
|
||||
simonvandel = "Simon Vandel Sillesen <simon.vandel@gmail.com>";
|
||||
sjagoe = "Simon Jagoe <simon@simonjagoe.com>";
|
||||
sjmackenzie = "Stewart Mackenzie <setori88@gmail.com>";
|
||||
skeidel = "Sven Keidel <svenkeidel@gmail.com>";
|
||||
smironov = "Sergey Mironov <ierton@gmail.com>";
|
||||
spacefrogg = "Michael Raitza <spacefrogg-nixos@meterriblecrew.net>";
|
||||
sprock = "Roger Mason <rmason@mun.ca>";
|
||||
spwhitt = "Spencer Whitt <sw@swhitt.me>";
|
||||
stephenmw = "Stephen Weinberg <stephen@q5comm.com>";
|
||||
szczyp = "Szczyp <qb@szczyp.com>";
|
||||
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
|
||||
tailhook = "Paul Colomiets <paul@colomiets.name>";
|
||||
taktoa = "Remy Goldschmidt <taktoa@gmail.com>";
|
||||
telotortium = "Robert Irelan <rirelan@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>";
|
||||
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
|
||||
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
|
||||
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
|
||||
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
|
||||
tstrobel = "Thomas Strobel <ts468@cam.ac.uk>";
|
||||
ttuegel = "Thomas Tuegel <ttuegel@gmail.com>";
|
||||
tv = "Tomislav Viljetić <tv@shackspace.de>";
|
||||
twey = "James ‘Twey’ Kay <twey@twey.co.uk>";
|
||||
urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>";
|
||||
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
||||
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
||||
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
||||
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
||||
viric = "Lluís Batlle i Rossell <viric@viric.name>";
|
||||
vizanto = "Danny Wilson <danny@prime.vc>";
|
||||
vlstill = "Vladimír Štill <xstill@fi.muni.cz>";
|
||||
vmandela = "Venkateswara Rao Mandela <venkat.mandela@gmail.com>";
|
||||
vozz = "Oliver Hunt <oliver.huntuk@gmail.com>";
|
||||
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
|
||||
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
|
||||
wjlroe = "William Roe <willroe@gmail.com>";
|
||||
womfoo = "Kranium Gikos Mendoza <kranium@gikos.net>";
|
||||
wkennington = "William A. Kennington III <william@wkennington.com>";
|
||||
wmertens = "Wout Mertens <Wout.Mertens@gmail.com>";
|
||||
wscott = "Wayne Scott <wsc9tt@gmail.com>";
|
||||
wyvie = "Elijah Rum <elijahrum@gmail.com>";
|
||||
yarr = "Dmitry V. <savraz@gmail.com>";
|
||||
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
|
||||
zef = "Zef Hemel <zef@zef.me>";
|
||||
zimbatm = "zimbatm <zimbatm@zimbatm.com>";
|
||||
zoomulator = "Kim Simmons <zoomulator@gmail.com>";
|
||||
Gonzih = "Max Gonzih <gonzih@gmail.com>";
|
||||
}
|
||||
66
lib/meta.nix
66
lib/meta.nix
@@ -1,66 +0,0 @@
|
||||
/* Some functions for manipulating meta attributes, as well as the
|
||||
name attribute. */
|
||||
|
||||
let lib = import ./default.nix;
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
|
||||
/* Add to or override the meta attributes of the given
|
||||
derivation.
|
||||
|
||||
Example:
|
||||
addMetaAttrs {description = "Bla blah";} somePkg
|
||||
*/
|
||||
addMetaAttrs = newAttrs: drv:
|
||||
drv // { meta = (drv.meta or {}) // newAttrs; };
|
||||
|
||||
|
||||
/* Change the symbolic name of a package for presentation purposes
|
||||
(i.e., so that nix-env users can tell them apart).
|
||||
*/
|
||||
setName = name: drv: drv // {inherit name;};
|
||||
|
||||
|
||||
/* Like `setName', but takes the previous name as an argument.
|
||||
|
||||
Example:
|
||||
updateName (oldName: oldName + "-experimental") somePkg
|
||||
*/
|
||||
updateName = updater: drv: drv // {name = updater (drv.name);};
|
||||
|
||||
|
||||
/* Append a suffix to the name of a package (before the version
|
||||
part). */
|
||||
appendToName = suffix: updateName (name:
|
||||
let x = builtins.parseDrvName name; in "${x.name}-${suffix}-${x.version}");
|
||||
|
||||
|
||||
/* Apply a function to each derivation and only to derivations in an attrset
|
||||
*/
|
||||
mapDerivationAttrset = f: set: lib.mapAttrs (name: pkg: if lib.isDerivation pkg then (f pkg) else pkg) set;
|
||||
|
||||
|
||||
/* Decrease the nix-env priority of the package, i.e., other
|
||||
versions/variants of the package will be preferred.
|
||||
*/
|
||||
lowPrio = drv: addMetaAttrs { priority = "10"; } drv;
|
||||
|
||||
|
||||
/* Apply lowPrio to an attrset with derivations
|
||||
*/
|
||||
lowPrioSet = set: mapDerivationAttrset lowPrio set;
|
||||
|
||||
|
||||
/* Increase the nix-env priority of the package, i.e., this
|
||||
version/variant of the package will be preferred.
|
||||
*/
|
||||
hiPrio = drv: addMetaAttrs { priority = "-10"; } drv;
|
||||
|
||||
|
||||
/* Apply hiPrio to an attrset with derivations
|
||||
*/
|
||||
hiPrioSet = set: mapDerivationAttrset hiPrio set;
|
||||
|
||||
}
|
||||
501
lib/modules.nix
501
lib/modules.nix
@@ -1,501 +0,0 @@
|
||||
with import ./lists.nix;
|
||||
with import ./trivial.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./options.nix;
|
||||
with import ./debug.nix;
|
||||
with import ./types.nix;
|
||||
|
||||
rec {
|
||||
|
||||
/* Evaluate a set of modules. The result is a set of two
|
||||
attributes: ‘options’: the nested set of all option declarations,
|
||||
and ‘config’: the nested set of all option values.
|
||||
!!! Please think twice before adding to this argument list! The more
|
||||
that is specified here instead of in the modules themselves the harder
|
||||
it is to transparently move a set of modules to be a submodule of another
|
||||
config (as the proper arguments need to be replicated at each call to
|
||||
evalModules) and the less declarative the module set is. */
|
||||
evalModules = { modules
|
||||
, prefix ? []
|
||||
, # This should only be used for special arguments that need to be evaluated
|
||||
# when resolving module structure (like in imports). For everything else,
|
||||
# there's _module.args.
|
||||
specialArgs ? {}
|
||||
, # This would be remove in the future, Prefer _module.args option instead.
|
||||
args ? {}
|
||||
, # This would be remove in the future, Prefer _module.check option instead.
|
||||
check ? true
|
||||
}:
|
||||
let
|
||||
# This internal module declare internal options under the `_module'
|
||||
# attribute. These options are fragile, as they are used by the
|
||||
# module system to change the interpretation of modules.
|
||||
internalModule = rec {
|
||||
_file = ./modules.nix;
|
||||
|
||||
key = _file;
|
||||
|
||||
options = {
|
||||
_module.args = mkOption {
|
||||
type = types.attrsOf types.unspecified;
|
||||
internal = true;
|
||||
description = "Arguments passed to each module.";
|
||||
};
|
||||
|
||||
_module.check = mkOption {
|
||||
type = types.bool;
|
||||
internal = true;
|
||||
default = check;
|
||||
description = "Whether to check whether all option definitions have matching declarations.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
_module.args = args;
|
||||
};
|
||||
};
|
||||
|
||||
closed = closeModules (modules ++ [ internalModule ]) ({ inherit config options; lib = import ./.; } // specialArgs);
|
||||
|
||||
# Note: the list of modules is reversed to maintain backward
|
||||
# compatibility with the old module system. Not sure if this is
|
||||
# the most sensible policy.
|
||||
options = mergeModules prefix (reverseList closed);
|
||||
|
||||
# Traverse options and extract the option values into the final
|
||||
# config set. At the same time, check whether all option
|
||||
# definitions have matching declarations.
|
||||
# !!! _module.check's value can't depend on any other config values
|
||||
# without an infinite recursion. One way around this is to make the
|
||||
# 'config' passed around to the modules be unconditionally unchecked,
|
||||
# and only do the check in 'result'.
|
||||
config = yieldConfig prefix options;
|
||||
yieldConfig = prefix: set:
|
||||
let res = removeAttrs (mapAttrs (n: v:
|
||||
if isOption v then v.value
|
||||
else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"];
|
||||
in
|
||||
if options._module.check.value && set ? _definedNames then
|
||||
foldl' (res: m:
|
||||
foldl' (res: name:
|
||||
if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
|
||||
res m.names)
|
||||
res set._definedNames
|
||||
else
|
||||
res;
|
||||
result = { inherit options config; };
|
||||
in result;
|
||||
|
||||
/* Close a set of modules under the ‘imports’ relation. */
|
||||
closeModules = modules: args:
|
||||
let
|
||||
toClosureList = file: parentKey: imap (n: x:
|
||||
if isAttrs x || isFunction x then
|
||||
let key = "${parentKey}:anon-${toString n}"; in
|
||||
unifyModuleSyntax file key (unpackSubmodule (applyIfFunction key) x args)
|
||||
else
|
||||
let file = toString x; key = toString x; in
|
||||
unifyModuleSyntax file key (applyIfFunction key (import x) args));
|
||||
in
|
||||
builtins.genericClosure {
|
||||
startSet = toClosureList unknownModule "" modules;
|
||||
operator = m: toClosureList m.file m.key m.imports;
|
||||
};
|
||||
|
||||
/* Massage a module into canonical form, that is, a set consisting
|
||||
of ‘options’, ‘config’ and ‘imports’ attributes. */
|
||||
unifyModuleSyntax = file: key: m:
|
||||
if m ? config || m ? options then
|
||||
let badAttrs = removeAttrs m ["imports" "options" "config" "key" "_file"]; in
|
||||
if badAttrs != {} then
|
||||
throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by assignments to the top-level attributes `config' or `options'."
|
||||
else
|
||||
{ file = m._file or file;
|
||||
key = toString m.key or key;
|
||||
imports = m.imports or [];
|
||||
options = m.options or {};
|
||||
config = m.config or {};
|
||||
}
|
||||
else
|
||||
{ file = m._file or file;
|
||||
key = toString m.key or key;
|
||||
imports = m.require or [] ++ m.imports or [];
|
||||
options = {};
|
||||
config = removeAttrs m ["key" "_file" "require" "imports"];
|
||||
};
|
||||
|
||||
applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
|
||||
let
|
||||
# Module arguments are resolved in a strict manner when attribute set
|
||||
# deconstruction is used. As the arguments are now defined with the
|
||||
# config._module.args option, the strictness used on the attribute
|
||||
# set argument would cause an infinite loop, if the result of the
|
||||
# option is given as argument.
|
||||
#
|
||||
# To work-around the strictness issue on the deconstruction of the
|
||||
# attributes set argument, we create a new attribute set which is
|
||||
# constructed to satisfy the expected set of attributes. Thus calling
|
||||
# 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);
|
||||
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
|
||||
extraArgs = builtins.listToAttrs (map (name: {
|
||||
inherit name;
|
||||
value = addErrorContext (context name)
|
||||
(args.${name} or config._module.args.${name});
|
||||
}) requiredArgs);
|
||||
|
||||
# Note: we append in the opposite order such that we can add an error
|
||||
# context on the explicited arguments of "args" too. This update
|
||||
# operator is used to make the "args@{ ... }: with args.lib;" notation
|
||||
# works.
|
||||
in f (args // extraArgs)
|
||||
else
|
||||
f;
|
||||
|
||||
/* We have to pack and unpack submodules. We cannot wrap the expected
|
||||
result of the function as we would no longer be able to list the arguments
|
||||
of the submodule. (see applyIfFunction) */
|
||||
unpackSubmodule = unpack: m: args:
|
||||
if isType "submodule" m then
|
||||
{ _file = m.file; } // (unpack m.submodule args)
|
||||
else unpack m args;
|
||||
|
||||
packSubmodule = file: m:
|
||||
{ _type = "submodule"; file = file; submodule = m; };
|
||||
|
||||
/* Merge a list of modules. This will recurse over the option
|
||||
declarations in all modules, combining them into a single set.
|
||||
At the same time, for each option declaration, it will merge the
|
||||
corresponding option definitions in all machines, returning them
|
||||
in the ‘value’ attribute of each option. */
|
||||
mergeModules = prefix: modules:
|
||||
mergeModules' prefix modules
|
||||
(concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);
|
||||
|
||||
mergeModules' = prefix: options: configs:
|
||||
listToAttrs (map (name: {
|
||||
# We're descending into attribute ‘name’.
|
||||
inherit name;
|
||||
value =
|
||||
let
|
||||
loc = prefix ++ [name];
|
||||
# Get all submodules that declare ‘name’.
|
||||
decls = concatMap (m:
|
||||
if m.options ? ${name}
|
||||
then [ { inherit (m) file; options = m.options.${name}; } ]
|
||||
else []
|
||||
) options;
|
||||
# Get all submodules that define ‘name’.
|
||||
defns = concatMap (m:
|
||||
if m.config ? ${name}
|
||||
then map (config: { inherit (m) file; inherit config; })
|
||||
(pushDownProperties m.config.${name})
|
||||
else []
|
||||
) configs;
|
||||
nrOptions = count (m: isOption m.options) decls;
|
||||
# Extract the definitions for this loc
|
||||
defns' = map (m: { inherit (m) file; value = m.config.${name}; })
|
||||
(filter (m: m.config ? ${name}) configs);
|
||||
in
|
||||
if nrOptions == length decls then
|
||||
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
|
||||
in evalOptionValue loc opt defns'
|
||||
else if nrOptions != 0 then
|
||||
let
|
||||
firstOption = findFirst (m: isOption m.options) "" decls;
|
||||
firstNonOption = findFirst (m: !isOption m.options) "" decls;
|
||||
in
|
||||
throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
|
||||
else
|
||||
mergeModules' loc decls defns;
|
||||
}) (concatMap (m: attrNames m.options) options))
|
||||
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
|
||||
|
||||
/* Merge multiple option declarations into a single declaration. In
|
||||
general, there should be only one declaration of each option.
|
||||
The exception is the ‘options’ attribute, which specifies
|
||||
sub-options. These can be specified multiple times to allow one
|
||||
module to add sub-options to an option declared somewhere else
|
||||
(e.g. multiple modules define sub-options for ‘fileSystems’).
|
||||
|
||||
'loc' is the list of attribute names where the option is located.
|
||||
|
||||
'opts' is a list of modules. Each module has an options attribute which
|
||||
correspond to the definition of 'loc' in 'opt.file'. */
|
||||
mergeOptionDecls = loc: opts:
|
||||
foldl' (res: opt:
|
||||
if opt.options ? default && res ? default ||
|
||||
opt.options ? example && res ? example ||
|
||||
opt.options ? description && res ? description ||
|
||||
opt.options ? apply && res ? apply ||
|
||||
# Accept to merge options which have identical types.
|
||||
opt.options ? type && res ? type && opt.options.type.name != res.type.name
|
||||
then
|
||||
throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}."
|
||||
else
|
||||
let
|
||||
/* Add the modules of the current option to the list of modules
|
||||
already collected. The options attribute except either a list of
|
||||
submodules or a submodule. For each submodule, we add the file of the
|
||||
current option declaration as the file use for the submodule. If the
|
||||
submodule defines any filename, then we ignore the enclosing option file. */
|
||||
options' = toList opt.options.options;
|
||||
coerceOption = file: opt:
|
||||
if isFunction opt then packSubmodule file opt
|
||||
else packSubmodule file { options = opt; };
|
||||
getSubModules = opt.options.type.getSubModules or null;
|
||||
submodules =
|
||||
if getSubModules != null then map (packSubmodule opt.file) getSubModules ++ res.options
|
||||
else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options
|
||||
else res.options;
|
||||
in opt.options // res //
|
||||
{ declarations = res.declarations ++ [opt.file];
|
||||
options = submodules;
|
||||
}
|
||||
) { inherit loc; declarations = []; options = []; } opts;
|
||||
|
||||
/* Merge all the definitions of an option to produce the final
|
||||
config value. */
|
||||
evalOptionValue = loc: opt: defs:
|
||||
let
|
||||
# Add in the default value for this option, if any.
|
||||
defs' =
|
||||
(optional (opt ? default)
|
||||
{ file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
|
||||
|
||||
# Handle properties, check types, and merge everything together.
|
||||
res =
|
||||
if opt.readOnly or false && length defs' > 1 then
|
||||
throw "The option `${showOption loc}' is read-only, but it's set multiple times."
|
||||
else
|
||||
mergeDefinitions loc opt.type defs';
|
||||
|
||||
# Check whether the option is defined, and apply the ‘apply’
|
||||
# function to the merged value. This allows options to yield a
|
||||
# value computed from the definitions.
|
||||
value =
|
||||
if !res.isDefined then
|
||||
throw "The option `${showOption loc}' is used but not defined."
|
||||
else if opt ? apply then
|
||||
opt.apply res.mergedValue
|
||||
else
|
||||
res.mergedValue;
|
||||
|
||||
in opt //
|
||||
{ value = addErrorContext "while evaluating the option `${showOption loc}':" value;
|
||||
definitions = map (def: def.value) res.defsFinal;
|
||||
files = map (def: def.file) res.defsFinal;
|
||||
inherit (res) isDefined;
|
||||
};
|
||||
|
||||
# Merge definitions of a value of a given type.
|
||||
mergeDefinitions = loc: type: defs: rec {
|
||||
defsFinal =
|
||||
let
|
||||
# Process mkMerge and mkIf properties.
|
||||
defs' = concatMap (m:
|
||||
map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value)
|
||||
) defs;
|
||||
|
||||
# Process mkOverride properties.
|
||||
defs'' = filterOverrides defs';
|
||||
|
||||
# Sort mkOrder properties.
|
||||
defs''' =
|
||||
# Avoid sorting if we don't have to.
|
||||
if any (def: def.value._type or "" == "order") defs''
|
||||
then sortProperties defs''
|
||||
else defs'';
|
||||
in defs''';
|
||||
|
||||
# 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.name}.")
|
||||
(type.merge loc defsFinal) defsFinal;
|
||||
|
||||
isDefined = defsFinal != [];
|
||||
|
||||
optionalValue =
|
||||
if isDefined then { value = mergedValue; }
|
||||
else {};
|
||||
};
|
||||
|
||||
/* Given a config set, expand mkMerge properties, and push down the
|
||||
other properties into the children. The result is a list of
|
||||
config sets that do not have properties at top-level. For
|
||||
example,
|
||||
|
||||
mkMerge [ { boot = set1; } (mkIf cond { boot = set2; services = set3; }) ]
|
||||
|
||||
is transformed into
|
||||
|
||||
[ { boot = set1; } { boot = mkIf cond set2; services = mkIf cond set3; } ].
|
||||
|
||||
This transform is the critical step that allows mkIf conditions
|
||||
to refer to the full configuration without creating an infinite
|
||||
recursion.
|
||||
*/
|
||||
pushDownProperties = cfg:
|
||||
if cfg._type or "" == "merge" then
|
||||
concatMap pushDownProperties cfg.contents
|
||||
else if cfg._type or "" == "if" then
|
||||
map (mapAttrs (n: v: mkIf cfg.condition v)) (pushDownProperties cfg.content)
|
||||
else if cfg._type or "" == "override" then
|
||||
map (mapAttrs (n: v: mkOverride cfg.priority v)) (pushDownProperties cfg.content)
|
||||
else # FIXME: handle mkOrder?
|
||||
[ cfg ];
|
||||
|
||||
/* Given a config value, expand mkMerge properties, and discharge
|
||||
any mkIf conditions. That is, this is the place where mkIf
|
||||
conditions are actually evaluated. The result is a list of
|
||||
config values. For example, ‘mkIf false x’ yields ‘[]’,
|
||||
‘mkIf true x’ yields ‘[x]’, and
|
||||
|
||||
mkMerge [ 1 (mkIf true 2) (mkIf true (mkIf false 3)) ]
|
||||
|
||||
yields ‘[ 1 2 ]’.
|
||||
*/
|
||||
dischargeProperties = def:
|
||||
if def._type or "" == "merge" then
|
||||
concatMap dischargeProperties def.contents
|
||||
else if def._type or "" == "if" then
|
||||
if def.condition then
|
||||
dischargeProperties def.content
|
||||
else
|
||||
[ ]
|
||||
else
|
||||
[ def ];
|
||||
|
||||
/* Given a list of config values, process the mkOverride properties,
|
||||
that is, return the values that have the highest (that is,
|
||||
numerically lowest) priority, and strip the mkOverride
|
||||
properties. For example,
|
||||
|
||||
[ { file = "/1"; value = mkOverride 10 "a"; }
|
||||
{ file = "/2"; value = mkOverride 20 "b"; }
|
||||
{ file = "/3"; value = "z"; }
|
||||
{ file = "/4"; value = mkOverride 10 "d"; }
|
||||
]
|
||||
|
||||
yields
|
||||
|
||||
[ { file = "/1"; value = "a"; }
|
||||
{ file = "/4"; value = "d"; }
|
||||
]
|
||||
|
||||
Note that "z" has the default priority 100.
|
||||
*/
|
||||
filterOverrides = defs:
|
||||
let
|
||||
defaultPrio = 100;
|
||||
getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio;
|
||||
highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs;
|
||||
strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def;
|
||||
in concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
|
||||
|
||||
/* Sort a list of properties. The sort priority of a property is
|
||||
1000 by default, but can be overriden by wrapping the property
|
||||
using mkOrder. */
|
||||
sortProperties = defs:
|
||||
let
|
||||
strip = def:
|
||||
if def.value._type or "" == "order"
|
||||
then def // { value = def.value.content; inherit (def.value) priority; }
|
||||
else def;
|
||||
defs' = map strip defs;
|
||||
compare = a: b: (a.priority or 1000) < (b.priority or 1000);
|
||||
in sort compare defs';
|
||||
|
||||
/* Hack for backward compatibility: convert options of type
|
||||
optionSet to options of type submodule. FIXME: remove
|
||||
eventually. */
|
||||
fixupOptionType = loc: opt:
|
||||
let
|
||||
options = opt.options or
|
||||
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
|
||||
f = tp:
|
||||
if tp.name == "option set" || tp.name == "submodule" then
|
||||
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
|
||||
else if tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options)
|
||||
else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options)
|
||||
else if tp.name == "list of option sets" then types.listOf (types.submodule options)
|
||||
else if tp.name == "null or option set" then types.nullOr (types.submodule options)
|
||||
else tp;
|
||||
in
|
||||
if opt.type.getSubModules or null == null
|
||||
then opt // { type = f (opt.type or types.unspecified); }
|
||||
else opt // { type = opt.type.substSubModules opt.options; options = []; };
|
||||
|
||||
|
||||
/* Properties. */
|
||||
|
||||
mkIf = condition: content:
|
||||
{ _type = "if";
|
||||
inherit condition content;
|
||||
};
|
||||
|
||||
mkAssert = assertion: message: content:
|
||||
mkIf
|
||||
(if assertion then true else throw "\nFailed assertion: ${message}")
|
||||
content;
|
||||
|
||||
mkMerge = contents:
|
||||
{ _type = "merge";
|
||||
inherit contents;
|
||||
};
|
||||
|
||||
mkOverride = priority: content:
|
||||
{ _type = "override";
|
||||
inherit priority content;
|
||||
};
|
||||
|
||||
mkOptionDefault = mkOverride 1001; # priority of option defaults
|
||||
mkDefault = mkOverride 1000; # used in config sections of non-user modules to set a default
|
||||
mkForce = mkOverride 50;
|
||||
mkVMOverride = mkOverride 10; # used by ‘nixos-rebuild build-vm’
|
||||
|
||||
mkStrict = builtins.trace "`mkStrict' is obsolete; use `mkOverride 0' instead." (mkOverride 0);
|
||||
|
||||
mkFixStrictness = id; # obsolete, no-op
|
||||
|
||||
mkOrder = priority: content:
|
||||
{ _type = "order";
|
||||
inherit priority content;
|
||||
};
|
||||
|
||||
mkBefore = mkOrder 500;
|
||||
mkAfter = mkOrder 1500;
|
||||
|
||||
# Convenient property used to transfer all definitions and their
|
||||
# properties from one option to another. This property is useful for
|
||||
# renaming options, and also for including properties from another module
|
||||
# system, including sub-modules.
|
||||
#
|
||||
# { config, options, ... }:
|
||||
#
|
||||
# {
|
||||
# # 'bar' might not always be defined in the current module-set.
|
||||
# config.foo.enable = mkAliasDefinitions (options.bar.enable or {});
|
||||
#
|
||||
# # 'barbaz' has to be defined in the current module-set.
|
||||
# config.foobar.paths = mkAliasDefinitions options.barbaz.paths;
|
||||
# }
|
||||
#
|
||||
# Note, this is different than taking the value of the option and using it
|
||||
# as a definition, as the new definition will not keep the mkOverride /
|
||||
# mkDefault properties of the previous option.
|
||||
#
|
||||
mkAliasDefinitions = mkAliasAndWrapDefinitions id;
|
||||
mkAliasAndWrapDefinitions = wrap: option:
|
||||
mkMerge
|
||||
(optional (isOption option && option.isDefined)
|
||||
(wrap (mkMerge option.definitions)));
|
||||
|
||||
|
||||
/* Compatibility. */
|
||||
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
|
||||
|
||||
}
|
||||
133
lib/options.nix
133
lib/options.nix
@@ -1,133 +0,0 @@
|
||||
# Nixpkgs/NixOS option handling.
|
||||
|
||||
let lib = import ./default.nix; in
|
||||
|
||||
with import ./trivial.nix;
|
||||
with import ./lists.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./strings.nix;
|
||||
|
||||
rec {
|
||||
|
||||
isOption = lib.isType "option";
|
||||
mkOption =
|
||||
{ default ? null # Default value used when no definition is given in the configuration.
|
||||
, 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.
|
||||
, 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.
|
||||
, visible ? null # Whether the option shows up in the manual.
|
||||
, readOnly ? null # Whether the option can be set only once
|
||||
, options ? null # Obsolete, used by types.optionSet.
|
||||
} @ attrs:
|
||||
attrs // { _type = "option"; };
|
||||
|
||||
mkEnableOption = name: mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
description = "Whether to enable ${name}.";
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
# This option accept anything, but it does not produce any result. This
|
||||
# is useful for sharing a module across different module sets without
|
||||
# having to implement similar features as long as the value of the options
|
||||
# are not expected.
|
||||
mkSinkUndeclaredOptions = attrs: mkOption ({
|
||||
internal = true;
|
||||
visible = false;
|
||||
default = false;
|
||||
description = "Sink for option definitions.";
|
||||
type = mkOptionType {
|
||||
name = "sink";
|
||||
check = x: true;
|
||||
merge = loc: defs: false;
|
||||
};
|
||||
apply = x: throw "Option value is not readable because the option is not declared.";
|
||||
} // attrs);
|
||||
|
||||
mergeDefaultOption = loc: defs:
|
||||
let list = getValues defs; in
|
||||
if length list == 1 then head list
|
||||
else if all isFunction list then x: mergeDefaultOption loc (map (f: f x) list)
|
||||
else if all isList list then concatLists list
|
||||
else if all isAttrs list then foldl' lib.mergeAttrs {} list
|
||||
else if all isBool list then foldl' lib.or false list
|
||||
else if all isString list then lib.concatStrings list
|
||||
else if all isInt list && all (x: x == head list) list then head list
|
||||
else throw "Cannot merge definitions of `${showOption loc}' given in ${showFiles (getFiles defs)}.";
|
||||
|
||||
mergeOneOption = loc: defs:
|
||||
if defs == [] then abort "This case should never happen."
|
||||
else if length defs != 1 then
|
||||
throw "The unique option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
|
||||
else (head defs).value;
|
||||
|
||||
/* "Merge" option definitions by checking that they all have the same value. */
|
||||
mergeEqualOption = loc: defs:
|
||||
if defs == [] then abort "This case should never happen."
|
||||
else foldl' (val: def:
|
||||
if def.value != val then
|
||||
throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}."
|
||||
else
|
||||
val) (head defs).value defs;
|
||||
|
||||
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' [];
|
||||
|
||||
optionAttrSetToDocList' = prefix: options:
|
||||
concatMap (opt:
|
||||
let
|
||||
docOption = rec {
|
||||
name = showOption opt.loc;
|
||||
description = opt.description or (throw "Option `${name}' has no description.");
|
||||
declarations = filter (x: x != unknownModule) opt.declarations;
|
||||
internal = opt.internal or false;
|
||||
visible = opt.visible or true;
|
||||
readOnly = opt.readOnly or false;
|
||||
type = opt.type.name 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 {});
|
||||
|
||||
subOptions =
|
||||
let ss = opt.type.getSubOptions opt.loc;
|
||||
in if ss != {} then optionAttrSetToDocList' opt.loc ss else [];
|
||||
in
|
||||
[ docOption ] ++ subOptions) (collect isOption options);
|
||||
|
||||
|
||||
/* This function recursively removes all derivation attributes from
|
||||
`x' except for the `name' attribute. This is to make the
|
||||
generation of `options.xml' much more efficient: the XML
|
||||
representation of derivations is very large (on the order of
|
||||
megabytes) and is not actually used by the manual generator. */
|
||||
scrubOptionValue = x:
|
||||
if isDerivation x then
|
||||
{ type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; }
|
||||
else if isList x then map scrubOptionValue x
|
||||
else if isAttrs x then mapAttrs (n: v: scrubOptionValue v) (removeAttrs x ["_args"])
|
||||
else x;
|
||||
|
||||
|
||||
/* For use in the ‘example’ option attribute. It causes the given
|
||||
text to be included verbatim in documentation. This is necessary
|
||||
for example values that are not simple values, e.g.,
|
||||
functions. */
|
||||
literalExample = text: { _type = "literalExample"; inherit text; };
|
||||
|
||||
|
||||
/* Helper functions. */
|
||||
showOption = concatStringsSep ".";
|
||||
showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files);
|
||||
unknownModule = "<unknown-file>";
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
let lists = import ./lists.nix; in
|
||||
|
||||
rec {
|
||||
gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */
|
||||
linux = ["i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "mips64el-linux"];
|
||||
darwin = ["x86_64-darwin"];
|
||||
freebsd = ["i686-freebsd" "x86_64-freebsd"];
|
||||
openbsd = ["i686-openbsd" "x86_64-openbsd"];
|
||||
netbsd = ["i686-netbsd" "x86_64-netbsd"];
|
||||
cygwin = ["i686-cygwin" "x86_64-cygwin"];
|
||||
unix = linux ++ darwin ++ freebsd ++ openbsd;
|
||||
all = linux ++ darwin ++ cygwin ++ freebsd ++ openbsd;
|
||||
none = [];
|
||||
allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
|
||||
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux"];
|
||||
x86_64 = ["x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin"];
|
||||
i686 = ["i686-linux" "i686-freebsd" "i686-netbsd" "i686-cygwin"];
|
||||
arm = ["armv5tel-linux" "armv6l-linux" "armv7l-linux" ];
|
||||
mips = [ "mips64el-linux" ];
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
# Functions for copying sources to the Nix store.
|
||||
|
||||
let lib = import ./default.nix; in
|
||||
|
||||
rec {
|
||||
|
||||
|
||||
# Bring in a path as a source, filtering out all Subversion and CVS
|
||||
# directories, as well as backup files (*~).
|
||||
cleanSource =
|
||||
let filter = 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.
|
||||
lib.hasSuffix "~" baseName ||
|
||||
# Filter out generates files.
|
||||
lib.hasSuffix ".o" baseName ||
|
||||
lib.hasSuffix ".so" baseName
|
||||
);
|
||||
in src: builtins.filterSource filter src;
|
||||
|
||||
|
||||
# Get all files ending with the specified suffices from the given
|
||||
# directory or its descendants. E.g. `sourceFilesBySuffices ./dir
|
||||
# [".xml" ".c"]'.
|
||||
sourceFilesBySuffices = path: exts:
|
||||
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;
|
||||
|
||||
}
|
||||
226
lib/strings.nix
226
lib/strings.nix
@@ -1,226 +0,0 @@
|
||||
/* String manipulation functions. */
|
||||
|
||||
let lib = import ./default.nix;
|
||||
|
||||
inherit (builtins) length;
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) stringLength substring head tail isString replaceStrings;
|
||||
|
||||
|
||||
# Concatenate a list of strings.
|
||||
concatStrings =
|
||||
if builtins ? concatStringsSep then
|
||||
builtins.concatStringsSep ""
|
||||
else
|
||||
lib.foldl' (x: y: x + y) "";
|
||||
|
||||
|
||||
# Map a function over a list and concatenate the resulting strings.
|
||||
concatMapStrings = f: list: concatStrings (map f list);
|
||||
concatImapStrings = f: list: concatStrings (lib.imap f list);
|
||||
|
||||
|
||||
# Place an element between each element of a list, e.g.,
|
||||
# `intersperse "," ["a" "b" "c"]' returns ["a" "," "b" "," "c"].
|
||||
intersperse = separator: list:
|
||||
if list == [] || length list == 1
|
||||
then list
|
||||
else tail (lib.concatMap (x: [separator x]) list);
|
||||
|
||||
|
||||
# Concatenate a list of strings with a separator between each element, e.g.
|
||||
# concatStringsSep " " ["foo" "bar" "xyzzy"] == "foo bar xyzzy"
|
||||
concatStringsSep = builtins.concatStringsSep or (separator: list:
|
||||
concatStrings (intersperse separator list));
|
||||
|
||||
concatMapStringsSep = sep: f: list: concatStringsSep sep (map f list);
|
||||
concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap f list);
|
||||
|
||||
|
||||
# Construct a Unix-style search path consisting of each `subDir"
|
||||
# directory of the given list of packages. For example,
|
||||
# `makeSearchPath "bin" ["x" "y" "z"]' returns "x/bin:y/bin:z/bin".
|
||||
makeSearchPath = subDir: packages:
|
||||
concatStringsSep ":" (map (path: path + "/" + subDir) packages);
|
||||
|
||||
|
||||
# Construct a library search path (such as RPATH) containing the
|
||||
# libraries for a set of packages, e.g. "${pkg1}/lib:${pkg2}/lib:...".
|
||||
makeLibraryPath = makeSearchPath "lib";
|
||||
|
||||
|
||||
# Idem for Perl search paths.
|
||||
makePerlPath = makeSearchPath "lib/perl5/site_perl";
|
||||
|
||||
|
||||
# Dependening on the boolean `cond', return either the given string
|
||||
# or the empty string.
|
||||
optionalString = cond: string: if cond then string else "";
|
||||
|
||||
|
||||
# Determine whether a string has given prefix/suffix.
|
||||
hasPrefix = pref: str:
|
||||
substring 0 (stringLength pref) str == pref;
|
||||
hasSuffix = suff: str:
|
||||
let
|
||||
lenStr = stringLength str;
|
||||
lenSuff = stringLength suff;
|
||||
in lenStr >= lenSuff &&
|
||||
substring (lenStr - lenSuff) lenStr str == suff;
|
||||
|
||||
|
||||
# Convert a string to a list of characters (i.e. singleton strings).
|
||||
# For instance, "abc" becomes ["a" "b" "c"]. This allows you to,
|
||||
# e.g., map a function over each character. However, note that this
|
||||
# will likely be horribly inefficient; Nix is not a general purpose
|
||||
# programming language. Complex string manipulations should, if
|
||||
# appropriate, be done in a derivation.
|
||||
stringToCharacters = s:
|
||||
map (p: substring p 1 s) (lib.range 0 (stringLength s - 1));
|
||||
|
||||
|
||||
# Manipulate a string charactter by character and replace them by
|
||||
# strings before concatenating the results.
|
||||
stringAsChars = f: s:
|
||||
concatStrings (
|
||||
map f (stringToCharacters s)
|
||||
);
|
||||
|
||||
|
||||
# Escape occurrence of the elements of ‘list’ in ‘string’ by
|
||||
# prefixing it with a backslash. For example, ‘escape ["(" ")"]
|
||||
# "(foo)"’ returns the string ‘\(foo\)’.
|
||||
escape = list: replaceChars list (map (c: "\\${c}") list);
|
||||
|
||||
|
||||
# Escape all characters that have special meaning in the Bourne shell.
|
||||
escapeShellArg = lib.escape (stringToCharacters "\\ ';$`()|<>\t*[]");
|
||||
|
||||
|
||||
# Obsolete - use replaceStrings instead.
|
||||
replaceChars = builtins.replaceStrings or (
|
||||
del: new: s:
|
||||
let
|
||||
substList = lib.zipLists del new;
|
||||
subst = c:
|
||||
let found = lib.findFirst (sub: sub.fst == c) null substList; in
|
||||
if found == null then
|
||||
c
|
||||
else
|
||||
found.snd;
|
||||
in
|
||||
stringAsChars subst s);
|
||||
|
||||
|
||||
# Case conversion utilities.
|
||||
lowerChars = stringToCharacters "abcdefghijklmnopqrstuvwxyz";
|
||||
upperChars = stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
toLower = replaceChars upperChars lowerChars;
|
||||
toUpper = replaceChars lowerChars upperChars;
|
||||
|
||||
|
||||
# Appends string context from another string.
|
||||
addContextFrom = a: b: substring 0 0 a + b;
|
||||
|
||||
|
||||
# Cut a string with a separator and produces a list of strings which
|
||||
# were separated by this separator; e.g., `splitString "."
|
||||
# "foo.bar.baz"' returns ["foo" "bar" "baz"].
|
||||
splitString = _sep: _s:
|
||||
let
|
||||
sep = addContextFrom _s _sep;
|
||||
s = addContextFrom _sep _s;
|
||||
sepLen = stringLength sep;
|
||||
sLen = stringLength s;
|
||||
lastSearch = sLen - sepLen;
|
||||
startWithSep = startAt:
|
||||
substring startAt sepLen s == sep;
|
||||
|
||||
recurse = index: startAt:
|
||||
let cutUntil = i: [(substring startAt (i - startAt) s)]; in
|
||||
if index < lastSearch then
|
||||
if startWithSep index then
|
||||
let restartAt = index + sepLen; in
|
||||
cutUntil index ++ recurse restartAt restartAt
|
||||
else
|
||||
recurse (index + 1) startAt
|
||||
else
|
||||
cutUntil sLen;
|
||||
in
|
||||
recurse 0 0;
|
||||
|
||||
|
||||
# return the suffix of the second argument if the first argument match its
|
||||
# prefix. e.g.,
|
||||
# `removePrefix "foo." "foo.bar.baz"' returns "bar.baz".
|
||||
removePrefix = pre: s:
|
||||
let
|
||||
preLen = stringLength pre;
|
||||
sLen = stringLength s;
|
||||
in
|
||||
if hasPrefix pre s then
|
||||
substring preLen (sLen - preLen) s
|
||||
else
|
||||
s;
|
||||
|
||||
removeSuffix = suf: s:
|
||||
let
|
||||
sufLen = stringLength suf;
|
||||
sLen = stringLength s;
|
||||
in
|
||||
if sufLen <= sLen && suf == substring (sLen - sufLen) sufLen s then
|
||||
substring 0 (sLen - sufLen) s
|
||||
else
|
||||
s;
|
||||
|
||||
# Return true iff string v1 denotes a version older than v2.
|
||||
versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1;
|
||||
|
||||
|
||||
# Return true iff string v1 denotes a version equal to or newer than v2.
|
||||
versionAtLeast = v1: v2: !versionOlder v1 v2;
|
||||
|
||||
|
||||
# Get the version of the specified derivation, as specified in its
|
||||
# ‘name’ attribute.
|
||||
getVersion = drv: (builtins.parseDrvName drv.name).version;
|
||||
|
||||
|
||||
# Extract name with version from URL. Ask for separator which is
|
||||
# supposed to start extension.
|
||||
nameFromURL = url: sep:
|
||||
let
|
||||
components = splitString "/" url;
|
||||
filename = lib.last components;
|
||||
name = builtins.head (splitString sep filename);
|
||||
in assert name != filename; name;
|
||||
|
||||
|
||||
# Create an --{enable,disable}-<feat> string that can be passed to
|
||||
# standard GNU Autoconf scripts.
|
||||
enableFeature = enable: feat: "--${if enable then "enable" else "disable"}-${feat}";
|
||||
|
||||
|
||||
# Create a fixed width string with additional prefix to match
|
||||
# required width.
|
||||
fixedWidthString = width: filler: str:
|
||||
let
|
||||
strw = lib.stringLength str;
|
||||
reqWidth = width - (lib.stringLength filler);
|
||||
in
|
||||
assert strw <= width;
|
||||
if strw == width then str else filler + fixedWidthString reqWidth filler str;
|
||||
|
||||
|
||||
# Format a number adding leading zeroes up to fixed width.
|
||||
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
|
||||
|
||||
|
||||
# Check whether a value is a store path.
|
||||
isStorePath = x: builtins.substring 0 1 (toString x) == "/" && dirOf (builtins.toPath x) == builtins.storeDir;
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This script is used to test that the module system is working as expected.
|
||||
# By default it test the version of nixpkgs which is defined in the NIX_PATH.
|
||||
|
||||
cd ./modules
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
|
||||
evalConfig() {
|
||||
local attr=$1
|
||||
shift;
|
||||
local script="import ./default.nix { modules = [ $@ ];}"
|
||||
nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only --show-trace
|
||||
}
|
||||
|
||||
reportFailure() {
|
||||
local attr=$1
|
||||
shift;
|
||||
local script="import ./default.nix { modules = [ $@ ];}"
|
||||
echo 2>&1 "$ nix-instantiate -E '$script' -A '$attr' --eval-only"
|
||||
evalConfig "$attr" "$@"
|
||||
fail=$((fail + 1))
|
||||
}
|
||||
|
||||
checkConfigOutput() {
|
||||
local outputContains=$1
|
||||
shift;
|
||||
if evalConfig "$@" 2>/dev/null | grep --silent "$outputContains" ; then
|
||||
pass=$((pass + 1))
|
||||
return 0;
|
||||
else
|
||||
echo 2>&1 "error: Expected result matching '$outputContains', while evaluating"
|
||||
reportFailure "$@"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
checkConfigError() {
|
||||
local errorContains=$1
|
||||
local err=""
|
||||
shift;
|
||||
if err==$(evalConfig "$@" 2>&1 >/dev/null); then
|
||||
echo 2>&1 "error: Expected error code, got exit code 0, while evaluating"
|
||||
reportFailure "$@"
|
||||
return 1
|
||||
else
|
||||
if echo "$err" | grep --silent "$errorContains" ; then
|
||||
pass=$((pass + 1))
|
||||
return 0;
|
||||
else
|
||||
echo 2>&1 "error: Expected error matching '$errorContains', while evaluating"
|
||||
reportFailure "$@"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Check boolean option.
|
||||
checkConfigOutput "false" config.enable ./declare-enable.nix
|
||||
checkConfigError 'The option .* defined in .* does not exist.' config.enable ./define-enable.nix
|
||||
|
||||
# Check mkForce without submodules.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable.nix
|
||||
checkConfigOutput "true" "$@"
|
||||
checkConfigOutput "false" "$@" ./define-force-enable.nix
|
||||
checkConfigOutput "false" "$@" ./define-enable-force.nix
|
||||
|
||||
# Check mkForce with option and submodules.
|
||||
checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix
|
||||
checkConfigOutput 'false' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
|
||||
set -- config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@"
|
||||
checkConfigOutput 'false' "$@" ./define-force-loaOfSub-foo-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-force-foo-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-force-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-force.nix
|
||||
|
||||
# Check overriding effect of mkForce on submodule definitions.
|
||||
checkConfigError 'attribute .*bar.* .* not found' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
|
||||
checkConfigOutput 'false' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar.nix
|
||||
set -- config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar-enable.nix
|
||||
checkConfigOutput 'true' "$@"
|
||||
checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-force-loaOfSub-foo-enable.nix
|
||||
checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-loaOfSub-force-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-force-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-enable-force.nix
|
||||
|
||||
# Check mkIf with submodules.
|
||||
checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
|
||||
set -- config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
|
||||
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-if-loaOfSub-foo-enable.nix
|
||||
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-if-foo-enable.nix
|
||||
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-foo-if-enable.nix
|
||||
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-if.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-if-loaOfSub-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-if-foo-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-if-enable.nix
|
||||
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-enable-if.nix
|
||||
|
||||
# Check _module.args.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable-with-custom-arg.nix
|
||||
checkConfigError 'while evaluating the module argument .*custom.* in .*define-enable-with-custom-arg.nix.*:' "$@"
|
||||
checkConfigOutput "true" "$@" ./define-_module-args-custom.nix
|
||||
|
||||
# Check that using _module.args on imports cause infinite recursions, with
|
||||
# the proper error context.
|
||||
set -- "$@" ./define-_module-args-custom.nix ./import-custom-arg.nix
|
||||
checkConfigError 'while evaluating the module argument .*custom.* in .*import-custom-arg.nix.*:' "$@"
|
||||
checkConfigError 'infinite recursion encountered' "$@"
|
||||
|
||||
# Check _module.check.
|
||||
set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub-foo.nix
|
||||
checkConfigError 'The option .* defined in .* does not exist.' "$@"
|
||||
checkConfigOutput "true" "$@" ./define-module-check.nix
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
$fail Fail
|
||||
EOF
|
||||
|
||||
if test $fail -ne 0; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
@@ -1,14 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
submod = { ... }: {
|
||||
options = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
loaOfSub = lib.mkOption {
|
||||
default = {};
|
||||
example = {};
|
||||
type = lib.types.loaOf (lib.types.submodule [ submod ]);
|
||||
description = ''
|
||||
Some descriptive text
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib ? import <nixpkgs/lib>, modules ? [] }:
|
||||
|
||||
{
|
||||
inherit (lib.evalModules {
|
||||
inherit modules;
|
||||
}) config options;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
_module.args.custom = true;
|
||||
};
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
enable = lib.mkForce false;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, custom, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
enable = custom;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
enable = true;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
lib.mkForce {
|
||||
enable = false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
lib.mkForce {
|
||||
loaOfSub.foo.enable = false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
lib.mkIf config.enable {
|
||||
loaOfSub.foo.enable = true;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.bar.enable = true;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.bar = {};
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo.enable = lib.mkForce false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo.enable = lib.mkIf config.enable true;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.foo.enable = true;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo = lib.mkForce {
|
||||
enable = false;
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub.foo = lib.mkIf config.enable {
|
||||
enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
loaOfSub.foo = {};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub = lib.mkForce {
|
||||
foo.enable = false;
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
loaOfSub = lib.mkIf config.enable {
|
||||
foo.enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
_module.check = false;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{ lib, custom, ... }:
|
||||
|
||||
{
|
||||
imports = []
|
||||
++ lib.optional custom ./define-enable-force.nix;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{ nixpkgs }:
|
||||
|
||||
with import ./../.. { };
|
||||
with lib;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-lib-tests";
|
||||
buildInputs = [ nix ];
|
||||
NIX_PATH="nixpkgs=${nixpkgs}";
|
||||
|
||||
buildCommand = ''
|
||||
datadir="${nix}/share"
|
||||
export TEST_ROOT=$(pwd)/test-tmp
|
||||
export NIX_STORE_DIR=$TEST_ROOT/store
|
||||
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
|
||||
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
|
||||
export NIX_STATE_DIR=$TEST_ROOT/var/nix
|
||||
export NIX_DB_DIR=$TEST_ROOT/db
|
||||
export NIX_CONF_DIR=$TEST_ROOT/etc
|
||||
export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
|
||||
export NIX_BUILD_HOOK=
|
||||
export PAGER=cat
|
||||
cacheDir=$TEST_ROOT/binary-cache
|
||||
nix-store --init
|
||||
|
||||
cd ${nixpkgs}/lib/tests
|
||||
./modules.sh
|
||||
|
||||
touch $out
|
||||
'';
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
rec {
|
||||
|
||||
# Identity function.
|
||||
id = x: x;
|
||||
|
||||
# Constant function.
|
||||
const = x: y: x;
|
||||
|
||||
# Named versions corresponding to some builtin operators.
|
||||
concat = x: y: x ++ y;
|
||||
or = x: y: x || y;
|
||||
and = x: y: x && y;
|
||||
mergeAttrs = x: y: x // y;
|
||||
|
||||
# Take a function and evaluate it with its own returned value.
|
||||
fix = f: let result = f result; in result;
|
||||
|
||||
# Flip the order of the arguments of a binary function.
|
||||
flip = f: a: b: f b a;
|
||||
|
||||
# Pull in some builtins not included elsewhere.
|
||||
inherit (builtins)
|
||||
pathExists readFile isBool isFunction
|
||||
isInt add sub lessThan
|
||||
seq deepSeq genericClosure;
|
||||
|
||||
# Return the Nixpkgs version number.
|
||||
nixpkgsVersion =
|
||||
let suffixFile = ../.version-suffix; in
|
||||
readFile ../.version
|
||||
+ (if pathExists suffixFile then readFile suffixFile else "pre-git");
|
||||
|
||||
# Whether we're being called by nix-shell.
|
||||
inNixShell = builtins.getEnv "IN_NIX_SHELL" == "1";
|
||||
|
||||
# Return minimum/maximum of two numbers.
|
||||
min = x: y: if x < y then x else y;
|
||||
max = x: y: if x > y then x else y;
|
||||
|
||||
}
|
||||
240
lib/types.nix
240
lib/types.nix
@@ -1,240 +0,0 @@
|
||||
# Definitions related to run-time type checking. Used in particular
|
||||
# to type-check NixOS configurations.
|
||||
|
||||
with import ./lists.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./options.nix;
|
||||
with import ./trivial.nix;
|
||||
with import ./strings.nix;
|
||||
with {inherit (import ./modules.nix) mergeDefinitions; };
|
||||
|
||||
rec {
|
||||
|
||||
isType = type: x: (x._type or "") == type;
|
||||
|
||||
setType = typeName: value: value // {
|
||||
_type = typeName;
|
||||
};
|
||||
|
||||
|
||||
isOptionType = isType "option-type";
|
||||
mkOptionType =
|
||||
{ # Human-readable representation of the type.
|
||||
name
|
||||
, # Function applied to each definition that should return true if
|
||||
# its type-correct, false otherwise.
|
||||
check ? (x: true)
|
||||
, # Merge a list of definitions together into a single value.
|
||||
# This function is called with two arguments: the location of
|
||||
# the option in the configuration as a list of strings
|
||||
# (e.g. ["boot" "loader "grub" "enable"]), and a list of
|
||||
# definition values and locations (e.g. [ { file = "/foo.nix";
|
||||
# value = 1; } { file = "/bar.nix"; value = 2 } ]).
|
||||
merge ? mergeDefaultOption
|
||||
, # Return a flat list of sub-options. Used to generate
|
||||
# documentation.
|
||||
getSubOptions ? prefix: {}
|
||||
, # List of modules if any, or null if none.
|
||||
getSubModules ? null
|
||||
, # Function for building the same option type with a different list of
|
||||
# modules.
|
||||
substSubModules ? m: null
|
||||
}:
|
||||
{ _type = "option-type";
|
||||
inherit name check merge getSubOptions getSubModules substSubModules;
|
||||
};
|
||||
|
||||
|
||||
types = rec {
|
||||
|
||||
unspecified = mkOptionType {
|
||||
name = "unspecified";
|
||||
};
|
||||
|
||||
bool = mkOptionType {
|
||||
name = "boolean";
|
||||
check = isBool;
|
||||
merge = mergeEqualOption;
|
||||
};
|
||||
|
||||
int = mkOptionType {
|
||||
name = "integer";
|
||||
check = isInt;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
str = mkOptionType {
|
||||
name = "string";
|
||||
check = isString;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
# Merge multiple definitions by concatenating them (with the given
|
||||
# separator between the values).
|
||||
separatedString = sep: mkOptionType {
|
||||
name = "string";
|
||||
check = isString;
|
||||
merge = loc: defs: concatStringsSep sep (getValues defs);
|
||||
};
|
||||
|
||||
lines = separatedString "\n";
|
||||
commas = separatedString ",";
|
||||
envVar = separatedString ":";
|
||||
|
||||
# Deprecated; should not be used because it quietly concatenates
|
||||
# strings, which is usually not what you want.
|
||||
string = separatedString "";
|
||||
|
||||
attrs = mkOptionType {
|
||||
name = "attribute set";
|
||||
check = isAttrs;
|
||||
merge = loc: foldl' (res: def: mergeAttrs res def.value) {};
|
||||
};
|
||||
|
||||
# derivation is a reserved keyword.
|
||||
package = mkOptionType {
|
||||
name = "derivation";
|
||||
check = x: isDerivation x || isStorePath x;
|
||||
merge = loc: defs:
|
||||
let res = mergeOneOption loc defs;
|
||||
in if isDerivation res then res else toDerivation res;
|
||||
};
|
||||
|
||||
path = mkOptionType {
|
||||
name = "path";
|
||||
# Hacky: there is no ‘isPath’ primop.
|
||||
check = x: builtins.substring 0 1 (toString x) == "/";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
# drop this in the future:
|
||||
list = builtins.trace "`types.list' is deprecated; use `types.listOf' instead" types.listOf;
|
||||
|
||||
listOf = elemType: mkOptionType {
|
||||
name = "list of ${elemType.name}s";
|
||||
check = isList;
|
||||
merge = loc: defs:
|
||||
map (x: x.value) (filter (x: x ? value) (concatLists (imap (n: def: imap (m: def':
|
||||
(mergeDefinitions
|
||||
(loc ++ ["[definition ${toString n}-entry ${toString m}]"])
|
||||
elemType
|
||||
[{ inherit (def) file; value = def'; }]
|
||||
).optionalValue
|
||||
) def.value) defs)));
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: listOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
attrsOf = elemType: mkOptionType {
|
||||
name = "attribute set of ${elemType.name}s";
|
||||
check = isAttrs;
|
||||
merge = loc: defs:
|
||||
mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
|
||||
(mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
|
||||
)
|
||||
# Push down position info.
|
||||
(map (def: listToAttrs (mapAttrsToList (n: def':
|
||||
{ name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs)));
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: attrsOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
# List or attribute set of ...
|
||||
loaOf = elemType:
|
||||
let
|
||||
convertIfList = defIdx: def:
|
||||
if isList def.value then
|
||||
{ inherit (def) file;
|
||||
value = listToAttrs (
|
||||
imap (elemIdx: elem:
|
||||
{ name = elem.name or "unnamed-${toString defIdx}.${toString elemIdx}";
|
||||
value = elem;
|
||||
}) def.value);
|
||||
}
|
||||
else
|
||||
def;
|
||||
listOnly = listOf elemType;
|
||||
attrOnly = attrsOf elemType;
|
||||
in mkOptionType {
|
||||
name = "list or attribute set of ${elemType.name}s";
|
||||
check = x: isList x || isAttrs x;
|
||||
merge = loc: defs: attrOnly.merge loc (imap convertIfList defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: loaOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
uniq = elemType: mkOptionType {
|
||||
inherit (elemType) name check;
|
||||
merge = mergeOneOption;
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: uniq (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
nullOr = elemType: mkOptionType {
|
||||
name = "null or ${elemType.name}";
|
||||
check = x: builtins.isNull x || elemType.check x;
|
||||
merge = loc: defs:
|
||||
let nrNulls = count (def: isNull def.value) 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)}."
|
||||
else elemType.merge loc defs;
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: nullOr (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
submodule = opts:
|
||||
let
|
||||
opts' = toList opts;
|
||||
inherit (import ./modules.nix) evalModules;
|
||||
in
|
||||
mkOptionType rec {
|
||||
name = "submodule";
|
||||
check = x: isAttrs x || isFunction x;
|
||||
merge = loc: defs:
|
||||
let
|
||||
coerce = def: if isFunction def then def else { config = def; };
|
||||
modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
|
||||
in (evalModules {
|
||||
inherit modules;
|
||||
args.name = last loc;
|
||||
prefix = loc;
|
||||
}).config;
|
||||
getSubOptions = prefix: (evalModules
|
||||
{ modules = opts'; inherit prefix;
|
||||
# FIXME: hack to get shit to evaluate.
|
||||
args = { name = ""; }; }).options;
|
||||
getSubModules = opts';
|
||||
substSubModules = m: submodule m;
|
||||
};
|
||||
|
||||
enum = values: mkOptionType {
|
||||
name = "one of ${concatStringsSep ", " values}";
|
||||
check = flip elem values;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
either = t1: t2: mkOptionType {
|
||||
name = "${t1.name} or ${t2.name}";
|
||||
check = x: t1.check x || t2.check x;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
# Obsolete alternative to configOf. It takes its option
|
||||
# declarations from the ‘options’ attribute of containing option
|
||||
# declaration.
|
||||
optionSet = mkOptionType {
|
||||
name = /* builtins.trace "types.optionSet is deprecated; use types.submodule instead" */ "option set";
|
||||
};
|
||||
|
||||
# Augment the given type with an additional type check function.
|
||||
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
*~
|
||||
,*
|
||||
.*.swp
|
||||
.*.swo
|
||||
result
|
||||
result-*
|
||||
/doc/NEWS.html
|
||||
/doc/NEWS.txt
|
||||
/doc/manual.html
|
||||
/doc/manual.pdf
|
||||
.version-suffix
|
||||
|
||||
.DS_Store
|
||||
.git
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM busybox
|
||||
|
||||
RUN dir=`mktemp -d` && trap 'rm -rf "$dir"' EXIT && \
|
||||
wget -O- https://nixos.org/releases/nix/nix-1.7/nix-1.7-x86_64-linux.tar.bz2 | bzcat | tar x -C $dir && \
|
||||
mkdir -m 0755 /nix && USER=root sh $dir/*/install && \
|
||||
echo ". /root/.nix-profile/etc/profile.d/nix.sh" >> /etc/profile
|
||||
|
||||
ADD . /root/nix/nixpkgs
|
||||
ONBUILD ENV NIX_PATH nixpkgs=/root/nix/nixpkgs:nixos=/root/nix/nixpkgs/nixos
|
||||
ONBUILD ENV PATH /root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin
|
||||
ONBUILD ENV ENV /etc/profile
|
||||
ENV ENV /etc/profile
|
||||
@@ -41,7 +41,7 @@ NB:
|
||||
|
||||
Keep in mind that many programs are not very well suited for cross
|
||||
compilation. Either they are not intended to run on other platforms,
|
||||
because the code is highly platform specific, or the configuration process
|
||||
because the code is highly platform specific, or the configuration proces
|
||||
is not written with cross compilation in mind.
|
||||
|
||||
Nix will not solve these problems for you!
|
||||
@@ -184,10 +184,10 @@ if test "$noSysDirs" = "1"; then
|
||||
if test "$noSysDirs" = "1"; then
|
||||
# Figure out what extra flags to pass to the gcc compilers
|
||||
# being generated to make sure that they use our glibc.
|
||||
if test -e $NIX_CC/nix-support/orig-glibc; then
|
||||
glibc=$(cat $NIX_CC/nix-support/orig-glibc)
|
||||
if test -e $NIX_GCC/nix-support/orig-glibc; then
|
||||
glibc=$(cat $NIX_GCC/nix-support/orig-glibc)
|
||||
# Ugh. Copied from gcc-wrapper/builder.sh. We can't just
|
||||
# source in $NIX_CC/nix-support/add-flags, since that
|
||||
# source in $NIX_GCC/nix-support/add-flags, since that
|
||||
# would cause *this* GCC to be linked against the
|
||||
# *previous* GCC. Need some more modularity there.
|
||||
extraCFlags="-B$glibc/lib -isystem $glibc/include"
|
||||
@@ -233,9 +233,9 @@ preConfigure() {
|
||||
fi
|
||||
|
||||
# Cross compiler evilness
|
||||
mkdir -p $out
|
||||
mkdir -p $out/arm-linux
|
||||
mkdir -p $out/arm-linux/bin
|
||||
ensureDir $out
|
||||
ensureDir $out/arm-linux
|
||||
ensureDir $out/arm-linux/bin
|
||||
ln -s $binutilsArm/arm-linux/bin/as $out/arm-linux/bin/as
|
||||
ln -s $binutilsArm/arm-linux/bin/ld $out/arm-linux/bin/ld
|
||||
ln -s $binutilsArm/arm-linux/bin/ar $out/arm-linux/bin/ar
|
||||
@@ -290,7 +290,7 @@ this compiler and verified to be working on a HP Jornada 820 running Linux
|
||||
are "patch", "make" and "wget".
|
||||
|
||||
If we want to build C++ programs it gets a lot more difficult. GCC has a
|
||||
three step compilation process. In the first step a simple compiler, called
|
||||
three step compilation proces. In the first step a simple compiler, called
|
||||
xgcc, that can compile only C programs is built. With that compiler it
|
||||
compiles itself two more times: one time to build a full compiler, and another
|
||||
time to build a full compiler once again with the freshly built compiler from
|
||||
@@ -318,7 +318,7 @@ with compilation flags. This is still work in progress for Nix.
|
||||
|
||||
---
|
||||
|
||||
After successfully completing the whole toolchain you can start building
|
||||
After succesfully completing the whole toolchain you can start building
|
||||
packages with the newly built tools. To make everything build correctly
|
||||
you will need a stdenv for your target platform. Setting up this platform
|
||||
will take some effort. Right now there is a very experimental setup for
|
||||
27
maintainers/docs/uclibc-cross.txt
Normal file
27
maintainers/docs/uclibc-cross.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Adding uClibc support for a new platform
|
||||
|
||||
Sometimes you want to cross-compile to another architecture, for example an
|
||||
embedded devices. For embedded devices the uClibc C library is popular.
|
||||
In Nixpkgs there is support for uClibc for several architectures but not
|
||||
everything is supported.
|
||||
|
||||
Adding support is not very difficult,
|
||||
|
||||
* Add your architecture to the buildfiles in
|
||||
$nixpkgs/development/tools/misc/binutils-cross
|
||||
|
||||
* Add your architecture to the buildfiles in
|
||||
$nixpkgs/development/compilers/gcc-4.0-cross
|
||||
|
||||
* Add your architecture to the buildfiles in
|
||||
$nixpkgs/os-specific/linux/kernel-headers-cross
|
||||
|
||||
* Add your architecture to the buildfiles in
|
||||
$nixpkgs/development/uclibc
|
||||
|
||||
In the latter directory you will also need a configuration file for uClibc.
|
||||
You can make these by unpacking the uClibc sources and run a "make menuconfig".
|
||||
In the configuration a few things need to be adapted:
|
||||
|
||||
- kernel sources -> need to point at our own kernel headers
|
||||
- install -> needs to point at $out
|
||||
@@ -1,97 +0,0 @@
|
||||
#! /run/current-system/sw/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use XML::Simple;
|
||||
use File::Basename;
|
||||
use File::Path;
|
||||
use File::Copy 'cp';
|
||||
use IPC::Open2;
|
||||
use Nix::Store;
|
||||
|
||||
my $myDir = dirname($0);
|
||||
|
||||
my $tarballsCache = $ENV{'NIX_TARBALLS_CACHE'} // "/tarballs";
|
||||
|
||||
my $xml = `nix-instantiate --eval-only --xml --strict '<nixpkgs/maintainers/scripts/find-tarballs.nix>'`;
|
||||
die "$0: evaluation failed\n" if $? != 0;
|
||||
|
||||
my $data = XMLin($xml) or die;
|
||||
|
||||
mkpath($tarballsCache);
|
||||
mkpath("$tarballsCache/md5");
|
||||
mkpath("$tarballsCache/sha1");
|
||||
mkpath("$tarballsCache/sha256");
|
||||
|
||||
foreach my $file (@{$data->{list}->{attrs}}) {
|
||||
my $url = $file->{attr}->{url}->{string}->{value};
|
||||
my $algo = $file->{attr}->{type}->{string}->{value};
|
||||
my $hash = $file->{attr}->{hash}->{string}->{value};
|
||||
|
||||
if ($url !~ /^http:/ && $url !~ /^https:/ && $url !~ /^ftp:/ && $url !~ /^mirror:/) {
|
||||
print STDERR "skipping $url (unsupported scheme)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
$url =~ /([^\/]+)$/;
|
||||
my $fn = $1;
|
||||
|
||||
if (!defined $fn) {
|
||||
print STDERR "skipping $url (no file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn =~ /[&?=%]/ || $fn =~ /^\./) {
|
||||
print STDERR "skipping $url (bad character in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn !~ /[a-zA-Z]/) {
|
||||
print STDERR "skipping $url (no letter in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn !~ /[0-9]/) {
|
||||
print STDERR "skipping $url (no digit in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn !~ /[-_\.]/) {
|
||||
print STDERR "skipping $url (no dash/dot/underscore in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $dstPath = "$tarballsCache/$fn";
|
||||
|
||||
next if -e $dstPath;
|
||||
|
||||
print "downloading $url to $dstPath...\n";
|
||||
|
||||
next if $ENV{DRY_RUN};
|
||||
|
||||
$ENV{QUIET} = 1;
|
||||
$ENV{PRINT_PATH} = 1;
|
||||
my $fh;
|
||||
my $pid = open($fh, "-|", "nix-prefetch-url", "--type", $algo, $url, $hash) or die;
|
||||
waitpid($pid, 0) or die;
|
||||
if ($? != 0) {
|
||||
print STDERR "failed to fetch $url: $?\n";
|
||||
next;
|
||||
}
|
||||
<$fh>; my $storePath = <$fh>; chomp $storePath;
|
||||
|
||||
die unless -e $storePath;
|
||||
|
||||
cp($storePath, $dstPath) or die;
|
||||
|
||||
my $md5 = hashFile("md5", 0, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/md5/$md5");
|
||||
|
||||
my $sha1 = hashFile("sha1", 0, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/sha1/$sha1");
|
||||
|
||||
my $sha256 = hashFile("sha256", 0, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/sha256/$sha256");
|
||||
|
||||
$sha256 = hashFile("sha256", 1, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/sha256/$sha256");
|
||||
}
|
||||
57
maintainers/scripts/copy-tarballs.sh
Executable file
57
maintainers/scripts/copy-tarballs.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#! /bin/sh -e
|
||||
|
||||
distDir=/data/webserver/tarballs
|
||||
|
||||
urls=$(nix-instantiate --eval-only --xml --strict ./eval-release.nix \
|
||||
| grep -A2 'name="urls"' \
|
||||
| grep '<string value=' \
|
||||
| sed 's/.*"\(.*\)".*/\1/' \
|
||||
| sort | uniq)
|
||||
|
||||
for url in $urls; do
|
||||
|
||||
if echo "$url" | grep -q -E "www.cs.uu.nl|nixos.org|.stratego-language.org|java.sun.com|ut2004|linuxq3a|RealPlayer|Adbe|belastingdienst|microsoft|armijn/.nix|sun.com|archive.eclipse.org"; then continue; fi
|
||||
|
||||
base="$(basename "$url")"
|
||||
newPath="$distDir/$base"
|
||||
|
||||
if ! test -e "$newPath"; then
|
||||
|
||||
#if echo $url | grep -q 'mirror://'; then
|
||||
# echo "$fn: skipping mirrored $url"
|
||||
# continue
|
||||
#fi
|
||||
|
||||
echo "downloading $url to $newPath"
|
||||
|
||||
if test -n "$doCopy"; then
|
||||
declare -a res
|
||||
if ! res=($(PRINT_PATH=1 nix-prefetch-url "$url")); then
|
||||
continue
|
||||
fi
|
||||
storePath=${res[1]}
|
||||
cp $storePath "$newPath.tmp.$$"
|
||||
mv -f "$newPath.tmp.$$" "$newPath"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if test -n "$doCopy" -a -e "$newPath"; then
|
||||
|
||||
echo "hashing $newPath"
|
||||
|
||||
md5=$(nix-hash --flat --type md5 "$newPath")
|
||||
ln -sfn "../$base" $distDir/md5/$md5
|
||||
|
||||
sha1=$(nix-hash --flat --type sha1 "$newPath")
|
||||
ln -sfn "../$base" $distDir/sha1/$sha1
|
||||
|
||||
sha256=$(nix-hash --flat --type sha256 "$newPath")
|
||||
ln -sfn "../$base" $distDir/sha256/$sha256
|
||||
ln -sfn "../$base" $distDir/sha256/$(nix-hash --type sha256 --to-base32 "$sha256")
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
echo DONE
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Download patches from debian project
|
||||
# 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
|
||||
declare -a deb_patches
|
||||
mapfile -t deb_patches < $1
|
||||
|
||||
prefix="${DEB_URL}/${deb_patches[0]}"
|
||||
|
||||
if [[ -n "$2" ]]; then
|
||||
exec 1> $2
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
# Generated by $(basename $0) from $(basename $1)
|
||||
let
|
||||
prefix = "${prefix}";
|
||||
in
|
||||
[
|
||||
EOF
|
||||
for ((i=1;i < ${#deb_patches[@]}; ++i)); do
|
||||
url="${prefix}/${deb_patches[$i]}"
|
||||
sha256=$(nix-prefetch-url $url)
|
||||
echo " {"
|
||||
echo " url = \"\${prefix}/${deb_patches[$i]}\";"
|
||||
echo " sha256 = \"$sha256\";"
|
||||
echo " }"
|
||||
done
|
||||
echo "]"
|
||||
@@ -1,24 +1,24 @@
|
||||
# Evaluate `release.nix' like Hydra would. Too bad nix-instantiate
|
||||
# can't to do this.
|
||||
|
||||
with import ../../lib;
|
||||
# Evaluate `release.nix' like Hydra would (i.e. call each job
|
||||
# attribute with the expected `system' argument). Too bad
|
||||
# nix-instantiate can't to do this.
|
||||
|
||||
let
|
||||
trace = if builtins.getEnv "VERBOSE" == "1" then builtins.trace else (x: y: y);
|
||||
|
||||
rel = removeAttrs (import ../../pkgs/top-level/release.nix { }) [ "tarball" "unstable" "xbursttools" ];
|
||||
lib = (import ../.. {}).lib;
|
||||
|
||||
# Add the ‘recurseForDerivations’ attribute to ensure that
|
||||
# nix-instantiate recurses into nested attribute sets.
|
||||
recurse = path: attrs:
|
||||
if (builtins.tryEval attrs).success then
|
||||
if isDerivation attrs
|
||||
then
|
||||
if (builtins.tryEval attrs.drvPath).success
|
||||
then { inherit (attrs) name drvPath; }
|
||||
else { failed = true; }
|
||||
else { recurseForDerivations = true; } //
|
||||
mapAttrs (n: v: let path' = path ++ [n]; in trace path' (recurse path' v)) attrs
|
||||
else { };
|
||||
rel = removeAttrs (import ../../pkgs/top-level/release.nix) [ "tarball" "xbursttools" ];
|
||||
|
||||
in recurse [] rel
|
||||
seqList = xs: res: lib.fold (x: xs: lib.seq x xs) res xs;
|
||||
|
||||
strictAttrs = as: seqList (lib.attrValues as) as;
|
||||
|
||||
maybe = as: let y = builtins.tryEval (strictAttrs as); in if y.success then y.value else builtins.trace "FAIL" null;
|
||||
|
||||
call = attrs: lib.flip lib.mapAttrs attrs
|
||||
(n: v: builtins.trace n (
|
||||
if builtins.isFunction v then maybe (v { system = "i686-linux"; })
|
||||
else if builtins.isAttrs v then call v
|
||||
else null
|
||||
));
|
||||
|
||||
in call rel
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
# This expression returns a list of all fetchurl calls used by all
|
||||
# packages reachable from release.nix.
|
||||
|
||||
with import ../.. { };
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
root = removeAttrs (import ../../pkgs/top-level/release.nix { }) [ "tarball" "unstable" ];
|
||||
|
||||
uniqueUrls = map (x: x.file) (genericClosure {
|
||||
startSet = map (file: { key = file.url; inherit file; }) urls;
|
||||
operator = const [ ];
|
||||
});
|
||||
|
||||
urls = map (drv: { url = head drv.urls; hash = drv.outputHash; type = drv.outputHashAlgo; }) fetchurlDependencies;
|
||||
|
||||
fetchurlDependencies = filter (drv: drv.outputHash or "" != "" && drv ? urls) dependencies;
|
||||
|
||||
dependencies = map (x: x.value) (genericClosure {
|
||||
startSet = map keyDrv (derivationsIn' root);
|
||||
operator = { key, value }: map keyDrv (immediateDependenciesOf value);
|
||||
});
|
||||
|
||||
derivationsIn' = x:
|
||||
if !canEval x then []
|
||||
else if isDerivation x then optional (canEval x.drvPath) x
|
||||
else if isList x then concatLists (map derivationsIn' x)
|
||||
else if isAttrs x then concatLists (mapAttrsToList (n: v: derivationsIn' v) x)
|
||||
else [ ];
|
||||
|
||||
keyDrv = drv: if canEval drv.drvPath then { key = drv.drvPath; value = drv; } else { };
|
||||
|
||||
immediateDependenciesOf = drv:
|
||||
concatLists (mapAttrsToList (n: v: derivationsIn v) (removeAttrs drv ["meta" "passthru"]));
|
||||
|
||||
derivationsIn = x:
|
||||
if !canEval x then []
|
||||
else if isDerivation x then optional (canEval x.drvPath) x
|
||||
else if isList x then concatLists (map derivationsIn x)
|
||||
else [ ];
|
||||
|
||||
canEval = val: (builtins.tryEval val).success;
|
||||
|
||||
in uniqueUrls
|
||||
@@ -1,95 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
GNOME_FTP="ftp.gnome.org/pub/GNOME/sources"
|
||||
|
||||
project=$1
|
||||
|
||||
if [ "$project" == "--help" ]; then
|
||||
echo "Usage: $0 project [major.minor]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
baseVersion=$2
|
||||
|
||||
if [ -z "$project" ]; then
|
||||
echo "No project specified, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 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 -l "$1"/
|
||||
}
|
||||
fi
|
||||
|
||||
if [ -z "$baseVersion" ]; then
|
||||
echo "Looking for available versions..." >&2
|
||||
available_baseversions=( `ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n` )
|
||||
echo -e "The following versions are available:\n ${available_baseversions[@]}" >&2
|
||||
echo -en "Choose one of them: " >&2
|
||||
read baseVersion
|
||||
fi
|
||||
|
||||
FTPDIR="${GNOME_FTP}/${project}/${baseVersion}"
|
||||
|
||||
#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.
|
||||
|
||||
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"
|
||||
;;
|
||||
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`
|
||||
echo "Latest version is: ${version}" >&2
|
||||
|
||||
name=${project}-${version}
|
||||
echo "Fetching .sha256 file" >&2
|
||||
curl -O http://${FTPDIR}/${name}.sha256sum
|
||||
|
||||
extensions=( "xz" "bz2" "gz" )
|
||||
echo "Choosing archive extension (known are ${extensions[@]})..." >&2
|
||||
for ext in ${extensions[@]}; do
|
||||
if grep "\\.tar\\.${ext}$" ${name}.sha256sum >& /dev/null; then
|
||||
ext_pref=$ext
|
||||
sha256=$(grep "\\.tar\\.${ext}$" ${name}.sha256sum | cut -f1 -d\ )
|
||||
break
|
||||
fi
|
||||
done
|
||||
sha256=`nix-hash --to-base32 --type sha256 $sha256`
|
||||
echo "Chosen ${ext_pref}, hash is ${sha256}" >&2
|
||||
|
||||
cat <<EOF
|
||||
name = "${project}-${version}";
|
||||
|
||||
src = fetchurl {
|
||||
url = mirror://gnome/sources/${project}/${baseVersion}/${project}-${version}.tar.${ext_pref};
|
||||
sha256 = "${sha256}";
|
||||
};
|
||||
EOF
|
||||
|
||||
rm -v ${name}.sha256sum >&2
|
||||
@@ -28,7 +28,6 @@ exec ${GUILE-guile} -L "$PWD" -l "$0" \
|
||||
#:use-module (ice-9 popen)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (ice-9 rdelim)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (ice-9 regex)
|
||||
#:use-module (ice-9 vlist)
|
||||
#:use-module (srfi srfi-1)
|
||||
@@ -117,19 +116,8 @@ exec ${GUILE-guile} -L "$PWD" -l "$0" \
|
||||
(if (pair? body)
|
||||
(values `(derivation ,drv-path ,out-path ,(cdr body))
|
||||
derivations)
|
||||
|
||||
;; DRV-PATH hasn't been encountered yet but may be later
|
||||
;; (see <http://article.gmane.org/gmane.linux.distributions.nixos/5946>.)
|
||||
;; Return an `unresolved' node.
|
||||
(values `(unresolved
|
||||
,(lambda (derivations)
|
||||
(let ((body (vhash-assoc drv-path derivations)))
|
||||
(if (pair? body)
|
||||
`(derivation ,drv-path ,out-path
|
||||
,(cdr body))
|
||||
(error "no previous occurrence of derivation"
|
||||
drv-path)))))
|
||||
derivations)))
|
||||
(error "no previous occurrence of derivation"
|
||||
drv-path)))
|
||||
(values `(derivation ,drv-path ,out-path ,body)
|
||||
(vhash-cons drv-path body derivations)))))
|
||||
((ellipsis)
|
||||
@@ -157,32 +145,6 @@ exec ${GUILE-guile} -L "$PWD" -l "$0" \
|
||||
(values `(varpat ,(assq-ref attributes 'name)) derivations))
|
||||
(else (error "unhandled Nix XML element" elem))))
|
||||
|
||||
(define (resolve snix derivations)
|
||||
"Return a new SNix tree where `unresolved' nodes from SNIX have been
|
||||
replaced by the result of their application to DERIVATIONS, a vhash."
|
||||
(let loop ((node snix)
|
||||
(seen vlist-null))
|
||||
(if (vhash-assq node seen)
|
||||
(values node seen)
|
||||
(match node
|
||||
(('unresolved proc)
|
||||
(let ((n (proc derivations)))
|
||||
(values n seen)))
|
||||
((tag body ...)
|
||||
(let ((body+seen (fold (lambda (n body+seen)
|
||||
(call-with-values
|
||||
(lambda ()
|
||||
(loop n (cdr body+seen)))
|
||||
(lambda (n* seen)
|
||||
(cons (cons n* (car body+seen))
|
||||
(vhash-consq n #t seen)))))
|
||||
(cons '() (vhash-consq node #t seen))
|
||||
body)))
|
||||
(values (cons tag (reverse (car body+seen)))
|
||||
(vhash-consq node #t (cdr body+seen)))))
|
||||
(anything
|
||||
(values anything seen))))))
|
||||
|
||||
(define xml->snix
|
||||
;; Return the SNix represention of TREE, an SXML tree as returned by
|
||||
;; parsing the XML output of `nix-instantiate' on Nixpkgs.
|
||||
@@ -210,9 +172,9 @@ replaced by the result of their application to DERIVATIONS, a vhash."
|
||||
;; Discard inter-node strings, which are blanks.
|
||||
seed))))
|
||||
(lambda (port)
|
||||
(match (parse port (cons '() vlist-null))
|
||||
(((snix) . derivations)
|
||||
(resolve snix derivations))))))
|
||||
;; Discard the second value returned by the parser (the derivation
|
||||
;; vhash).
|
||||
(caar (parse port (cons '() vlist-null))))))
|
||||
|
||||
(define (call-with-package snix proc)
|
||||
(match snix
|
||||
@@ -308,17 +270,12 @@ replaced by the result of their application to DERIVATIONS, a vhash."
|
||||
;; DERIVATION lacks an "src" attribute.
|
||||
(and=> (derivation-source derivation) source-output-path))
|
||||
|
||||
(define* (open-nixpkgs nixpkgs #:optional attribute)
|
||||
;; Return an input pipe to the XML representation of Nixpkgs. When
|
||||
;; ATTRIBUTE is true, only that attribute is considered.
|
||||
(define (open-nixpkgs nixpkgs)
|
||||
(let ((script (string-append nixpkgs
|
||||
"/maintainers/scripts/eval-release.nix")))
|
||||
(apply open-pipe* OPEN_READ
|
||||
"nix-instantiate" "--strict" "--eval-only" "--xml"
|
||||
`(,@(if attribute
|
||||
`("-A" ,attribute)
|
||||
'())
|
||||
,script))))
|
||||
(open-pipe* OPEN_READ "nix-instantiate"
|
||||
"--strict" "--eval-only" "--xml"
|
||||
script)))
|
||||
|
||||
(define (pipe-failed? pipe)
|
||||
"Close pipe and return its status if it failed."
|
||||
@@ -328,36 +285,21 @@ replaced by the result of their application to DERIVATIONS, a vhash."
|
||||
status
|
||||
#f)))
|
||||
|
||||
(define (memoize proc)
|
||||
"Return a memoizing version of PROC."
|
||||
(let ((cache (make-hash-table)))
|
||||
(lambda args
|
||||
(let ((results (hash-ref cache args)))
|
||||
(if results
|
||||
(apply values results)
|
||||
(let ((results (call-with-values (lambda ()
|
||||
(apply proc args))
|
||||
list)))
|
||||
(hash-set! cache args results)
|
||||
(apply values results)))))))
|
||||
|
||||
(define nix-prefetch-url
|
||||
(memoize
|
||||
(lambda (url)
|
||||
"Download URL in the Nix store and return the base32-encoded SHA256 hash of
|
||||
the file at URL."
|
||||
(let* ((pipe (open-pipe* OPEN_READ "nix-prefetch-url" url))
|
||||
(hash (read-line pipe)))
|
||||
(if (or (pipe-failed? pipe)
|
||||
(eof-object? hash))
|
||||
(values #f #f)
|
||||
(let* ((pipe (open-pipe* OPEN_READ "nix-store" "--print-fixed-path"
|
||||
"sha256" hash (basename url)))
|
||||
(path (read-line pipe)))
|
||||
(if (or (pipe-failed? pipe)
|
||||
(eof-object? path))
|
||||
(values #f #f)
|
||||
(values (string-trim-both hash) (string-trim-both path)))))))))
|
||||
(define (nix-prefetch-url url)
|
||||
;; Download URL in the Nix store and return the base32-encoded SHA256 hash
|
||||
;; of the file at URL
|
||||
(let* ((pipe (open-pipe* OPEN_READ "nix-prefetch-url" url))
|
||||
(hash (read-line pipe)))
|
||||
(if (or (pipe-failed? pipe)
|
||||
(eof-object? hash))
|
||||
(values #f #f)
|
||||
(let* ((pipe (open-pipe* OPEN_READ "nix-store" "--print-fixed-path"
|
||||
"sha256" hash (basename url)))
|
||||
(path (read-line pipe)))
|
||||
(if (or (pipe-failed? pipe)
|
||||
(eof-object? path))
|
||||
(values #f #f)
|
||||
(values (string-trim-both hash) (string-trim-both path)))))))
|
||||
|
||||
(define (update-nix-expression file
|
||||
old-version old-hash
|
||||
@@ -420,127 +362,6 @@ the file at URL."
|
||||
;; Return the output path of the "src" derivation of PACKAGE.
|
||||
(derivation-source-output-path (attribute-value package)))
|
||||
|
||||
|
||||
;;;
|
||||
;;; GnuPG interface.
|
||||
;;;
|
||||
|
||||
(define %gpg-command "gpg2")
|
||||
(define %openpgp-key-server "keys.gnupg.net")
|
||||
|
||||
(define (gnupg-verify sig file)
|
||||
"Verify signature SIG for FILE. Return a status s-exp if GnuPG failed."
|
||||
|
||||
(define (status-line->sexp line)
|
||||
;; See file `doc/DETAILS' in GnuPG.
|
||||
(define sigid-rx
|
||||
(make-regexp
|
||||
"^\\[GNUPG:\\] SIG_ID ([A-Za-z0-9/]+) ([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}) ([[:digit:]]+)"))
|
||||
(define goodsig-rx
|
||||
(make-regexp "^\\[GNUPG:\\] GOODSIG ([[:xdigit:]]+) (.+)$"))
|
||||
(define validsig-rx
|
||||
(make-regexp
|
||||
"^\\[GNUPG:\\] VALIDSIG ([[:xdigit:]]+) ([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}) ([[:digit:]]+) .*$"))
|
||||
(define expkeysig-rx ; good signature, but expired key
|
||||
(make-regexp "^\\[GNUPG:\\] EXPKEYSIG ([[:xdigit:]]+) (.*)$"))
|
||||
(define errsig-rx
|
||||
(make-regexp
|
||||
"^\\[GNUPG:\\] ERRSIG ([[:xdigit:]]+) ([^ ]+) ([^ ]+) ([^ ]+) ([[:digit:]]+) ([[:digit:]]+)"))
|
||||
|
||||
(cond ((regexp-exec sigid-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
`(signature-id ,(match:substring match 1) ; sig id
|
||||
,(match:substring match 2) ; date
|
||||
,(string->number ; timestamp
|
||||
(match:substring match 3)))))
|
||||
((regexp-exec goodsig-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
`(good-signature ,(match:substring match 1) ; key id
|
||||
,(match:substring match 2)))) ; user name
|
||||
((regexp-exec validsig-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
`(valid-signature ,(match:substring match 1) ; fingerprint
|
||||
,(match:substring match 2) ; sig creation date
|
||||
,(string->number ; timestamp
|
||||
(match:substring match 3)))))
|
||||
((regexp-exec expkeysig-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
`(expired-key-signature ,(match:substring match 1) ; fingerprint
|
||||
,(match:substring match 2)))) ; user name
|
||||
((regexp-exec errsig-rx line)
|
||||
=>
|
||||
(lambda (match)
|
||||
`(signature-error ,(match:substring match 1) ; key id or fingerprint
|
||||
,(match:substring match 2) ; pubkey algo
|
||||
,(match:substring match 3) ; hash algo
|
||||
,(match:substring match 4) ; sig class
|
||||
,(string->number ; timestamp
|
||||
(match:substring match 5))
|
||||
,(let ((rc
|
||||
(string->number ; return code
|
||||
(match:substring match 6))))
|
||||
(case rc
|
||||
((9) 'missing-key)
|
||||
((4) 'unknown-algorithm)
|
||||
(else rc))))))
|
||||
(else
|
||||
`(unparsed-line ,line))))
|
||||
|
||||
(define (parse-status input)
|
||||
(let loop ((line (read-line input))
|
||||
(result '()))
|
||||
(if (eof-object? line)
|
||||
(reverse result)
|
||||
(loop (read-line input)
|
||||
(cons (status-line->sexp line) result)))))
|
||||
|
||||
(let* ((pipe (open-pipe* OPEN_READ %gpg-command "--status-fd=1"
|
||||
"--verify" sig file))
|
||||
(status (parse-status pipe)))
|
||||
;; Ignore PIPE's exit status since STATUS above should contain all the
|
||||
;; info we need.
|
||||
(close-pipe pipe)
|
||||
status))
|
||||
|
||||
(define (gnupg-status-good-signature? status)
|
||||
"If STATUS, as returned by `gnupg-verify', denotes a good signature, return
|
||||
a key-id/user pair; return #f otherwise."
|
||||
(any (lambda (sexp)
|
||||
(match sexp
|
||||
(((or 'good-signature 'expired-key-signature) key-id user)
|
||||
(cons key-id user))
|
||||
(_ #f)))
|
||||
status))
|
||||
|
||||
(define (gnupg-status-missing-key? status)
|
||||
"If STATUS denotes a missing-key error, then return the key-id of the
|
||||
missing key."
|
||||
(any (lambda (sexp)
|
||||
(match sexp
|
||||
(('signature-error key-id _ ...)
|
||||
key-id)
|
||||
(_ #f)))
|
||||
status))
|
||||
|
||||
(define (gnupg-receive-keys key-id)
|
||||
(system* %gpg-command "--keyserver" %openpgp-key-server "--recv-keys" key-id))
|
||||
|
||||
(define (gnupg-verify* sig file)
|
||||
"Like `gnupg-verify', but try downloading the public key if it's missing.
|
||||
Return #t if the signature was good, #f otherwise."
|
||||
(let ((status (gnupg-verify sig file)))
|
||||
(or (gnupg-status-good-signature? status)
|
||||
(let ((missing (gnupg-status-missing-key? status)))
|
||||
(and missing
|
||||
(begin
|
||||
;; Download the missing key and try again.
|
||||
(gnupg-receive-keys missing)
|
||||
(gnupg-status-good-signature? (gnupg-verify sig file))))))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; FTP client.
|
||||
@@ -694,9 +515,7 @@ Return #t if the signature was good, #f otherwise."
|
||||
"automake110x"
|
||||
"bison1875"
|
||||
"bison23"
|
||||
"bison24"
|
||||
"bison" ;; = 2.4
|
||||
"ccrtp_1_8"
|
||||
"bison" ;; = 2.3
|
||||
"emacs22"
|
||||
"emacsSnapshot"
|
||||
"gcc295"
|
||||
@@ -710,24 +529,13 @@ Return #t if the signature was good, #f otherwise."
|
||||
"gcc45"
|
||||
"gcc45_real"
|
||||
"gcc45_realCross"
|
||||
"gfortran45"
|
||||
"gcj45"
|
||||
"gcc46"
|
||||
"gcc46_real"
|
||||
"gcc46_realCross"
|
||||
"gfortran46"
|
||||
"gcj46"
|
||||
"glibc25"
|
||||
"glibc27"
|
||||
"glibc29"
|
||||
"guile_1_8"
|
||||
"icecat3"
|
||||
"icecat3Xul" ;; redundant with `icecat'
|
||||
"icecatWrapper"
|
||||
"icecat3Wrapper"
|
||||
"icecatXulrunner3"
|
||||
"libzrtpcpp_1_6"
|
||||
"parted_2_3"
|
||||
))
|
||||
|
||||
(define (gnu? package)
|
||||
@@ -742,11 +550,8 @@ Return #t if the signature was good, #f otherwise."
|
||||
(match attr
|
||||
(('attribute _ "description" value)
|
||||
(string-prefix? "GNU" value))
|
||||
(('attribute _ "homepage" (? string? value))
|
||||
(or (string-contains value "gnu.org")
|
||||
(string-contains value "gnupg.org")))
|
||||
(('attribute _ "homepage" ((? string? value) ...))
|
||||
(any (cut string-contains <> "www.gnu.org") value))
|
||||
(('attribute _ "homepage" value)
|
||||
(string-contains value "www.gnu.org"))
|
||||
(_ #f)))
|
||||
metas))
|
||||
(_ #f)))
|
||||
@@ -777,10 +582,11 @@ Return #t if the signature was good, #f otherwise."
|
||||
("libosip2" "ftp.gnu.org" "/gnu/osip" #f)
|
||||
("libgcrypt" "ftp.gnupg.org" "/gcrypt" #t)
|
||||
("libgpg-error" "ftp.gnupg.org" "/gcrypt" #t)
|
||||
("libassuan" "ftp.gnupg.org" "/gcrypt" #t)
|
||||
("freefont-ttf" "ftp.gnu.org" "/gnu/freefont" #f)
|
||||
("gnupg" "ftp.gnupg.org" "/gcrypt" #t)
|
||||
("gnu-ghostscript" "ftp.gnu.org" "/gnu/ghostscript" #f)
|
||||
("grub" "alpha.gnu.org" "/gnu" #t)
|
||||
("GNUnet" "ftp.gnu.org" "/gnu/gnunet" #f)
|
||||
("mit-scheme" "ftp.gnu.org" "/gnu/mit-scheme/stable.pkg" #f)
|
||||
("icecat" "ftp.gnu.org" "/gnu/gnuzilla" #f)
|
||||
("source-highlight" "ftp.gnu.org" "/gnu/src-highlite" #f)
|
||||
@@ -804,6 +610,7 @@ Return #t if the signature was good, #f otherwise."
|
||||
("gnumake" . "make")
|
||||
("gnused" . "sed")
|
||||
("gnutar" . "tar")
|
||||
("gnunet" . "GNUnet") ;; ftp.gnu.org/gnu/gnunet/GNUnet-x.y.tar.gz
|
||||
("mitscheme" . "mit-scheme")
|
||||
("texmacs" . "TeXmacs")))
|
||||
|
||||
@@ -948,7 +755,6 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
gnu-packages))
|
||||
|
||||
(define (fetch-gnu project directory version archive-type)
|
||||
"Download PROJECT's tarball over FTP."
|
||||
(let* ((server (ftp-server/directory project))
|
||||
(base (string-append project "-" version ".tar." archive-type))
|
||||
(url (string-append "ftp://" server "/" directory "/" base))
|
||||
@@ -961,9 +767,9 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
(false-if-exception (delete-file sig))
|
||||
(system* "wget" sig-url)
|
||||
(if (file-exists? sig)
|
||||
(let ((ret (gnupg-verify* sig path)))
|
||||
(let ((ret (system* "gpg" "--verify" sig path)))
|
||||
(false-if-exception (delete-file sig))
|
||||
(if ret
|
||||
(if (and ret (= 0 (status:exit-val ret)))
|
||||
hash
|
||||
(begin
|
||||
(format (current-error-port)
|
||||
@@ -991,18 +797,12 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
(format #t "~%")
|
||||
(format #t " -x, --xml=FILE Read XML output of `nix-instantiate'~%")
|
||||
(format #t " from FILE.~%")
|
||||
(format #t " -A, --attribute=ATTR~%")
|
||||
(format #t " Update only the package pointed to by attribute~%")
|
||||
(format #t " ATTR.~%")
|
||||
(format #t " -s, --select=SET Update only packages from SET, which may~%")
|
||||
(format #t " be either `all', `stdenv', or `non-stdenv'.~%")
|
||||
(format #t " -d, --dry-run Don't actually update Nix expressions~%")
|
||||
(format #t " -h, --help Give this help list.~%~%")
|
||||
(format #t "Report bugs to <ludo@gnu.org>~%")
|
||||
(exit 0)))
|
||||
(option '(#\A "attribute") #t #f
|
||||
(lambda (opt name arg result)
|
||||
(alist-cons 'attribute arg result)))
|
||||
(option '(#\s "select") #t #f
|
||||
(lambda (opt name arg result)
|
||||
(cond ((string-ci=? arg "stdenv")
|
||||
@@ -1028,14 +828,13 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
(define (gnupdate . args)
|
||||
;; Assume Nixpkgs is under $NIXPKGS or ~/src/nixpkgs.
|
||||
|
||||
(define (nixpkgs->snix xml-file attribute)
|
||||
(define (nixpkgs->snix xml-file)
|
||||
(format (current-error-port) "evaluating Nixpkgs...~%")
|
||||
(let* ((home (getenv "HOME"))
|
||||
(xml (if xml-file
|
||||
(open-input-file xml-file)
|
||||
(open-nixpkgs (or (getenv "NIXPKGS")
|
||||
(string-append home "/src/nixpkgs"))
|
||||
attribute)))
|
||||
(string-append home "/src/nixpkgs")))))
|
||||
(snix (xml->snix xml)))
|
||||
(if (not xml-file)
|
||||
(let ((status (pipe-failed? xml)))
|
||||
@@ -1044,37 +843,7 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
(format (current-error-port) "`nix-instantiate' failed: ~A~%"
|
||||
status)
|
||||
(exit 1)))))
|
||||
|
||||
;; If we asked for a specific attribute, rewrap the thing in an
|
||||
;; attribute set to match the expectations of `packages-to-update' & co.
|
||||
(if attribute
|
||||
(match snix
|
||||
(('snix loc ('derivation args ...))
|
||||
`(snix ,loc
|
||||
(attribute-set
|
||||
((attribute #f ,attribute
|
||||
(derivation ,@args)))))))
|
||||
snix)))
|
||||
|
||||
(define (selected-gnu-packages packages stdenv selection)
|
||||
;; Return the subset of PACKAGES that are/aren't in STDENV, according to
|
||||
;; SELECTION. To do that reliably, we check whether their "src"
|
||||
;; derivation is a requisite of STDENV.
|
||||
(define gnu
|
||||
(gnu-packages packages))
|
||||
|
||||
(case selection
|
||||
((stdenv)
|
||||
(filter (lambda (p)
|
||||
(member (package-source-output-path p)
|
||||
(force stdenv)))
|
||||
gnu))
|
||||
((non-stdenv)
|
||||
(filter (lambda (p)
|
||||
(not (member (package-source-output-path p)
|
||||
(force stdenv))))
|
||||
gnu))
|
||||
(else gnu)))
|
||||
snix))
|
||||
|
||||
(let* ((opts (args-fold (cdr args) %options
|
||||
(lambda (opt name arg result)
|
||||
@@ -1082,8 +851,7 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
(lambda (operand result)
|
||||
(error "extraneous argument `~A'" operand))
|
||||
'()))
|
||||
(snix (nixpkgs->snix (assq-ref opts 'xml-file)
|
||||
(assq-ref opts 'attribute)))
|
||||
(snix (nixpkgs->snix (assoc-ref opts 'xml-file)))
|
||||
(packages (match snix
|
||||
(('snix _ ('attribute-set attributes))
|
||||
attributes)
|
||||
@@ -1092,12 +860,23 @@ pairs. Example: (\"mit-scheme-9.0.1\" . \"/gnu/mit-scheme/stable.pkg/9.0.1\").
|
||||
;; The source tarballs that make up stdenv.
|
||||
(filter-map derivation-source-output-path
|
||||
(package-requisites (stdenv-package packages)))))
|
||||
(attribute (assq-ref opts 'attribute))
|
||||
(selection (assq-ref opts 'filter))
|
||||
(to-update (if attribute
|
||||
packages ; already a subset
|
||||
(selected-gnu-packages packages stdenv selection)))
|
||||
(updates (packages-to-update to-update)))
|
||||
(gnu (gnu-packages packages))
|
||||
(gnu* (case (assoc-ref opts 'filter)
|
||||
;; Filter out packages that are/aren't in `stdenv'. To
|
||||
;; do that reliably, we check whether their "src"
|
||||
;; derivation is a requisite of stdenv.
|
||||
((stdenv)
|
||||
(filter (lambda (p)
|
||||
(member (package-source-output-path p)
|
||||
(force stdenv)))
|
||||
gnu))
|
||||
((non-stdenv)
|
||||
(filter (lambda (p)
|
||||
(not (member (package-source-output-path p)
|
||||
(force stdenv))))
|
||||
gnu))
|
||||
(else gnu)))
|
||||
(updates (packages-to-update gnu*)))
|
||||
|
||||
(format #t "~%~A packages to update...~%" (length updates))
|
||||
(for-each (lambda (update)
|
||||
|
||||
@@ -5,8 +5,8 @@ hydra_eval_jobs \
|
||||
--argstr system x86_64-linux \
|
||||
--argstr system i686-linux \
|
||||
--argstr system x86_64-darwin \
|
||||
--argstr system i686-darwin \
|
||||
--argstr system i686-cygwin \
|
||||
--argstr system x86_64-cygwin \
|
||||
--argstr system i686-freebsd \
|
||||
--arg officialRelease false \
|
||||
--arg nixpkgs "{ outPath = builtins.storePath ./. ; rev = 1234; }" \
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{ stdenv, makeWrapper, perl, perlPackages }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nix-generate-from-cpan-1";
|
||||
|
||||
buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON perlPackages.CPANPLUS ];
|
||||
|
||||
unpackPhase = "true";
|
||||
buildPhase = "true";
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${./nix-generate-from-cpan.pl} $out/bin/nix-generate-from-cpan
|
||||
wrapProgram $out/bin/nix-generate-from-cpan --set PERL5LIB $PERL5LIB
|
||||
'';
|
||||
|
||||
meta = {
|
||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||
description = "Utility to generate a Nix expression for a Perl package from CPAN";
|
||||
};
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
#! /run/current-system/sw/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use CPANPLUS::Backend;
|
||||
use YAML::XS;
|
||||
use JSON;
|
||||
|
||||
my $module_name = $ARGV[0];
|
||||
die "syntax: $0 <MODULE-NAME>\n" unless defined $module_name;
|
||||
|
||||
my $cb = CPANPLUS::Backend->new;
|
||||
|
||||
my @modules = $cb->search(type => "name", allow => [$module_name]);
|
||||
die "module $module_name not found\n" if scalar @modules == 0;
|
||||
die "multiple packages that match module $module_name\n" if scalar @modules > 1;
|
||||
my $module = $modules[0];
|
||||
|
||||
sub pkg_to_attr {
|
||||
my ($pkg_name) = @_;
|
||||
my $attr_name = $pkg_name;
|
||||
$attr_name =~ s/-\d.*//; # strip version
|
||||
return "LWP" if $attr_name eq "libwww-perl";
|
||||
$attr_name =~ s/-//g;
|
||||
return $attr_name;
|
||||
}
|
||||
|
||||
sub get_pkg_name {
|
||||
my ($module) = @_;
|
||||
my $pkg_name = $module->package;
|
||||
$pkg_name =~ s/\.tar.*//;
|
||||
$pkg_name =~ s/\.zip//;
|
||||
return $pkg_name;
|
||||
}
|
||||
|
||||
my $pkg_name = get_pkg_name $module;
|
||||
my $attr_name = pkg_to_attr $pkg_name;
|
||||
|
||||
print STDERR "attribute name: ", $attr_name, "\n";
|
||||
print STDERR "module: ", $module->module, "\n";
|
||||
print STDERR "version: ", $module->version, "\n";
|
||||
print STDERR "package: ", $module->package, , " (", $pkg_name, ", ", $attr_name, ")\n";
|
||||
print STDERR "path: ", $module->path, "\n";
|
||||
|
||||
my $tar_path = $module->fetch();
|
||||
print STDERR "downloaded to: $tar_path\n";
|
||||
print STDERR "sha-256: ", $module->status->checksum_value, "\n";
|
||||
|
||||
my $pkg_path = $module->extract();
|
||||
print STDERR "unpacked to: $pkg_path\n";
|
||||
|
||||
my $meta;
|
||||
if (-e "$pkg_path/META.yml") {
|
||||
eval {
|
||||
$meta = YAML::XS::LoadFile("$pkg_path/META.yml");
|
||||
};
|
||||
if ($@) {
|
||||
system("iconv -f windows-1252 -t utf-8 '$pkg_path/META.yml' > '$pkg_path/META.yml.tmp'");
|
||||
$meta = YAML::XS::LoadFile("$pkg_path/META.yml.tmp");
|
||||
}
|
||||
} elsif (-e "$pkg_path/META.json") {
|
||||
local $/;
|
||||
open(my $fh, '<', "$pkg_path/META.json") or die;
|
||||
$meta = decode_json(<$fh>);
|
||||
} else {
|
||||
warn "package has no META.yml or META.json\n";
|
||||
}
|
||||
|
||||
print STDERR "metadata: ", encode_json($meta), "\n" if defined $meta;
|
||||
|
||||
# Map a module to the attribute corresponding to its package
|
||||
# (e.g. HTML::HeadParser will be mapped to HTMLParser, because that
|
||||
# module is in the HTML-Parser package).
|
||||
sub module_to_pkg {
|
||||
my ($module_name) = @_;
|
||||
my @modules = $cb->search(type => "name", allow => [$module_name]);
|
||||
if (scalar @modules == 0) {
|
||||
# Fallback.
|
||||
$module_name =~ s/:://g;
|
||||
return $module_name;
|
||||
}
|
||||
my $module = $modules[0];
|
||||
my $attr_name = pkg_to_attr(get_pkg_name $module);
|
||||
print STDERR "mapped dep $module_name to $attr_name\n";
|
||||
return $attr_name;
|
||||
}
|
||||
|
||||
sub get_deps {
|
||||
my ($type) = @_;
|
||||
my $deps;
|
||||
if (defined $meta->{prereqs}) {
|
||||
die "unimplemented";
|
||||
} elsif ($type eq "runtime") {
|
||||
$deps = $meta->{requires};
|
||||
} elsif ($type eq "configure") {
|
||||
$deps = $meta->{configure_requires};
|
||||
} elsif ($type eq "build") {
|
||||
$deps = $meta->{build_requires};
|
||||
}
|
||||
my @res;
|
||||
foreach my $n (keys %{$deps}) {
|
||||
next if $n eq "perl";
|
||||
# Hacky way to figure out if this module is part of Perl.
|
||||
if ($n !~ /^JSON/ && $n !~ /^YAML/ && $n !~ /^Module::Pluggable/) {
|
||||
eval "use $n;";
|
||||
if (!$@) {
|
||||
print STDERR "skipping Perl-builtin module $n\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
push @res, module_to_pkg($n);
|
||||
}
|
||||
return @res;
|
||||
}
|
||||
|
||||
sub uniq {
|
||||
return keys %{{ map { $_ => 1 } @_ }};
|
||||
}
|
||||
|
||||
my @build_deps = sort(uniq(get_deps("configure"), get_deps("build"), get_deps("test")));
|
||||
print STDERR "build deps: @build_deps\n";
|
||||
|
||||
my @runtime_deps = sort(uniq(get_deps("runtime")));
|
||||
print STDERR "runtime deps: @runtime_deps\n";
|
||||
|
||||
my $homepage = $meta->{resources}->{homepage};
|
||||
print STDERR "homepage: $homepage\n" if defined $homepage;
|
||||
|
||||
my $description = $meta->{abstract};
|
||||
if (defined $description) {
|
||||
$description = uc(substr($description, 0, 1)) . substr($description, 1); # capitalise first letter
|
||||
$description =~ s/\.$//; # remove period at the end
|
||||
$description =~ s/\s*$//;
|
||||
$description =~ s/^\s*//;
|
||||
print STDERR "description: $description\n";
|
||||
}
|
||||
|
||||
my $license = $meta->{license};
|
||||
if (defined $license) {
|
||||
$license = "perl5" if $license eq "perl_5";
|
||||
print STDERR "license: $license\n";
|
||||
}
|
||||
|
||||
my $build_fun = -e "$pkg_path/Build.PL" && ! -e "$pkg_path/Makefile.PL" ? "buildPerlModule" : "buildPerlPackage";
|
||||
|
||||
print STDERR "===\n";
|
||||
|
||||
print <<EOF;
|
||||
$attr_name = $build_fun {
|
||||
name = "$pkg_name";
|
||||
src = fetchurl {
|
||||
url = mirror://cpan/${\$module->path}/${\$module->package};
|
||||
sha256 = "${\$module->status->checksum_value}";
|
||||
};
|
||||
EOF
|
||||
print <<EOF if scalar @build_deps > 0;
|
||||
buildInputs = [ @build_deps ];
|
||||
EOF
|
||||
print <<EOF if scalar @runtime_deps > 0;
|
||||
propagatedBuildInputs = [ @runtime_deps ];
|
||||
EOF
|
||||
print <<EOF;
|
||||
meta = {
|
||||
EOF
|
||||
print <<EOF if defined $homepage;
|
||||
homepage = $homepage;
|
||||
EOF
|
||||
print <<EOF if defined $description;
|
||||
description = "$description";
|
||||
EOF
|
||||
print <<EOF if defined $license;
|
||||
license = "$license";
|
||||
EOF
|
||||
print <<EOF;
|
||||
};
|
||||
};
|
||||
EOF
|
||||
@@ -1,22 +0,0 @@
|
||||
{ stdenv, makeWrapper, perl, perlPackages }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-lint-1";
|
||||
|
||||
buildInputs = [ makeWrapper perl perlPackages.XMLSimple ];
|
||||
|
||||
unpackPhase = "true";
|
||||
buildPhase = "true";
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${./nixpkgs-lint.pl} $out/bin/nixpkgs-lint
|
||||
wrapProgram $out/bin/nixpkgs-lint --set PERL5LIB $PERL5LIB
|
||||
'';
|
||||
|
||||
meta = {
|
||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||
description = "A utility for Nixpkgs contributors to check Nixpkgs for common errors";
|
||||
};
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
#! /run/current-system/sw/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use List::Util qw(min);
|
||||
use XML::Simple qw(:strict);
|
||||
use Getopt::Long qw(:config gnu_getopt);
|
||||
|
||||
# Parse the command line.
|
||||
my $path = "<nixpkgs>";
|
||||
my $filter = "*";
|
||||
my $maintainer;
|
||||
|
||||
sub showHelp {
|
||||
print <<EOF;
|
||||
Usage: $0 [--package=NAME] [--maintainer=REGEXP] [--file=PATH]
|
||||
|
||||
Check Nixpkgs for common errors/problems.
|
||||
|
||||
-p, --package filter packages by name (default is ‘*’)
|
||||
-m, --maintainer filter packages by maintainer (case-insensitive regexp)
|
||||
-f, --file path to Nixpkgs (default is ‘<nixpkgs>’)
|
||||
|
||||
Examples:
|
||||
\$ nixpkgs-lint -f /my/nixpkgs -p firefox
|
||||
\$ nixpkgs-lint -f /my/nixpkgs -m eelco
|
||||
EOF
|
||||
exit 0;
|
||||
}
|
||||
|
||||
GetOptions("package|p=s" => \$filter,
|
||||
"maintainer|m=s" => \$maintainer,
|
||||
"file|f=s" => \$path,
|
||||
"help" => sub { showHelp() }
|
||||
) or exit 1;
|
||||
|
||||
# Evaluate Nixpkgs into an XML representation.
|
||||
my $xml = `nix-env -f '$path' -qa '$filter' --xml --meta --drv-path`;
|
||||
die "$0: evaluation of ‘$path’ failed\n" if $? != 0;
|
||||
|
||||
my $info = XMLin($xml, KeyAttr => { 'item' => '+attrPath', 'meta' => 'name' }, ForceArray => 1, SuppressEmpty => '' ) or die "cannot parse XML output";
|
||||
|
||||
# Check meta information.
|
||||
print "=== Package meta information ===\n\n";
|
||||
my $nrBadNames = 0;
|
||||
my $nrMissingMaintainers = 0;
|
||||
my $nrMissingPlatforms = 0;
|
||||
my $nrMissingDescriptions = 0;
|
||||
my $nrBadDescriptions = 0;
|
||||
my $nrMissingLicenses = 0;
|
||||
|
||||
foreach my $attr (sort keys %{$info->{item}}) {
|
||||
my $pkg = $info->{item}->{$attr};
|
||||
|
||||
my $pkgName = $pkg->{name};
|
||||
my $pkgVersion = "";
|
||||
if ($pkgName =~ /(.*)(-[0-9].*)$/) {
|
||||
$pkgName = $1;
|
||||
$pkgVersion = $2;
|
||||
}
|
||||
|
||||
# Check the maintainers.
|
||||
my @maintainers;
|
||||
my $x = $pkg->{meta}->{maintainers};
|
||||
if (defined $x && $x->{type} eq "strings") {
|
||||
@maintainers = map { $_->{value} } @{$x->{string}};
|
||||
} elsif (defined $x->{value}) {
|
||||
@maintainers = ($x->{value});
|
||||
}
|
||||
|
||||
if (defined $maintainer && scalar(grep { $_ =~ /$maintainer/i } @maintainers) == 0) {
|
||||
delete $info->{item}->{$attr};
|
||||
next;
|
||||
}
|
||||
|
||||
if (scalar @maintainers == 0) {
|
||||
print "$attr: Lacks a maintainer\n";
|
||||
$nrMissingMaintainers++;
|
||||
}
|
||||
|
||||
# Check the platforms.
|
||||
if (!defined $pkg->{meta}->{platforms}) {
|
||||
print "$attr: Lacks a platform\n";
|
||||
$nrMissingPlatforms++;
|
||||
}
|
||||
|
||||
# Package names should not be capitalised.
|
||||
if ($pkgName =~ /^[A-Z]/) {
|
||||
print "$attr: package name ‘$pkgName’ should not be capitalised\n";
|
||||
$nrBadNames++;
|
||||
}
|
||||
|
||||
if ($pkgVersion eq "") {
|
||||
print "$attr: package has no version\n";
|
||||
$nrBadNames++;
|
||||
}
|
||||
|
||||
# Check the license.
|
||||
if (!defined $pkg->{meta}->{license}) {
|
||||
print "$attr: Lacks a license\n";
|
||||
$nrMissingLicenses++;
|
||||
}
|
||||
|
||||
# Check the description.
|
||||
my $description = $pkg->{meta}->{description}->{value};
|
||||
if (!$description) {
|
||||
print "$attr: Lacks a description\n";
|
||||
$nrMissingDescriptions++;
|
||||
} else {
|
||||
my $bad = 0;
|
||||
if ($description =~ /^\s/) {
|
||||
print "$attr: Description starts with whitespace\n";
|
||||
$bad = 1;
|
||||
}
|
||||
if ($description =~ /\s$/) {
|
||||
print "$attr: Description ends with whitespace\n";
|
||||
$bad = 1;
|
||||
}
|
||||
if ($description =~ /\.$/) {
|
||||
print "$attr: Description ends with a period\n";
|
||||
$bad = 1;
|
||||
}
|
||||
if (index(lc($description), lc($attr)) != -1) {
|
||||
print "$attr: Description contains package name\n";
|
||||
$bad = 1;
|
||||
}
|
||||
$nrBadDescriptions++ if $bad;
|
||||
}
|
||||
}
|
||||
|
||||
print "\n";
|
||||
|
||||
# Find packages that have the same name.
|
||||
print "=== Package name collisions ===\n\n";
|
||||
|
||||
my %pkgsByName;
|
||||
|
||||
foreach my $attr (sort keys %{$info->{item}}) {
|
||||
my $pkg = $info->{item}->{$attr};
|
||||
#print STDERR "attr = $attr, name = $pkg->{name}\n";
|
||||
$pkgsByName{$pkg->{name}} //= [];
|
||||
push @{$pkgsByName{$pkg->{name}}}, $pkg;
|
||||
}
|
||||
|
||||
my $nrCollisions = 0;
|
||||
foreach my $name (sort keys %pkgsByName) {
|
||||
my @pkgs = @{$pkgsByName{$name}};
|
||||
|
||||
# Filter attributes that are aliases of each other (e.g. yield the
|
||||
# same derivation path).
|
||||
my %drvsSeen;
|
||||
@pkgs = grep { my $x = $drvsSeen{$_->{drvPath}}; $drvsSeen{$_->{drvPath}} = 1; !defined $x } @pkgs;
|
||||
|
||||
# Filter packages that have a lower priority.
|
||||
my $highest = min (map { $_->{meta}->{priority}->{value} // 0 } @pkgs);
|
||||
@pkgs = grep { ($_->{meta}->{priority}->{value} // 0) == $highest } @pkgs;
|
||||
|
||||
next if scalar @pkgs == 1;
|
||||
|
||||
$nrCollisions++;
|
||||
print "The following attributes evaluate to a package named ‘$name’:\n";
|
||||
print " ", join(", ", map { $_->{attrPath} } @pkgs), "\n\n";
|
||||
}
|
||||
|
||||
print "=== Bottom line ===\n";
|
||||
print "Number of packages: ", scalar(keys %{$info->{item}}), "\n";
|
||||
print "Number of bad names: $nrBadNames\n";
|
||||
print "Number of missing maintainers: $nrMissingMaintainers\n";
|
||||
print "Number of missing platforms: $nrMissingPlatforms\n";
|
||||
print "Number of missing licenses: $nrMissingLicenses\n";
|
||||
print "Number of missing descriptions: $nrMissingDescriptions\n";
|
||||
print "Number of bad descriptions: $nrBadDescriptions\n";
|
||||
print "Number of name collisions: $nrCollisions\n";
|
||||
@@ -62,7 +62,7 @@ for bin in $(find $binaryDist -executable -type f) :; do
|
||||
)
|
||||
|
||||
if test "$names" = "glibc"; then names="stdenv.glibc"; fi
|
||||
if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.cc.cc"; fi
|
||||
if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.gcc.gcc"; fi
|
||||
|
||||
if test $lib != $libPath; then
|
||||
interpreter="--interpreter \${$names}/lib/$lib"
|
||||
|
||||
146
maintainers/scripts/sort-attrs.str
Normal file
146
maintainers/scripts/sort-attrs.str
Normal file
@@ -0,0 +1,146 @@
|
||||
/* Tool to sort attribute sets. Primarily useful for keeping
|
||||
all-packages.nix tidy.
|
||||
|
||||
To compile:
|
||||
|
||||
$ strc -i ../../maintainers/scripts/sort-attrs.str -la stratego-lib
|
||||
|
||||
Typical invocation:
|
||||
|
||||
$ sglr -m -p ~/Dev/nix/src/libexpr/nix.tbl -i all-packages.nix \
|
||||
| implode-asfix --lex \
|
||||
| ../../maintainers/scripts/sort-attrs \
|
||||
| asfix-yield
|
||||
*/
|
||||
|
||||
module sort-attrs
|
||||
|
||||
imports
|
||||
libstratego-lib
|
||||
libstratego-sglr
|
||||
|
||||
|
||||
strategies
|
||||
|
||||
no-wsp = !appl(prod([], cf(opt(layout())), no-attrs()), [])
|
||||
|
||||
|
||||
rules
|
||||
|
||||
list-sep(s): [] -> []
|
||||
list-sep(s): [x | xs] -> [[x | before] | <list-sep(s)> [split | after]]
|
||||
where
|
||||
<split-fetch-keep(s)> xs => (before, split, after)
|
||||
list-sep(s): [x | xs] -> [[x | xs]]
|
||||
where
|
||||
<not(split-fetch-keep(s))> xs
|
||||
|
||||
list-sep-end(s): xs -> [<conc> (before, [split]) | <list-sep-end(s)> after]
|
||||
where
|
||||
<split-fetch-keep(s)> xs => (before, split, after)
|
||||
list-sep-end(s): xs -> [xs]
|
||||
where
|
||||
<not(split-fetch-keep(s))> xs
|
||||
|
||||
|
||||
sort-attrs:
|
||||
appl(p@prod(_, _, attrs([term(cons("Attrs"))])),
|
||||
[ lit("{")
|
||||
, ws1
|
||||
, appl(p2@list(cf(iter-star(sort("Bind")))), attrs)
|
||||
, ws2
|
||||
, lit("}")
|
||||
]
|
||||
) ->
|
||||
appl(p, [lit("{"), <no-wsp>, appl(p2, <concat> attrs'), ws2, lit("}")])
|
||||
where
|
||||
<debug> "found it";
|
||||
<attach-wsp> [ws1 | attrs] => withWSP;
|
||||
<list-sep(starts-section)> withWSP => groups;
|
||||
<length; debug> groups;
|
||||
<map({x', x'', x''', xs', starts, starts': \[x | xs] -> [x''' | xs']
|
||||
where
|
||||
<remove-section-start> x => (x', starts);
|
||||
<map(regularise-empty-lines); if !starts; debug; sortable-section; debug then qsort(compare-attrs) else id end> [x' | xs] => [x'' | xs'];
|
||||
<[] <+ \x -> ["\n\n\n" | x]\ > starts => starts';
|
||||
<prepend-layout> (starts', x'') => x'''
|
||||
\ })> groups => attrs';
|
||||
<debug> "did it"
|
||||
|
||||
|
||||
attach-wsp: [a, b | cs] -> [(a, b) | <attach-wsp> cs]
|
||||
attach-wsp: [] -> []
|
||||
|
||||
|
||||
strategies
|
||||
|
||||
starts-section =
|
||||
?x@(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr);
|
||||
<implode-string; is-substring(!"###")> cs;
|
||||
!x
|
||||
|
||||
rules
|
||||
|
||||
|
||||
sortable-section = ?[s]; !s; explode-string; not(fetch({x: ?x; !(x, 97); geq}))
|
||||
|
||||
|
||||
remove-section-start:
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr) ->
|
||||
((appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs'), attr), starts)
|
||||
where
|
||||
!cs;
|
||||
list-sep-end(?10); // separate into lines, keeping the \n
|
||||
map(implode-string);
|
||||
partition(where(is-substring(!"###"))) => (starts, rest);
|
||||
<map(explode-string); concat> rest => cs'
|
||||
|
||||
|
||||
regularise-empty-lines:
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr) ->
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs''), attr)
|
||||
where
|
||||
// separate into lines, keeping the \n
|
||||
// last whitespace is significant, keep
|
||||
<list-sep-end(?10); split-init-last> cs => (init, last);
|
||||
<regularise-empty-lines'> init => cs'; // remove whitespace-only lines
|
||||
<concat> [<explode-string> "\n\n", <concat> cs', last] => cs'' // add one empty line
|
||||
|
||||
/* Dirty hack: *do* keep the first empty line following a non-empty line. !!! order matters */
|
||||
regularise-empty-lines': [] -> []
|
||||
|
||||
regularise-empty-lines': [x, y | xs] -> [x, y | <regularise-empty-lines'> xs]
|
||||
where
|
||||
<fetch-elem(not(?10 <+ ?32))> x;
|
||||
<not(fetch-elem(not(?10 <+ ?32)))> y
|
||||
|
||||
regularise-empty-lines': [x | xs] -> [x | <regularise-empty-lines'> xs]
|
||||
where <fetch-elem(not(?10 <+ ?32))> x
|
||||
|
||||
regularise-empty-lines': [x | xs] -> <regularise-empty-lines'> xs
|
||||
where <not(fetch-elem(not(?10 <+ ?32)))> x
|
||||
|
||||
|
||||
prepend-layout:
|
||||
(text, (appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr)) ->
|
||||
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs''), attr)
|
||||
where
|
||||
<implode-string> cs => cs';
|
||||
<conc-strings; explode-string> (<concat-strings> text, cs') => cs''
|
||||
|
||||
|
||||
compare-attrs:
|
||||
x@
|
||||
( (_, appl(p1@prod(_, _, attrs([term(cons("Bind"))])), [id1 | xs1]))
|
||||
, (_, appl(p2@prod(_, _, attrs([term(cons("Bind"))])), [id2 | xs2]))
|
||||
)
|
||||
-> x
|
||||
where
|
||||
<string-lt> (id1, id2)
|
||||
|
||||
|
||||
strategies
|
||||
|
||||
main = io-wrap(
|
||||
oncetd(sort-attrs)
|
||||
)
|
||||
@@ -1,7 +1,3 @@
|
||||
#! /bin/sh
|
||||
|
||||
if [[ -z "$VERBOSE" ]]; then
|
||||
echo "You may set VERBOSE=1 to see debug output or to any other non-empty string to make this script completely silent"
|
||||
fi
|
||||
unset HOME NIXPKGS_CONFIG # Force empty config
|
||||
nix-instantiate --strict --eval-only --xml --show-trace "$(dirname "$0")"/eval-release.nix 2>&1 > /dev/null
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
set -e
|
||||
|
||||
export NIX_CURL_FLAGS=-sS
|
||||
|
||||
if [[ $1 == nix ]]; then
|
||||
echo "=== Installing Nix..."
|
||||
# Install Nix
|
||||
bash <(curl -sS https://nixos.org/nix/install)
|
||||
source $HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
# Make sure we can use hydra's binary cache
|
||||
sudo mkdir /etc/nix
|
||||
sudo tee /etc/nix/nix.conf <<EOF >/dev/null
|
||||
binary-caches = http://cache.nixos.org http://hydra.nixos.org
|
||||
trusted-binary-caches = http://hydra.nixos.org
|
||||
build-max-jobs = 4
|
||||
EOF
|
||||
|
||||
# Verify evaluation
|
||||
echo "=== Verifying that nixpkgs evaluates..."
|
||||
nix-env -f. -qa --json >/dev/null
|
||||
elif [[ $1 == nox ]]; then
|
||||
echo "=== Installing nox..."
|
||||
git clone -q https://github.com/madjar/nox
|
||||
pip --quiet install -e nox
|
||||
elif [[ $1 == build ]]; then
|
||||
source $HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
if [[ $TRAVIS_PULL_REQUEST == false ]]; then
|
||||
echo "=== Not a pull request"
|
||||
else
|
||||
echo "=== Checking PR"
|
||||
|
||||
if ! nox-review pr ${TRAVIS_PULL_REQUEST}; then
|
||||
if sudo dmesg | egrep 'Out of memory|Killed process' > /tmp/oom-log; then
|
||||
echo "=== The build failed due to running out of memory:"
|
||||
cat /tmp/oom-log
|
||||
echo "=== Please disregard the result of this Travis build."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
# echo "=== Checking tarball creation"
|
||||
# nix-build pkgs/top-level/release.nix -A tarball
|
||||
else
|
||||
echo "$0: Unknown option $1" >&2
|
||||
false
|
||||
fi
|
||||
@@ -1,112 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
: ${NIXOS_CHANNELS:=https://nixos.org/channels/}
|
||||
: ${CHANNELS_NAMESPACE:=refs/heads/channels/}
|
||||
|
||||
# List all channels which are currently in the repository which we would
|
||||
# have to remove if they are not found again.
|
||||
deadChannels=$(git for-each-ref --format="%(refname)" "$CHANNELS_NAMESPACE")
|
||||
|
||||
updateRef() {
|
||||
local channelName=$1
|
||||
local newRev=$2
|
||||
|
||||
# if the inputs are not valid, then we do not update any branch.
|
||||
test -z "$newRev" -o -z "$channelName" && return;
|
||||
|
||||
# Update the local refs/heads/channels/* branches to be in-sync with the
|
||||
# channel references.
|
||||
local branch=$CHANNELS_NAMESPACE$channelName
|
||||
oldRev=$(git rev-parse --short "$branch" 2>/dev/null || true)
|
||||
if test "$oldRev" != "$newRev"; then
|
||||
if git update-ref "$branch" "$newRev" 2>/dev/null; then
|
||||
if test -z "$oldRev"; then
|
||||
echo " * [new branch] $newRev -> ${branch#refs/heads/}"
|
||||
else
|
||||
echo " $oldRev..$newRev -> ${branch#refs/heads/}"
|
||||
fi
|
||||
else
|
||||
if test -z "$oldRev"; then
|
||||
echo " * [missing rev] $newRev -> ${branch#refs/heads/}"
|
||||
else
|
||||
echo " [missing rev] $oldRev..$newRev -> ${branch#refs/heads/}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Filter out the current channel from the list of dead channels.
|
||||
deadChannels=$(grep -v "$CHANNELS_NAMESPACE$channelName" <<EOF
|
||||
$deadChannels
|
||||
EOF
|
||||
) ||true
|
||||
}
|
||||
|
||||
# Find the name of all channels which are listed in the directory.
|
||||
echo "Fetching channels from $NIXOS_CHANNELS:"
|
||||
for channelName in : $(curl -s "$NIXOS_CHANNELS" | sed -n '/folder/ { s,.*href=",,; s,/".*,,; p }'); do
|
||||
test "$channelName" = : && continue;
|
||||
|
||||
# Do not follow redirections, such that we can extract the
|
||||
# short-changeset from the name of the directory where we are
|
||||
# redirected to.
|
||||
sha1=$(curl -sI "$NIXOS_CHANNELS$channelName" | sed -n '/Location/ { s,.*\.\([a-f0-9]*\)[ \r]*$,\1,; p; }')
|
||||
|
||||
updateRef "remotes/$channelName" "$sha1"
|
||||
done
|
||||
|
||||
echo "Fetching channels from nixos-version:"
|
||||
if currentSystem=$(nixos-version 2>/dev/null); then
|
||||
# If the system is entirely build from a custom nixpkgs version,
|
||||
# then the version is not annotated in git version. This sed
|
||||
# expression is basically matching that the expressions end with
|
||||
# ".<sha1> (Name)" to extract the sha1.
|
||||
sha1=$(echo "$currentSystem" | sed -n 's,^.*\.\([a-f0-9]*\) *(.*)$,\1,; T skip; p; :skip;')
|
||||
|
||||
updateRef current-system "$sha1"
|
||||
fi
|
||||
|
||||
echo "Fetching channels from $HOME/.nix-defexpr:"
|
||||
for revFile in : $(find -L "$HOME/.nix-defexpr/" -maxdepth 4 -name svn-revision); do
|
||||
test "$revFile" = : && continue;
|
||||
|
||||
# Deconstruct a path such as, into:
|
||||
#
|
||||
# /home/luke/.nix-defexpr/channels_root/nixos/nixpkgs/svn-revision
|
||||
# channelName = root/nixos
|
||||
#
|
||||
# /home/luke/.nix-defexpr/channels/nixpkgs/svn-revision
|
||||
# channelName = nixpkgs
|
||||
#
|
||||
user=${revFile#*.nix-defexpr/channels}
|
||||
repo=${user#*/}
|
||||
repo=${repo%%/*}
|
||||
user=${user%%/*}
|
||||
user=${user#_}
|
||||
test -z "$user" && user=$USER
|
||||
channelName="$user${user:+/}$repo"
|
||||
|
||||
sha1=$(sed -n 's,^.*\.\([a-f0-9]*\)$,\1,; T skip; p; :skip;' "$revFile")
|
||||
|
||||
updateRef "$channelName" "$sha1"
|
||||
done
|
||||
|
||||
# Suggest to remove channel branches which are no longer found by this
|
||||
# script. This is to handle the cases where a local/remote channel
|
||||
# disappear. We should not attempt to remove manually any branches, as they
|
||||
# might be user branches.
|
||||
if test -n "$deadChannels"; then
|
||||
|
||||
echo "
|
||||
Some old channel branches are still in your repository, if you
|
||||
want to remove them, run the following command(s):
|
||||
"
|
||||
|
||||
while read branch; do
|
||||
echo " git update-ref -d $branch"
|
||||
done <<EOF
|
||||
$deadChannels
|
||||
EOF
|
||||
|
||||
echo
|
||||
fi
|
||||
@@ -1,7 +0,0 @@
|
||||
viric viriketo@gmail.com
|
||||
Pjotr Prins pjotr.public01@thebird.nl
|
||||
Pjotr Prins pjotr.public05@thebird.nl
|
||||
Wouter den Breejen wbreejen
|
||||
MarcWeber marcweber
|
||||
Ricardo Correia Ricardo M. Correia
|
||||
ertesx@gmx.de ertes
|
||||
@@ -1,122 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
export LANG=C LC_ALL=C LC_COLLATE=C
|
||||
|
||||
# Load git log
|
||||
raw_git_log="$(git log)"
|
||||
git_data="$(echo "$raw_git_log" | grep 'Author:' |
|
||||
sed -e 's/^ *Author://; s/\\//g; s/^ *//; s/ *$//;
|
||||
s/ @ .*//; s/ *[<]/\t/; s/[>]//')"
|
||||
|
||||
# Name - nick - email correspondence from log and from maintainer list
|
||||
# Also there are a few manual entries
|
||||
maintainers="$(cat "$(dirname "$0")/../../lib/maintainers.nix" |
|
||||
grep '=' | sed -re 's/\\"/''/g;
|
||||
s/ *([^ =]*) *= *" *(.*[^ ]) *[<](.*)[>] *".*/\1\t\2\t\3/')"
|
||||
git_lines="$( ( echo "$git_data";
|
||||
cat "$(dirname "$0")/vanity-manual-equalities.txt") | sort |uniq)"
|
||||
|
||||
emails="$(
|
||||
( echo "$maintainers" | cut -f 3; echo "$git_data" | cut -f 2 ) |
|
||||
sort | uniq | grep -E ".+@.+[.].+"
|
||||
)"
|
||||
|
||||
fetchGithubName () {
|
||||
commitid="$(
|
||||
echo "$raw_git_log" | grep -B3 "Author: .*[<]$1[>]" | head -n 3 |
|
||||
grep '^commit ' | tail -n 1 | sed -e 's/^commit //'
|
||||
)"
|
||||
userid="$(
|
||||
curl https://github.com/NixOS/nixpkgs/commit/"$commitid" 2>/dev/null |
|
||||
grep authored -B10 | grep 'href="/' |
|
||||
sed -re 's@.* href="/@@; s@".*@@' |
|
||||
grep -v "/commit/"
|
||||
)";
|
||||
echo "$userid"
|
||||
}
|
||||
|
||||
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && {
|
||||
echo "$emails" | while read email; do
|
||||
line="$(grep "$email " "$NIXPKGS_GITHUB_NAME_CACHE")"
|
||||
[ -z "$line" ] && {
|
||||
echo "$email $(fetchGithubName "$email")" >> \
|
||||
"$NIXPKGS_GITHUB_NAME_CACHE"
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
# For RDF
|
||||
normalize_name () {
|
||||
sed -e 's/%/%25/g; s/ /%20/g; s/'\''/%27/g; s/"/%22/g; s/`/%60/g; s/\^/%5e/g; '
|
||||
}
|
||||
|
||||
denormalize_name () {
|
||||
sed -e 's/%20/ /g; s/%27/'\''/g; s/%22/"/g; s/%60/`/g; s/%5e/^/g; s/%25/%/g;';
|
||||
}
|
||||
|
||||
n3="$(mktemp --suffix .n3)"
|
||||
|
||||
# «The same person» relation and a sorting hint
|
||||
# Full name is something with a space
|
||||
(
|
||||
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
|
||||
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\1>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\3>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\3> <my://can-be> <my://name/\1>.@'
|
||||
echo "$git_lines" | grep ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
|
||||
echo "$git_lines" | grep -v ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://1>.@'
|
||||
echo "$maintainers" | cut -f 2 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
|
||||
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && cat "$NIXPKGS_GITHUB_NAME_CACHE" |
|
||||
grep -v " $" |
|
||||
sed -re 's@(.*)\t(.*)@<my://name/\1> <my://at-github> <my://github/\2>.@'
|
||||
) | normalize_name | grep -E '<my://[-a-z]+>' | sort | uniq > "$n3"
|
||||
|
||||
# Get transitive closure
|
||||
sparql="$(nix-build '<nixpkgs>' -Q -A apache-jena --no-out-link)/bin/sparql"
|
||||
name_list="$(
|
||||
"$sparql" --results=TSV --data="$n3" "
|
||||
select ?x ?y ?g where {
|
||||
?x <my://can-be>+ ?y.
|
||||
?x <my://is-name> ?g.
|
||||
}
|
||||
" | tail -n +2 |
|
||||
sed -re 's@<my://name/@@g; s@<my://@@g; s@>@@g;' |
|
||||
sort -k 2,3 -t ' '
|
||||
)"
|
||||
github_name_list="$(
|
||||
"$sparql" --results=TSV --data="$n3" "
|
||||
select ?x ?y where {
|
||||
?x (<my://can-be>+ / <my://at-github>) ?y.
|
||||
}
|
||||
" | tail -n +2 |
|
||||
sed -re 's@<my://(name|github)/@@g; s@<my://@@g; s@>@@g;'
|
||||
)"
|
||||
|
||||
# Take first spelling option for every person
|
||||
name_list_canonical="$(echo "$name_list" | cut -f 1,2 | uniq -f1)"
|
||||
|
||||
cleaner_script="$(echo "$name_list_canonical" | denormalize_name |
|
||||
sed -re 's/(.*)\t(.*)/s#^\2$#\1#g/g')"
|
||||
|
||||
# Add github usernames
|
||||
if [ -n "$NIXPKGS_GITHUB_NAME_CACHE" ]; then
|
||||
github_adder_script="$(echo "$github_name_list" |
|
||||
grep -E "$(echo "$name_list_canonical" | cut -f 2 |
|
||||
tr '\n' '|' )" |
|
||||
sort | uniq |
|
||||
sed -re 's/(.*)\t(.*)/s| \1$| \1\t\2|g;/' |
|
||||
denormalize_name
|
||||
)"
|
||||
else
|
||||
github_adder_script=''
|
||||
fi
|
||||
|
||||
echo "$name_list" | denormalize_name
|
||||
|
||||
echo
|
||||
|
||||
echo "$git_data" | cut -f 1 |
|
||||
sed -e "$cleaner_script" |
|
||||
sort | uniq -c | sort -k1n | sed -re "$github_adder_script" |
|
||||
sed -re 's/^ *([0-9]+) /\1\t/'
|
||||
@@ -1,18 +0,0 @@
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,5 +0,0 @@
|
||||
*** NixOS ***
|
||||
|
||||
NixOS is a Linux distribution based on the purely functional package
|
||||
management system Nix. More information can be found at
|
||||
http://nixos.org/nixos and in the manual in doc/manual.
|
||||
@@ -1,43 +0,0 @@
|
||||
{ configuration ? import ./lib/from-env.nix "NIXOS_CONFIG" <nixos-config>
|
||||
, system ? builtins.currentSystem
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
eval = import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules = [ configuration ];
|
||||
};
|
||||
|
||||
inherit (eval) pkgs;
|
||||
|
||||
# This is for `nixos-rebuild build-vm'.
|
||||
vmConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules = [ configuration ./modules/virtualisation/qemu-vm.nix ];
|
||||
}).config;
|
||||
|
||||
# This is for `nixos-rebuild build-vm-with-bootloader'.
|
||||
vmWithBootLoaderConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules =
|
||||
[ configuration
|
||||
./modules/virtualisation/qemu-vm.nix
|
||||
{ virtualisation.useBootLoader = true; }
|
||||
];
|
||||
}).config;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
inherit (eval) config options;
|
||||
|
||||
system = eval.config.system.build.toplevel;
|
||||
|
||||
vm = vmConfig.system.build.vm;
|
||||
|
||||
vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm;
|
||||
|
||||
# The following are used by nixos-rebuild.
|
||||
nixFallback = pkgs.nixUnstable;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
To build the manual, you need Nix installed on your system (no need
|
||||
for NixOS). To install Nix, follow the instructions at
|
||||
|
||||
https://nixos.org/nix/download.html
|
||||
|
||||
When you have Nix on your system, in the root directory of the project
|
||||
(i.e., `nixpkgs`), run:
|
||||
|
||||
nix-build nixos/release.nix -A manual.x86_64-linux
|
||||
|
||||
When this command successfully finishes, it will tell you where the
|
||||
manual got generated.
|
||||
@@ -1,65 +0,0 @@
|
||||
<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-boot-problems">
|
||||
|
||||
<title>Boot Problems</title>
|
||||
|
||||
<para>If NixOS fails to boot, there are a number of kernel command
|
||||
line parameters that may help you to identify or fix the issue. You
|
||||
can add these parameters in the GRUB boot menu by pressing “e” to
|
||||
modify the selected boot entry and editing the line starting with
|
||||
<literal>linux</literal>. The following are some useful kernel command
|
||||
line parameters that are recognised by the NixOS boot scripts or by
|
||||
systemd:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>boot.shell_on_fail</literal></term>
|
||||
<listitem><para>Start a root shell if something goes wrong in
|
||||
stage 1 of the boot process (the initial ramdisk). This is
|
||||
disabled by default because there is no authentication for the
|
||||
root shell.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>boot.debug1</literal></term>
|
||||
<listitem><para>Start an interactive shell in stage 1 before
|
||||
anything useful has been done. That is, no modules have been
|
||||
loaded and no file systems have been mounted, except for
|
||||
<filename>/proc</filename> and
|
||||
<filename>/sys</filename>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>boot.trace</literal></term>
|
||||
<listitem><para>Print every shell command executed by the stage 1
|
||||
and 2 boot scripts.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>single</literal></term>
|
||||
<listitem><para>Boot into rescue mode (a.k.a. single user mode).
|
||||
This will cause systemd to start nothing but the unit
|
||||
<literal>rescue.target</literal>, which runs
|
||||
<command>sulogin</command> to prompt for the root password and
|
||||
start a root login shell. Exiting the shell causes the system to
|
||||
continue with the normal boot process.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>systemd.log_level=debug systemd.log_target=console</literal></term>
|
||||
<listitem><para>Make systemd very verbose and send log messages to
|
||||
the console instead of the journal.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
For more parameters recognised by systemd, see
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>If no login prompts or X11 login screens appear (e.g. due to
|
||||
hanging dependencies), you can press Alt+ArrowUp. If you’re lucky,
|
||||
this will start rescue mode (described above). (Also note that since
|
||||
most units have a 90-second timeout before systemd gives up on them,
|
||||
the <command>agetty</command> login prompts should appear eventually
|
||||
unless something is very wrong.)</para>
|
||||
|
||||
</section>
|
||||
@@ -1,62 +0,0 @@
|
||||
<chapter 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-nix-gc">
|
||||
|
||||
<title>Cleaning the Nix Store</title>
|
||||
|
||||
<para>Nix has a purely functional model, meaning that packages are
|
||||
never upgraded in place. Instead new versions of packages end up in a
|
||||
different location in the Nix store (<filename>/nix/store</filename>).
|
||||
You should periodically run Nix’s <emphasis>garbage
|
||||
collector</emphasis> to remove old, unreferenced packages. This is
|
||||
easy:
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage
|
||||
</screen>
|
||||
|
||||
Alternatively, you can use a systemd unit that does the same in the
|
||||
background:
|
||||
|
||||
<screen>
|
||||
$ systemctl start nix-gc.service
|
||||
</screen>
|
||||
|
||||
You can tell NixOS in <filename>configuration.nix</filename> to run
|
||||
this unit automatically at certain points in time, for instance, every
|
||||
night at 03:15:
|
||||
|
||||
<programlisting>
|
||||
nix.gc.automatic = true;
|
||||
nix.gc.dates = "03:15";
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The commands above do not remove garbage collector roots, such
|
||||
as old system configurations. Thus they do not remove the ability to
|
||||
roll back to previous configurations. The following command deletes
|
||||
old roots, removing the ability to roll back to them:
|
||||
<screen>
|
||||
$ nix-collect-garbage -d
|
||||
</screen>
|
||||
You can also do this for specific profiles, e.g.
|
||||
<screen>
|
||||
$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old
|
||||
</screen>
|
||||
Note that NixOS system configurations are stored in the profile
|
||||
<filename>/nix/var/nix/profiles/system</filename>.</para>
|
||||
|
||||
<para>Another way to reclaim disk space (often as much as 40% of the
|
||||
size of the Nix store) is to run Nix’s store optimiser, which seeks
|
||||
out identical files in the store and replaces them with hard links to
|
||||
a single copy.
|
||||
<screen>
|
||||
$ nix-store --optimise
|
||||
</screen>
|
||||
Since this command needs to read the entire Nix store, it can take
|
||||
quite a while to finish.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,50 +0,0 @@
|
||||
<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-container-networking">
|
||||
|
||||
|
||||
<title>Container Networking</title>
|
||||
|
||||
<para>When you create a container using <literal>nixos-container
|
||||
create</literal>, it gets it own private IPv4 address in the range
|
||||
<literal>10.233.0.0/16</literal>. You can get the container’s IPv4
|
||||
address as follows:
|
||||
|
||||
<screen>
|
||||
$ nixos-container show-ip foo
|
||||
10.233.4.2
|
||||
|
||||
$ ping -c1 10.233.4.2
|
||||
64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Networking is implemented using a pair of virtual Ethernet
|
||||
devices. The network interface in the container is called
|
||||
<literal>eth0</literal>, while the matching interface in the host is
|
||||
called <literal>ve-<replaceable>container-name</replaceable></literal>
|
||||
(e.g., <literal>ve-foo</literal>). The container has its own network
|
||||
namespace and the <literal>CAP_NET_ADMIN</literal> capability, so it
|
||||
can perform arbitrary network configuration such as setting up
|
||||
firewall rules, without affecting or having access to the host’s
|
||||
network.</para>
|
||||
|
||||
<para>By default, containers cannot talk to the outside network. If
|
||||
you want that, you should set up Network Address Translation (NAT)
|
||||
rules on the host to rewrite container traffic to use your external
|
||||
IP address. This can be accomplished using the following configuration
|
||||
on the host:
|
||||
|
||||
<programlisting>
|
||||
networking.nat.enable = true;
|
||||
networking.nat.internalInterfaces = ["ve-+"];
|
||||
networking.nat.externalInterface = "eth0";
|
||||
</programlisting>
|
||||
where <literal>eth0</literal> should be replaced with the desired
|
||||
external interface. Note that <literal>ve-+</literal> is a wildcard
|
||||
that matches all container interfaces.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,34 +0,0 @@
|
||||
<chapter 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="ch-containers">
|
||||
|
||||
<title>Container Management</title>
|
||||
|
||||
<para>NixOS allows you to easily run other NixOS instances as
|
||||
<emphasis>containers</emphasis>. Containers are a light-weight
|
||||
approach to virtualisation that runs software in the container at the
|
||||
same speed as in the host system. NixOS containers share the Nix store
|
||||
of the host, making container creation very efficient.</para>
|
||||
|
||||
<warning><para>Currently, NixOS containers are not perfectly isolated
|
||||
from the host system. This means that a user with root access to the
|
||||
container can do things that affect the host. So you should not give
|
||||
container root access to untrusted users.</para></warning>
|
||||
|
||||
<para>NixOS containers can be created in two ways: imperatively, using
|
||||
the command <command>nixos-container</command>, and declaratively, by
|
||||
specifying them in your <filename>configuration.nix</filename>. The
|
||||
declarative approach implies that containers get upgraded along with
|
||||
your host system when you run <command>nixos-rebuild</command>, which
|
||||
is often not what you want. By contrast, in the imperative approach,
|
||||
containers are configured and updated independently from the host
|
||||
system.</para>
|
||||
|
||||
<xi:include href="imperative-containers.xml" />
|
||||
<xi:include href="declarative-containers.xml" />
|
||||
<xi:include href="container-networking.xml" />
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<chapter 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-cgroups">
|
||||
|
||||
<title>Control Groups</title>
|
||||
|
||||
<para>To keep track of the processes in a running system, systemd uses
|
||||
<emphasis>control groups</emphasis> (cgroups). A control group is a
|
||||
set of processes used to allocate resources such as CPU, memory or I/O
|
||||
bandwidth. There can be multiple control group hierarchies, allowing
|
||||
each kind of resource to be managed independently.</para>
|
||||
|
||||
<para>The command <command>systemd-cgls</command> lists all control
|
||||
groups in the <literal>systemd</literal> hierarchy, which is what
|
||||
systemd uses to keep track of the processes belonging to each service
|
||||
or user session:
|
||||
|
||||
<screen>
|
||||
$ systemd-cgls
|
||||
├─user
|
||||
│ └─eelco
|
||||
│ └─c1
|
||||
│ ├─ 2567 -:0
|
||||
│ ├─ 2682 kdeinit4: kdeinit4 Running...
|
||||
│ ├─ <replaceable>...</replaceable>
|
||||
│ └─10851 sh -c less -R
|
||||
└─system
|
||||
├─httpd.service
|
||||
│ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH
|
||||
│ └─<replaceable>...</replaceable>
|
||||
├─dhcpcd.service
|
||||
│ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf
|
||||
└─ <replaceable>...</replaceable>
|
||||
</screen>
|
||||
|
||||
Similarly, <command>systemd-cgls cpu</command> shows the cgroups in
|
||||
the CPU hierarchy, which allows per-cgroup CPU scheduling priorities.
|
||||
By default, every systemd service gets its own CPU cgroup, while all
|
||||
user sessions are in the top-level CPU cgroup. This ensures, for
|
||||
instance, that a thousand run-away processes in the
|
||||
<literal>httpd.service</literal> cgroup cannot starve the CPU for one
|
||||
process in the <literal>postgresql.service</literal> cgroup. (By
|
||||
contrast, it they were in the same cgroup, then the PostgreSQL process
|
||||
would get 1/1001 of the cgroup’s CPU time.) You can limit a service’s
|
||||
CPU share in <filename>configuration.nix</filename>:
|
||||
|
||||
<programlisting>
|
||||
systemd.services.httpd.serviceConfig.CPUShares = 512;
|
||||
</programlisting>
|
||||
|
||||
By default, every cgroup has 1024 CPU shares, so this will halve the
|
||||
CPU allocation of the <literal>httpd.service</literal> cgroup.</para>
|
||||
|
||||
<para>There also is a <literal>memory</literal> hierarchy that
|
||||
controls memory allocation limits; by default, all processes are in
|
||||
the top-level cgroup, so any service or session can exhaust all
|
||||
available memory. Per-cgroup memory limits can be specified in
|
||||
<filename>configuration.nix</filename>; for instance, to limit
|
||||
<literal>httpd.service</literal> to 512 MiB of RAM (excluding swap):
|
||||
|
||||
<programlisting>
|
||||
systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The command <command>systemd-cgtop</command> shows a
|
||||
continuously updated list of all cgroups with their CPU and memory
|
||||
usage.</para>
|
||||
|
||||
</chapter>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user