mirror of
https://github.com/CHN-beta/nixpkgs.git
synced 2026-01-13 11:30:35 +08:00
Compare commits
1 Commits
release-16
...
backups/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e3f729c35 |
15
.github/CONTRIBUTING.md
vendored
15
.github/CONTRIBUTING.md
vendored
@@ -1,15 +0,0 @@
|
||||
# How to contribute
|
||||
|
||||
Note: contributing implies licensing those contributions
|
||||
under the terms of [COPYING](../COPYING), which is an MIT-like license.
|
||||
|
||||
## 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).
|
||||
17
.github/ISSUE_TEMPLATE.md
vendored
17
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,17 +0,0 @@
|
||||
## Basic info
|
||||
|
||||
To make sure that we are on the same page:
|
||||
|
||||
* Kernel: (run `uname -a`)
|
||||
* System: (NixOS: `nixos-version`, Ubuntu/Fedora: `lsb_release -a`, ...)
|
||||
* Nix version: (run `nix-env --version`)
|
||||
* Nixpkgs version: (run `nix-instantiate --eval '<nixpkgs>' -A lib.nixpkgsVersion`)
|
||||
|
||||
## Describe your issue here
|
||||
|
||||
### Expected result
|
||||
|
||||
### Actual result
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,18 +0,0 @@
|
||||
###### Things done:
|
||||
|
||||
- [ ] Tested using sandboxing (`nix-build --option build-use-chroot true` or [nix.useChroot](http://nixos.org/nixos/manual/options.html#opt-nix.useChroot) on NixOS)
|
||||
- [ ] Built on platform(s): NixOS / OSX / Linux
|
||||
- [ ] Tested compilation of all pkgs that depend on this change using `nix-shell -p nox --run "nox-review wip"`
|
||||
- [ ] Tested execution of all binary files (usually in `./result/bin/`)
|
||||
- [ ] Fits [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/.github/CONTRIBUTING.md).
|
||||
|
||||
###### More
|
||||
|
||||
Fixes issue #<insert id>
|
||||
|
||||
cc @<maintainer>
|
||||
|
||||
|
||||
---
|
||||
|
||||
_Please note, that points are not mandatory, but rather desired._
|
||||
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,5 +0,0 @@
|
||||
{
|
||||
"userBlacklist": [
|
||||
"civodul"
|
||||
]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
language: python
|
||||
python: "3.4"
|
||||
sudo: required
|
||||
dist: trusty
|
||||
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
|
||||
2
COPYING
2
COPYING
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2003-2016 Eelco Dolstra and the Nixpkgs/NixOS contributors
|
||||
Copyright (c) 2003-2006 Eelco Dolstra
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
43
README.md
43
README.md
@@ -1,43 +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-15.09` for the latest
|
||||
release and `nixos-unstable` for the latest successful build of master:
|
||||
|
||||
```
|
||||
% git remote update channels
|
||||
% git rebase channels/nixos-15.09
|
||||
```
|
||||
|
||||
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/)
|
||||
* [Nix Wiki](https://nixos.org/wiki/)
|
||||
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
|
||||
* [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 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)
|
||||
10
default.nix
10
default.nix
@@ -1,9 +1 @@
|
||||
let requiredVersion = import ./lib/minver.nix; in
|
||||
|
||||
if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
|
||||
|
||||
abort "This version of Nixpkgs requires Nix >= ${requiredVersion}, 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
|
||||
|
||||
37
doc/Makefile
Normal file
37
doc/Makefile
Normal file
@@ -0,0 +1,37 @@
|
||||
# You may need to override this.
|
||||
docbookxsl = $(HOME)/.nix-profile/xml/xsl/docbook
|
||||
|
||||
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
|
||||
|
||||
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 manual.xml
|
||||
@@ -1,665 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-conventions">
|
||||
|
||||
<title>Coding conventions</title>
|
||||
|
||||
|
||||
<section xml:id="sec-syntax"><title>Syntax</title>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Use 2 spaces of indentation per indentation level in
|
||||
Nix expressions, 4 spaces in shell scripts.</para></listitem>
|
||||
|
||||
<listitem><para>Do not use tab characters, i.e. configure your
|
||||
editor to use soft tabs. For instance, use <literal>(setq-default
|
||||
indent-tabs-mode nil)</literal> in Emacs. Everybody has different
|
||||
tab settings so it’s asking for trouble.</para></listitem>
|
||||
|
||||
<listitem><para>Use <literal>lowerCamelCase</literal> for variable
|
||||
names, not <literal>UpperCamelCase</literal>. TODO: naming of
|
||||
attributes in
|
||||
<filename>all-packages.nix</filename>?</para></listitem>
|
||||
|
||||
<listitem><para>Function calls with attribute set arguments are
|
||||
written as
|
||||
|
||||
<programlisting>
|
||||
foo {
|
||||
arg = ...;
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
not
|
||||
|
||||
<programlisting>
|
||||
foo
|
||||
{
|
||||
arg = ...;
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
Also fine is
|
||||
|
||||
<programlisting>
|
||||
foo { arg = ...; }
|
||||
</programlisting>
|
||||
|
||||
if it's a short call.</para></listitem>
|
||||
|
||||
<listitem><para>In attribute sets or lists that span multiple lines,
|
||||
the attribute names or list elements should be aligned:
|
||||
|
||||
<programlisting>
|
||||
# A long list.
|
||||
list =
|
||||
[ elem1
|
||||
elem2
|
||||
elem3
|
||||
];
|
||||
|
||||
# A long attribute set.
|
||||
attrs =
|
||||
{ attr1 = short_expr;
|
||||
attr2 =
|
||||
if true then big_expr else big_expr;
|
||||
};
|
||||
|
||||
# Alternatively:
|
||||
attrs = {
|
||||
attr1 = short_expr;
|
||||
attr2 =
|
||||
if true then big_expr else big_expr;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Short lists or attribute sets can be written on one
|
||||
line:
|
||||
|
||||
<programlisting>
|
||||
# A short list.
|
||||
list = [ elem1 elem2 elem3 ];
|
||||
|
||||
# A short set.
|
||||
attrs = { x = 1280; y = 1024; };
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Breaking in the middle of a function argument can
|
||||
give hard-to-read code, like
|
||||
|
||||
<programlisting>
|
||||
someFunction { x = 1280;
|
||||
y = 1024; } otherArg
|
||||
yetAnotherArg
|
||||
</programlisting>
|
||||
|
||||
(especially if the argument is very large, spanning multiple
|
||||
lines).</para>
|
||||
|
||||
<para>Better:
|
||||
|
||||
<programlisting>
|
||||
someFunction
|
||||
{ x = 1280; y = 1024; }
|
||||
otherArg
|
||||
yetAnotherArg
|
||||
</programlisting>
|
||||
|
||||
or
|
||||
|
||||
<programlisting>
|
||||
let res = { x = 1280; y = 1024; };
|
||||
in someFunction res otherArg yetAnotherArg
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>The bodies of functions, asserts, and withs are not
|
||||
indented to prevent a lot of superfluous indentation levels, i.e.
|
||||
|
||||
<programlisting>
|
||||
{ arg1, arg2 }:
|
||||
assert system == "i686-linux";
|
||||
stdenv.mkDerivation { ...
|
||||
</programlisting>
|
||||
|
||||
not
|
||||
|
||||
<programlisting>
|
||||
{ arg1, arg2 }:
|
||||
assert system == "i686-linux";
|
||||
stdenv.mkDerivation { ...
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Function formal arguments are written as:
|
||||
|
||||
<programlisting>
|
||||
{ arg1, arg2, arg3 }:
|
||||
</programlisting>
|
||||
|
||||
but if they don't fit on one line they're written as:
|
||||
|
||||
<programlisting>
|
||||
{ arg1, arg2, arg3
|
||||
, arg4, ...
|
||||
, # Some comment...
|
||||
argN
|
||||
}:
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Functions should list their expected arguments as
|
||||
precisely as possible. That is, write
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, fetchurl, perl }: <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
|
||||
instead of
|
||||
|
||||
<programlisting>
|
||||
args: with args; <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
|
||||
or
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, fetchurl, perl, ... }: <replaceable>...</replaceable>
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>For functions that are truly generic in the number of
|
||||
arguments (such as wrappers around <varname>mkDerivation</varname>)
|
||||
that have some required arguments, you should write them using an
|
||||
<literal>@</literal>-pattern:
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, doCoverageAnalysis ? false, ... } @ args:
|
||||
|
||||
stdenv.mkDerivation (args // {
|
||||
<replaceable>...</replaceable> if doCoverageAnalysis then "bla" else "" <replaceable>...</replaceable>
|
||||
})
|
||||
</programlisting>
|
||||
|
||||
instead of
|
||||
|
||||
<programlisting>
|
||||
args:
|
||||
|
||||
args.stdenv.mkDerivation (args // {
|
||||
<replaceable>...</replaceable> if args ? doCoverageAnalysis && args.doCoverageAnalysis then "bla" else "" <replaceable>...</replaceable>
|
||||
})
|
||||
</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-package-naming"><title>Package naming</title>
|
||||
|
||||
<para>In Nixpkgs, there are generally three different names associated with a package:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>The <varname>name</varname> attribute of the
|
||||
derivation (excluding the version part). This is what most users
|
||||
see, in particular when using
|
||||
<command>nix-env</command>.</para></listitem>
|
||||
|
||||
<listitem><para>The variable name used for the instantiated package
|
||||
in <filename>all-packages.nix</filename>, and when passing it as a
|
||||
dependency to other functions. This is what Nix expression authors
|
||||
see. It can also be used when installing using <command>nix-env
|
||||
-iA</command>.</para></listitem>
|
||||
|
||||
<listitem><para>The filename for (the directory containing) the Nix
|
||||
expression.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
Most of the time, these are the same. For instance, the package
|
||||
<literal>e2fsprogs</literal> has a <varname>name</varname> attribute
|
||||
<literal>"e2fsprogs-<replaceable>version</replaceable>"</literal>, is
|
||||
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>
|
||||
|
||||
<para>There are a few naming guidelines:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Generally, try to stick to the upstream package
|
||||
name.</para></listitem>
|
||||
|
||||
<listitem><para>Don’t use uppercase letters in the
|
||||
<literal>name</literal> attribute — e.g.,
|
||||
<literal>"mplayer-1.0rc2"</literal> instead of
|
||||
<literal>"MPlayer-1.0rc2"</literal>.</para></listitem>
|
||||
|
||||
<listitem><para>The version part of the <literal>name</literal>
|
||||
attribute <emphasis>must</emphasis> start with a digit (following a
|
||||
dash) — e.g., <literal>"hello-0.3-pre-r3910"</literal> instead of
|
||||
<literal>"hello-svn-r3910"</literal>, as the latter would be seen as
|
||||
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>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>.
|
||||
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>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-organisation"><title>File naming and organisation</title>
|
||||
|
||||
<para>Names of files and directories should be in lowercase, with
|
||||
dashes between words — not in camel case. For instance, it should be
|
||||
<filename>all-packages.nix</filename>, not
|
||||
<filename>allPackages.nix</filename> or
|
||||
<filename>AllPackages.nix</filename>.</para>
|
||||
|
||||
<section xml:id="sec-hierarchy"><title>Hierarchy</title>
|
||||
|
||||
<para>Each package should be stored in its own directory somewhere in
|
||||
the <filename>pkgs/</filename> tree, i.e. in
|
||||
<filename>pkgs/<replaceable>category</replaceable>/<replaceable>subcategory</replaceable>/<replaceable>...</replaceable>/<replaceable>pkgname</replaceable></filename>.
|
||||
Below are some rules for picking the right category for a package.
|
||||
Many packages fall under several categories; what matters is the
|
||||
<emphasis>primary</emphasis> purpose of a package. For example, the
|
||||
<literal>libxml2</literal> package builds both a library and some
|
||||
tools; but it’s a library foremost, so it goes under
|
||||
<filename>pkgs/development/libraries</filename>.</para>
|
||||
|
||||
<para>When in doubt, consider refactoring the
|
||||
<filename>pkgs/</filename> tree, e.g. creating new categories or
|
||||
splitting up an existing category.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s used to support <emphasis>software development</emphasis>:</term>
|
||||
<listitem>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>library</emphasis> used by other packages:</term>
|
||||
<listitem>
|
||||
<para><filename>development/libraries</filename> (e.g. <filename>libxml2</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>compiler</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>development/compilers</filename> (e.g. <filename>gcc</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s an <emphasis>interpreter</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>development/interpreters</filename> (e.g. <filename>guile</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a (set of) development <emphasis>tool(s)</emphasis>:</term>
|
||||
<listitem>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>parser generator</emphasis> (including lexers):</term>
|
||||
<listitem>
|
||||
<para><filename>development/tools/parsing</filename> (e.g. <filename>bison</filename>, <filename>flex</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>build manager</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>development/tools/build-managers</filename> (e.g. <filename>gnumake</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>development/tools/misc</filename> (e.g. <filename>binutils</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>development/misc</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a (set of) <emphasis>tool(s)</emphasis>:</term>
|
||||
<listitem>
|
||||
<para>(A tool is a relatively small program, especially one intented
|
||||
to be used non-interactively.)</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s for <emphasis>networking</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>tools/networking</filename> (e.g. <filename>wget</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s for <emphasis>text processing</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>tools/text</filename> (e.g. <filename>diffutils</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>system utility</emphasis>, i.e.,
|
||||
something related or essential to the operation of a
|
||||
system:</term>
|
||||
<listitem>
|
||||
<para><filename>tools/system</filename> (e.g. <filename>cron</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s an <emphasis>archiver</emphasis> (which may
|
||||
include a compression function):</term>
|
||||
<listitem>
|
||||
<para><filename>tools/archivers</filename> (e.g. <filename>zip</filename>, <filename>tar</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>compression</emphasis> program:</term>
|
||||
<listitem>
|
||||
<para><filename>tools/compression</filename> (e.g. <filename>gzip</filename>, <filename>bzip2</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>security</emphasis>-related program:</term>
|
||||
<listitem>
|
||||
<para><filename>tools/security</filename> (e.g. <filename>nmap</filename>, <filename>gnupg</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>tools/misc</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>shell</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>shells</filename> (e.g. <filename>bash</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>server</emphasis>:</term>
|
||||
<listitem>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s a web server:</term>
|
||||
<listitem>
|
||||
<para><filename>servers/http</filename> (e.g. <filename>apache-httpd</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s an implementation of the X Windowing System:</term>
|
||||
<listitem>
|
||||
<para><filename>servers/x11</filename> (e.g. <filename>xorg</filename> — this includes the client libraries and programs)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>servers/misc</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>desktop environment</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>
|
||||
<para>A (typically large) program with a distinct user
|
||||
interface, primarily used interactively.</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>version management system</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/version-management</filename> (e.g. <filename>subversion</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s for <emphasis>video playback / editing</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/video</filename> (e.g. <filename>vlc</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s for <emphasis>graphics viewing / editing</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/graphics</filename> (e.g. <filename>gimp</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s for <emphasis>networking</emphasis>:</term>
|
||||
<listitem>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>mailreader</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/networking/mailreaders</filename> (e.g. <filename>thunderbird</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>newsreader</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/networking/newsreaders</filename> (e.g. <filename>pan</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>web browser</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/networking/browsers</filename> (e.g. <filename>firefox</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/networking/misc</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>applications/misc</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s <emphasis>data</emphasis> (i.e., does not have a
|
||||
straight-forward executable semantics):</term>
|
||||
<listitem>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>font</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>data/fonts</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s related to <emphasis>SGML/XML processing</emphasis>:</term>
|
||||
<listitem>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>If it’s an <emphasis>XML DTD</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>data/sgml+xml/schemas/xml-dtd</filename> (e.g. <filename>docbook</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s an <emphasis>XSLT stylesheet</emphasis>:</term>
|
||||
<listitem>
|
||||
<para>(Okay, these are executable...)</para>
|
||||
<para><filename>data/sgml+xml/stylesheets/xslt</filename> (e.g. <filename>docbook-xsl</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s a <emphasis>game</emphasis>:</term>
|
||||
<listitem>
|
||||
<para><filename>games</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Else:</term>
|
||||
<listitem>
|
||||
<para><filename>misc</filename></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-versioning"><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
|
||||
kept unless there is a good reason to do so. For instance, Nixpkgs
|
||||
contains several versions of GCC because other packages don’t build
|
||||
with the latest version of GCC. Other examples are having both the
|
||||
latest stable and latest pre-release version of a package, or to keep
|
||||
several major releases of an application that differ significantly in
|
||||
functionality.</para>
|
||||
|
||||
<para>If there is only one version of a package, its Nix expression
|
||||
should be named <filename>e2fsprogs/default.nix</filename>. If there
|
||||
are multiple versions, this should be reflected in the filename,
|
||||
e.g. <filename>e2fsprogs/1.41.8.nix</filename> and
|
||||
<filename>e2fsprogs/1.41.9.nix</filename>. The version in the
|
||||
filename should leave out unnecessary detail. For instance, if we
|
||||
keep the latest Firefox 2.0.x and 3.5.x versions in Nixpkgs, they
|
||||
should be named <filename>firefox/2.0.nix</filename> and
|
||||
<filename>firefox/3.5.nix</filename>, respectively (which, at a given
|
||||
point, might contain versions <literal>2.0.0.20</literal> and
|
||||
<literal>3.5.4</literal>). If a version requires many auxiliary
|
||||
files, you can use a subdirectory for each version,
|
||||
e.g. <filename>firefox/2.0/default.nix</filename> and
|
||||
<filename>firefox/3.5/default.nix</filename>.</para>
|
||||
|
||||
<para>All versions of a package <emphasis>must</emphasis> be included
|
||||
in <filename>all-packages.nix</filename> to make sure that they
|
||||
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,109 +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.</para>
|
||||
|
||||
<para>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.nix</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>
|
||||
@@ -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,85 +0,0 @@
|
||||
with import ./.. { };
|
||||
with lib;
|
||||
let
|
||||
sources = sourceFilesBySuffices ./. [".xml"];
|
||||
sources-langs = ./languages-frameworks;
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-manual";
|
||||
|
||||
|
||||
buildInputs = [ pandoc 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 = let toDocbook = { useChapters ? false, inputFile, outputFile }:
|
||||
let
|
||||
extraHeader = ''xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" '';
|
||||
in ''
|
||||
{
|
||||
pandoc '${inputFile}' -w docbook ${optionalString useChapters "--chapters"} \
|
||||
| sed -e 's|<ulink url=|<link xlink:href=|' \
|
||||
-e 's|</ulink>|</link>|' \
|
||||
-e 's|<sect. id=|<section xml:id=|' \
|
||||
-e 's|</sect[0-9]>|</section>|' \
|
||||
-e '1s| id=| xml:id=|' \
|
||||
-e '1s|\(<[^ ]* \)|\1${extraHeader}|'
|
||||
} > '${outputFile}'
|
||||
'';
|
||||
in
|
||||
|
||||
''
|
||||
ln -s '${sources}/'*.xml .
|
||||
mkdir ./languages-frameworks
|
||||
cp -s '${sources-langs}'/* ./languages-frameworks
|
||||
''
|
||||
+ toDocbook {
|
||||
inputFile = ./introduction.md;
|
||||
outputFile = "introduction.xml";
|
||||
useChapters = true;
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./haskell-users-guide.md;
|
||||
outputFile = "haskell-users-guide.xml";
|
||||
useChapters = true;
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./../pkgs/development/idris-modules/README.md;
|
||||
outputFile = "languages-frameworks/idris.xml";
|
||||
}
|
||||
+ toDocbook {
|
||||
inputFile = ./../pkgs/development/r-modules/README.md;
|
||||
outputFile = "languages-frameworks/r.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,305 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="users-guide-to-the-erlang-infrastructure">
|
||||
|
||||
<title>User's Guide to the Erlang Infrastructure</title>
|
||||
<section xml:id="build-tools">
|
||||
<title>Build Tools</title>
|
||||
<para>
|
||||
By default Rebar3 wants to manage it's own dependencies. In the
|
||||
normal non-Nix, this is perfectly acceptable. In the Nix world it
|
||||
is not. To support this we have created two versions of rebar3,
|
||||
<literal>rebar3</literal> and <literal>rebar3-open</literal>. The
|
||||
<literal>rebar3</literal> version has been patched to remove the
|
||||
ability to download anything from it. If you are not running it a
|
||||
nix-shell or a nix-build then its probably not going to work for
|
||||
you. <literal>rebar3-open</literal> is the normal, un-modified
|
||||
rebar3. It should work exactly as would any other version of
|
||||
rebar3. Any Erlang package should rely on
|
||||
<literal>rebar3</literal> and thats really what you should be
|
||||
using too.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="how-to-install-erlang-packages">
|
||||
<title>How to install Erlang packages</title>
|
||||
<para>
|
||||
Erlang packages are not registered in the top level simply because
|
||||
they are not relevant to the vast majority of Nix users. They are
|
||||
installable using the <literal>erlangPackages</literal> attribute set.
|
||||
|
||||
You can list the avialable packages in the
|
||||
<literal>erlangPackages</literal> with the following command:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A erlangPackages
|
||||
erlangPackages.esqlite esqlite-0.2.1
|
||||
erlangPackages.goldrush goldrush-0.1.7
|
||||
erlangPackages.ibrowse ibrowse-4.2.2
|
||||
erlangPackages.jiffy jiffy-0.14.5
|
||||
erlangPackages.lager lager-3.0.2
|
||||
erlangPackages.meck meck-0.8.3
|
||||
erlangPackages.rebar3-pc pc-1.1.0
|
||||
</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 erlangPackages.ibrowse
|
||||
</programlisting>
|
||||
<para>
|
||||
The attribute path of any Erlang packages corresponds to the name
|
||||
of that particular package in Hex or its OTP Application/Release name.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="packaging-erlang-applications">
|
||||
<title>Packaging Erlang Applications</title>
|
||||
<section xml:id="rebar3-packages">
|
||||
<title>Rebar3 Packages</title>
|
||||
<para>
|
||||
There is a Nix functional called
|
||||
<literal>buildRebar3</literal>. We use this function to make a
|
||||
derivation that understands how to build the rebar3 project. For
|
||||
example, the epression we use to build the <link
|
||||
xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link>
|
||||
project follows.
|
||||
</para>
|
||||
<programlisting>
|
||||
{stdenv, fetchFromGitHub, buildRebar3, ibrowse, jsx, erlware_commons }:
|
||||
|
||||
buildRebar3 rec {
|
||||
name = "hex2nix";
|
||||
version = "0.0.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ericbmerritt";
|
||||
repo = "hex2nix";
|
||||
rev = "${version}";
|
||||
sha256 = "1w7xjidz1l5yjmhlplfx7kphmnpvqm67w99hd2m7kdixwdxq0zqg";
|
||||
};
|
||||
|
||||
erlangDeps = [ ibrowse jsx erlware_commons ];
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
The only visible difference between this derivation and
|
||||
something like <literal>stdenv.mkDerivation</literal> is that we
|
||||
have added <literal>erlangDeps</literal> to the derivation. If
|
||||
you add your Erlang dependencies here they will be correctly
|
||||
handled by the system.
|
||||
</para>
|
||||
<para>
|
||||
If your package needs to compile native code via Rebar's port
|
||||
compilation mechenism. You should add <literal>compilePort =
|
||||
true;</literal> to the derivation.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="hex-packages">
|
||||
<title>Hex Packages</title>
|
||||
<para>
|
||||
Hex packages are based on Rebar packages. In fact, at the moment
|
||||
we can only compile Hex packages that are buildable with
|
||||
Rebar3. Packages that use Mix and other build systems are not
|
||||
supported. That being said, we know a lot more about Hex and can
|
||||
do more for you.
|
||||
</para>
|
||||
<programlisting>
|
||||
{ buildHex }:
|
||||
buildHex {
|
||||
name = "esqlite";
|
||||
version = "0.2.1";
|
||||
sha256 = "1296fn1lz4lz4zqzn4dwc3flgkh0i6n4sydg501faabfbv8d3wkr";
|
||||
compilePort = true;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
For Hex packages you need to provide the name, the version, and
|
||||
the Sha 256 digest of the package and use
|
||||
<literal>buildHex</literal> to build it. Obviously, the package
|
||||
needs to have already been published to Hex.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="how-to-develop">
|
||||
<title>How to develop</title>
|
||||
<section xml:id="accessing-an-environment">
|
||||
<title>Accessing an Environment</title>
|
||||
<para>
|
||||
Often, all you want to do is be able to access a valid
|
||||
environment that contains a specific package and its
|
||||
dependencies. we can do that with the <literal>env</literal>
|
||||
part of a derivation. For example, lets say we want to access an
|
||||
erlang repl with ibrowse loaded up. We could do the following.
|
||||
</para>
|
||||
<programlisting>
|
||||
~/w/nixpkgs ❯❯❯ nix-shell -A erlangPackages.ibrowse.env --run "erl"
|
||||
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
|
||||
|
||||
Eshell V7.0 (abort with ^G)
|
||||
1> m(ibrowse).
|
||||
Module: ibrowse
|
||||
MD5: 3b3e0137d0cbb28070146978a3392945
|
||||
Compiled: January 10 2016, 23:34
|
||||
Object file: /nix/store/g1rlf65rdgjs4abbyj4grp37ry7ywivj-ibrowse-4.2.2/lib/erlang/lib/ibrowse-4.2.2/ebin/ibrowse.beam
|
||||
Compiler options: [{outdir,"/tmp/nix-build-ibrowse-4.2.2.drv-0/hex-source-ibrowse-4.2.2/_build/default/lib/ibrowse/ebin"},
|
||||
debug_info,debug_info,nowarn_shadow_vars,
|
||||
warn_unused_import,warn_unused_vars,warnings_as_errors,
|
||||
{i,"/tmp/nix-build-ibrowse-4.2.2.drv-0/hex-source-ibrowse-4.2.2/_build/default/lib/ibrowse/include"}]
|
||||
Exports:
|
||||
add_config/1 send_req_direct/7
|
||||
all_trace_off/0 set_dest/3
|
||||
code_change/3 set_max_attempts/3
|
||||
get_config_value/1 set_max_pipeline_size/3
|
||||
get_config_value/2 set_max_sessions/3
|
||||
get_metrics/0 show_dest_status/0
|
||||
get_metrics/2 show_dest_status/1
|
||||
handle_call/3 show_dest_status/2
|
||||
handle_cast/2 spawn_link_worker_process/1
|
||||
handle_info/2 spawn_link_worker_process/2
|
||||
init/1 spawn_worker_process/1
|
||||
module_info/0 spawn_worker_process/2
|
||||
module_info/1 start/0
|
||||
rescan_config/0 start_link/0
|
||||
rescan_config/1 stop/0
|
||||
send_req/3 stop_worker_process/1
|
||||
send_req/4 stream_close/1
|
||||
send_req/5 stream_next/1
|
||||
send_req/6 terminate/2
|
||||
send_req_direct/4 trace_off/0
|
||||
send_req_direct/5 trace_off/2
|
||||
send_req_direct/6 trace_on/0
|
||||
trace_on/2
|
||||
ok
|
||||
2>
|
||||
</programlisting>
|
||||
<para>
|
||||
Notice the <literal>-A erlangPackages.ibrowse.env</literal>.That
|
||||
is the key to this functionality.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="creating-a-shell">
|
||||
<title>Creating a Shell</title>
|
||||
<para>
|
||||
Getting access to an environment often isn't enough to do real
|
||||
development. Many times we need to create a
|
||||
<literal>shell.nix</literal> file and do our development inside
|
||||
of the environment specified by that file. This file looks a lot
|
||||
like the packageing described above. The main difference is that
|
||||
<literal>src</literal> points to project root and we call the
|
||||
package directly.
|
||||
</para>
|
||||
<programlisting>
|
||||
{ pkgs ? import "<nixpkgs"> {} }:
|
||||
|
||||
with pkgs;
|
||||
|
||||
let
|
||||
|
||||
f = { buildHex, ibrowse, jsx, erlware_commons }:
|
||||
buildHex {
|
||||
name = "hex2nix";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
erlangDeps = [ ibrowse jsx erlware_commons ];
|
||||
};
|
||||
drv = erlangPackages.callPackage f {};
|
||||
|
||||
in
|
||||
drv
|
||||
</programlisting>
|
||||
<section xml:id="building-in-a-shell">
|
||||
<title>Building in a shell</title>
|
||||
<para>
|
||||
Unfortunatly for us users of Nix, Rebar isn't very cooperative
|
||||
with us from the standpoint of building a hermetic
|
||||
environment. When building the rebar3 support we had to do some
|
||||
sneaky things to get it not to go out and pull packages on its
|
||||
own. Also unfortunately, you have to do some of the same things
|
||||
when building a project inside of a Nix shell.
|
||||
|
||||
<orderedlist numeration="arabic">
|
||||
<listitem>
|
||||
<para>Run <literal>rebar3-nix-bootstrap</literal> every time
|
||||
dependencies change</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Set Home to the current directory.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
If you do these two things then Rebar will be happy with you. I
|
||||
codify these into a makefile. Forunately, rebar3-nix-bootstrap
|
||||
is idempotent and fairly quick. so you can run it as often as
|
||||
you like.
|
||||
</para>
|
||||
<programlisting>
|
||||
# =============================================================================
|
||||
# Rules
|
||||
# =============================================================================
|
||||
.PHONY= all test clean repl shell build test analyze bootstrap
|
||||
|
||||
all: test
|
||||
|
||||
clean:
|
||||
rm -rf _build
|
||||
rm -rf .cache
|
||||
|
||||
repl:
|
||||
nix-shell --run "erl"
|
||||
|
||||
shell:
|
||||
nix-shell --run "bash"
|
||||
|
||||
bootstrap:
|
||||
nix-shell --pure --run "rebar3-nix-bootstrap"
|
||||
|
||||
build: bootstrap
|
||||
nix-shell --pure --run "HOME=$(CURDIR) rebar3 compile"
|
||||
|
||||
analyze: bootstrap
|
||||
nix-shell --pure --run "HOME=$(CURDIR) rebar3 do compile,dialyzer"
|
||||
|
||||
test: bootstrap
|
||||
nix-shell --pure --run "HOME=$(CURDIR) rebar3 do compile,dialyzer,eunit"
|
||||
|
||||
</programlisting>
|
||||
<para>
|
||||
If you add the <literal>shell.nix</literal> as described and
|
||||
user rebar as follows things should simply work.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section xml:id="generating-packages-from-hex-with-hex2nix">
|
||||
<title>Generating Packages from Hex with Hex2Nix</title>
|
||||
<para>
|
||||
Updating the Hex packages requires the use of the
|
||||
<literal>hex2nix</literal> tool. Given the path to the Erlang
|
||||
modules (usually
|
||||
<literal>pkgs/development/erlang-modules</literal>). It will
|
||||
happily dump a file called
|
||||
<literal>hex-packages.nix</literal>. That file will contain all
|
||||
the packages that use a recognized build system in Hex. However,
|
||||
it can't know whether or not all those packages are buildable.
|
||||
</para>
|
||||
<para>
|
||||
To make life easier for our users, it makes good sense to go
|
||||
ahead and attempt to build all those packages and remove the
|
||||
ones that don't build. To do that, simply run the command (in
|
||||
the root of your <literal>nixpkgs</literal> repository). that follows.
|
||||
</para>
|
||||
<programlisting>
|
||||
$ nix-build -A erlangPackages
|
||||
</programlisting>
|
||||
<para>
|
||||
That will build every package in
|
||||
<literal>erlangPackages</literal>. Then you can go through and
|
||||
manually remove the ones that fail. Hopefully, someone will
|
||||
improve <literal>hex2nix</literal> in the future to automate
|
||||
that.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,629 +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>
|
||||
|
||||
<warning>
|
||||
<para>Do not use this function in Nixpkgs. Because it breaks
|
||||
package abstraction and doesn’t provide error checking for
|
||||
function arguments, it is only intended for ad-hoc customisation
|
||||
(such as in <filename>~/.nixpkgs/config.nix</filename>).</para>
|
||||
</warning>
|
||||
|
||||
<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 to 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>.
|
||||
</para>
|
||||
<para>
|
||||
It also uses <literal>CHROOTENV_EXTRA_BINDS</literal> environment variable
|
||||
for binding extra directories in the sandbox to outside places. The format of
|
||||
the variable is <literal>/mnt=test-mnt:/data</literal>, where
|
||||
<literal>/mnt</literal> would be mounted as <literal>/test-mnt</literal>
|
||||
and <literal>/data</literal> would be mounted as <literal>/data</literal>.
|
||||
<literal>extraBindMounts</literal> array argument to
|
||||
<function>buildFHSUserEnv</function> function is prepended to this variable.
|
||||
Latter entries take priority if defined several times -- i.e. in case of
|
||||
<literal>/data=data1:/data=data2</literal> the actual bind path would be
|
||||
<literal>/data2</literal>.
|
||||
</para>
|
||||
<para>
|
||||
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.xorg;
|
||||
[ libX11
|
||||
libXcursor
|
||||
libXrandr
|
||||
]);
|
||||
multiPkgs = pkgs: (with pkgs;
|
||||
[ udev
|
||||
alsaLib
|
||||
]);
|
||||
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>
|
||||
|
||||
<section xml:id="sec-pkgs-dockerTools">
|
||||
<title>pkgs.dockerTools</title>
|
||||
|
||||
<para>
|
||||
<varname>pkgs.dockerTools</varname> is a set of functions for creating and
|
||||
manipulating Docker images according to the
|
||||
<link xlink:href="https://github.com/docker/docker/blob/master/image/spec/v1.md#docker-image-specification-v100">
|
||||
Docker Image Specification v1.0.0
|
||||
</link>. Docker itself is not used to perform any of the operations done by these
|
||||
functions.
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
The <varname>dockerTools</varname> API is unstable and may be subject to
|
||||
backwards-incompatible changes in the future.
|
||||
</para>
|
||||
</warning>
|
||||
|
||||
<section xml:id="ssec-pkgs-dockerTools-buildImage">
|
||||
<title>buildImage</title>
|
||||
|
||||
<para>
|
||||
This function is analogous to the <command>docker build</command> command,
|
||||
in that can used to build a Docker-compatible repository tarball containing
|
||||
a single image with one or multiple layers. As such, the result
|
||||
is suitable for being loaded in Docker with <command>docker load</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The parameters of <varname>buildImage</varname> with relative example values are
|
||||
described below:
|
||||
</para>
|
||||
|
||||
<example xml:id='ex-dockerTools-buildImage'><title>Docker build</title>
|
||||
<programlisting>
|
||||
buildImage {
|
||||
name = "redis"; <co xml:id='ex-dockerTools-buildImage-1' />
|
||||
tag = "latest"; <co xml:id='ex-dockerTools-buildImage-2' />
|
||||
|
||||
fromImage = someBaseImage; <co xml:id='ex-dockerTools-buildImage-3' />
|
||||
fromImageName = null; <co xml:id='ex-dockerTools-buildImage-4' />
|
||||
fromImageTag = "latest"; <co xml:id='ex-dockerTools-buildImage-5' />
|
||||
|
||||
contents = pkgs.redis; <co xml:id='ex-dockerTools-buildImage-6' />
|
||||
runAsRoot = '' <co xml:id='ex-dockerTools-buildImage-runAsRoot' />
|
||||
#!${stdenv.shell}
|
||||
mkdir -p /data
|
||||
'';
|
||||
|
||||
config = { <co xml:id='ex-dockerTools-buildImage-8' />
|
||||
Cmd = [ "/bin/redis-server" ];
|
||||
WorkingDir = "/data";
|
||||
Volumes = {
|
||||
"/data" = {};
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>The above example will build a Docker image <literal>redis/latest</literal>
|
||||
from the given base image. Loading and running this image in Docker results in
|
||||
<literal>redis-server</literal> being started automatically.
|
||||
</para>
|
||||
|
||||
<calloutlist>
|
||||
<callout arearefs='ex-dockerTools-buildImage-1'>
|
||||
<para>
|
||||
<varname>name</varname> specifies the name of the resulting image.
|
||||
This is the only required argument for <varname>buildImage</varname>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-2'>
|
||||
<para>
|
||||
<varname>tag</varname> specifies the tag of the resulting image.
|
||||
By default it's <literal>latest</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-3'>
|
||||
<para>
|
||||
<varname>fromImage</varname> is the repository tarball containing the base image.
|
||||
It must be a valid Docker image, such as exported by <command>docker save</command>.
|
||||
By default it's <literal>null</literal>, which can be seen as equivalent
|
||||
to <literal>FROM scratch</literal> of a <filename>Dockerfile</filename>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-4'>
|
||||
<para>
|
||||
<varname>fromImageName</varname> can be used to further specify
|
||||
the base image within the repository, in case it contains multiple images.
|
||||
By default it's <literal>null</literal>, in which case
|
||||
<varname>buildImage</varname> will peek the first image available
|
||||
in the repository.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-5'>
|
||||
<para>
|
||||
<varname>fromImageTag</varname> can be used to further specify the tag
|
||||
of the base image within the repository, in case an image contains multiple tags.
|
||||
By default it's <literal>null</literal>, in which case
|
||||
<varname>buildImage</varname> will peek the first tag available for the base image.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-6'>
|
||||
<para>
|
||||
<varname>contents</varname> is a derivation that will be copied in the new
|
||||
layer of the resulting image. This can be similarly seen as
|
||||
<command>ADD contents/ /</command> in a <filename>Dockerfile</filename>.
|
||||
By default it's <literal>null</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-runAsRoot'>
|
||||
<para>
|
||||
<varname>runAsRoot</varname> is a bash script that will run as root
|
||||
in an environment that overlays the existing layers of the base image with
|
||||
the new resulting layer, including the previously copied
|
||||
<varname>contents</varname> derivation.
|
||||
This can be similarly seen as
|
||||
<command>RUN ...</command> in a <filename>Dockerfile</filename>.
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Using this parameter requires the <literal>kvm</literal>
|
||||
device to be available.
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-buildImage-8'>
|
||||
<para>
|
||||
<varname>config</varname> is used to specify the configuration of the
|
||||
containers that will be started off the built image in Docker.
|
||||
The available options are listed in the
|
||||
<link xlink:href="https://github.com/docker/docker/blob/master/image/spec/v1.md#container-runconfig-field-descriptions">
|
||||
Docker Image Specification v1.0.0
|
||||
</link>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
</calloutlist>
|
||||
|
||||
<para>
|
||||
After the new layer has been created, its closure
|
||||
(to which <varname>contents</varname>, <varname>config</varname> and
|
||||
<varname>runAsRoot</varname> contribute) will be copied in the layer itself.
|
||||
Only new dependencies that are not already in the existing layers will be copied.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At the end of the process, only one new single layer will be produced and
|
||||
added to the resulting image.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The resulting repository will only list the single image
|
||||
<varname>image/tag</varname>. In the case of <xref linkend='ex-dockerTools-buildImage'/>
|
||||
it would be <varname>redis/latest</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is possible to inspect the arguments with which an image was built
|
||||
using its <varname>buildArgs</varname> attribute.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-pkgs-dockerTools-fetchFromRegistry">
|
||||
<title>pullImage</title>
|
||||
|
||||
<para>
|
||||
This function is analogous to the <command>docker pull</command> command,
|
||||
in that can be used to fetch a Docker image from a Docker registry.
|
||||
Currently only registry <literal>v1</literal> is supported.
|
||||
By default <link xlink:href="https://hub.docker.com/">Docker Hub</link>
|
||||
is used to pull images.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Its parameters are described in the example below:
|
||||
</para>
|
||||
|
||||
<example xml:id='ex-dockerTools-pullImage'><title>Docker pull</title>
|
||||
<programlisting>
|
||||
pullImage {
|
||||
imageName = "debian"; <co xml:id='ex-dockerTools-pullImage-1' />
|
||||
imageTag = "jessie"; <co xml:id='ex-dockerTools-pullImage-2' />
|
||||
imageId = null; <co xml:id='ex-dockerTools-pullImage-3' />
|
||||
sha256 = "1bhw5hkz6chrnrih0ymjbmn69hyfriza2lr550xyvpdrnbzr4gk2"; <co xml:id='ex-dockerTools-pullImage-4' />
|
||||
|
||||
indexUrl = "https://index.docker.io"; <co xml:id='ex-dockerTools-pullImage-5' />
|
||||
registryVersion = "v1";
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<calloutlist>
|
||||
<callout arearefs='ex-dockerTools-pullImage-1'>
|
||||
<para>
|
||||
<varname>imageName</varname> specifies the name of the image to be downloaded,
|
||||
which can also include the registry namespace (e.g. <literal>library/debian</literal>).
|
||||
This argument is required.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-pullImage-2'>
|
||||
<para>
|
||||
<varname>imageTag</varname> specifies the tag of the image to be downloaded.
|
||||
By default it's <literal>latest</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-pullImage-3'>
|
||||
<para>
|
||||
<varname>imageId</varname>, if specified this exact image will be fetched, instead
|
||||
of <varname>imageName/imageTag</varname>. However, the resulting repository
|
||||
will still be named <varname>imageName/imageTag</varname>.
|
||||
By default it's <literal>null</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-pullImage-4'>
|
||||
<para>
|
||||
<varname>sha256</varname> is the checksum of the whole fetched image.
|
||||
This argument is required.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>The checksum is computed on the unpacked directory, not on the final tarball.</para>
|
||||
</note>
|
||||
|
||||
</callout>
|
||||
|
||||
<callout arearefs='ex-dockerTools-pullImage-5'>
|
||||
<para>
|
||||
In the above example the default values are shown for the variables
|
||||
<varname>indexUrl</varname> and <varname>registryVersion</varname>.
|
||||
Hence by default the Docker.io registry is used to pull the images.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-pkgs-dockerTools-exportImage">
|
||||
<title>exportImage</title>
|
||||
|
||||
<para>
|
||||
This function is analogous to the <command>docker export</command> command,
|
||||
in that can used to flatten a Docker image that contains multiple layers.
|
||||
It is in fact the result of the merge of all the layers of the image.
|
||||
As such, the result is suitable for being imported in Docker
|
||||
with <command>docker import</command>.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Using this function requires the <literal>kvm</literal>
|
||||
device to be available.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
The parameters of <varname>exportImage</varname> are the following:
|
||||
</para>
|
||||
|
||||
<example xml:id='ex-dockerTools-exportImage'><title>Docker export</title>
|
||||
<programlisting>
|
||||
exportImage {
|
||||
fromImage = someLayeredImage;
|
||||
fromImageName = null;
|
||||
fromImageTag = null;
|
||||
|
||||
name = someLayeredImage.name;
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>
|
||||
The parameters relative to the base image have the same synopsis as
|
||||
described in <xref linkend='ssec-pkgs-dockerTools-buildImage'/>, except that
|
||||
<varname>fromImage</varname> is the only required argument in this case.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <varname>name</varname> argument is the name of the derivation output,
|
||||
which defaults to <varname>fromImage.name</varname>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-pkgs-dockerTools-shadowSetup">
|
||||
<title>shadowSetup</title>
|
||||
|
||||
<para>
|
||||
This constant string is a helper for setting up the base files for managing
|
||||
users and groups, only if such files don't exist already.
|
||||
It is suitable for being used in a
|
||||
<varname>runAsRoot</varname> <xref linkend='ex-dockerTools-buildImage-runAsRoot'/> script for cases like
|
||||
in the example below:
|
||||
</para>
|
||||
|
||||
<example xml:id='ex-dockerTools-shadowSetup'><title>Shadow base files</title>
|
||||
<programlisting>
|
||||
buildImage {
|
||||
name = "shadow-basic";
|
||||
|
||||
runAsRoot = ''
|
||||
#!${stdenv.shell}
|
||||
${shadowSetup}
|
||||
groupadd -r redis
|
||||
useradd -r -g redis redis
|
||||
mkdir /data
|
||||
chown redis:redis /data
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<para>
|
||||
Creating base files like <literal>/etc/passwd</literal> or
|
||||
<literal>/etc/login.defs</literal> are necessary for shadow-utils to
|
||||
manipulate users and groups.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
@@ -1,721 +0,0 @@
|
||||
---
|
||||
title: User's Guide for Haskell in Nixpkgs
|
||||
author: Peter Simons
|
||||
date: 2015-06-01
|
||||
---
|
||||
# User's Guide to the Haskell Infrastructure
|
||||
|
||||
|
||||
## How to install Haskell packages
|
||||
|
||||
Nixpkgs distributes build instructions for all Haskell packages registered on
|
||||
[Hackage](http://hackage.haskell.org/), but strangely enough normal Nix package
|
||||
lookups don't seem to discover any of them, except for the default version of ghc, cabal-install, and stack:
|
||||
|
||||
$ nix-env -i alex
|
||||
error: selector ‘alex’ matches no derivations
|
||||
$ nix-env -qa ghc
|
||||
ghc-7.10.2
|
||||
|
||||
The Haskell package set is not registered in the top-level namespace because it
|
||||
is *huge*. 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 `haskellPackages`, which the following command will list:
|
||||
|
||||
$ 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 ...]
|
||||
|
||||
To install any of those packages into your profile, refer to them by their
|
||||
attribute path (first column):
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -iA haskellPackages.Allure ...
|
||||
|
||||
The attribute path of any Haskell packages corresponds to the name of that
|
||||
particular package on Hackage: the package `cabal-install` has the attribute
|
||||
`haskellPackages.cabal-install`, and so on. (Actually, this convention causes
|
||||
trouble with packages like `3dmodels` and `4Blocks`, because these names are
|
||||
invalid identifiers in the Nix language. The issue of how to deal with these
|
||||
rare corner cases is currently unresolved.)
|
||||
|
||||
Haskell packages who's Nix name (second column) begins with a `haskell-` prefix
|
||||
are packages that provide a library whereas packages without that prefix
|
||||
provide just executables. Libraries may provide executables too, though: the
|
||||
package `haskell-pandoc`, for example, installs both a library and an
|
||||
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 [How to
|
||||
create a development environment].
|
||||
|
||||
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
|
||||
`nix-env` an explicit `-f "<nixpkgs>"` parameter, but if you call `nix-env`
|
||||
without that flag, then chances are the invocation fails:
|
||||
|
||||
$ nix-env -iA haskellPackages.cabal-install
|
||||
error: attribute ‘haskellPackages’ in selection path
|
||||
‘haskellPackages.cabal-install’ not found
|
||||
|
||||
On NixOS, for example, Nixpkgs does *not* 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.:
|
||||
|
||||
$ nix-env -qaP coreutils
|
||||
nixos.coreutils coreutils-8.23
|
||||
|
||||
If your system responds like that (most NixOS installations will), then the
|
||||
attribute path to `haskellPackages` is `nixos.haskellPackages`. Thus, if you
|
||||
want to use `nix-env` without giving an explicit `-f` flag, then that's the way
|
||||
to do it:
|
||||
|
||||
$ nix-env -qaP -A nixos.haskellPackages
|
||||
$ nix-env -iA nixos.haskellPackages.cabal-install
|
||||
|
||||
Our current default compiler is GHC 7.10.x and the `haskellPackages` 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:
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc6123
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.packages.ghc763
|
||||
|
||||
The name `haskellPackages` is really just a synonym for
|
||||
`haskell.packages.ghc7102`, 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:
|
||||
|
||||
$ 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
|
||||
|
||||
We have no package sets for `jhc` or `uhc` yet, unfortunately, but for every
|
||||
version of GHC listed above, there exists a package set based on that compiler.
|
||||
Also, the attributes `haskell.compiler.ghcXYC` and
|
||||
`haskell.packages.ghcXYC.ghc` are synonymous for the sake of convenience.
|
||||
|
||||
## How to create a development environment
|
||||
|
||||
### How to install a compiler
|
||||
|
||||
A simple development environment consists of a Haskell compiler and the tool
|
||||
`cabal-install`, and we saw in section [How to install Haskell packages] how
|
||||
you can install those programs into your user profile:
|
||||
|
||||
$ nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install
|
||||
|
||||
Instead of the default package set `haskellPackages`, you can also use the more
|
||||
precise name `haskell.compiler.ghc7102`, which has the advantage that it refers
|
||||
to the same GHC version regardless of what Nixpkgs considers "default" at any
|
||||
given time.
|
||||
|
||||
Once you've made those tools available in `$PATH`, it's possible to build
|
||||
Hackage packages the same way people without access to Nix do it all the time:
|
||||
|
||||
$ cabal get lens-4.11 && cd lens-4.11
|
||||
$ cabal install -j --dependencies-only
|
||||
$ cabal configure
|
||||
$ cabal build
|
||||
|
||||
If you enjoy working with Cabal sandboxes, then that's entirely possible too:
|
||||
just execute the command
|
||||
|
||||
$ cabal sandbox init
|
||||
|
||||
before installing the required dependencies.
|
||||
|
||||
The `nix-shell` utility makes it easy to switch to a different compiler
|
||||
version; just enter the Nix shell environment with the command
|
||||
|
||||
$ nix-shell -p haskell.compiler.ghc784
|
||||
|
||||
to bring GHC 7.8.4 into `$PATH`. Re-running `cabal configure` 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 `cabal configure` command inside of the shell:
|
||||
|
||||
$ nix-shell -p haskell.compiler.ghc784 --command "cabal configure"
|
||||
|
||||
Afterwards, all other commands like `cabal build` 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 `dist/`
|
||||
directory. Please note, however, that `nix-collect-garbage` can break such an
|
||||
environment because the Nix store paths created by `nix-shell` aren't "alive"
|
||||
anymore once `nix-shell` has terminated. If you find that your Haskell builds
|
||||
no longer work after garbage collection, then you'll have to re-run `cabal
|
||||
configure` inside of a new `nix-shell` environment.
|
||||
|
||||
### How to install a compiler with libraries
|
||||
|
||||
GHC expects to find all installed libraries inside of its own `lib` 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 `base`,
|
||||
`containers`, `Cabal`, etc.
|
||||
|
||||
We can register additional libraries to GHC, however, using a special build
|
||||
function called `ghcWithPackages`. 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 `ghcWithPackages (pkgs: [pkgs.mtl])`
|
||||
generates a copy of GHC that has the `mtl` library registered in addition to
|
||||
its normal core packages:
|
||||
|
||||
$ 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
|
||||
|
||||
This function allows users to define their own development environment by means
|
||||
of an override. After adding the following snippet to `~/.nixpkgs/config.nix`,
|
||||
|
||||
{
|
||||
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
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
it's possible to install that compiler with `nix-env -f "<nixpkgs>" -iA
|
||||
myHaskellEnv`. If you'd like to switch that development environment to a
|
||||
different version of GHC, just replace the `ghc7102` 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.)
|
||||
|
||||
The generated `ghc` program is a wrapper script that re-directs the real
|
||||
GHC executable to use a new `lib` directory --- one that we specifically
|
||||
constructed to contain all those packages the user requested:
|
||||
|
||||
$ 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" "$@"
|
||||
|
||||
The variables `$NIX_GHC`, `$NIX_GHCPKG`, etc. point to the *new* store path
|
||||
`ghcWithPackages` constructed specifically for this environment. The last line
|
||||
of the wrapper script then executes the real `ghc`, but passes the path to the
|
||||
new `lib` directory using GHC's `-B` flag.
|
||||
|
||||
The purpose of those environment variables is to work around an impurity in the
|
||||
popular [ghc-paths](http://hackage.haskell.org/package/ghc-paths) 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 `ghcWithPackages`. So we [patched
|
||||
ghc-paths](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/haskell-modules/patches/ghc-paths-nix.patch)
|
||||
to return the paths found in those environment variables at run-time rather
|
||||
than trying to guess them at compile-time.
|
||||
|
||||
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 `~/.bashrc`:
|
||||
|
||||
if type >/dev/null 2>&1 -p ghc; then
|
||||
eval "$(egrep ^export "$(type -p ghc)")"
|
||||
fi
|
||||
|
||||
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 `nix-env -u` operation updates the GHC
|
||||
environment in your profile:
|
||||
|
||||
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
|
||||
|
||||
### How to install a compiler with libraries, hoogle and documentation indexes
|
||||
|
||||
If you plan to use your environment for interactive programming, not just
|
||||
compiling random Haskell code, you might want to replace `ghcWithPackages` in
|
||||
all the listings above with `ghcWithHoogle`.
|
||||
|
||||
This environment generator not only produces an environment with GHC and all
|
||||
the specified libraries, but also generates a `hoogle` and `haddock` indexes
|
||||
for all the packages, and provides a wrapper script around `hoogle` binary that
|
||||
uses all those things. A precise name for this thing would be
|
||||
"`ghcWithPackagesAndHoogleAndDocumentationIndexes`", which is, regrettably, too
|
||||
long and scary.
|
||||
|
||||
For example, installing the following environment
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
myHaskellEnv = self.haskellPackages.ghcWithHoogle
|
||||
(haskellPackages: with haskellPackages; [
|
||||
# libraries
|
||||
arrows async cgi criterion
|
||||
# tools
|
||||
cabal-install haskintex
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
allows one to browse module documentation index [not too dissimilar to
|
||||
this](https://downloads.haskell.org/~ghc/latest/docs/html/libraries/index.html)
|
||||
for all the specified packages and their dependencies by directing a browser of
|
||||
choice to `~/.nix-profiles/share/doc/hoogle/index.html` (or
|
||||
`/run/current-system/sw/share/doc/hoogle/index.html` in case you put it in
|
||||
`environment.systemPackages` in NixOS).
|
||||
|
||||
After you've marveled enough at that try adding the following to your
|
||||
`~/.ghc/ghci.conf`
|
||||
|
||||
:def hoogle \s -> return $ ":! hoogle search -cl --count=15 \"" ++ s ++ "\""
|
||||
:def doc \s -> return $ ":! hoogle search -cl --info \"" ++ s ++ "\""
|
||||
|
||||
and test it by typing into `ghci`:
|
||||
|
||||
:hoogle a -> a
|
||||
:doc a -> a
|
||||
|
||||
Be sure to note the links to `haddock` files in the output. With any modern and
|
||||
properly configured terminal emulator you can just click those links to
|
||||
navigate there.
|
||||
|
||||
Finally, you can run
|
||||
|
||||
hoogle server -p 8080
|
||||
|
||||
and navigate to http://localhost:8080/ for your own local
|
||||
[Hoogle](https://www.haskell.org/hoogle/). Note, however, that Firefox and
|
||||
possibly other browsers disallow navigation from `http:` to `file:` URIs for
|
||||
security reasons, which might be quite an inconvenience. See [this
|
||||
page](http://kb.mozillazine.org/Links_to_local_pages_do_not_work) for
|
||||
workarounds.
|
||||
|
||||
|
||||
### How to create ad hoc environments for `nix-shell`
|
||||
|
||||
The easiest way to create an ad hoc development environment is to run
|
||||
`nix-shell` with the appropriate GHC environment given on the command-line:
|
||||
|
||||
nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [mtl pandoc])"
|
||||
|
||||
For more sophisticated use-cases, however, it's more convenient to save the
|
||||
desired configuration in a file called `shell.nix` that looks like this:
|
||||
|
||||
{ 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)";
|
||||
}
|
||||
|
||||
Now run `nix-shell` --- or even `nix-shell --pure` --- to enter a shell
|
||||
environment that has the appropriate compiler in `$PATH`. If you use `--pure`,
|
||||
then add all other packages that your development environment needs into the
|
||||
`buildInputs` attribute. If you'd like to switch to a different compiler
|
||||
version, then pass an appropriate `compiler` argument to the expression, i.e.
|
||||
`nix-shell --argstr compiler ghc784`.
|
||||
|
||||
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 `env` attribute that provides a shell
|
||||
environment suitable for compiling that particular package. If you'd like to
|
||||
hack the `lens` library, for example, then you just have to check out the
|
||||
source code and enter the appropriate environment:
|
||||
|
||||
$ 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]$
|
||||
|
||||
At point, you can run `cabal configure`, `cabal build`, and all the other
|
||||
development commands. Note that you need `cabal-install` installed in your
|
||||
`$PATH` already to use it here --- the `nix-shell` environment does not provide
|
||||
it.
|
||||
|
||||
## How to create Nix builds for your own private Haskell packages
|
||||
|
||||
If your own Haskell packages have build instructions for Cabal, then you can
|
||||
convert those automatically into build instructions for Nix using the
|
||||
`cabal2nix` utility, which you can install into your profile by running
|
||||
`nix-env -i cabal2nix`.
|
||||
|
||||
### How to build a stand-alone project
|
||||
|
||||
For example, let's assume that you're working on a private project called
|
||||
`foo`. To generate a Nix build expression for it, change into the project's
|
||||
top-level directory and run the command:
|
||||
|
||||
$ cabal2nix . >foo.nix
|
||||
|
||||
Then write the following snippet into a file called `default.nix`:
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
nixpkgs.pkgs.haskell.packages.${compiler}.callPackage ./foo.nix { }
|
||||
|
||||
Finally, store the following code in a file called `shell.nix`:
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
(import ./default.nix { inherit nixpkgs compiler; }).env
|
||||
|
||||
At this point, you can run `nix-build` to have Nix compile your project and
|
||||
install it into a Nix store path. The local directory will contain a symlink
|
||||
called `result` after `nix-build` returns that points into that location. Of
|
||||
course, passing the flag `--argstr compiler ghc763` allows switching the build
|
||||
to any version of GHC currently supported.
|
||||
|
||||
Furthermore, you can call `nix-shell` to enter an interactive development
|
||||
environment in which you can use `cabal configure` and `cabal build` 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.
|
||||
|
||||
If your package does not depend on any system-level libraries, then it's
|
||||
sufficient to run
|
||||
|
||||
$ nix-shell --command "cabal configure"
|
||||
|
||||
once to set up your build. `cabal-install` determines the absolute paths to all
|
||||
resources required for the build and writes them into a config file in the
|
||||
`dist/` directory. Once that's done, you can run `cabal build` and any other
|
||||
command for that project even outside of the `nix-shell` environment. This
|
||||
feature is particularly nice for those of us who like to edit their code with
|
||||
an IDE, like Emacs' `haskell-mode`, 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; `cabal-install` has already done that for us.
|
||||
|
||||
If you want to do some quick-and-dirty hacking and don't want to bother setting
|
||||
up a `default.nix` and `shell.nix` file manually, then you can use the
|
||||
`--shell` flag offered by `cabal2nix` to have it generate a stand-alone
|
||||
`nix-shell` environment for you. With that feature, running
|
||||
|
||||
$ cabal2nix --shell . >shell.nix
|
||||
$ nix-shell --command "cabal configure"
|
||||
|
||||
is usually enough to set up a build environment for any given Haskell package.
|
||||
You can even use that generated file to run `nix-build`, too:
|
||||
|
||||
$ nix-build shell.nix
|
||||
|
||||
### How to build projects that depend on each other
|
||||
|
||||
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 `callPackage`. First of all, change
|
||||
into each of your projects top-level directories and generate a `default.nix`
|
||||
file with `cabal2nix`:
|
||||
|
||||
$ cd ~/src/foo && cabal2nix . >default.nix
|
||||
$ cd ~/src/bar && cabal2nix . >default.nix
|
||||
|
||||
Then edit your `~/.nixpkgs/config.nix` file to register those builds in the
|
||||
default Haskell package set:
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
haskellPackages = super.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
foo = self.callPackage ../src/foo {};
|
||||
bar = self.callPackage ../src/bar {};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Once that's accomplished, `nix-env -f "<nixpkgs>" -qA haskellPackages` will
|
||||
show your packages like any other package from Hackage, and you can build them
|
||||
|
||||
$ nix-build "<nixpkgs>" -A haskellPackages.foo
|
||||
|
||||
or enter an interactive shell environment suitable for building them:
|
||||
|
||||
$ nix-shell "<nixpkgs>" -A haskellPackages.bar.env
|
||||
|
||||
## Miscellaneous Topics
|
||||
|
||||
### How to build with profiling enabled
|
||||
|
||||
Every Haskell package set takes a function called `overrides` that you can use
|
||||
to manipulate the package as much as you please. One useful application of this
|
||||
feature is to replace the default `mkDerivation` function with one that enables
|
||||
library profiling for all packages. To accomplish that, add configure the
|
||||
following snippet in your `~/.nixpkgs/config.nix` file:
|
||||
|
||||
{
|
||||
packageOverrides = super: let self = super.pkgs; in
|
||||
{
|
||||
profiledHaskellPackages = self.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
mkDerivation = args: super.mkDerivation (args // {
|
||||
enableLibraryProfiling = true;
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Then, replace instances of `haskellPackages` in the `cabal2nix`-generated
|
||||
`default.nix` or `shell.nix` files with `profiledHaskellPackages`.
|
||||
|
||||
### How to override package versions in a compiler-specific package set
|
||||
|
||||
Nixpkgs provides the latest version of
|
||||
[`ghc-events`](http://hackage.haskell.org/package/ghc-events), 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 `ghc-events` in the 7.8.x-specific package set.
|
||||
The first step is to generate Nix build instructions with `cabal2nix`:
|
||||
|
||||
$ cabal2nix cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix
|
||||
|
||||
Then add the override in `~/.nixpkgs/config.nix`:
|
||||
|
||||
{
|
||||
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 {};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
This code is a little crazy, no doubt, but it's necessary because the intuitive
|
||||
version
|
||||
|
||||
haskell.packages.ghc784 = super.haskell.packages.ghc784.override {
|
||||
overrides = self: super: {
|
||||
ghc-events = self.callPackage ./ghc-events-0.4.3.0.nix {};
|
||||
};
|
||||
};
|
||||
|
||||
doesn't do what we want it to: that code replaces the `haskell` package set in
|
||||
Nixpkgs with one that contains only one entry,`packages`, which contains only
|
||||
one entry `ghc784`. This override loses the `haskell.compiler` set, and it
|
||||
loses the `haskell.packages.ghcXYZ` 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.
|
||||
|
||||
Once it's accomplished, however, we can install a variant of `ghc-events`
|
||||
that's compiled with GHC 7.8.4:
|
||||
|
||||
nix-env -f "<nixpkgs>" -iA haskell.packages.ghc784.ghc-events
|
||||
|
||||
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 `--no-check` flag:
|
||||
|
||||
$ cabal2nix --no-check cabal://ghc-events-0.4.3.0 >~/.nixpkgs/ghc-events-0.4.3.0.nix
|
||||
|
||||
Now the builds succeeds.
|
||||
|
||||
Of course, in the concrete example of `ghc-events` this whole exercise is not
|
||||
an ideal solution, because `ghc-events` 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.
|
||||
|
||||
### How to recover from GHC's infamous non-deterministic library ID bug
|
||||
|
||||
GHC and distributed build farms don't get along well:
|
||||
|
||||
https://ghc.haskell.org/trac/ghc/ticket/4012
|
||||
|
||||
When you see an error like this one
|
||||
|
||||
package foo-0.7.1.0 is broken due to missing package
|
||||
text-1.2.0.4-98506efb1b9ada233bb5c2b2db516d91
|
||||
|
||||
then you have to download and re-install `foo` and all its dependents from
|
||||
scratch:
|
||||
|
||||
# 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
|
||||
|
||||
If you're using additional Hydra servers other than `hydra.nixos.org`, 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:
|
||||
|
||||
rm /nix/var/nix/binary-cache-v3.sqlite
|
||||
rm /nix/var/nix/manifests/*
|
||||
rm /nix/var/nix/channel-cache/*
|
||||
|
||||
### Builds on Darwin fail with `math.h` not found
|
||||
|
||||
Users of GHC on Darwin have occasionally reported that builds fail, because the
|
||||
compiler complains about a missing include file:
|
||||
|
||||
fatal error: 'math.h' file not found
|
||||
|
||||
The issue has been discussed at length in [ticket
|
||||
6390](https://github.com/NixOS/nixpkgs/issues/6390), and so far no good
|
||||
solution has been proposed. As a work-around, users who run into this problem
|
||||
can configure the environment variables
|
||||
|
||||
export NIX_CFLAGS_COMPILE="-idirafter /usr/include"
|
||||
export NIX_CFLAGS_LINK="-L/usr/lib"
|
||||
|
||||
in their `~/.bashrc` file to avoid the compiler error.
|
||||
|
||||
### Using Stack together with Nix
|
||||
|
||||
-- While building package zlib-0.5.4.2 using:
|
||||
runhaskell -package=Cabal-1.22.4.0 -clear-package-db [... lots of flags ...]
|
||||
Process exited with code: ExitFailure 1
|
||||
Logs have been written to: /home/foo/src/stack-ide/.stack-work/logs/zlib-0.5.4.2.log
|
||||
|
||||
Configuring zlib-0.5.4.2...
|
||||
Setup.hs: Missing dependency on a foreign library:
|
||||
* Missing (or bad) header file: zlib.h
|
||||
This problem can usually be solved by installing the system package that
|
||||
provides this library (you may need the "-dev" version). If the library is
|
||||
already installed but in a non-standard location then you can use the flags
|
||||
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
|
||||
If the header file does exist, it may contain errors that are caught by the C
|
||||
compiler at the preprocessing stage. In this case you can re-run configure
|
||||
with the verbosity flag -v3 to see the error messages.
|
||||
|
||||
When you run the build inside of the nix-shell environment, the system
|
||||
is configured to find libz.so without any special flags -- the compiler
|
||||
and linker "just know" how to find it. Consequently, Cabal won't record
|
||||
any search paths for libz.so in the package description, which means
|
||||
that the package works fine inside of nix-shell, but once you leave the
|
||||
shell the shared object can no longer be found. That issue is by no
|
||||
means specific to Stack: you'll have that problem with any other
|
||||
Haskell package that's built inside of nix-shell but run outside of that
|
||||
environment.
|
||||
|
||||
I suppose we could try to remedy the issue by wrapping `stack` or
|
||||
`cabal` with a script that tries to find those kind of implicit search
|
||||
paths and makes them explicit on the "cabal configure" command line. I
|
||||
don't think anyone is working on that subject yet, though, because the
|
||||
problem doesn't seem so bad in practice.
|
||||
|
||||
You can remedy that issue in several ways. First of all, run
|
||||
|
||||
$ nix-build --no-out-link "<nixpkgs>" -A zlib
|
||||
/nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8
|
||||
|
||||
to find out the store path of the system's zlib library. Now, you can
|
||||
|
||||
1) add that path (plus a "/lib" suffix) to your $LD_LIBRARY_PATH
|
||||
environment variable to make sure your system linker finds libz.so
|
||||
automatically. It's no pretty solution, but it will work.
|
||||
|
||||
2) As a variant of (1), you can also install any number of system
|
||||
libraries into your user's profile (or some other profile) and point
|
||||
$LD_LIBRARY_PATH to that profile instead, so that you don't have to
|
||||
list dozens of those store paths all over the place.
|
||||
|
||||
3) The solution I prefer is to call stack with an appropriate
|
||||
--extra-lib-dirs flag like so:
|
||||
|
||||
$ stack --extra-lib-dirs=/nix/store/alsvwzkiw4b7ip38l4nlfjijdvg3fvzn-zlib-1.2.8/lib build
|
||||
|
||||
Typically, you'll need --extra-include-dirs as well. It's possible
|
||||
to add those flag to the project's "stack.yaml" or your user's
|
||||
global "~/.stack/global/stack.yaml" file so that you don't have to
|
||||
specify them manually every time.
|
||||
|
||||
The same thing applies to `cabal configure`, of course, if you're
|
||||
building with `cabal-install` instead of Stack.
|
||||
|
||||
### Creating statically linked binaries
|
||||
|
||||
There are two levels of static linking. The first option is to configure the
|
||||
build with the Cabal flag `--disable-executable-dynamic`. In Nix expressions,
|
||||
this can be achieved by setting the attribute:
|
||||
|
||||
enableSharedExecutables = false;
|
||||
|
||||
That gives you a binary with statically linked Haskell libraries and
|
||||
dynamically linked system libraries.
|
||||
|
||||
To link both Haskell libraries and system libraries statically, the additional
|
||||
flags `--ghc-option=-optl=-static --ghc-option=-optl=-pthread` need to be used.
|
||||
In Nix, this is accomplished with:
|
||||
|
||||
configureFlags = [ "--ghc-option=-optl=-static" "--ghc-option=-optl=-pthread" ];
|
||||
|
||||
It's important to realize, however, that most system libraries in Nix are built
|
||||
as shared libraries only, i.e. there is just no static library available that
|
||||
Cabal could link!
|
||||
|
||||
|
||||
## Other resources
|
||||
|
||||
- The Youtube video [Nix Loves Haskell](https://www.youtube.com/watch?v=BsBhi_r-OeE)
|
||||
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.
|
||||
|
||||
- Another Youtube video is [Escaping Cabal Hell with Nix](https://www.youtube.com/watch?v=mQd3s57n_2Y),
|
||||
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.
|
||||
|
||||
- Oliver Charles wrote a very nice [Tutorial how to develop Haskell packages with Nix](http://wiki.ocharles.org.uk/Nix).
|
||||
|
||||
- The *Journey into the Haskell NG infrastructure* series of postings
|
||||
describe the new Haskell infrastructure in great detail:
|
||||
|
||||
- [Part 1](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015591.html)
|
||||
explains the differences between the old and the new code and gives
|
||||
instructions how to migrate to the new setup.
|
||||
|
||||
- [Part 2](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015608.html)
|
||||
looks in-depth at how to tweak and configure your setup by means of
|
||||
overrides.
|
||||
|
||||
- [Part 3](http://lists.science.uu.nl/pipermail/nix-dev/2015-April/016912.html)
|
||||
describes the infrastructure that keeps the Haskell package set in Nixpkgs
|
||||
up-to-date.
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
title: Introduction
|
||||
author: Frederik Rietdijk
|
||||
date: 2015-11-25
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
The Nix Packages collection (Nixpkgs) is a set of over 30,000 packages for the
|
||||
[Nix package manager](http://nixos.org/nix/), released under a [permissive MIT/X11 license](https://github.com/NixOS/nixpkgs/blob/master/COPYING).
|
||||
Packages are available for several architectures, and can be used with the Nix package manager
|
||||
on most GNU/Linux distributions as well as NixOS.
|
||||
|
||||
This manual describes how to write packages for the Nix Packages collection
|
||||
(Nixpkgs). Thus it’s for packagers and developers who want to add packages to
|
||||
Nixpkgs. If you like to learn more about the Nix package manager and the Nix
|
||||
expression language, then you are kindly referred to the [Nix manual](http://nixos.org/nix/manual/).
|
||||
|
||||
## Overview of Nixpkgs
|
||||
|
||||
Nix expressions describe how to build packages from source and are collected in
|
||||
the [nixpkgs repository](https://github.com/NixOS/nixpkgs). Also included in the
|
||||
collection are Nix expressions for [NixOS modules](http://nixos.org/nixos/manual/index.html#sec-writing-modules). With
|
||||
these expressions the Nix package manager can build binary packages.
|
||||
|
||||
Packages, including the Nix packages collection, are distributed through
|
||||
[channels](http://nixos.org/nix/manual/#sec-channels). The collection is
|
||||
distributed for users of Nix on non-NixOS distributions through the channel
|
||||
`nixpkgs`. Users of NixOS generally use one of the `nixos-*` channels, e.g.
|
||||
`nixos-15.09`, which includes all packages and modules for the stable NixOS
|
||||
15.09. The channels of the stable NixOS releases are generally only given
|
||||
security updates. More up to date packages and modules are available via the
|
||||
`nixos-unstable` channel.
|
||||
|
||||
Both `nixos-unstable` and `nixpkgs` follow the `master` branch of the Nixpkgs
|
||||
repository, although both do lag the `master` branch by generally [a couple of days](http://howoldis.herokuapp.com/). Updates to a channel are distributed as
|
||||
soon as all tests for that channel pass, e.g. [this table](http://hydra.nixos.org/job/nixpkgs/trunk/unstable#tabs-constituents)
|
||||
shows the status of tests for the `nixpkgs` channel.
|
||||
|
||||
The tests are conducted by a cluster called [Hydra](http://nixos.org/hydra/),
|
||||
which also builds binary packages from the Nix expressions in Nixpkgs. As soon
|
||||
as a channel is updated, the binaries are made available via a [binary cache](https://cache.nixos.org). Until the channel updates, binaries that have
|
||||
already been built, are available via [Hydra's binary cache](https://hydra.nixos.org).
|
||||
|
||||
The current Nix expressions of the channels are available in the
|
||||
[`nixpkgs-channels`](https://github.com/NixOS/nixpkgs-channels) repository,
|
||||
which has branches corresponding to the available channels. There is also the
|
||||
Nixpkgs Monitor which keeps track of updates and security vulnerabilities.
|
||||
21
doc/introduction.xml
Normal file
21
doc/introduction.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-introduction">
|
||||
|
||||
<title>Introduction</title>
|
||||
|
||||
<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://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://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>
|
||||
|
||||
</chapter>
|
||||
185
doc/language-support.xml
Normal file
185
doc/language-support.xml
Normal file
@@ -0,0 +1,185 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-meta">
|
||||
|
||||
<title>Support for specific programming languages</title>
|
||||
|
||||
<para>The <link linkend="chap-stdenv">standard build
|
||||
environment</link> makes it easy to build typical Autotools-based
|
||||
packages with very little code. Any other kind of package can be
|
||||
accomodated by overriding the appropriate phases of
|
||||
<literal>stdenv</literal>. However, there are specialised functions
|
||||
in Nixpkgs to easily build packages for other programming languages,
|
||||
such as Perl or Haskell. These are described in this chapter.</para>
|
||||
|
||||
|
||||
<section><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://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://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
|
||||
called from <filename>perl-packages.nix</filename>. However, more
|
||||
complicated packages should be put in a separate file, typically in
|
||||
<filename>pkgs/development/perl-modules</filename>. Here is an
|
||||
example of the former:
|
||||
|
||||
<programlisting>
|
||||
ClassC3 = buildPerlPackage rec {
|
||||
name = "Class-C3-0.21";
|
||||
src = fetchurl {
|
||||
url = "mirror://cpan/authors/id/F/FL/FLORA/${name}.tar.gz";
|
||||
sha256 = "1bl8z095y4js66pwxnm7s853pi9czala4sqc743fdlnk27kq94gz";
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
Note the use of <literal>mirror://cpan/</literal>, and the
|
||||
<literal>${name}</literal> in the URL definition to ensure that the
|
||||
name attribute is consistent with the source that we’re actually
|
||||
downloading. Perl packages are made available in
|
||||
<filename>all-packages.nix</filename> through the variable
|
||||
<varname>perlPackages</varname>. For instance, if you have a package
|
||||
that needs <varname>ClassC3</varname>, you would typically write
|
||||
|
||||
<programlisting>
|
||||
foo = import ../path/to/foo.nix {
|
||||
inherit stdenv fetchurl ...;
|
||||
inherit (perlPackages) ClassC3;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
in <filename>all-packages.nix</filename>. You can test building a
|
||||
Perl package as follows:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A perlPackages.ClassC3
|
||||
</screen>
|
||||
|
||||
<varname>buildPerlPackage</varname> adds <literal>perl-</literal> to
|
||||
the start of the name attribute, so the package above is actually
|
||||
called <literal>perl-Class-C3-0.21</literal>. So to install it, you
|
||||
can say:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i perl-Class-C3
|
||||
</screen>
|
||||
|
||||
(Of course you can also install using the attribute name:
|
||||
<literal>nix-env -i -A perlPackages.ClassC3</literal>.)</para>
|
||||
|
||||
<para>So what does <varname>buildPerlPackage</varname> do? It does
|
||||
the following:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>In the configure phase, it calls <literal>perl
|
||||
Makefile.PL</literal> to generate a Makefile. You can set the
|
||||
variable <varname>makeMakerFlags</varname> to pass flags to
|
||||
<filename>Makefile.PL</filename></para></listitem>
|
||||
|
||||
<listitem><para>It adds the contents of the <envar>PERL5LIB</envar>
|
||||
environment variable to <literal>#! .../bin/perl</literal> line of
|
||||
Perl scripts as <literal>-I<replaceable>dir</replaceable></literal>
|
||||
flags. This ensures that a script can find its
|
||||
dependencies.</para></listitem>
|
||||
|
||||
<listitem><para>In the fixup phase, it writes the propagated build
|
||||
inputs (<varname>propagatedBuildInputs</varname>) to the file
|
||||
<filename>$out/nix-support/propagated-user-env-packages</filename>.
|
||||
<command>nix-env</command> recursively installs all packages listed
|
||||
in this file when you install a package that has it. This ensures
|
||||
that a Perl package can find its dependencies.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para><varname>buildPerlPackage</varname> is built on top of
|
||||
<varname>stdenv</varname>, so everything can be customised in the
|
||||
usual way. For instance, the <literal>BerkeleyDB</literal> module has
|
||||
a <varname>preConfigure</varname> hook to generate a configuration
|
||||
file used by <filename>Makefile.PL</filename>:
|
||||
|
||||
<programlisting>
|
||||
{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 = ${db4}/lib" > config.in
|
||||
echo "INCLUDE = ${db4}/include" >> config.in
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Dependencies on other Perl 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>. For instance, this
|
||||
builds a Perl module that has runtime dependencies on a bunch of other
|
||||
modules:
|
||||
|
||||
<programlisting>
|
||||
ClassC3Componentised = buildPerlPackage rec {
|
||||
name = "Class-C3-Componentised-1.0004";
|
||||
src = fetchurl {
|
||||
url = "mirror://cpan/authors/id/A/AS/ASH/${name}.tar.gz";
|
||||
sha256 = "0xql73jkcdbq4q9m0b0rnca6nrlvf5hyzy8is0crdk65bynvs8q1";
|
||||
};
|
||||
propagatedBuildInputs = [
|
||||
ClassC3 ClassInspector TestException MROCompat
|
||||
];
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Python</title>
|
||||
|
||||
<para>TODO</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Haskell</title>
|
||||
|
||||
<para>TODO</para>
|
||||
|
||||
</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>
|
||||
@@ -1,41 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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>
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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/ipv6</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 built 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>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="chap-language-support">
|
||||
|
||||
<title>Support for specific programming languages and frameworks</title>
|
||||
|
||||
<para>The <link linkend="chap-stdenv">standard build
|
||||
environment</link> makes it easy to build typical Autotools-based
|
||||
packages with very little code. Any other kind of package can be
|
||||
accomodated by overriding the appropriate phases of
|
||||
<literal>stdenv</literal>. However, there are specialised functions
|
||||
in Nixpkgs to easily build packages for other programming languages,
|
||||
such as Perl or Haskell. These are described in this chapter.</para>
|
||||
|
||||
|
||||
<xi:include href="perl.xml" />
|
||||
<xi:include href="python.xml" />
|
||||
<xi:include href="ruby.xml" />
|
||||
<xi:include href="go.xml" />
|
||||
<xi:include href="java.xml" />
|
||||
<xi:include href="lua.xml" />
|
||||
<xi:include href="coq.xml" />
|
||||
<xi:include href="idris.xml" /> <!-- generated from ../../pkgs/development/idris-modules/README.md -->
|
||||
<xi:include href="r.xml" /> <!-- generated from ../../pkgs/development/r-modules/README.md -->
|
||||
<xi:include href="qt.xml" />
|
||||
|
||||
|
||||
<!--
|
||||
<section><title>Haskell</title>
|
||||
|
||||
<para>TODO</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>TeX / LaTeX</title>
|
||||
|
||||
<para>* Special support for building TeX documents</para>
|
||||
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
</chapter>
|
||||
@@ -1,84 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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 ];
|
||||
};
|
||||
};
|
||||
</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>
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="sec-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>
|
||||
|
||||
<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>,
|
||||
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
|
||||
called from <filename>perl-packages.nix</filename>. However, more
|
||||
complicated packages should be put in a separate file, typically in
|
||||
<filename>pkgs/development/perl-modules</filename>. Here is an
|
||||
example of the former:
|
||||
|
||||
<programlisting>
|
||||
ClassC3 = buildPerlPackage rec {
|
||||
name = "Class-C3-0.21";
|
||||
src = fetchurl {
|
||||
url = "mirror://cpan/authors/id/F/FL/FLORA/${name}.tar.gz";
|
||||
sha256 = "1bl8z095y4js66pwxnm7s853pi9czala4sqc743fdlnk27kq94gz";
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
Note the use of <literal>mirror://cpan/</literal>, and the
|
||||
<literal>${name}</literal> in the URL definition to ensure that the
|
||||
name attribute is consistent with the source that we’re actually
|
||||
downloading. Perl packages are made available in
|
||||
<filename>all-packages.nix</filename> through the variable
|
||||
<varname>perlPackages</varname>. For instance, if you have a package
|
||||
that needs <varname>ClassC3</varname>, you would typically write
|
||||
|
||||
<programlisting>
|
||||
foo = import ../path/to/foo.nix {
|
||||
inherit stdenv fetchurl ...;
|
||||
inherit (perlPackages) ClassC3;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
in <filename>all-packages.nix</filename>. You can test building a
|
||||
Perl package as follows:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A perlPackages.ClassC3
|
||||
</screen>
|
||||
|
||||
<varname>buildPerlPackage</varname> adds <literal>perl-</literal> to
|
||||
the start of the name attribute, so the package above is actually
|
||||
called <literal>perl-Class-C3-0.21</literal>. So to install it, you
|
||||
can say:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i perl-Class-C3
|
||||
</screen>
|
||||
|
||||
(Of course you can also install using the attribute name:
|
||||
<literal>nix-env -i -A perlPackages.ClassC3</literal>.)</para>
|
||||
|
||||
<para>So what does <varname>buildPerlPackage</varname> do? It does
|
||||
the following:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para>In the configure phase, it calls <literal>perl
|
||||
Makefile.PL</literal> to generate a Makefile. You can set the
|
||||
variable <varname>makeMakerFlags</varname> to pass flags to
|
||||
<filename>Makefile.PL</filename></para></listitem>
|
||||
|
||||
<listitem><para>It adds the contents of the <envar>PERL5LIB</envar>
|
||||
environment variable to <literal>#! .../bin/perl</literal> line of
|
||||
Perl scripts as <literal>-I<replaceable>dir</replaceable></literal>
|
||||
flags. This ensures that a script can find its
|
||||
dependencies.</para></listitem>
|
||||
|
||||
<listitem><para>In the fixup phase, it writes the propagated build
|
||||
inputs (<varname>propagatedBuildInputs</varname>) to the file
|
||||
<filename>$out/nix-support/propagated-user-env-packages</filename>.
|
||||
<command>nix-env</command> recursively installs all packages listed
|
||||
in this file when you install a package that has it. This ensures
|
||||
that a Perl package can find its dependencies.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para><varname>buildPerlPackage</varname> is built on top of
|
||||
<varname>stdenv</varname>, so everything can be customised in the
|
||||
usual way. For instance, the <literal>BerkeleyDB</literal> module has
|
||||
a <varname>preConfigure</varname> hook to generate a configuration
|
||||
file used by <filename>Makefile.PL</filename>:
|
||||
|
||||
<programlisting>
|
||||
{ buildPerlPackage, fetchurl, db }:
|
||||
|
||||
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
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Dependencies on other Perl 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>. For instance, this
|
||||
builds a Perl module that has runtime dependencies on a bunch of other
|
||||
modules:
|
||||
|
||||
<programlisting>
|
||||
ClassC3Componentised = buildPerlPackage rec {
|
||||
name = "Class-C3-Componentised-1.0004";
|
||||
src = fetchurl {
|
||||
url = "mirror://cpan/authors/id/A/AS/ASH/${name}.tar.gz";
|
||||
sha256 = "0xql73jkcdbq4q9m0b0rnca6nrlvf5hyzy8is0crdk65bynvs8q1";
|
||||
};
|
||||
propagatedBuildInputs = [
|
||||
ClassC3 ClassInspector TestException MROCompat
|
||||
];
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
</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>
|
||||
|
||||
@@ -1,447 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="sec-python">
|
||||
|
||||
<title>Python</title>
|
||||
|
||||
<para>
|
||||
Currently supported interpreters are <varname>python26</varname>, <varname>python27</varname>,
|
||||
<varname>python33</varname>, <varname>python34</varname>, <varname>python35</varname>
|
||||
and <varname>pypy</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python</varname> is an alias to <varname>python27</varname> and <varname>python3</varname> is an alias to <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>
|
||||
|
||||
<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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
All packages depending on any Python interpreter get appended <varname>$out/${python.sitePackages}</varname>
|
||||
to <literal>$PYTHONPATH</literal> if such directory exists.
|
||||
</para>
|
||||
|
||||
<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">
|
||||
twisted = buildPythonPackage {
|
||||
name = "twisted-8.1.0";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
|
||||
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ self.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>python35Packages</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>buildPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py bdist_wheel</literal> to build a wheel binary zipfile.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>installPhase</varname>, it installs the wheel file using
|
||||
<literal>pip install *.whl</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>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>installCheck</varname> phase, <literal>${python.interpreter} setup.py test</literal>
|
||||
is ran.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>By default <varname>doCheck = true</varname> is set</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>setupPyBuildFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py build_ext</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
|
||||
(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>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>pip install -e . --prefix $TMPDIR/</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>
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="sec-language-qt">
|
||||
|
||||
<title>Qt</title>
|
||||
|
||||
<para>The information in this section applies to Qt 5.5 and later.</para>
|
||||
|
||||
<para>Qt is an application development toolkit for C++. Although it is
|
||||
not a distinct programming language, there are special considerations
|
||||
for packaging Qt-based programs and libraries. A small set of tools
|
||||
and conventions has grown out of these considerations.</para>
|
||||
|
||||
<section xml:id="ssec-qt-libraries"><title>Libraries</title>
|
||||
|
||||
<para>Packages that provide libraries should be listed in
|
||||
<varname>qt5LibsFun</varname> so that the library is built with each
|
||||
Qt version. A set of packages is provided for each version of Qt; for
|
||||
example, <varname>qt5Libs</varname> always provides libraries built
|
||||
with the latest version, <varname>qt55Libs</varname> provides
|
||||
libraries built with Qt 5.5, and so on. To avoid version conflicts, no
|
||||
top-level attributes are created for these packages.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-qt-programs"><title>Programs</title>
|
||||
|
||||
<para>Application packages do not need to be built with every Qt
|
||||
version. To ensure consistency between the package's dependencies,
|
||||
call the package with <literal>qt5Libs.callPackage</literal> instead
|
||||
of the usual <literal>callPackage</literal>. An older version may be
|
||||
selected in case of incompatibility. For example, to build with Qt
|
||||
5.5, call the package with
|
||||
<literal>qt55Libs.callPackage</literal>.</para>
|
||||
|
||||
<para>Several environment variables must be set at runtime for Qt
|
||||
applications to function correctly, including:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><envar>QT_PLUGIN_PATH</envar></para></listitem>
|
||||
<listitem><para><envar>QML_IMPORT_PATH</envar></para></listitem>
|
||||
<listitem><para><envar>QML2_IMPORT_PATH</envar></para></listitem>
|
||||
<listitem><para><envar>XDG_DATA_DIRS</envar></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>To ensure that these are set correctly, the program must be wrapped by
|
||||
invoking <literal>wrapQtProgram <replaceable>program</replaceable></literal>
|
||||
during installation (for example, during
|
||||
<literal>fixupPhase</literal>). <literal>wrapQtProgram</literal>
|
||||
accepts the same options as <literal>makeWrapper</literal>.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-qt-kde"><title>KDE</title>
|
||||
|
||||
<para>Many of the considerations above also apply to KDE packages,
|
||||
especially the need to set the correct environment variables at
|
||||
runtime. To ensure that this is done, invoke <literal>wrapKDEProgram
|
||||
<replaceable>program</replaceable></literal> during
|
||||
installation. <literal>wrapKDEProgram</literal> also generates a
|
||||
<literal>ksycoca</literal> database so that required data and services
|
||||
can be found. Like its Qt counterpart,
|
||||
<literal>wrapKDEProgram</literal> accepts the same options as
|
||||
<literal>makeWrapper</literal>.</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
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>
|
||||
|
||||
<para>Resulting derivations also have two helpful items, <literal>env</literal> and <literal>wrapper</literal>. The first one allows one to quickly drop into
|
||||
<command>nix-shell</command> with the specified environment present. E.g. <command>nix-shell -A sensu.env</command> would give you an environment with Ruby preset
|
||||
so it has all the libraries necessary for <literal>sensu</literal> in its paths. The second one can be used to make derivations from custom Ruby scripts which have
|
||||
<filename>Gemfile</filename>s with their dependencies specified. It is a derivation with <command>ruby</command> wrapped so it can find all the needed dependencies.
|
||||
For example, to make a derivation <literal>my-script</literal> for a <filename>my-script.rb</filename> (which should be placed in <filename>bin</filename>) you should
|
||||
run <command>bundix</command> as specified above and then use <literal>bundlerEnv</literal> lile this:</para>
|
||||
|
||||
<programlisting>
|
||||
<![CDATA[let env = bundlerEnv {
|
||||
name = "my-script-env";
|
||||
|
||||
inherit ruby;
|
||||
gemfile = ./Gemfile;
|
||||
lockfile = ./Gemfile.lock;
|
||||
gemset = ./gemset.nix;
|
||||
};
|
||||
|
||||
in stdenv.mkDerivation {
|
||||
name = "my-script";
|
||||
|
||||
buildInputs = [ env.wrapper ];
|
||||
|
||||
script = ./my-script.rb;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin
|
||||
install -D -m755 $script $out/bin/my-script
|
||||
patchShebangs $out/bin/my-script
|
||||
'';
|
||||
}]]>
|
||||
</programlisting>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -3,24 +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>
|
||||
<holder>Eelco Dolstra</holder>
|
||||
</copyright>
|
||||
|
||||
<date>June 2008</date>
|
||||
|
||||
</info>
|
||||
|
||||
<xi:include href="introduction.xml" />
|
||||
<xi:include href="quick-start.xml" />
|
||||
<xi:include href="stdenv.xml" />
|
||||
<xi:include href="configuration.xml" />
|
||||
<xi:include href="functions.xml" />
|
||||
<xi:include href="meta.xml" />
|
||||
<xi:include href="languages-frameworks/index.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="erlang-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 --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/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,71 +84,16 @@ meta-attributes</title>
|
||||
package.</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>
|
||||
</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
|
||||
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>
|
||||
<listitem><para>The license for the package. See below for the
|
||||
allowed values.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -189,123 +106,91 @@ 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>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="sec-meta-license"><title>Licenses</title>
|
||||
<section><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.</para>
|
||||
<note><para>This is just a first attempt at standardising the license
|
||||
attribute.</para></note>
|
||||
|
||||
<para>Although it's typically better to indicate the specific license,
|
||||
a few generic options are available:
|
||||
<para>The <varname>meta.license</varname> attribute must be one of the
|
||||
following:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>stdenv.lib.licenses.free</varname>,
|
||||
<varname>"free"</varname></term>
|
||||
<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>free</varname></term>
|
||||
<listitem><para>Catch-all for free software licenses not listed
|
||||
above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>stdenv.lib.licenses.unfreeRedistributable</varname>,
|
||||
<varname>"unfree-redistributable"</varname></term>
|
||||
<term><varname>free-copyleft</varname></term>
|
||||
<listitem><para>Catch-all for free, 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
|
||||
form. That is, it’s legal to redistribute the
|
||||
form. That is, it’s legal to redistribute the
|
||||
<emphasis>output</emphasis> of the derivation. This means that
|
||||
the package can be included in the Nixpkgs
|
||||
channel.</para>
|
||||
|
||||
<para>Sometimes proprietary software can only be redistributed
|
||||
unmodified. Make sure the builder doesn’t actually modify the
|
||||
unmodified. Make sure the builder doesn’t actually modify the
|
||||
original binaries; otherwise we’re breaking the license. For
|
||||
instance, the NVIDIA X11 drivers can be redistributed unmodified,
|
||||
but our builder applies <command>patchelf</command> to make them
|
||||
work. Thus, its license is <varname>"unfree"</varname> and it
|
||||
work. Thus, its license is <varname>unfree</varname> and it
|
||||
cannot be included in the Nixpkgs channel.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>stdenv.lib.licenses.unfree</varname>,
|
||||
<varname>"unfree"</varname></term>
|
||||
|
||||
<listitem><para>Unfree package that cannot be redistributed. You
|
||||
<term><varname>unfree</varname></term>
|
||||
<listitem><para>Unfree package that cannot be redistributed. You
|
||||
can build it yourself, but you cannot redistribute the output of
|
||||
the derivation. Thus it cannot be included in the Nixpkgs
|
||||
the derivation. Thus it cannot be included in the Nixpkgs
|
||||
channel.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>stdenv.lib.licenses.unfreeRedistributableFirmware</varname>,
|
||||
<varname>"unfree-redistributable-firmware"</varname></term>
|
||||
|
||||
<term><varname>unfree-redistributable-firmware</varname></term>
|
||||
<listitem><para>This package supplies unfree, redistributable
|
||||
firmware. This is a separate value from
|
||||
<varname>unfree-redistributable</varname> because not everybody
|
||||
@@ -315,9 +200,9 @@ a few generic options are available:
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
Semi-automatic source information updating using "update-upstream-data.sh" script and "src-{,info-}for-*.nix"
|
||||
|
||||
1. Recognizing when a pre-existing package uses this mechanism.
|
||||
|
||||
Packages using this automatical update mechanism have src-info-for-default.nix and src-for-default.nix next to default.nix. src-info-for-default.nix describes getting the freshest source from upstream web site; src-for-default.nix is a generated file with the current data about used source. Both files define a simple attrSet.
|
||||
|
||||
src-info-for-default.nix (for a file grabbed via http) contains at least downloadPage attribute - it is the page we need to look at to find out the latest version. It also contains baseName that is used for automatical generation of package name containing version. It can contain extra data for trickier cases.
|
||||
|
||||
src-for-default.nix will contain advertisedUrl (raw URL chosen on the site; its change prompts regeneration of source data), url for fetchurl, hash, version retrieved from the download URL and suggested package name.
|
||||
|
||||
2. Updating a package
|
||||
|
||||
nixpkgs/pkgs/build-support/upstream-updater directory contains some scripts. The worker script is called update-upstream-data.sh. This script requires main expression name (e.g. default.nix). It can optionally accpet a second parameter, URL which will be used instead of getting one by parsing the downloadPage (version extraction, mirror URL creation etc. will still be run). After running the script, check src-for-default.nix (or replace default.nix with expression name, if there are seceral expressions in the directory) for new version information.
|
||||
|
||||
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>
|
||||
|
||||
@@ -11,12 +11,12 @@ Linux kernel or X.org.</para>
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-linux-kernel">
|
||||
<section>
|
||||
|
||||
<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>
|
||||
@@ -125,11 +135,24 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
<listitem>
|
||||
<para>It may be that the new kernel requires updating the external
|
||||
kernel modules and kernel-dependent packages listed in the
|
||||
<varname>linuxPackagesFor</varname> function in
|
||||
<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,24 +164,21 @@ $ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-xorg">
|
||||
<section>
|
||||
|
||||
<title>X.org</title>
|
||||
|
||||
<para>The Nix expressions for the X.org packages reside in
|
||||
<filename>pkgs/servers/x11/xorg/default.nix</filename>. This file is
|
||||
automatically generated from lists of tarballs in an X.org release.
|
||||
As such it should not be modified directly; rather, you should modify
|
||||
the lists, the generator script or the file
|
||||
<filename>pkgs/servers/x11/xorg/overrides.nix</filename>, in which you
|
||||
can override or add to the derivations produced by the
|
||||
generator.</para>
|
||||
automatically generated from lists of tarballs in an X.org
|
||||
release. As such it should not be modified directly; rather, you
|
||||
should modify the lists or the generator script.</para>
|
||||
|
||||
<para>The generator is invoked as follows:
|
||||
|
||||
<screen>
|
||||
$ cd pkgs/servers/x11/xorg
|
||||
$ cat tarballs-7.5.list extra.list old.list \
|
||||
$ cat tarballs-7.4.list extra.list old.list \
|
||||
| perl ./generate-expr-from-tarballs.pl
|
||||
</screen>
|
||||
|
||||
@@ -172,7 +192,7 @@ tarballs between runs. Pay close attention to the <literal>NOT FOUND:
|
||||
run, since they may indicate missing dependencies. (Some might be
|
||||
optional dependencies, however.)</para>
|
||||
|
||||
<para>A file like <filename>tarballs-7.5.list</filename> contains all
|
||||
<para>A file like <filename>tarballs-7.4.list</filename> contains all
|
||||
tarballs in a X.org release. It can be generated like this:
|
||||
|
||||
<screen>
|
||||
@@ -192,8 +212,8 @@ some people or by other packages (such as
|
||||
<para>If the expression for a package requires derivation attributes
|
||||
that the generator cannot figure out automatically (say,
|
||||
<varname>patches</varname> or a <varname>postInstall</varname> hook),
|
||||
you should modify
|
||||
<filename>pkgs/servers/x11/xorg/overrides.nix</filename>.</para>
|
||||
you should modify the generator script
|
||||
(<varname>generate-expr-from-tarballs.pl</varname>).</para>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -201,169 +221,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,6 +1,6 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-quick-start">
|
||||
xml:id="chap-overvie">
|
||||
|
||||
<title>Quick Start to Adding a Package</title>
|
||||
|
||||
@@ -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>
|
||||
@@ -25,11 +25,11 @@ $ cd nixpkgs</screen>
|
||||
<filename>pkgs/development/libraries/<replaceable>pkgname</replaceable></filename>,
|
||||
while a web browser goes into
|
||||
<filename>pkgs/applications/networking/browsers/<replaceable>pkgname</replaceable></filename>.
|
||||
See <xref linkend="sec-organisation" /> for some hints on the tree
|
||||
organisation. Create a directory for your package, e.g.
|
||||
See Section XXX for some hints on the tree 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/default.nix"><filename>pkgs/applications/misc/hello/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,42 +86,54 @@ $ 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>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>.
|
||||
<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>Firefox: <link
|
||||
xlink:href="https://svn.nixos.org/repos/nix/nixpkgs/trunk/pkgs/applications/networking/browsers/firefox-3/default.nix"><filename>pkgs/applications/networking/browsers/firefox-3/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>
|
||||
(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>;
|
||||
no need to make a separate file for them.</para>
|
||||
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>
|
||||
(search for the <varname>perlXMLSimple</varname>
|
||||
attribute). Most Perl modules are so simple to build that
|
||||
they are defined directly in
|
||||
<filename>all-packages.nix</filename>, no need to make a
|
||||
separate file for them.</para>
|
||||
</listitem>
|
||||
|
||||
<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/acrobat-reader/default.nix"><filename>pkgs/applications/misc/acrobat-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/acrobat-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>
|
||||
@@ -136,24 +148,22 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>All <varname linkend="chap-meta">meta</varname>
|
||||
attributes are optional, but it’s still a good idea to
|
||||
provide at least the <varname>description</varname>,
|
||||
<varname>homepage</varname> and <varname
|
||||
linkend="sec-meta-license">license</varname>.</para>
|
||||
<para>All <varname>meta</varname> attributes are optional,
|
||||
but it’s still a good idea to provide at least the
|
||||
<varname>description</varname> and
|
||||
<varname>homepage</varname>.</para>
|
||||
</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,13 +220,21 @@ $ 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/build-for-release.nix"><filename>pkgs/top-level/build-for-release.nix</filename></link>.</para>
|
||||
</listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
</chapter>
|
||||
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,46 +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
|
||||
updates are:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Glibc 2.9.</para></listitem>
|
||||
|
||||
<listitem><para>GCC 4.3.3.</para></listitem>
|
||||
|
||||
<listitem><para>Linux 2.6.32.</para></listitem>
|
||||
|
||||
<listitem><para>X.org 7.5.</para></listitem>
|
||||
|
||||
<listitem><para>KDE 4.3.4.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Release 0.12 (April 24, 2009)</title>
|
||||
|
||||
<para>There are way too many additions to Nixpkgs since the last
|
||||
@@ -95,7 +55,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 +197,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 +406,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>
|
||||
|
||||
239
doc/stdenv.xml
239
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
|
||||
@@ -224,67 +222,10 @@ genericBuild
|
||||
|
||||
</variablelist>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables affecting build properties</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>enableParallelBuilding</varname></term>
|
||||
<listitem><para>If set, <literal>stdenv</literal> will pass specific
|
||||
flags to <literal>make</literal> and other build tools to enable
|
||||
parallel building with up to <literal>build-cores</literal>
|
||||
workers.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>preferLocalBuild</varname></term>
|
||||
<listitem><para>If set, specifies that the package is so lightweight
|
||||
in terms of build operations (e.g. write a text file from a Nix string
|
||||
to the store) that there's no need to look for it in binary caches --
|
||||
it's faster to just build it locally. It also tells Hydra and other
|
||||
facilities that this package doesn't need to be exported in binary
|
||||
caches (noone would use it, after all).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<variablelist>
|
||||
<title>Special variables</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>passthru</varname></term>
|
||||
<listitem><para>This is an attribute set which can be filled with arbitrary
|
||||
values. For example:
|
||||
|
||||
<programlisting>
|
||||
passthru = {
|
||||
foo = "bar";
|
||||
baz = {
|
||||
value1 = 4;
|
||||
value2 = 5;
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Values inside it are not passed to the builder, so you can change
|
||||
them without triggering a rebuild. However, they can be accessed outside of a
|
||||
derivation directly, as if they were set inside a derivation itself, e.g.
|
||||
<literal>hello.baz.value1</literal>. We don't specify any usage or
|
||||
schema of <literal>passthru</literal> - it is meant for values that would be
|
||||
useful outside the derivation in other parts of a Nix expression (e.g. in other
|
||||
derivations). An example would be to convey some specific dependency of your
|
||||
derivation which contains a program with plugins support. Later, others who
|
||||
make derivations with plugins can use passed-through dependency to ensure that
|
||||
their plugin would be binary-compatible with built program.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</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
|
||||
@@ -292,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
|
||||
@@ -302,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:
|
||||
@@ -358,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>
|
||||
@@ -387,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
|
||||
@@ -401,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>
|
||||
@@ -494,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>
|
||||
@@ -507,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>
|
||||
@@ -537,10 +467,10 @@ 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
|
||||
default <function>unpackPhase</function> runs
|
||||
<filename>./configure</filename> (typically an Autoconf-generated
|
||||
script) if it exists.</para>
|
||||
|
||||
@@ -573,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>
|
||||
@@ -590,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>
|
||||
@@ -603,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>
|
||||
@@ -633,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>
|
||||
@@ -646,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>
|
||||
@@ -717,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
|
||||
@@ -777,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
|
||||
@@ -786,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> /
|
||||
@@ -832,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
|
||||
@@ -865,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>
|
||||
@@ -873,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
|
||||
@@ -956,48 +867,19 @@ following:
|
||||
phase.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>separateDebugInfo</varname></term>
|
||||
<listitem><para>If set to <literal>true</literal>, the standard
|
||||
environment will enable debug information in C/C++ builds. After
|
||||
installation, the debug information will be separated from the
|
||||
executables and stored in the output named
|
||||
<literal>debug</literal>. (This output is enabled automatically;
|
||||
you don’t need to set the <varname>outputs</varname> attribute
|
||||
explicitly.) To be precise, the debug information is stored in
|
||||
<filename><replaceable>debug</replaceable>/lib/debug/.build-id/<replaceable>XX</replaceable>/<replaceable>YYYY…</replaceable></filename>,
|
||||
where <replaceable>XXYYYY…</replaceable> is the <replaceable>build
|
||||
ID</replaceable> of the binary — a SHA-1 hash of the contents of
|
||||
the binary. Debuggers like GDB use the build ID to look up the
|
||||
separated debug information.</para>
|
||||
|
||||
<para>For example, with GDB, you can add
|
||||
|
||||
<programlisting>
|
||||
set debug-file-directory ~/.nix-profile/lib/debug
|
||||
</programlisting>
|
||||
|
||||
to <filename>~/.gdbinit</filename>. GDB will then be able to find
|
||||
debug information installed via <literal>nix-env
|
||||
-i</literal>.</para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</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 <varname>doDist</varname> is not set.</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Variables controlling the distribution phase</title>
|
||||
@@ -1057,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>
|
||||
@@ -1172,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>
|
||||
@@ -1223,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>
|
||||
@@ -1243,14 +1127,6 @@ echo @foo@
|
||||
environment variable.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Autoconf</term>
|
||||
<listitem><para>The <varname>autoreconfHook</varname> derivation adds
|
||||
<varname>autoreconfPhase</varname>, which runs autoreconf, libtoolize and
|
||||
automake, essentially preparing the configure script in autotools-based
|
||||
builds.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>libxml2</term>
|
||||
<listitem><para>Adds every file named
|
||||
@@ -1269,32 +1145,17 @@ echo @foo@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Qt 4</term>
|
||||
<term>Qt</term>
|
||||
<listitem><para>Sets the <envar>QTDIR</envar> environment variable
|
||||
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>
|
||||
@@ -1302,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,332 +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>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>
|
||||
<title>Master branch</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
It should only see non-breaking commits that do not cause mass rebuilds.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Staging branch</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
It's only for 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 the branch 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>.
|
||||
If any fixes for staging happen to be already in master, then master can
|
||||
be merged into staging.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Stable release branches</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
If you're cherry-picking a commit to a stable release branch, always use
|
||||
<command>git cherry-pick -xe</command> and ensure the message contains a
|
||||
clear description about why this needs to be included in the stable
|
||||
branch.
|
||||
</para>
|
||||
<para>An example of a cherry-picked commit would look like this:</para>
|
||||
<screen>
|
||||
nixos: Refactor the world.
|
||||
|
||||
The original commit message describing the reason why the world was torn apart.
|
||||
|
||||
(cherry picked from commit abcdef)
|
||||
Reason: I just had a gut feeling that this would also be wanted by people from
|
||||
the stone age.
|
||||
</screen>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
368
lib/attrsets.nix
368
lib/attrsets.nix
@@ -1,368 +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 if an attribute from nested attribute set exists.
|
||||
For instance ["x" "y"] applied to some set e returns true, if e.x.y exists. False
|
||||
is returned otherwise. */
|
||||
hasAttrByPath = attrPath: e:
|
||||
let attr = head attrPath;
|
||||
in
|
||||
if attrPath == [] then true
|
||||
else if e ? ${attr}
|
||||
then hasAttrByPath (tail attrPath) e.${attr}
|
||||
else false;
|
||||
|
||||
|
||||
/* 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));
|
||||
|
||||
|
||||
/* Filter an attribute set recursivelly by removing all attributes for
|
||||
which the given predicate return false.
|
||||
|
||||
Example:
|
||||
filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
|
||||
=> { foo = {}; }
|
||||
*/
|
||||
filterAttrsRecursive = pred: set:
|
||||
listToAttrs (
|
||||
concatMap (name:
|
||||
let v = set.${name}; in
|
||||
if pred name v then [
|
||||
(nameValuePair name (
|
||||
if isAttrs v then filterAttrsRecursive pred v
|
||||
else 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 -> [x]
|
||||
|
||||
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,186 +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';
|
||||
|
||||
/* Make a set of packages with a common scope. All packages called
|
||||
with the provided `callPackage' will be evaluated with the same
|
||||
arguments. Any package in the set may depend on any other. The
|
||||
`override' function allows subsequent modification of the package
|
||||
set in a consistent way, i.e. all packages in the set will be
|
||||
called with the overridden packages. The package sets may be
|
||||
hierarchical: the packages in the set are called with the scope
|
||||
provided by `newScope' and the set provides a `newScope' attribute
|
||||
which can form the parent scope for later package sets. */
|
||||
makeScope = newScope: f:
|
||||
let self = f self // {
|
||||
newScope = scope: newScope (self // scope);
|
||||
callPackage = self.newScope {};
|
||||
override = g: makeScope newScope (self_:
|
||||
let super = f self_;
|
||||
in super // g super self_);
|
||||
};
|
||||
in self;
|
||||
|
||||
}
|
||||
113
lib/debug.nix
113
lib/debug.nix
@@ -1,113 +0,0 @@
|
||||
let lib = import ./default.nix;
|
||||
|
||||
inherit (builtins) trace attrNamesToStr isAttrs isFunction isList isInt
|
||||
isString isBool head substring attrNames;
|
||||
|
||||
inherit (lib) all id mapAttrsFlatten elem;
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) addErrorContext;
|
||||
|
||||
addErrorContextToAttrs = lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v);
|
||||
|
||||
traceIf = p: msg: x: if p then trace msg x else x;
|
||||
|
||||
traceVal = x: trace x x;
|
||||
traceXMLVal = x: trace (builtins.toXML x) x;
|
||||
traceXMLValMarked = str: x: trace (str + builtins.toXML x) x;
|
||||
|
||||
# this can help debug your code as well - designed to not produce thousands of lines
|
||||
traceShowVal = x : trace (showVal x) x;
|
||||
traceShowValMarked = str: x: trace (str + showVal x) x;
|
||||
attrNamesToStr = a : lib.concatStringsSep "; " (map (x : "${x}=") (attrNames a));
|
||||
showVal = x :
|
||||
if isAttrs x then
|
||||
if x ? outPath then "x is a derivation, name ${if x ? name then x.name else "<no name>"}, { ${attrNamesToStr x} }"
|
||||
else "x is attr set { ${attrNamesToStr x} }"
|
||||
else if isFunction x then "x is a function"
|
||||
else if x == [] then "x is an empty list"
|
||||
else if isList x then "x is a list, first element is: ${showVal (head x)}"
|
||||
else if x == true then "x is boolean true"
|
||||
else if x == false then "x is boolean false"
|
||||
else if x == null then "x is null"
|
||||
else if isInt x then "x is an integer `${toString x}'"
|
||||
else if isString x then "x is a string `${substring 0 50 x}...'"
|
||||
else "x is probably a path `${substring 0 50 (toString x)}...'";
|
||||
|
||||
# trace the arguments passed to function and its result
|
||||
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough
|
||||
traceCall = n : f : a : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
|
||||
traceCall2 = n : f : a : b : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
|
||||
traceCall3 = n : f : a : b : c : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
|
||||
|
||||
# FIXME: rename this?
|
||||
traceValIfNot = c: x:
|
||||
if c x then true else trace (showVal x) false;
|
||||
|
||||
/* Evaluate a set of tests. A test is an attribute set {expr,
|
||||
expected}, denoting an expression and its expected result. The
|
||||
result is a list of failed tests, each represented as {name,
|
||||
expected, actual}, denoting the attribute name of the failing
|
||||
test and its expected and actual results. Used for regression
|
||||
testing of the functions in lib; see tests.nix for an example.
|
||||
Only tests having names starting with "test" are run.
|
||||
Add attr { tests = ["testName"]; } to run these test only
|
||||
*/
|
||||
runTests = tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test:
|
||||
let testsToRun = if tests ? tests then tests.tests else [];
|
||||
in if (substring 0 4 name == "test" || elem name testsToRun)
|
||||
&& ((testsToRun == []) || elem name tests.tests)
|
||||
&& (test.expr != test.expected)
|
||||
|
||||
then [ { inherit name; expected = test.expected; result = test.expr; } ]
|
||||
else [] ) tests));
|
||||
|
||||
# create a test assuming that list elements are true
|
||||
# usage: { testX = allTrue [ true ]; }
|
||||
testAllTrue = expr : { inherit expr; expected = map (x: true) expr; };
|
||||
|
||||
# evaluate everything once so that errors will occur earlier
|
||||
# hacky: traverse attrs by adding a dummy
|
||||
# ignores functions (should this behavior change?) See strictf
|
||||
#
|
||||
# Note: This should be a primop! Something like seq of haskell would be nice to
|
||||
# have as well. It's used fore debugging only anyway
|
||||
strict = x :
|
||||
let
|
||||
traverse = x :
|
||||
if isString x then true
|
||||
else if isAttrs x then
|
||||
if x ? outPath then true
|
||||
else all id (mapAttrsFlatten (n: traverse) x)
|
||||
else if isList x then
|
||||
all id (map traverse x)
|
||||
else if isBool x then true
|
||||
else if isFunction x then true
|
||||
else if isInt x then true
|
||||
else if x == null then true
|
||||
else true; # a (store) path?
|
||||
in if traverse x then x else throw "else never reached";
|
||||
|
||||
# example: (traceCallXml "myfun" id 3) will output something like
|
||||
# calling myfun arg 1: 3 result: 3
|
||||
# this forces deep evaluation of all arguments and the result!
|
||||
# note: if result doesn't evaluate you'll get no trace at all (FIXME)
|
||||
# args should be printed in any case
|
||||
traceCallXml = a:
|
||||
if !isInt a then
|
||||
traceCallXml 1 "calling ${a}\n"
|
||||
else
|
||||
let nr = a;
|
||||
in (str: expr:
|
||||
if isFunction expr then
|
||||
(arg:
|
||||
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg)
|
||||
)
|
||||
else
|
||||
let r = strict expr;
|
||||
in trace "${str}\n result:\n${builtins.toXML r}" r
|
||||
);
|
||||
}
|
||||
@@ -1,31 +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;
|
||||
sandbox = import ./sandbox.nix;
|
||||
|
||||
in
|
||||
{ inherit trivial lists strings stringsWithDeps attrsets sources options
|
||||
modules types meta debug maintainers licenses platforms systems sandbox;
|
||||
}
|
||||
# !!! 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 "attrs"
|
||||
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";
|
||||
|
||||
}
|
||||
496
lib/licenses.nix
496
lib/licenses.nix
@@ -1,496 +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-nc-sa-20 = spdx {
|
||||
spdxId = "CC-BY-NC-SA-2.0";
|
||||
fullName = "Creative Commons Attribution Non Commercial Share Alike 2.0";
|
||||
};
|
||||
|
||||
cc-by-nc-sa-25 = spdx {
|
||||
spdxId = "CC-BY-NC-SA-2.5";
|
||||
fullName = "Creative Commons Attribution Non Commercial Share Alike 2.5";
|
||||
};
|
||||
|
||||
cc-by-nc-sa-30 = spdx {
|
||||
spdxId = "CC-BY-NC-SA-3.0";
|
||||
fullName = "Creative Commons Attribution Non Commercial Share Alike 3.0";
|
||||
};
|
||||
|
||||
cc-by-nc-sa-40 = spdx {
|
||||
spdxId = "CC-BY-NC-SA-4.0";
|
||||
fullName = "Creative Commons Attribution Non Commercial Share Alike 4.0";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
doc = spdx {
|
||||
spdxId = "DOC";
|
||||
fullName = "DOC License";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
fdl13 = spdx {
|
||||
spdxId = "GFDL-1.3";
|
||||
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";
|
||||
};
|
||||
|
||||
ufl = {
|
||||
fullName = "Ubuntu Font License 1.0";
|
||||
url = http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt;
|
||||
};
|
||||
|
||||
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,366 +0,0 @@
|
||||
/* List of NixOS maintainers. The format is:
|
||||
|
||||
handle = "Real Name <address@example.org>";
|
||||
|
||||
where <handle> is preferred to be your GitHub username (so it's easy
|
||||
to ping a package @<handle>), and <Real Name> is your real name, not
|
||||
a pseudonym. Please keep the list alphabetically sorted. */
|
||||
{
|
||||
a1russell = "Adam Russell <adamlr6+pub@gmail.com>";
|
||||
aaronschif = "Aaron Schif <aaronschif@gmail.com>";
|
||||
abaldeau = "Andreas Baldeau <andreas@baldeau.net>";
|
||||
abbradar = "Nikolay Amiantov <ab@fmap.me>";
|
||||
adev = "Adrien Devresse <adev@adev.name>";
|
||||
aespinosa = "Allan Espinosa <allan.espinosa@outlook.com>";
|
||||
aflatter = "Alexander Flatter <flatter@fastmail.fm>";
|
||||
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
|
||||
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>";
|
||||
ambrop72 = "Ambroz Bizjak <ambrop7@gmail.com>";
|
||||
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>";
|
||||
aneeshusa = "Aneesh Agrawal <aneeshusa@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>";
|
||||
Baughn = "Svein Ove Aas <sveina@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>";
|
||||
benley = "Benjamin Staffin <benley@gmail.com>";
|
||||
bennofs = "Benno Fünfstück <benno.fuenfstueck@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>";
|
||||
bzizou = "Bruno Bzeznik <Bruno@bzizou.net>";
|
||||
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>";
|
||||
codsl = "codsl <codsl@riseup.net>";
|
||||
codyopel = "Cody Opel <codyopel@gmail.com>";
|
||||
colemickens = "Cole Mickens <cole.mickens@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>";
|
||||
dasuxullebt = "Christoph-Simon Senjak <christoph.senjak@googlemail.com>";
|
||||
davidak = "David Kleuker <post@davidak.de>";
|
||||
davidrusu = "David Rusu <davidrusu.me@gmail.com>";
|
||||
dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>";
|
||||
deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>";
|
||||
demin-dmitriy = "Dmitriy Demin <demindf@gmail.com>";
|
||||
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
|
||||
desiderius = "Didier J. Devroye <didier@devroye.name>";
|
||||
devhell = "devhell <\"^\"@regexmail.net>";
|
||||
dezgeg = "Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>";
|
||||
dfoxfranke = "Daniel Fox Franke <dfoxfranke@gmail.com>";
|
||||
dgonyeo = "Derek Gonyeo <derek@gonyeo.com>";
|
||||
dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>";
|
||||
dochang = "Desmond O. Chang <dochang@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>";
|
||||
ehegnes = "Eric Hegnes <eric.hegnes@gmail.com>";
|
||||
ehmry = "Emery Hemingway <emery@vfemail.net>";
|
||||
eikek = "Eike Kettner <eike.kettner@posteo.de>";
|
||||
elasticdog = "Aaron Bull Schaefer <aaron@elasticdog.com>";
|
||||
elitak = "Eric Litak <elitak@gmail.com>";
|
||||
ellis = "Ellis Whitehead <nixos@ellisw.net>";
|
||||
epitrochoid = "Mabry Cervin <mpcervin@uncg.edu>";
|
||||
ericbmerritt = "Eric Merritt <eric@afiniate.com>";
|
||||
ericsagnes = "Eric Sagnes <eric.sagnes@gmail.com>";
|
||||
erikryb = "Erik Rybakken <erik.rybakken@math.ntnu.no>";
|
||||
ertes = "Ertugrul Söylemez <ertesx@gmx.de>";
|
||||
exi = "Reno Reckling <nixos@reckling.org>";
|
||||
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
||||
fadenb = "Tristan Helmich <tristan.helmich+nixos@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>";
|
||||
fornever = "Friedrich von Never <friedrich@fornever.me>";
|
||||
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
|
||||
fps = "Florian Paul Schmidt <mista.tapas@gmx.net>";
|
||||
fridh = "Frederik Rietdijk <fridh@fridh.nl>";
|
||||
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>";
|
||||
fxfactorial = "Edgar Aroutiounian <edgar.factorial@gmail.com>";
|
||||
gal_bolle = "Florent Becker <florent.becker@ens-lyon.org>";
|
||||
garbas = "Rok Garbas <rok@garbas.si>";
|
||||
garrison = "Jim Garrison <jim@garrison.cc>";
|
||||
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
|
||||
gebner = "Gabriel Ebner <gebner@gebner.org>";
|
||||
gfxmonk = "Tim Cuthbertson <tim@gfxmonk.net>";
|
||||
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
|
||||
gleber = "Gleb Peregud <gleber.p@gmail.com>";
|
||||
globin = "Robin Gloster <mail@glob.in>";
|
||||
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
|
||||
Gonzih = "Max Gonzih <gonzih@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>";
|
||||
igsha = "Igor Sharonov <igor.sharonov@gmail.com>";
|
||||
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>";
|
||||
javaguirre = "Javier Aguirre <contacto@javaguirre.net>";
|
||||
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 <jascha@jgeerds.name>";
|
||||
jgillich = "Jakob Gillich <jakob@gillich.me>";
|
||||
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>";
|
||||
kampfschlaefer = "Arnold Krille <arnold@arnoldarts.de>";
|
||||
kevincox = "Kevin Cox <kevincox@kevincox.ca>";
|
||||
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 <louis@kragniz.eu>";
|
||||
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>";
|
||||
leenaars = "Michiel Leenaars <ml.software@leenaa.rs>";
|
||||
leonardoce = "Leonardo Cecchi <leonardo.cecchi@gmail.com>";
|
||||
lethalman = "Luca Bruno <lucabru@src.gnome.org>";
|
||||
lewo = "Antoine Eiche <lewo@abesis.fr>";
|
||||
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>";
|
||||
luispedro = "Luis Pedro Coelho <luis@luispedro.org>";
|
||||
lukasepple = "Lukas Epple <post@lukasepple.de>";
|
||||
lukego = "Luke Gorrie <luke@snabb.co>";
|
||||
lw = "Sergey Sofeychuk <lw@fmap.me>";
|
||||
madjar = "Georges Dubus <georges.dubus@compiletoi.net>";
|
||||
magnetophon = "Bart Brouns <bart@magnetophon.nl>";
|
||||
mahe = "Matthias Herrmann <matthias.mh.herrmann@gmail.com>";
|
||||
makefu = "Felix Richter <makefu@syntax-fehler.de>";
|
||||
malyn = "Michael Alyn Miller <malyn@strangeGizmo.com>";
|
||||
manveru = "Michael Fellinger <m.fellinger@gmail.com>";
|
||||
marcweber = "Marc Weber <marco-oweber@gmx.de>";
|
||||
markWot = "Markus Wotringer <markus@wotringer.de>";
|
||||
matejc = "Matej Cotman <cotman.matej@gmail.com>";
|
||||
mathnerd314 = "Mathnerd314 <mathnerd314.gph+hs@gmail.com>";
|
||||
matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>";
|
||||
maurer = "Matthew Maurer <matthew.r.maurer+nix@gmail.com>";
|
||||
mbakke = "Marius Bakke <ymse@tuta.io>";
|
||||
mbe = "Brandon Edens <brandonedens@gmail.com>";
|
||||
mcmtroffaes = "Matthias C. M. Troffaes <matthias.troffaes@gmail.com>";
|
||||
meditans = "Carlo Nucera <meditans@gmail.com>";
|
||||
meisternu = "Matt Miemiec <meister@krutt.org>";
|
||||
michaelpj = "Michael Peyton Jones <michaelpj@gmail.com>";
|
||||
michelk = "Michel Kuhlmann <michel@kuhlmanns.info>";
|
||||
mingchuan = "Ming Chuan <ming@culpring.com>";
|
||||
mirdhyn = "Merlin Gaillard <mirdhyn@gmail.com>";
|
||||
modulistic = "Pablo Costa <modulistic@gmail.com>";
|
||||
mog = "Matthew O'Gorman <mog-lists@rldn.net>";
|
||||
mornfall = "Petr Ročkai <me@mornfall.net>";
|
||||
MP2E = "Cray Elliott <MP2E@archlinux.us>";
|
||||
msackman = "Matthew Sackman <matthew@wellquite.org>";
|
||||
mschristiansen = "Mikkel Christiansen <mikkel@rheosystems.com>";
|
||||
msteen = "Matthijs Steen <emailmatthijs@gmail.com>";
|
||||
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>";
|
||||
nequissimus = "Tim Steinbach <tim@nequissimus.com>";
|
||||
nfjinjing = "Jinjing Wang <nfjinjing@gmail.com>";
|
||||
nico202 = "Nicolò Balzarotti <anothersms@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>";
|
||||
oxij = "Jan Malakhovski <oxij@oxij.org>";
|
||||
page = "Carles Pagès <page@cubata.homelinux.net>";
|
||||
paholg = "Paho Lurie-Gregg <paho@paholg.com>";
|
||||
pakhfn = "Fedor Pakhomov <pakhfn@gmail.com>";
|
||||
palo = "Ingolf Wanger <palipalo9@googlemail.com>";
|
||||
pashev = "Igor Pashev <pashev.igor@gmail.com>";
|
||||
pesterhazy = "Paulus Esterhazy <pesterhazy@gmail.com>";
|
||||
philandstuff = "Philip Potter <philip.g.potter@gmail.com>";
|
||||
phile314 = "Philipp Hausmann <nix@314.ch>";
|
||||
Phlogistique = "Noé Rubinstein <noe.rubinstein@gmail.com>";
|
||||
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
|
||||
phunehehe = "Hoang Xuan Phu <phunehehe@gmail.com>";
|
||||
pierron = "Nicolas B. Pierron <nixos@nbp.name>";
|
||||
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
|
||||
pjbarnoy = "Perry Barnoy <pjbarnoy@gmail.com>";
|
||||
pjones = "Peter Jones <pjones@devalot.com>";
|
||||
pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>";
|
||||
plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>";
|
||||
pmahoney = "Patrick Mahoney <pat@polycrystal.org>";
|
||||
pmiddend = "Philipp Middendorf <pmidden@secure.mailbox.org>";
|
||||
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
||||
profpatsch = "Profpatsch <mail@profpatsch.de>";
|
||||
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>";
|
||||
rnhmjoj = "Michele Guerini Rocco <micheleguerinirocco@me.com>";
|
||||
rob = "Rob Vermaas <rob.vermaas@gmail.com>";
|
||||
robberer = "Longrin Wischnewski <robberer@freakmail.de>";
|
||||
robbinch = "Robbin C. <robbinch33@gmail.com>";
|
||||
robgssp = "Rob Glossop <robgssp@gmail.com>";
|
||||
roconnor = "Russell O'Connor <roconnor@theorem.ca>";
|
||||
romildo = "José Romildo Malaquias <malaquias@gmail.com>";
|
||||
rszibele = "Richard Szibele <richard_szibele@hotmail.com>";
|
||||
rushmorem = "Rushmore Mushambi <rushmore@webenchanter.com>";
|
||||
rvl = "Rodney Lorrimar <dev+nix@rodney.id.au>";
|
||||
rvlander = "Gaëtan André <rvlander@gaetanandre.eu>";
|
||||
ryantm = "Ryan Mulligan <ryan@ryantm.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>";
|
||||
sjourdois = "Stéphane ‘kwisatz’ Jourdois <sjourdois@gmail.com>";
|
||||
skeidel = "Sven Keidel <svenkeidel@gmail.com>";
|
||||
sleexyz = "Sean Lee <freshdried@gmail.com>";
|
||||
smironov = "Sergey Mironov <ierton@gmail.com>";
|
||||
spacefrogg = "Michael Raitza <spacefrogg-nixos@meterriblecrew.net>";
|
||||
spencerjanssen = "Spencer Janssen <spencerjanssen@gmail.com>";
|
||||
spinus = "Tomasz Czyż <tomasz.czyz@gmail.com>";
|
||||
sprock = "Roger Mason <rmason@mun.ca>";
|
||||
spwhitt = "Spencer Whitt <sw@swhitt.me>";
|
||||
stephenmw = "Stephen Weinberg <stephen@q5comm.com>";
|
||||
steveej = "Stefan Junker <mail@stefanjunker.de>";
|
||||
szczyp = "Szczyp <qb@szczyp.com>";
|
||||
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
|
||||
taeer = "Taeer Bar-Yam <taeer@necsi.edu>";
|
||||
tailhook = "Paul Colomiets <paul@colomiets.name>";
|
||||
taktoa = "Remy Goldschmidt <taktoa@gmail.com>";
|
||||
tavyc = "Octavian Cerna <octavian.cerna@gmail.com>";
|
||||
telotortium = "Robert Irelan <rirelan@gmail.com>";
|
||||
thall = "Niclas Thall <niclas.thall@gmail.com>";
|
||||
thammers = "Tobias Hammerschmidt <jawr@gmx.de>";
|
||||
the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>";
|
||||
theuni = "Christian Theune <ct@flyingcircus.io>";
|
||||
thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
|
||||
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
|
||||
tohl = "Tomas Hlavaty <tom@logand.com>";
|
||||
tokudan = "Daniel Frank <git@danielfrank.net>";
|
||||
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>";
|
||||
tvestelind = "Tomas Vestelind <tomas.vestelind@fripost.org>";
|
||||
twey = "James ‘Twey’ Kay <twey@twey.co.uk>";
|
||||
urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>";
|
||||
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
||||
vanzef = "Ivan Solyankin <vanzef@gmail.com>";
|
||||
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
||||
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
||||
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
||||
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>";
|
||||
wedens = "wedens <kirill.wedens@gmail.com>";
|
||||
willtim = "Tim Philip Williams <tim.williams.public@gmail.com>";
|
||||
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
|
||||
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
|
||||
wjlroe = "William Roe <willroe@gmail.com>";
|
||||
wkennington = "William A. Kennington III <william@wkennington.com>";
|
||||
wmertens = "Wout Mertens <Wout.Mertens@gmail.com>";
|
||||
womfoo = "Kranium Gikos Mendoza <kranium@gikos.net>";
|
||||
wscott = "Wayne Scott <wsc9tt@gmail.com>";
|
||||
wyvie = "Elijah Rum <elijahrum@gmail.com>";
|
||||
yarr = "Dmitry V. <savraz@gmail.com>";
|
||||
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
|
||||
zagy = "Christian Zagrodnick <cz@flyingcircus.io>";
|
||||
zef = "Zef Hemel <zef@zef.me>";
|
||||
zimbatm = "zimbatm <zimbatm@zimbatm.com>";
|
||||
zohl = "Al Zohali <zohl@fmap.me>";
|
||||
zoomulator = "Kim Simmons <zoomulator@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;
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
# Expose the minimum required version for evaluating Nixpkgs
|
||||
"1.10"
|
||||
566
lib/modules.nix
566
lib/modules.nix
@@ -1,566 +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; };
|
||||
|
||||
|
||||
/* Return a module that causes a warning to be shown if the
|
||||
specified option is defined. For example,
|
||||
|
||||
mkRemovedOptionModule [ "boot" "loader" "grub" "bootDevice" ]
|
||||
|
||||
causes a warning if the user defines boot.loader.grub.bootDevice.
|
||||
*/
|
||||
mkRemovedOptionModule = optionName:
|
||||
{ options, ... }:
|
||||
{ options = setAttrByPath optionName (mkOption {
|
||||
visible = false;
|
||||
});
|
||||
config.warnings =
|
||||
let opt = getAttrFromPath optionName options; in
|
||||
optional opt.isDefined
|
||||
"The option definition `${showOption optionName}' in ${showFiles opt.files} no longer has any effect; please remove it.";
|
||||
};
|
||||
|
||||
/* Return a module that causes a warning to be shown if the
|
||||
specified "from" option is defined; the defined value is however
|
||||
forwarded to the "to" option. This can be used to rename options
|
||||
while providing backward compatibility. For example,
|
||||
|
||||
mkRenamedOptionModule [ "boot" "copyKernels" ] [ "boot" "loader" "grub" "copyKernels" ]
|
||||
|
||||
forwards any definitions of boot.copyKernels to
|
||||
boot.loader.grub.copyKernels while printing a warning.
|
||||
*/
|
||||
mkRenamedOptionModule = from: to: doRename {
|
||||
inherit from to;
|
||||
visible = false;
|
||||
warn = true;
|
||||
use = builtins.trace "Obsolete option `${showOption from}' is used. It was renamed to `${showOption to}'.";
|
||||
};
|
||||
|
||||
/* Like ‘mkRenamedOptionModule’, but doesn't show a warning. */
|
||||
mkAliasOptionModule = from: to: doRename {
|
||||
inherit from to;
|
||||
visible = true;
|
||||
warn = false;
|
||||
use = id;
|
||||
};
|
||||
|
||||
doRename = { from, to, visible, warn, use }:
|
||||
let
|
||||
toOf = attrByPath to
|
||||
(abort "Renaming error: option `${showOption to}' does not exists.");
|
||||
in
|
||||
{ config, options, ... }:
|
||||
{ options = setAttrByPath from (mkOption {
|
||||
description = "Alias of <option>${showOption to}</option>.";
|
||||
apply = x: use (toOf config);
|
||||
});
|
||||
config = {
|
||||
/*
|
||||
warnings =
|
||||
let opt = getAttrFromPath from options; in
|
||||
optional (warn && opt.isDefined)
|
||||
"The option `${showOption from}' defined in ${showFiles opt.files} has been renamed to `${showOption to}'.";
|
||||
*/
|
||||
} // setAttrByPath to (mkAliasDefinitions (getAttrFromPath from options));
|
||||
};
|
||||
|
||||
}
|
||||
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,24 +0,0 @@
|
||||
let lists = import ./lists.nix; in
|
||||
|
||||
rec {
|
||||
all = linux ++ darwin ++ cygwin ++ freebsd ++ openbsd ++ netbsd ++ illumos;
|
||||
allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
|
||||
none = [];
|
||||
|
||||
arm = ["armv5tel-linux" "armv6l-linux" "armv7l-linux" ];
|
||||
i686 = ["i686-linux" "i686-freebsd" "i686-netbsd" "i686-cygwin"];
|
||||
mips = [ "mips64el-linux" ];
|
||||
x86_64 = ["x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin"];
|
||||
|
||||
cygwin = ["i686-cygwin" "x86_64-cygwin"];
|
||||
darwin = ["x86_64-darwin"];
|
||||
freebsd = ["i686-freebsd" "x86_64-freebsd"];
|
||||
gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */
|
||||
illumos = ["x86_64-solaris"];
|
||||
linux = ["i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "mips64el-linux"];
|
||||
netbsd = ["i686-netbsd" "x86_64-netbsd"];
|
||||
openbsd = ["i686-openbsd" "x86_64-openbsd"];
|
||||
unix = linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos;
|
||||
|
||||
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux"];
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
with import ./strings.nix;
|
||||
|
||||
/* Helpers for creating lisp S-exprs for the Apple sandbox
|
||||
|
||||
lib.sandbox.allowFileRead [ "/usr/bin/file" ];
|
||||
# => "(allow file-read* (literal \"/usr/bin/file\"))";
|
||||
|
||||
lib.sandbox.allowFileRead {
|
||||
literal = [ "/usr/bin/file" ];
|
||||
subpath = [ "/usr/lib/system" ];
|
||||
}
|
||||
# => "(allow file-read* (literal \"/usr/bin/file\") (subpath \"/usr/lib/system\"))"
|
||||
*/
|
||||
|
||||
let
|
||||
|
||||
sexp = tokens: "(" + builtins.concatStringsSep " " tokens + ")";
|
||||
generateFileList = files:
|
||||
if builtins.isList files
|
||||
then concatMapStringsSep " " (x: sexp [ "literal" ''"${x}"'' ]) files
|
||||
else if builtins.isString files
|
||||
then generateFileList [ files ]
|
||||
else concatStringsSep " " (
|
||||
(map (x: sexp [ "literal" ''"${x}"'' ]) (files.literal or [])) ++
|
||||
(map (x: sexp [ "subpath" ''"${x}"'' ]) (files.subpath or []))
|
||||
);
|
||||
applyToFiles = f: act: files: f "${act} ${generateFileList files}";
|
||||
genActions = actionName: let
|
||||
action = feature: sexp [ actionName feature ];
|
||||
self = {
|
||||
"${actionName}" = action;
|
||||
"${actionName}File" = applyToFiles action "file*";
|
||||
"${actionName}FileRead" = applyToFiles action "file-read*";
|
||||
"${actionName}FileReadMetadata" = applyToFiles action "file-read-metadata";
|
||||
"${actionName}DirectoryList" = self."${actionName}FileReadMetadata";
|
||||
"${actionName}FileWrite" = applyToFiles action "file-write*";
|
||||
"${actionName}FileWriteMetadata" = applyToFiles action "file-write-metadata";
|
||||
};
|
||||
in self;
|
||||
|
||||
in
|
||||
|
||||
genActions "allow" // genActions "deny" // {
|
||||
importProfile = derivation: ''
|
||||
(import "${derivation}")
|
||||
'';
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
Usage:
|
||||
|
||||
You define you custom builder script by adding all build steps to a list.
|
||||
for example:
|
||||
builder = writeScript "fsg-4.4-builder"
|
||||
(textClosure [doUnpack addInputs preBuild doMake installPhase doForceShare]);
|
||||
|
||||
a step is defined by noDepEntry, fullDepEntry or packEntry.
|
||||
To ensure that prerequisite are met those are added before the task itself by
|
||||
textClosureDupList. Duplicated items are removed again.
|
||||
|
||||
See trace/nixpkgs/trunk/pkgs/top-level/builder-defs.nix for some predefined build steps
|
||||
|
||||
Attention:
|
||||
|
||||
let
|
||||
pkgs = (import /etc/nixos/nixpkgs/pkgs/top-level/all-packages.nix) {};
|
||||
in let
|
||||
inherit (pkgs.stringsWithDeps) fullDepEntry packEntry noDepEntry textClosureMap;
|
||||
inherit (pkgs.lib) id;
|
||||
|
||||
nameA = noDepEntry "Text a";
|
||||
nameB = fullDepEntry "Text b" ["nameA"];
|
||||
nameC = fullDepEntry "Text c" ["nameA"];
|
||||
|
||||
stages = {
|
||||
nameHeader = noDepEntry "#! /bin/sh \n";
|
||||
inherit nameA nameB nameC;
|
||||
};
|
||||
in
|
||||
textClosureMap id stages
|
||||
[ "nameHeader" "nameA" "nameB" "nameC"
|
||||
nameC # <- added twice. add a dep entry if you know that it will be added once only [1]
|
||||
"nameB" # <- this will not be added again because the attr name (reference) is used
|
||||
]
|
||||
|
||||
# result: Str("#! /bin/sh \n\nText a\nText b\nText c\nText c",[])
|
||||
|
||||
[1] maybe this behaviour should be removed to keep things simple (?)
|
||||
*/
|
||||
|
||||
with import ./lists.nix;
|
||||
with import ./attrsets.nix;
|
||||
with import ./strings.nix;
|
||||
|
||||
rec {
|
||||
|
||||
/* !!! The interface of this function is kind of messed up, since
|
||||
it's way too overloaded and almost but not quite computes a
|
||||
topological sort of the depstrings. */
|
||||
|
||||
textClosureList = predefined: arg:
|
||||
let
|
||||
f = done: todo:
|
||||
if todo == [] then {result = []; inherit done;}
|
||||
else
|
||||
let entry = head todo; in
|
||||
if isAttrs entry then
|
||||
let x = f done entry.deps;
|
||||
y = f x.done (tail todo);
|
||||
in { result = x.result ++ [entry.text] ++ y.result;
|
||||
done = y.done;
|
||||
}
|
||||
else if done ? ${entry} then f done (tail todo)
|
||||
else f (done // listToAttrs [{name = entry; value = 1;}]) ([predefined.${entry}] ++ tail todo);
|
||||
in (f {} arg).result;
|
||||
|
||||
textClosureMap = f: predefined: names:
|
||||
concatStringsSep "\n" (map f (textClosureList predefined names));
|
||||
|
||||
noDepEntry = text: {inherit text; deps = [];};
|
||||
fullDepEntry = text: deps: {inherit text deps;};
|
||||
packEntry = deps: {inherit deps; text="";};
|
||||
|
||||
stringAfter = deps: text: { inherit text deps; };
|
||||
|
||||
}
|
||||
257
lib/strings.nix
257
lib/strings.nix
@@ -1,257 +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";
|
||||
|
||||
# Construct a binary search path (such as $PATH) containing the
|
||||
# binaries for a set of packages, e.g. "${pkg1}/bin:${pkg2}/bin:...".
|
||||
makeBinPath = makeSearchPath "bin";
|
||||
|
||||
|
||||
# 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;
|
||||
|
||||
|
||||
# This function takes an argument that's either a derivation or a
|
||||
# derivation's "name" attribute and extracts the version part from that
|
||||
# argument. For example:
|
||||
#
|
||||
# lib.getVersion "youtube-dl-2016.01.01" ==> "2016.01.01"
|
||||
# lib.getVersion pkgs.youtube-dl ==> "2016.01.01"
|
||||
getVersion = x: (builtins.parseDrvName (x.name or x)).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;
|
||||
|
||||
# Convert string to int
|
||||
# Obviously, it is a bit hacky to use fromJSON that way.
|
||||
toInt = str:
|
||||
let may_be_int = builtins.fromJSON str; in
|
||||
if builtins.isInt may_be_int
|
||||
then may_be_int
|
||||
else throw "Could not convert ${str} to int.";
|
||||
|
||||
# Read a list of paths from `file', relative to the `rootPath'. Lines
|
||||
# beginning with `#' are treated as comments and ignored. Whitespace
|
||||
# is significant.
|
||||
readPathsFromFile = rootPath: file:
|
||||
let
|
||||
root = toString rootPath;
|
||||
lines =
|
||||
builtins.map (lib.removeSuffix "\n")
|
||||
(lib.splitString "\n" (builtins.readFile file));
|
||||
removeComments = lib.filter (line: !(lib.hasPrefix "#" line));
|
||||
relativePaths = removeComments lines;
|
||||
absolutePaths = builtins.map (path: builtins.toPath (root + "/" + path)) relativePaths;
|
||||
in
|
||||
absolutePaths;
|
||||
|
||||
}
|
||||
126
lib/systems.nix
126
lib/systems.nix
@@ -1,126 +0,0 @@
|
||||
# Define the list of system with their properties. Only systems tested for
|
||||
# Nixpkgs are listed below
|
||||
|
||||
with import ./lists.nix;
|
||||
with import ./types.nix;
|
||||
with import ./attrsets.nix;
|
||||
|
||||
let
|
||||
lib = import ./default.nix;
|
||||
setTypes = type:
|
||||
mapAttrs (name: value:
|
||||
setType type ({inherit name;} // value)
|
||||
);
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
isSignificantByte = isType "significant-byte";
|
||||
significantBytes = setTypes "significant-byte" {
|
||||
bigEndian = {};
|
||||
littleEndian = {};
|
||||
};
|
||||
|
||||
|
||||
isCpuType = x: isType "cpu-type" x
|
||||
&& elem x.bits [8 16 32 64 128]
|
||||
&& (8 < x.bits -> isSignificantByte x.significantByte);
|
||||
|
||||
cpuTypes = with significantBytes;
|
||||
setTypes "cpu-type" {
|
||||
arm = { bits = 32; significantByte = littleEndian; };
|
||||
armv5tel = { bits = 32; significantByte = littleEndian; };
|
||||
armv7l = { bits = 32; significantByte = littleEndian; };
|
||||
i686 = { bits = 32; significantByte = littleEndian; };
|
||||
powerpc = { bits = 32; significantByte = bigEndian; };
|
||||
x86_64 = { bits = 64; significantByte = littleEndian; };
|
||||
};
|
||||
|
||||
|
||||
isExecFormat = isType "exec-format";
|
||||
execFormats = setTypes "exec-format" {
|
||||
aout = {}; # a.out
|
||||
elf = {};
|
||||
macho = {};
|
||||
pe = {};
|
||||
unknow = {};
|
||||
};
|
||||
|
||||
|
||||
isKernel = isType "kernel";
|
||||
kernels = with execFormats;
|
||||
setTypes "kernel" {
|
||||
cygwin = { execFormat = pe; };
|
||||
darwin = { execFormat = macho; };
|
||||
freebsd = { execFormat = elf; };
|
||||
linux = { execFormat = elf; };
|
||||
netbsd = { execFormat = elf; };
|
||||
none = { execFormat = unknow; };
|
||||
openbsd = { execFormat = elf; };
|
||||
win32 = { execFormat = pe; };
|
||||
};
|
||||
|
||||
|
||||
isArchitecture = isType "architecture";
|
||||
architectures = setTypes "architecture" {
|
||||
apple = {};
|
||||
pc = {};
|
||||
unknow = {};
|
||||
};
|
||||
|
||||
|
||||
isSystem = x: isType "system" x
|
||||
&& isCpuType x.cpu
|
||||
&& isArchitecture x.arch
|
||||
&& isKernel x.kernel;
|
||||
|
||||
mkSystem = {
|
||||
cpu ? cpuTypes.i686,
|
||||
arch ? architectures.pc,
|
||||
kernel ? kernels.linux,
|
||||
name ? "${cpu.name}-${arch.name}-${kernel.name}"
|
||||
}: setType "system" {
|
||||
inherit name cpu arch kernel;
|
||||
};
|
||||
|
||||
|
||||
is64Bit = matchAttrs { cpu = { bits = 64; }; };
|
||||
isDarwin = matchAttrs { kernel = kernels.darwin; };
|
||||
isi686 = matchAttrs { cpu = cpuTypes.i686; };
|
||||
isLinux = matchAttrs { kernel = kernels.linux; };
|
||||
|
||||
|
||||
# This should revert the job done by config.guess from the gcc compiler.
|
||||
mkSystemFromString = s: let
|
||||
l = lib.splitString "-" s;
|
||||
|
||||
getCpu = name:
|
||||
attrByPath [name] (throw "Unknow cpuType `${name}'.")
|
||||
cpuTypes;
|
||||
getArch = name:
|
||||
attrByPath [name] (throw "Unknow architecture `${name}'.")
|
||||
architectures;
|
||||
getKernel = name:
|
||||
attrByPath [name] (throw "Unknow kernel `${name}'.")
|
||||
kernels;
|
||||
|
||||
system =
|
||||
if builtins.length l == 2 then
|
||||
mkSystem rec {
|
||||
name = s;
|
||||
cpu = getCpu (head l);
|
||||
arch =
|
||||
if isDarwin system
|
||||
then architectures.apple
|
||||
else architectures.pc;
|
||||
kernel = getKernel (head (tail l));
|
||||
}
|
||||
else
|
||||
mkSystem {
|
||||
name = s;
|
||||
cpu = getCpu (head l);
|
||||
arch = getArch (head (tail l));
|
||||
kernel = getKernel (head (tail (tail l)));
|
||||
};
|
||||
in assert isSystem system; system;
|
||||
}
|
||||
133
lib/tests.nix
133
lib/tests.nix
@@ -1,133 +0,0 @@
|
||||
let inherit (builtins) add; in
|
||||
with import ./default.nix;
|
||||
|
||||
runTests {
|
||||
|
||||
testId = {
|
||||
expr = id 1;
|
||||
expected = 1;
|
||||
};
|
||||
|
||||
testConst = {
|
||||
expr = const 2 3;
|
||||
expected = 2;
|
||||
};
|
||||
|
||||
/*
|
||||
testOr = {
|
||||
expr = or true false;
|
||||
expected = true;
|
||||
};
|
||||
*/
|
||||
|
||||
testAnd = {
|
||||
expr = and true false;
|
||||
expected = false;
|
||||
};
|
||||
|
||||
testFix = {
|
||||
expr = fix (x: {a = if x ? a then "a" else "b";});
|
||||
expected = {a = "a";};
|
||||
};
|
||||
|
||||
testConcatMapStrings = {
|
||||
expr = concatMapStrings (x: x + ";") ["a" "b" "c"];
|
||||
expected = "a;b;c;";
|
||||
};
|
||||
|
||||
testConcatStringsSep = {
|
||||
expr = concatStringsSep "," ["a" "b" "c"];
|
||||
expected = "a,b,c";
|
||||
};
|
||||
|
||||
testFilter = {
|
||||
expr = filter (x: x != "a") ["a" "b" "c" "a"];
|
||||
expected = ["b" "c"];
|
||||
};
|
||||
|
||||
testFold = {
|
||||
expr = fold (builtins.add) 0 (range 0 100);
|
||||
expected = 5050;
|
||||
};
|
||||
|
||||
testTake = testAllTrue [
|
||||
([] == (take 0 [ 1 2 3 ]))
|
||||
([1] == (take 1 [ 1 2 3 ]))
|
||||
([ 1 2 ] == (take 2 [ 1 2 3 ]))
|
||||
([ 1 2 3 ] == (take 3 [ 1 2 3 ]))
|
||||
([ 1 2 3 ] == (take 4 [ 1 2 3 ]))
|
||||
];
|
||||
|
||||
testFoldAttrs = {
|
||||
expr = foldAttrs (n: a: [n] ++ a) [] [
|
||||
{ a = 2; b = 7; }
|
||||
{ a = 3; c = 8; }
|
||||
];
|
||||
expected = { a = [ 2 3 ]; b = [7]; c = [8];};
|
||||
};
|
||||
|
||||
testOverridableDelayableArgsTest = {
|
||||
expr =
|
||||
let res1 = defaultOverridableDelayableArgs id {};
|
||||
res2 = defaultOverridableDelayableArgs id { a = 7; };
|
||||
res3 = let x = defaultOverridableDelayableArgs id { a = 7; };
|
||||
in (x.merge) { b = 10; };
|
||||
res4 = let x = defaultOverridableDelayableArgs id { a = 7; };
|
||||
in (x.merge) ( x: { b = 10; });
|
||||
res5 = let x = defaultOverridableDelayableArgs id { a = 7; };
|
||||
in (x.merge) ( x: { a = add x.a 3; });
|
||||
res6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = add; }; };
|
||||
y = x.merge {};
|
||||
in (y.merge) { a = 10; };
|
||||
|
||||
resRem7 = res6.replace (a : removeAttrs a ["a"]);
|
||||
|
||||
resReplace6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = add; }; };
|
||||
x2 = x.merge { a = 20; }; # now we have 27
|
||||
in (x2.replace) { a = 10; }; # and override the value by 10
|
||||
|
||||
# fixed tests (delayed args): (when using them add some comments, please)
|
||||
resFixed1 =
|
||||
let x = defaultOverridableDelayableArgs id ( x : { a = 7; c = x.fixed.b; });
|
||||
y = x.merge (x : { name = "name-${builtins.toString x.fixed.c}"; });
|
||||
in (y.merge) { b = 10; };
|
||||
strip = attrs : removeAttrs attrs ["merge" "replace"];
|
||||
in all id
|
||||
[ ((strip res1) == { })
|
||||
((strip res2) == { a = 7; })
|
||||
((strip res3) == { a = 7; b = 10; })
|
||||
((strip res4) == { a = 7; b = 10; })
|
||||
((strip res5) == { a = 10; })
|
||||
((strip res6) == { a = 17; })
|
||||
((strip resRem7) == {})
|
||||
((strip resFixed1) == { a = 7; b = 10; c =10; name = "name-10"; })
|
||||
];
|
||||
expected = true;
|
||||
};
|
||||
|
||||
testSort = {
|
||||
expr = sort builtins.lessThan [ 40 2 30 42 ];
|
||||
expected = [2 30 40 42];
|
||||
};
|
||||
|
||||
testToIntShouldConvertStringToInt = {
|
||||
expr = toInt "27";
|
||||
expected = 27;
|
||||
};
|
||||
|
||||
testToIntShouldThrowErrorIfItCouldNotConvertToInt = {
|
||||
expr = builtins.tryEval (toInt "\"foo\"");
|
||||
expected = { success = false; value = false; };
|
||||
};
|
||||
|
||||
testHasAttrByPathTrue = {
|
||||
expr = hasAttrByPath ["a" "b"] { a = { b = "yey"; }; };
|
||||
expected = true;
|
||||
};
|
||||
|
||||
testHasAttrByPathFalse = {
|
||||
expr = hasAttrByPath ["a" "b"] { a = { c = "yey"; }; };
|
||||
expected = false;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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_BUILD_HOOK=
|
||||
export NIX_CONF_DIR=$TEST_ROOT/etc
|
||||
export NIX_DB_DIR=$TEST_ROOT/db
|
||||
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
|
||||
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
|
||||
export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
|
||||
export NIX_STATE_DIR=$TEST_ROOT/var/nix
|
||||
export NIX_STORE_DIR=$TEST_ROOT/store
|
||||
export PAGER=cat
|
||||
cacheDir=$TEST_ROOT/binary-cache
|
||||
nix-store --init
|
||||
|
||||
cd ${nixpkgs}/lib/tests
|
||||
./modules.sh
|
||||
|
||||
touch $out
|
||||
'';
|
||||
}
|
||||
@@ -1,78 +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;
|
||||
|
||||
# Compute the fixed point of the given function `f`, which is usually an
|
||||
# attribute set that expects its final, non-recursive representation as an
|
||||
# argument:
|
||||
#
|
||||
# f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
|
||||
#
|
||||
# Nix evaluates this recursion until all references to `self` have been
|
||||
# resolved. At that point, the final result is returned and `f x = x` holds:
|
||||
#
|
||||
# nix-repl> fix f
|
||||
# { bar = "bar"; foo = "foo"; foobar = "foobar"; }
|
||||
#
|
||||
# See https://en.wikipedia.org/wiki/Fixed-point_combinator for further
|
||||
# details.
|
||||
fix = f: let x = f x; in x;
|
||||
|
||||
# A variant of `fix` that records the original recursive attribute set in the
|
||||
# result. This is useful in combination with the `extends` function to
|
||||
# implement deep overriding. See pkgs/development/haskell-modules/default.nix
|
||||
# for a concrete example.
|
||||
fix' = f: let x = f x // { __unfix__ = f; }; in x;
|
||||
|
||||
# Modify the contents of an explicitly recursive attribute set in a way that
|
||||
# honors `self`-references. This is accomplished with a function
|
||||
#
|
||||
# g = self: super: { foo = super.foo + " + "; }
|
||||
#
|
||||
# that has access to the unmodified input (`super`) as well as the final
|
||||
# non-recursive representation of the attribute set (`self`). `extends`
|
||||
# differs from the native `//` operator insofar as that it's applied *before*
|
||||
# references to `self` are resolved:
|
||||
#
|
||||
# nix-repl> fix (extends g f)
|
||||
# { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; }
|
||||
#
|
||||
# The name of the function is inspired by object-oriented inheritance, i.e.
|
||||
# think of it as an infix operator `g extends f` that mimics the syntax from
|
||||
# Java. It may seem counter-intuitive to have the "base class" as the second
|
||||
# argument, but it's nice this way if several uses of `extends` are cascaded.
|
||||
extends = f: rattrs: self: let super = rattrs self; in super // f self super;
|
||||
|
||||
# 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;
|
||||
|
||||
}
|
||||
264
lib/types.nix
264
lib/types.nix
@@ -1,264 +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 filterOverrides; };
|
||||
|
||||
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 = "package";
|
||||
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);
|
||||
};
|
||||
|
||||
# List or element of ...
|
||||
loeOf = elemType: mkOptionType {
|
||||
name = "element or list of ${elemType.name}s";
|
||||
check = x: isList x || elemType.check x;
|
||||
merge = loc: defs:
|
||||
let
|
||||
defs' = filterOverrides defs;
|
||||
res = (head defs').value;
|
||||
in
|
||||
if isList res then concatLists (getValues defs')
|
||||
else if lessThan 1 (length defs') then
|
||||
throw "The option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}."
|
||||
else if !isString res then
|
||||
throw "The option `${showOption loc}' does not have a string value, in ${showFiles (getFiles defs)}."
|
||||
else res;
|
||||
};
|
||||
|
||||
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: x == null || elemType.check x;
|
||||
merge = loc: defs:
|
||||
let nrNulls = count (def: def.value == null) defs; in
|
||||
if nrNulls == length defs then null
|
||||
else if nrNulls != 0 then
|
||||
throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}."
|
||||
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:
|
||||
let
|
||||
show = v:
|
||||
if builtins.isString v then ''"${v}"''
|
||||
else if builtins.isInt v then builtins.toString v
|
||||
else ''<${builtins.typeOf v}>'';
|
||||
in
|
||||
mkOptionType {
|
||||
name = "one of ${concatMapStringsSep ", " show 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
|
||||
49
maintainers/docs/bugs.txt
Normal file
49
maintainers/docs/bugs.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
*** All these bugs should be moved to JIRA (if they still exist) ***
|
||||
|
||||
|
||||
* If NIX_DEBUG is turned on (set to "1"), autoconf configure scripts
|
||||
may fail to find the correct preprocessor:
|
||||
|
||||
checking how to run the C preprocessor... /lib/cpp
|
||||
|
||||
|
||||
* When building gcc using a Nix gcc, generated libraries link against
|
||||
the libraries of the latter:
|
||||
|
||||
$ ldd /nix/store/3b1d3995c4edbf026be5c73f66f69245-gcc-3.3.3/lib/libstdc++.so
|
||||
...
|
||||
libgcc_s.so.1 => /nix/store/1f19e61d1b7051f1131f78b41b2a0e7e-gcc-3.3.2/lib/libgcc_s.so.1 (0x400de000)
|
||||
(wrong! should be .../3b1d.../lib/libgcc_s...)
|
||||
...
|
||||
|
||||
|
||||
* In libXt:
|
||||
|
||||
/bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I. -I. -DXTHREADS -DXUSE_MTSAFE_API -I/nix/store/aadf0bd4a908da11d14f6538503b8408-libX11-6.2.1/include -I/nix/store/ba366e3b944ead64ec9b0490bb615874-xproto-6.6.1/include -I./include/X11 -g -O2 -c -o ActionHook.lo `test -f 'ActionHook.c' || echo './'`ActionHook.c
|
||||
mkdir .libs
|
||||
gcc -DHAVE_CONFIG_H -I. -I. -I. -DXTHREADS -DXUSE_MTSAFE_API -I/nix/store/aadf0bd4a908da11d14f6538503b8408-libX11-6.2.1/include -I/nix/store/ba366e3b944ead64ec9b0490bb615874-xproto-6.6.1/include -I./include/X11 -g -O2 -c ActionHook.c -fPIC -DPIC -o .libs/ActionHook.o
|
||||
In file included from IntrinsicI.h:55,
|
||||
from ActionHook.c:69:
|
||||
include/X11/IntrinsicP.h:54:27: X11/Intrinsic.h: No such file or directory
|
||||
|
||||
|
||||
* Then:
|
||||
|
||||
gcc -DHAVE_CONFIG_H -I. -I. -I. -DXTHREADS -DXUSE_MTSAFE_API -I/nix/store/aadf0bd4a908da11d14f6538503b8408-libX11-6.2.1/include -I/nix/store/ba366e3b944ead64ec9b0490bb615874-xproto-6.6.1/include -I./include -I./include/X11 -g -O2 -c ActionHook.c -fPIC -DPIC -o .libs/ActionHook.o
|
||||
In file included from IntrinsicI.h:55,
|
||||
from ActionHook.c:69:
|
||||
include/X11/IntrinsicP.h:202:25: X11/ObjectP.h: No such file or directory
|
||||
|
||||
(moved to include/X11; should edit include/Makefile.am)
|
||||
|
||||
|
||||
* In gtksourceview-sharp: does the prefix patch cause problems (e.g.,
|
||||
makefile.am says "mimeinfodir should be the same as the gnome
|
||||
prefix")?
|
||||
|
||||
|
||||
* fgrep/egrep: these fail if grep is not in the $PATH.
|
||||
|
||||
|
||||
* teTeX: some programs (such as epstopdf) depend on /usr/bin/env, and
|
||||
expect perl to be in the environment.
|
||||
116
maintainers/docs/classification.txt
Normal file
116
maintainers/docs/classification.txt
Normal file
@@ -0,0 +1,116 @@
|
||||
* Classification scheme for packages
|
||||
|
||||
- many packages fall under several categories; what matters is the
|
||||
*primary* purpose of a package. For example, the libxml2 package
|
||||
builds both a library and some tools; but it's a library foremost,
|
||||
so it goes under ./development/libraries.
|
||||
|
||||
- when in doubt, refactor.
|
||||
|
||||
IF it's used to support SOFTWARE DEVELOPMENT:
|
||||
|
||||
IF it's a LIBRARY used by other packages:
|
||||
IF it's directly related to GTK:
|
||||
./development/libraries/gtk+
|
||||
ELSE
|
||||
./development/libraries
|
||||
(e.g., libxml2)
|
||||
ELSE IF it's a COMPILER:
|
||||
./development/compilers
|
||||
(e.g., gcc)
|
||||
ELSE IF it's an INTERPRETER:
|
||||
./development/interpreters
|
||||
ELSE IF it's a development TOOL (or set of):
|
||||
IF it's a PARSER GENERATOR (incl. lexers):
|
||||
./development/tools/parsing
|
||||
(e.g., bison, flex)
|
||||
ELSE IF it's a BUILD MANAGER:
|
||||
./development/tools/build-managers
|
||||
(e.g., gnumake
|
||||
ELSE
|
||||
./development/tools/misc
|
||||
(e.g., binutils)
|
||||
ELSE
|
||||
./development/misc
|
||||
|
||||
ELSE IF it's a TOOL (or set of):
|
||||
# a tool is a relatively *small* program, esp. one intented to be
|
||||
# used non-interactively
|
||||
|
||||
IF it's for NETWORKING:
|
||||
./tools/networking
|
||||
(e.g., wget)
|
||||
ELSE IF it's for TEXT PROCESSING:
|
||||
./tools/text
|
||||
(e.g., diffutils)
|
||||
ELSE IF it's a SYSTEM utility, i.e., something related or essential
|
||||
to the operation of a system:
|
||||
./tools/system
|
||||
(e.g., init)
|
||||
ELSE IF it's an ARCHIVER (which may include a compression function):
|
||||
./tools/archivers
|
||||
(e.g., zip, tar)
|
||||
ELSE IF it's a COMPRESSION program:
|
||||
./tools/compression
|
||||
(e.g., gzip, bzip2)
|
||||
ELSE IF it's a SECURITY program:
|
||||
./tools/security
|
||||
(e.g., nmap, gnupg)
|
||||
ELSE
|
||||
./tools/misc
|
||||
|
||||
ELSE IF it's a SHELL:
|
||||
|
||||
./shells
|
||||
|
||||
ELSE IF it's a SERVER:
|
||||
|
||||
IF it's a HTTP server:
|
||||
./servers/http
|
||||
(e.g., apache)
|
||||
IF it's a X11 server:
|
||||
./servers/x11
|
||||
(e.g., xfree86)
|
||||
ELSE
|
||||
./servers/misc
|
||||
|
||||
ELSE IF it's a DESKTOP ENVIRONMENT (incl. WINDOW MANAGERS):
|
||||
|
||||
./desktops
|
||||
(e.g., kde, gnome, fvwm)
|
||||
|
||||
ELSE IF it's an APPLICATION:
|
||||
# a (typically large) program with a distinct user interface,
|
||||
# primarily used interactively
|
||||
|
||||
IF it's a VERSION MANAGEMENT system:
|
||||
./applications/version-management
|
||||
ELSE IF it's for VIDEO playback/etc:
|
||||
./applications/video
|
||||
ELSE IF it's for GRAPHICS viewing/editing/etc:
|
||||
./applications/graphics
|
||||
ELSE IF it's for NETWORKING:
|
||||
IF it's a MAILREADER:
|
||||
./applications/networking/mailreaders
|
||||
IF it's a NEWSREADER:
|
||||
./applications/networking/newsreaders
|
||||
ELSE
|
||||
./applications/networking/misc
|
||||
ELSE
|
||||
./applications/misc
|
||||
|
||||
ELSE IF it's DATA (i.e., does not have a straight-forward executable semantics):
|
||||
|
||||
IF it's related to SGML/XML processing:
|
||||
IF it's a XML DTD:
|
||||
./data/sgml+xml/schemas/xml-dtd
|
||||
ELSE IF it's an XSLT stylesheet (okay, these are executable...):
|
||||
./data/sgml+xml/stylesheets/xslt
|
||||
|
||||
ELSE IF it's a GAME:
|
||||
|
||||
./games
|
||||
|
||||
ELSE:
|
||||
|
||||
./misc
|
||||
101
maintainers/docs/coding-conventions.txt
Normal file
101
maintainers/docs/coding-conventions.txt
Normal file
@@ -0,0 +1,101 @@
|
||||
Some conventions:
|
||||
|
||||
* Directories / file names: lowercase, and use dashes between words,
|
||||
no camel case. I.e., all-packages.nix, not all allPackages.nix or
|
||||
AllPackages.nix.
|
||||
|
||||
* Don't use TABs. Everybody has different TAB settings so it's asking
|
||||
for trouble.
|
||||
|
||||
* Use 2 spaces of indentation per indentation level in Nix
|
||||
expressions, 4 spaces in shell scripts. (Maybe 2 is too low, but
|
||||
for consistency's sake it should be the same. Certainly indentation
|
||||
should be consistent within a single file.)
|
||||
|
||||
* Use lowerCamelCase for variable names, not UpperCamelCase.
|
||||
|
||||
* Function calls with attribute set arguments are written as
|
||||
|
||||
foo {
|
||||
arg = ...;
|
||||
}
|
||||
|
||||
not
|
||||
|
||||
foo
|
||||
{
|
||||
arg = ...;
|
||||
}
|
||||
|
||||
Also fine is
|
||||
|
||||
foo { arg = ...; }
|
||||
|
||||
if it's a short call.
|
||||
|
||||
* In attribute sets or lists that span multiple lines, the attribute
|
||||
names or list elements should be aligned:
|
||||
|
||||
# A long list.
|
||||
list = [
|
||||
elem1
|
||||
elem2
|
||||
elem3
|
||||
];
|
||||
|
||||
# A long attribute set.
|
||||
attrs = {
|
||||
attr1 = short_expr;
|
||||
attr2 =
|
||||
if true then big_expr else big_expr;
|
||||
};
|
||||
|
||||
* Short lists or attribute sets can be written on one line:
|
||||
|
||||
# A short list.
|
||||
list = [ elem1 elem2 elem3 ];
|
||||
|
||||
# A short set.
|
||||
attrs = { x = 1280; y = 1024; };
|
||||
|
||||
* Breaking in the middle of a function argument can give hard-to-read
|
||||
code, like
|
||||
|
||||
someFunction { x = 1280;
|
||||
y = 1024; } otherArg
|
||||
yetAnotherArg
|
||||
|
||||
(especially if the argument is very large, spanning multiple lines).
|
||||
|
||||
Better:
|
||||
|
||||
someFunction
|
||||
{ x = 1280; y = 1024; }
|
||||
otherArg
|
||||
yetAnotherArg
|
||||
|
||||
or
|
||||
|
||||
let res = { x = 1280; y = 1024; };
|
||||
in someFunction res otherArg yetAnotherArg
|
||||
|
||||
* The bodies of functions, asserts, and withs are not indented, so
|
||||
|
||||
assert system == "i686-linux";
|
||||
stdenv.mkDerivation { ...
|
||||
|
||||
not
|
||||
|
||||
assert system == "i686-linux";
|
||||
stdenv.mkDerivation { ...
|
||||
|
||||
* Function formal arguments are written as:
|
||||
|
||||
{arg1, arg2, arg3}:
|
||||
|
||||
but if they don't fit on one line they're written as:
|
||||
|
||||
{ arg1, arg2, arg3
|
||||
, arg4, ...
|
||||
, argN
|
||||
}:
|
||||
31
maintainers/docs/create-new-static-env
Normal file
31
maintainers/docs/create-new-static-env
Normal file
@@ -0,0 +1,31 @@
|
||||
Creating a new static stdenv
|
||||
----------------------------
|
||||
|
||||
When Nix is ported to a new (Linux) platform and you want to have a completely
|
||||
pure setup for the stdenv (for example for NixOS) it is necessary to rebuild
|
||||
the static tools.
|
||||
|
||||
The challenge is that there is no Nix environment yet, for bootstrapping.
|
||||
The first task is to create all the tools that are necessary. For most tools
|
||||
there are ready made Nix expressions.
|
||||
|
||||
|
||||
GCC
|
||||
|
||||
There is an expression gcc-static-3.4. Depending on whether or not you already
|
||||
have an environment built with Nix (x86-linux: yes, rest: not yet) you should
|
||||
set the noSysDirs parameter in all-packages.nix. If there is an environment,
|
||||
leave it, but if the system is still impure (like most systems), set noSysDirs
|
||||
to false.
|
||||
|
||||
bash
|
||||
|
||||
There is an expression for bash-static. Simply build it.
|
||||
|
||||
bzip2
|
||||
|
||||
There is an expression for bzip2-static. Simply build it.
|
||||
|
||||
findutils
|
||||
|
||||
There is an expression for findutils-static. Simply build it.
|
||||
@@ -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
|
||||
35
maintainers/docs/static-initial-env
Normal file
35
maintainers/docs/static-initial-env
Normal file
@@ -0,0 +1,35 @@
|
||||
Upgrading the standard initial environment
|
||||
|
||||
For Nix on i686-linux we make use of an environment of statically linked
|
||||
tools (see $nixpkgs/stdenv/linux). The first version of these tools were
|
||||
compiled outside of Nix, in an impure environment. They are used as some
|
||||
magical ingredient to make everything work. To keep these tools more in
|
||||
synchronization with the rest of nixpkgs and to make porting of nixpkgs
|
||||
to other platforms easier the static versions are now also built with Nix
|
||||
and nixpkgs.
|
||||
|
||||
The tools can be found in nixpkgs in:
|
||||
|
||||
- shells/bash-static
|
||||
- tools/networking/curl-diet
|
||||
- tools/archivers/gnutar-diet
|
||||
- tools/compression/gzip-diet
|
||||
- tools/compression/bzip2-static
|
||||
- tools/text/gnused-diet
|
||||
- tools/text/diffutils-diet
|
||||
- tools/text/gnupatch-diet
|
||||
- tools/misc/findutils-static
|
||||
|
||||
and
|
||||
- development/compilers/gcc-static-3.4
|
||||
|
||||
Most packages are compiled with dietlibc, an alternate C library, apart
|
||||
from bash and findutils, which are statically linked to glibc. The reason
|
||||
we chose dietlibc has various reasons. First of all, curl cannot be built
|
||||
statically with glibc. If we do, we get a static binary, but it cannot resolve
|
||||
hostnames to IP addresses. glibc dynamically loads functionality at runtime
|
||||
to do resolving. When linking with dietlibc this doesn't happen.
|
||||
|
||||
The static tools are not used as part of the input hashing (see Eelco's
|
||||
PhD thesis, paragraph 5.4.1), so changing them does not change anything and
|
||||
will not force a massive rebuild.
|
||||
12
maintainers/docs/todo.txt
Normal file
12
maintainers/docs/todo.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
* Patch development/tools/misc/libtool not to search standard
|
||||
directories for libraries (like setup.sh does now). [do we want
|
||||
this?]
|
||||
|
||||
* Inform freedesktop people that Xaw requires Xpm.
|
||||
|
||||
* After building gcc, filter out references to /tmp/nix... in
|
||||
.../lib/libsupc++.la and .../lib/libstdc++.la
|
||||
|
||||
* Add gettext to glib propagatedBuildInputs? Glib's `gi18n.h' doesn't
|
||||
seem to like Glibc `libintl.h'; needs the gettext one instead.
|
||||
[Move from libbonoboui]
|
||||
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,18 +0,0 @@
|
||||
/* Helper expression for copy-tarballs. This returns (nearly) all
|
||||
tarballs used the free packages in Nixpkgs.
|
||||
|
||||
Typical usage:
|
||||
|
||||
$ copy-tarballs.pl --expr 'import <nixpkgs/maintainers/scripts/all-tarballs.nix>'
|
||||
*/
|
||||
|
||||
removeAttrs (import ../../pkgs/top-level/release.nix
|
||||
{ # Don't apply ‘hydraJob’ to jobs, because then we can't get to the
|
||||
# dependency graph.
|
||||
scrubJobs = false;
|
||||
# No need to evaluate on i686.
|
||||
supportedSystems = [ "x86_64-linux" ];
|
||||
})
|
||||
[ # Remove jobs whose evaluation depends on a writable Nix store.
|
||||
"tarball" "unstable"
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user