mirror of
https://github.com/CHN-beta/nixpkgs.git
synced 2026-01-13 03:22:53 +08:00
Compare commits
1 Commits
staging.pa
...
0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f61e1b99f |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,13 +0,0 @@
|
||||
*~
|
||||
,*
|
||||
.*.swp
|
||||
.*.swo
|
||||
result
|
||||
result-*
|
||||
/doc/NEWS.html
|
||||
/doc/NEWS.txt
|
||||
/doc/manual.html
|
||||
/doc/manual.pdf
|
||||
.version-suffix
|
||||
|
||||
.DS_Store
|
||||
@@ -1,5 +0,0 @@
|
||||
language: python
|
||||
python: "3.4"
|
||||
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
|
||||
31
COPYING
31
COPYING
@@ -1,31 +0,0 @@
|
||||
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
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
======================================================================
|
||||
|
||||
Note: the license above does not apply to the packages built by the
|
||||
Nix Packages collection, merely to the package descriptions (i.e., Nix
|
||||
expressions, build scripts, etc.). Also, the license does not apply
|
||||
to some of the binaries used for bootstrapping Nixpkgs (e.g.,
|
||||
pkgs/stdenv/linux/tools/bash). It also might not apply to patches
|
||||
included in Nixpkgs, which may be derivative works of the packages to
|
||||
which they apply. The aforementioned artifacts are all covered by the
|
||||
licenses of the respective packages.
|
||||
10
README.md
10
README.md
@@ -1,10 +0,0 @@
|
||||
Nixpkgs is a collection of packages for [Nix](https://nixos.org/nix/) package
|
||||
manager. Nixpkgs also includes [NixOS](https://nixos.org/nixos/) linux distribution source code.
|
||||
|
||||
* [NixOS installation instructions](https://nixos.org/nixos/manual/#ch-installation)
|
||||
* [Manual (How to write packages for Nix)](https://nixos.org/nixpkgs/manual/)
|
||||
* [Manual (NixOS)](https://nixos.org/nixos/manual/)
|
||||
* [Continuous build](https://hydra.nixos.org/jobset/nixos/trunk-combined)
|
||||
* [Tests](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
|
||||
* [Mailing list](https://lists.science.uu.nl/mailman/listinfo/nix-dev)
|
||||
* [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)
|
||||
@@ -1,7 +0,0 @@
|
||||
if ! builtins ? nixVersion || builtins.compareVersions "1.7" builtins.nixVersion == 1 then
|
||||
|
||||
abort "This version of Nixpkgs requires Nix >= 1.7, please upgrade!"
|
||||
|
||||
else
|
||||
|
||||
import ./pkgs/top-level/all-packages.nix
|
||||
27
doc/Makefile
Normal file
27
doc/Makefile
Normal file
@@ -0,0 +1,27 @@
|
||||
ENV = SGML_CATALOG_FILES=$(docbookcatalog)
|
||||
|
||||
XMLLINT = $(ENV) xmllint --catalogs
|
||||
XSLTPROC = $(ENV) 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
|
||||
|
||||
NEWS_OPTS = \
|
||||
--stringparam generate.toc "article nop" \
|
||||
--stringparam section.autolabel.max.depth 0 \
|
||||
--stringparam header.rule 0
|
||||
|
||||
all: NEWS.html NEWS.txt
|
||||
|
||||
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
|
||||
@@ -1,603 +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><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><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>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><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>
|
||||
(including <emphasis>window managers</emphasis>):</term>
|
||||
<listitem>
|
||||
<para><filename>desktops</filename> (e.g. <filename>kde</filename>, <filename>gnome</filename>, <filename>enlightenment</filename>)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>If it’s 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>
|
||||
|
||||
|
||||
</chapter>
|
||||
@@ -1,19 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-contributing">
|
||||
|
||||
<title>Contributing</title>
|
||||
|
||||
<para>If you make modifications to the manual, it's important to build the manual before contributing:</para>
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem><para><command>$ git clone git://github.com/NixOS/nixpkgs.git</command></para></listitem>
|
||||
|
||||
<listitem><para><command>$ nix-build -A manual nixpkgs/pkgs/top-level/release.nix</command></para></listitem>
|
||||
|
||||
<listitem><para>Inside the built derivation you shall see <literal>manual/index.html</literal> file.</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</chapter>
|
||||
@@ -1,42 +0,0 @@
|
||||
with import ./.. { };
|
||||
with lib;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-manual";
|
||||
|
||||
sources = sourceFilesBySuffices ./. [".xml"];
|
||||
|
||||
buildInputs = [ libxml2 libxslt ];
|
||||
|
||||
xsltFlags = ''
|
||||
--param section.autolabel 1
|
||||
--param section.label.includes.component.label 1
|
||||
--param html.stylesheet 'style.css'
|
||||
--param xref.with.number.and.title 1
|
||||
--param toc.section.depth 3
|
||||
--param admon.style '''
|
||||
--param callout.graphics.extension '.gif'
|
||||
'';
|
||||
|
||||
buildCommand = ''
|
||||
ln -s $sources/*.xml . # */
|
||||
|
||||
echo ${nixpkgsVersion} > .version
|
||||
|
||||
xmllint --noout --nonet --xinclude --noxincludenode \
|
||||
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
|
||||
manual.xml
|
||||
|
||||
dst=$out/share/doc/nixpkgs
|
||||
mkdir -p $dst
|
||||
xsltproc $xsltFlags --nonet --xinclude \
|
||||
--output $dst/manual.html \
|
||||
${docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \
|
||||
./manual.xml
|
||||
|
||||
cp ${./style.css} $dst/style.css
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<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://hydra.nixos.org/job/nix/trunk/tarball/latest/download-by-type/doc/manual">Nix
|
||||
manual</link>.</para>
|
||||
|
||||
<para>This manual does not describe the syntax and semantics of the
|
||||
Nix expression language, which are given in the Nix manual in the
|
||||
<link
|
||||
xlink:href="http://hydra.nixos.org/job/nix/trunk/tarball/latest/download-by-type/doc/manual/#chap-writing-nix-expressions">chapter
|
||||
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>
|
||||
@@ -1,812 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-language-support">
|
||||
|
||||
<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 xml:id="ssec-language-perl"><title>Perl</title>
|
||||
|
||||
<para>Nixpkgs provides a function <varname>buildPerlPackage</varname>,
|
||||
a generic package builder function for any Perl package that has a
|
||||
standard <varname>Makefile.PL</varname>. It’s implemented in <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/perl-modules/generic"><filename>pkgs/development/perl-modules/generic</filename></link>.</para>
|
||||
|
||||
<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><title>Generation from CPAN</title>
|
||||
|
||||
<para>Nix expressions for Perl packages can be generated (almost)
|
||||
automatically from CPAN. This is done by the program
|
||||
<command>nix-generate-from-cpan</command>, which can be installed
|
||||
as follows:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-env -i nix-generate-from-cpan
|
||||
</screen>
|
||||
|
||||
<para>This program takes a Perl module name, looks it up on CPAN,
|
||||
fetches and unpacks the corresponding package, and prints a Nix
|
||||
expression on standard output. For example:
|
||||
|
||||
<screen>
|
||||
$ nix-generate-from-cpan XML::Simple
|
||||
XMLSimple = buildPerlPackage {
|
||||
name = "XML-Simple-2.20";
|
||||
src = fetchurl {
|
||||
url = mirror://cpan/authors/id/G/GR/GRANTM/XML-Simple-2.20.tar.gz;
|
||||
sha256 = "5cff13d0802792da1eb45895ce1be461903d98ec97c9c953bc8406af7294434a";
|
||||
};
|
||||
propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ];
|
||||
meta = {
|
||||
description = "Easily read/write XML (esp config files)";
|
||||
license = "perl";
|
||||
};
|
||||
};
|
||||
</screen>
|
||||
|
||||
The output can be pasted into
|
||||
<filename>pkgs/top-level/perl-packages.nix</filename> or wherever else
|
||||
you need it.</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="python"><title>Python</title>
|
||||
|
||||
<para>
|
||||
Currently supported interpreters are <varname>python26</varname>, <varname>python27</varname>,
|
||||
<varname>python32</varname>, <varname>python33</varname>, <varname>python34</varname>
|
||||
and <varname>pypy</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python</varname> is an alias of <varname>python27</varname> and <varname>python3</varname> is an alias of <varname>python34</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<varname>python26</varname> and <varname>python27</varname> do not include modules that require
|
||||
external dependencies (to reduce dependency bloat). Following modules need to be added as
|
||||
<varname>buildInput</varname> explicitly:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para><varname>python.modules.bsddb</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.curses</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.curses_panel</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.crypt</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.gdbm</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.sqlite3</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.tkinter</varname></para></listitem>
|
||||
<listitem><para><varname>python.modules.readline</varname></para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For convenience <varname>python27Full</varname> and <varname>python26Full</varname>
|
||||
are provided with all modules included.</para>
|
||||
|
||||
<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.libPrefix}/site-packages</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="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="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>python32Packages</varname>, <varname>python33Packages</varname>,
|
||||
<varname>python34Packages</varname> and <varname>pypyPackages</varname>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>buildPythonPackage</function> mainly does four things:
|
||||
|
||||
<orderedlist>
|
||||
<listitem><para>
|
||||
In the <varname>configurePhase</varname>, it patches
|
||||
<literal>setup.py</literal> to always include setuptools before
|
||||
distutils for monkeypatching machinery to take place.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>buildPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py build ...</literal>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>installPhase</varname>, it calls
|
||||
<literal>${python.interpreter} setup.py install ...</literal>
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
In the <varname>postFixup</varname> phase, <literal>wrapPythonPrograms</literal>
|
||||
bash function is called to wrap all programs in <filename>$out/bin/*</filename>
|
||||
directory to include <literal>$PYTHONPATH</literal> and <literal>$PATH</literal>
|
||||
environment variables.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>By default <varname>doCheck = true</varname> is set and tests are run with
|
||||
<literal>${python.interpreter} setup.py test</literal> command in <varname>checkPhase</varname>.</para>
|
||||
|
||||
<para><varname>propagatedBuildInputs</varname> packages are propagated to user environment.</para>
|
||||
|
||||
<para>
|
||||
By default <varname>meta.platforms</varname> is set to the same value
|
||||
as the interpreter unless overriden otherwise.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>
|
||||
<varname>buildPythonPackage</varname> parameters
|
||||
(all parameters from <varname>mkDerivation</varname> function are still supported)
|
||||
</title>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>namePrefix</varname></term>
|
||||
<listitem><para>
|
||||
Prepended text to <varname>${name}</varname> parameter.
|
||||
Defaults to <literal>"python3.3-"</literal> for Python 3.3, etc. Set it to
|
||||
<literal>""</literal>
|
||||
if you're packaging an application or a command line tool.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>disabled</varname></term>
|
||||
<listitem><para>
|
||||
If <varname>true</varname>, package is not build for
|
||||
particular python interpreter version. Grep around
|
||||
<filename>pkgs/top-level/python-packages.nix</filename>
|
||||
for examples.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>setupPyInstallFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py install</command> command.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>setupPyBuildFlags</varname></term>
|
||||
<listitem><para>
|
||||
List of flags passed to <command>setup.py build</command> command.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>pythonPath</varname></term>
|
||||
<listitem><para>
|
||||
List of packages to be added into <literal>$PYTHONPATH</literal>.
|
||||
Packages in <varname>pythonPath</varname> are not propagated into user environment
|
||||
(contrary to <varname>propagatedBuildInputs</varname>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>preShellHook</varname></term>
|
||||
<listitem><para>
|
||||
Hook to execute commands before <varname>shellHook</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>postShellHook</varname></term>
|
||||
<listitem><para>
|
||||
Hook to execute commands after <varname>shellHook</varname>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>distutilsExtraCfg</varname></term>
|
||||
<listitem><para>
|
||||
Extra lines passed to <varname>[easy_install]</varname> section of
|
||||
<filename>distutils.cfg</filename> (acts as global setup.cfg
|
||||
configuration).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="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>
|
||||
|
||||
<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="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="python-development"><title>Development</title>
|
||||
|
||||
<para>
|
||||
To develop Python packages <function>buildPythonPackage</function> has
|
||||
additional logic inside <varname>shellPhase</varname> to run
|
||||
<command>${python.interpreter} setup.py develop</command> for the package.
|
||||
</para>
|
||||
|
||||
<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="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="python-build-env" /> to create self-contained
|
||||
interpreter with a set of packages.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="python-contrib"><title>Contributing guidelines</title>
|
||||
<para>
|
||||
Following rules are desired to be respected:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>
|
||||
Make sure package builds for all python interpreters. Use <varname>disabled</varname> argument to
|
||||
<function>buildPythonPackage</function> to set unsupported interpreters.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
If tests need to be disabled for a package, make sure you leave a comment about reasoning.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
Packages in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
|
||||
are sorted quasi-alphabetically to avoid merge conflicts.
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-language-ruby"><title>Ruby</title>
|
||||
<para>For example, to package yajl-ruby package, use gem-nix:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-env -i gem-nix
|
||||
$ gem-nix --no-user-install --nix-file=pkgs/development/interpreters/ruby/generated.nix yajl-ruby
|
||||
$ nix-build -A rubyLibs.yajl-ruby
|
||||
</screen>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-language-go"><title>Go</title>
|
||||
<para>To extract dependency information from a Go package in automated way use <link xlink:href="https://github.com/cstrahan/go2nix">go2nix</link>.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-language-java"><title>Java</title>
|
||||
|
||||
<para>Ant-based Java packages are typically built from source as follows:
|
||||
|
||||
<programlisting>
|
||||
stdenv.mkDerivation {
|
||||
name = "...";
|
||||
src = fetchurl { ... };
|
||||
|
||||
buildInputs = [ jdk ant ];
|
||||
|
||||
buildPhase = "ant";
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
Note that <varname>jdk</varname> is an alias for the OpenJDK.</para>
|
||||
|
||||
<para>JAR files that are intended to be used by other packages should
|
||||
be installed in <filename>$out/share/java</filename>. The OpenJDK has
|
||||
a stdenv setup hook that adds any JARs in the
|
||||
<filename>share/java</filename> directories of the build inputs to the
|
||||
<envar>CLASSPATH</envar> environment variable. For instance, if the
|
||||
package <literal>libfoo</literal> installs a JAR named
|
||||
<filename>foo.jar</filename> in its <filename>share/java</filename>
|
||||
directory, and another package declares the attribute
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ jdk libfoo ];
|
||||
</programlisting>
|
||||
|
||||
then <envar>CLASSPATH</envar> will be set to
|
||||
<filename>/nix/store/...-libfoo/share/java/foo.jar</filename>.</para>
|
||||
|
||||
<para>Private JARs
|
||||
should be installed in a location like
|
||||
<filename>$out/share/<replaceable>package-name</replaceable></filename>.</para>
|
||||
|
||||
<para>If your Java package provides a program, you need to generate a
|
||||
wrapper script to run it using the OpenJRE. You can use
|
||||
<literal>makeWrapper</literal> for this:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ makeWrapper ];
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper ${jre}/bin/java $out/bin/foo \
|
||||
--add-flags "-cp $out/share/java/foo.jar org.foo.Main"
|
||||
'';
|
||||
</programlisting>
|
||||
|
||||
Note the use of <literal>jre</literal>, which is the part of the
|
||||
OpenJDK package that contains the Java Runtime Environment. By using
|
||||
<literal>${jre}/bin/java</literal> instead of
|
||||
<literal>${jdk}/bin/java</literal>, you prevent your package from
|
||||
depending on the JDK at runtime.</para>
|
||||
|
||||
<para>It is possible to use a different Java compiler than
|
||||
<command>javac</command> from the OpenJDK. For instance, to use the
|
||||
Eclipse Java Compiler:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ jre ant ecj ];
|
||||
</programlisting>
|
||||
|
||||
(Note that here you don’t need the full JDK as an input, but just the
|
||||
JRE.) The ECJ has a stdenv setup hook that sets some environment
|
||||
variables to cause Ant to use ECJ, but this doesn’t work with all Ant
|
||||
files. Similarly, you can use the GNU Java Compiler:
|
||||
|
||||
<programlisting>
|
||||
buildInputs = [ gcj ant ];
|
||||
</programlisting>
|
||||
|
||||
Here, Ant will automatically use <command>gij</command> (the GNU Java
|
||||
Runtime) instead of the OpenJRE.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-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="ssec-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>
|
||||
|
||||
<section xml:id="ssec-language-coq"><title>Coq</title>
|
||||
<para>
|
||||
Coq libraries should be installed in
|
||||
<literal>$(out)/lib/coq/${coq.coq-version}/user-contrib/</literal>.
|
||||
Such directories are automatically added to the
|
||||
<literal>$COQPATH</literal> environment variable by the hook defined
|
||||
in the Coq derivation.
|
||||
</para>
|
||||
<para>
|
||||
Some libraries require OCaml and sometimes also Camlp5. The exact
|
||||
versions that were used to build Coq are saved in the
|
||||
<literal>coq.ocaml</literal> and <literal>coq.camlp5</literal>
|
||||
attributes.
|
||||
</para>
|
||||
<para>
|
||||
Here is a simple package example. It is a pure Coq library, thus it
|
||||
only depends on Coq. Its <literal>makefile</literal> has been
|
||||
generated using <literal>coq_makefile</literal> so we only have to
|
||||
set the <literal>$COQLIB</literal> variable at install time.
|
||||
</para>
|
||||
<programlisting>
|
||||
{stdenv, fetchurl, coq}:
|
||||
stdenv.mkDerivation {
|
||||
src = fetchurl {
|
||||
url = http://coq.inria.fr/pylons/contribs/files/Karatsuba/v8.4/Karatsuba.tar.gz;
|
||||
sha256 = "0ymfpv4v49k4fm63nq6gcl1hbnnxrvjjp7yzc4973n49b853c5b1";
|
||||
};
|
||||
|
||||
name = "coq-karatsuba";
|
||||
|
||||
buildInputs = [ coq ];
|
||||
|
||||
installFlags = "COQLIB=$(out)/lib/coq/${coq.coq-version}/";
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<!--
|
||||
<section><title>Haskell</title>
|
||||
|
||||
<para>TODO</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>TeX / LaTeX</title>
|
||||
|
||||
<para>* Special support for building TeX documents</para>
|
||||
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
</chapter>
|
||||
@@ -1,21 +0,0 @@
|
||||
<book xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<info>
|
||||
|
||||
<title>Nixpkgs Contributors Guide</title>
|
||||
|
||||
<subtitle>Version <xi:include href=".version" parse="text" /></subtitle>
|
||||
|
||||
</info>
|
||||
|
||||
<xi:include href="introduction.xml" />
|
||||
<xi:include href="quick-start.xml" />
|
||||
<xi:include href="stdenv.xml" />
|
||||
<xi:include href="meta.xml" />
|
||||
<xi:include href="language-support.xml" />
|
||||
<xi:include href="package-notes.xml" />
|
||||
<xi:include href="coding-conventions.xml" />
|
||||
<xi:include href="contributing.xml" />
|
||||
|
||||
</book>
|
||||
291
doc/meta.xml
291
doc/meta.xml
@@ -1,291 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-meta">
|
||||
|
||||
<title>Meta-attributes</title>
|
||||
|
||||
<para>Nix packages can declare <emphasis>meta-attributes</emphasis>
|
||||
that contain information about a package such as a description, its
|
||||
homepage, its license, and so on. For instance, the GNU Hello package
|
||||
has a <varname>meta</varname> declaration like this:
|
||||
|
||||
<programlisting>
|
||||
meta = {
|
||||
description = "A program that produces a familiar, friendly greeting";
|
||||
longDescription = ''
|
||||
GNU Hello is a program that prints "Hello, world!" when you run it.
|
||||
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;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<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>
|
||||
|
||||
<para>The meta-attributes of a package can be queried from the
|
||||
command-line using <command>nix-env</command>:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa hello --meta --json
|
||||
{
|
||||
"hello": {
|
||||
"meta": {
|
||||
"description": "A program that produces a familiar, friendly greeting",
|
||||
"homepage": "http://www.gnu.org/software/hello/manual/",
|
||||
"license": {
|
||||
"fullName": "GNU General Public License version 3 or later",
|
||||
"shortName": "GPLv3+",
|
||||
"url": "http://www.fsf.org/licensing/licenses/gpl.html"
|
||||
},
|
||||
"longDescription": "GNU Hello is a program that prints \"Hello, world!\" when you run it.\nIt is fully customizable.\n",
|
||||
"maintainers": [
|
||||
"Ludovic Court\u00e8s <ludo@gnu.org>"
|
||||
],
|
||||
"platforms": [
|
||||
"i686-linux",
|
||||
"x86_64-linux",
|
||||
"armv5tel-linux",
|
||||
"armv7l-linux",
|
||||
"mips64el-linux",
|
||||
"x86_64-darwin",
|
||||
"i686-cygwin",
|
||||
"i686-freebsd",
|
||||
"x86_64-freebsd",
|
||||
"i686-openbsd",
|
||||
"x86_64-openbsd"
|
||||
],
|
||||
"position": "/home/user/dev/nixpkgs/pkgs/applications/misc/hello/ex-2/default.nix:14"
|
||||
},
|
||||
"name": "hello-2.9",
|
||||
"system": "x86_64-linux"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</screen>
|
||||
|
||||
<command>nix-env</command> knows about the
|
||||
<varname>description</varname> field specifically:
|
||||
|
||||
<screen>
|
||||
$ nix-env -qa hello --description
|
||||
hello-2.3 A program that produces a familiar, friendly greeting
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<section><title>Standard meta-attributes</title>
|
||||
|
||||
<para>It is expected that each meta-attribute is one of the following:</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>description</varname></term>
|
||||
<listitem><para>A short (one-line) description of the package.
|
||||
This is shown by <command>nix-env -q --description</command> and
|
||||
also on the Nixpkgs release pages.</para>
|
||||
|
||||
<para>Don’t include a period at the end. Don’t include newline
|
||||
characters. Capitalise the first character. For brevity, don’t
|
||||
repeat the name of package — just describe what it does.</para>
|
||||
|
||||
<para>Wrong: <literal>"libpng is a library that allows you to decode PNG images."</literal></para>
|
||||
|
||||
<para>Right: <literal>"A library for decoding PNG images"</literal></para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>longDescription</varname></term>
|
||||
<listitem><para>An arbitrarily long description of the
|
||||
package.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>version</varname></term>
|
||||
<listitem><para>Package version.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>branch</varname></term>
|
||||
<listitem><para>Release branch. Used to specify that a package is not
|
||||
going to receive updates that are not in this branch; for example, Linux
|
||||
kernel 3.0 is supposed to be updated to 3.0.X, not 3.1.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>homepage</varname></term>
|
||||
<listitem><para>The package’s homepage. Example:
|
||||
<literal>http://www.gnu.org/software/hello/manual/</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>downloadPage</varname></term>
|
||||
<listitem><para>The page where a link to the current version can be found. Example:
|
||||
<literal>http://ftp.gnu.org/gnu/hello/</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>license</varname></term>
|
||||
<listitem><para>The license 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>. Example:
|
||||
<literal>stdenv.lib.licenses.gpl3</literal>. 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>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>priority</varname></term>
|
||||
<listitem><para>The <emphasis>priority</emphasis> of the package,
|
||||
used by <command>nix-env</command> to resolve file name conflicts
|
||||
between packages. See the Nix manual page for
|
||||
<command>nix-env</command> for details. Example:
|
||||
<literal>"10"</literal> (a low-priority
|
||||
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>
|
||||
|
||||
<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.
|
||||
|
||||
A few generic options are available, although it's typically better
|
||||
to indicate the specific license:
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>free</varname></term>
|
||||
<listitem><para>Catch-all for free 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
|
||||
<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
|
||||
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
|
||||
cannot be included in the Nixpkgs channel.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<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
|
||||
channel.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<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
|
||||
cares whether firmware is free.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</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.
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-package-notes">
|
||||
|
||||
<title>Package Notes</title>
|
||||
|
||||
<para>This chapter contains information about how to use and maintain
|
||||
the Nix expressions for a number of specific packages, such as the
|
||||
Linux kernel or X.org.</para>
|
||||
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<section xml:id="sec-linux-kernel">
|
||||
|
||||
<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>
|
||||
|
||||
<para>The function that builds the kernel has an argument
|
||||
<varname>kernelPatches</varname> which should be a list of
|
||||
<literal>{name, patch, extraConfig}</literal> attribute sets, where
|
||||
<varname>name</varname> is the name of the patch (which is included in
|
||||
the kernel’s <varname>meta.description</varname> attribute),
|
||||
<varname>patch</varname> is the patch itself (possibly compressed),
|
||||
and <varname>extraConfig</varname> (optional) is a string specifying
|
||||
extra options to be concatenated to the kernel configuration file
|
||||
(<filename>.config</filename>).</para>
|
||||
|
||||
<para>The kernel derivation exports an attribute
|
||||
<varname>features</varname> specifying whether optional functionality
|
||||
is or isn’t enabled. This is used in NixOS to implement
|
||||
kernel-specific behaviour. For instance, if the kernel has the
|
||||
<varname>iwlwifi</varname> feature (i.e. has built-in support for
|
||||
Intel wireless chipsets), then NixOS doesn’t have to build the
|
||||
external <varname>iwlwifi</varname> package:
|
||||
|
||||
<programlisting>
|
||||
modulesTree = [kernel]
|
||||
++ pkgs.lib.optional (!kernel.features ? iwlwifi) kernelPackages.iwlwifi
|
||||
++ ...;
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>How to add a new (major) version of the Linux kernel to Nixpkgs:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Copy 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>
|
||||
|
||||
<listitem>
|
||||
<para>Add the new kernel to <filename>all-packages.nix</filename>
|
||||
(e.g., create an attribute
|
||||
<varname>kernel_2_6_22</varname>).</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Now we’re going to update the kernel configuration. First
|
||||
unpack the kernel. Then for each supported platform
|
||||
(<literal>i686</literal>, <literal>x86_64</literal>,
|
||||
<literal>uml</literal>) do the following:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Make an copy 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>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Copy the config file for this platform
|
||||
(e.g. <filename>config-2.6.22-i686-smp</filename>) to
|
||||
<filename>.config</filename> in the kernel source tree.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Run <literal>make oldconfig
|
||||
ARCH=<replaceable>{i386,x86_64,um}</replaceable></literal>
|
||||
and answer all questions. (For the uml configuration, also
|
||||
add <literal>SHELL=bash</literal>.) Make sure to keep the
|
||||
configuration consistent between platforms (i.e. don’t
|
||||
enable some feature on <literal>i686</literal> and disable
|
||||
it on <literal>x86_64</literal>).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If needed you can also run <literal>make
|
||||
menuconfig</literal>:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i ncurses
|
||||
$ export NIX_CFLAGS_LINK=-lncurses
|
||||
$ make menuconfig ARCH=<replaceable>arch</replaceable></screen>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Copy <filename>.config</filename> over the new config
|
||||
file (e.g. <filename>config-2.6.22-i686-smp</filename>).</para>
|
||||
</listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Test building the kernel: <literal>nix-build -A
|
||||
kernel_2_6_22</literal>. If it compiles, ship it! For extra
|
||||
credit, try booting NixOS with it.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>It may be that the new kernel requires updating the external
|
||||
kernel modules and kernel-dependent packages listed in the
|
||||
<varname>kernelPackagesFor</varname> function in
|
||||
<filename>all-packages.nix</filename> (such as the NVIDIA drivers,
|
||||
AUFS, etc.). If the updated packages aren’t backwards compatible
|
||||
with older kernels, you may need to keep the older versions
|
||||
around.</para>
|
||||
</listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<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>
|
||||
|
||||
<para>The generator is invoked as follows:
|
||||
|
||||
<screen>
|
||||
$ cd pkgs/servers/x11/xorg
|
||||
$ cat tarballs-7.5.list extra.list old.list \
|
||||
| perl ./generate-expr-from-tarballs.pl
|
||||
</screen>
|
||||
|
||||
For each of the tarballs in the <filename>.list</filename> files, the
|
||||
script downloads it, unpacks it, and searches its
|
||||
<filename>configure.ac</filename> and <filename>*.pc.in</filename>
|
||||
files for dependencies. This information is used to generate
|
||||
<filename>default.nix</filename>. The generator caches downloaded
|
||||
tarballs between runs. Pay close attention to the <literal>NOT FOUND:
|
||||
<replaceable>name</replaceable></literal> messages at the end of the
|
||||
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
|
||||
tarballs in a X.org release. It can be generated like this:
|
||||
|
||||
<screen>
|
||||
$ export i="mirror://xorg/X11R7.4/src/everything/"
|
||||
$ cat $(PRINT_PATH=1 nix-prefetch-url $i | tail -n 1) \
|
||||
| perl -e 'while (<>) { if (/(href|HREF)="([^"]*.bz2)"/) { print "$ENV{'i'}$2\n"; }; }' \
|
||||
| sort > tarballs-7.4.list
|
||||
</screen>
|
||||
|
||||
<filename>extra.list</filename> contains libraries that aren’t part of
|
||||
X.org proper, but are closely related to it, such as
|
||||
<literal>libxcb</literal>. <filename>old.list</filename> contains
|
||||
some packages that were removed from X.org, but are still needed by
|
||||
some people or by other packages (such as
|
||||
<varname>imake</varname>).</para>
|
||||
|
||||
<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>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<!--
|
||||
<section>
|
||||
<title>Gnome</title>
|
||||
<para>* Expression is auto-generated</para>
|
||||
<para>* How to update</para>
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
<!--============================================================-->
|
||||
|
||||
<!--
|
||||
<section>
|
||||
<title>GCC</title>
|
||||
<para>…</para>
|
||||
</section>
|
||||
-->
|
||||
|
||||
|
||||
</chapter>
|
||||
@@ -1,223 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="chap-quick-start">
|
||||
|
||||
<title>Quick Start to Adding a Package</title>
|
||||
|
||||
<para>To add a package to Nixpkgs:
|
||||
|
||||
<orderedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Checkout the Nixpkgs source tree:
|
||||
|
||||
<screen>
|
||||
$ git clone git://github.com/NixOS/nixpkgs.git
|
||||
$ cd nixpkgs</screen>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Find a good place in the Nixpkgs tree to add the Nix
|
||||
expression for your package. For instance, a library package
|
||||
typically goes into
|
||||
<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.
|
||||
|
||||
<screen>
|
||||
$ mkdir pkgs/development/libraries/libfoo</screen>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>In the package directory, create a Nix expression — a piece
|
||||
of code that describes how to build the package. In this case, it
|
||||
should be a <emphasis>function</emphasis> that is called with the
|
||||
package dependencies as arguments, and returns a build of the
|
||||
package in the Nix store. The expression should usually be called
|
||||
<filename>default.nix</filename>.
|
||||
|
||||
<screen>
|
||||
$ emacs pkgs/development/libraries/libfoo/default.nix
|
||||
$ git add pkgs/development/libraries/libfoo/default.nix</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>You can have a look at the existing Nix expressions under
|
||||
<filename>pkgs/</filename> to see how it’s done. Here are some
|
||||
good ones:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<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>.
|
||||
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://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/hello/ex-2/default.nix"><filename>pkgs/applications/misc/hello/ex-2/default.nix</filename></link>.
|
||||
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>.
|
||||
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>.
|
||||
Has an optional dependency on <varname>gtkspell</varname>,
|
||||
which is only built if <varname>spellCheck</varname> is
|
||||
<literal>true</literal>.</para>
|
||||
</listitem>
|
||||
|
||||
<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>.
|
||||
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>.
|
||||
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>
|
||||
(and the <link
|
||||
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/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>
|
||||
</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>.
|
||||
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>
|
||||
uses <command>patchelf</command> to set the RUNPATH and ELF
|
||||
interpreter of the executables so that the right libraries
|
||||
are found at runtime.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Some notes:
|
||||
|
||||
<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>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>You can use <command>nix-prefetch-url</command> (or similar nix-prefetch-git, etc)
|
||||
<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>
|
||||
</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>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<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
|
||||
on writing Nix expressions</link>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<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>
|
||||
with some descriptive name for the variable,
|
||||
e.g. <varname>libfoo</varname>.
|
||||
|
||||
<screen>
|
||||
$ emacs pkgs/top-level/all-packages.nix</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The attributes in that file are sorted by category (like
|
||||
“Development / Libraries”) that more-or-less correspond to the
|
||||
directory structure of Nixpkgs, and then by attribute name.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>To test whether the package builds, run the following command
|
||||
from the root of the nixpkgs source tree:
|
||||
|
||||
<screen>
|
||||
$ nix-build -A libfoo</screen>
|
||||
|
||||
where <varname>libfoo</varname> should be the variable name
|
||||
defined in the previous step. You may want to add the flag
|
||||
<option>-K</option> to keep the temporary build directory in case
|
||||
something fails. If the build succeeds, a symlink
|
||||
<filename>./result</filename> to the package in the Nix store is
|
||||
created.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>If you want to install the package into your profile
|
||||
(optional), do
|
||||
|
||||
<screen>
|
||||
$ nix-env -f . -iA libfoo</screen>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Optionally commit the new package and open a pull request, or send a patch to
|
||||
<literal>nix-dev@cs.uu.nl</literal>.</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
</orderedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
40
doc/quote-literals.xsl
Normal file
40
doc/quote-literals.xsl
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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:stylesheet>
|
||||
@@ -1,537 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<article xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<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
|
||||
release to list here: for example, the number of packages on Linux has
|
||||
increased from 1002 to 2159. However, some specific improvements are
|
||||
worth listing:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Nixpkgs now has a manual. In particular, it
|
||||
describes the standard build environment in
|
||||
detail.</para></listitem>
|
||||
|
||||
<listitem><para>Major new packages:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>KDE 4.</para></listitem>
|
||||
|
||||
<listitem><para>TeXLive.</para></listitem>
|
||||
|
||||
<listitem><para>VirtualBox.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
… and many others.
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Important updates:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Glibc 2.7.</para></listitem>
|
||||
|
||||
<listitem><para>GCC 4.2.4.</para></listitem>
|
||||
|
||||
<listitem><para>Linux 2.6.25 — 2.6.28.</para></listitem>
|
||||
|
||||
<listitem><para>Firefox 3.</para></listitem>
|
||||
|
||||
<listitem><para>X.org 7.3.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
<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
|
||||
details.</para></listitem>
|
||||
|
||||
<listitem><para>Improved support for building Haskell
|
||||
packages.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The following people contributed to this release:
|
||||
|
||||
Andres Löh,
|
||||
Arie Middelkoop,
|
||||
Armijn Hemel,
|
||||
Eelco Dolstra,
|
||||
Lluís Batlle,
|
||||
Ludovic Courtès,
|
||||
Marc Weber,
|
||||
Mart Kolthof,
|
||||
Martin Bravenboer,
|
||||
Michael Raskin,
|
||||
Nicolas Pierron,
|
||||
Peter Simons,
|
||||
Pjotr Prins,
|
||||
Rob Vermaas,
|
||||
Sander van der Burg,
|
||||
Tobias Hammerschmidt,
|
||||
Valentin David,
|
||||
Wouter den Breejen and
|
||||
Yury G. Kudryashov.
|
||||
|
||||
In addition, several people contributed patches on the
|
||||
<literal>nix-dev</literal> mailing list.</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Release 0.11 (September 11, 2007)</title>
|
||||
|
||||
<para>This release has the following improvements:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
|
||||
<listitem><para>The standard build environment
|
||||
(<literal>stdenv</literal>) is now pure on the
|
||||
<literal>x86_64-linux</literal> and <literal>powerpc-linux</literal>
|
||||
platforms, just as on <literal>i686-linux</literal>. (Purity means
|
||||
that building and using the standard environment has no dependencies
|
||||
outside of the Nix store. For instance, it doesn’t require an
|
||||
external C compiler such as <filename>/usr/bin/gcc</filename>.)
|
||||
Also, the statically linked binaries used in the bootstrap process
|
||||
are now automatically reproducible, making it easy to update the
|
||||
bootstrap tools and to add support for other Linux platforms. See
|
||||
<filename>pkgs/stdenv/linux/make-bootstrap-tools.nix</filename> for
|
||||
details.</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>Hook variables in the generic builder are now
|
||||
executed using the <function>eval</function> shell command. This
|
||||
has a major advantage: you can write hooks directly in Nix
|
||||
expressions. For instance, rather than writing a builder like this:
|
||||
|
||||
<programlisting>
|
||||
source $stdenv/setup
|
||||
|
||||
postInstall=postInstall
|
||||
postInstall() {
|
||||
ln -sf gzip $out/bin/gunzip
|
||||
ln -sf gzip $out/bin/zcat
|
||||
}
|
||||
|
||||
genericBuild</programlisting>
|
||||
|
||||
(the <literal>gzip</literal> builder), you can just add this
|
||||
attribute to the derivation:
|
||||
|
||||
<programlisting>
|
||||
postInstall = "ln -sf gzip $out/bin/gunzip; ln -sf gzip $out/bin/zcat";</programlisting>
|
||||
|
||||
and so a separate build script becomes unnecessary. This should
|
||||
allow us to get rid of most builders in Nixpkgs.</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>It is now possible to have the generic builder pass
|
||||
arguments to <command>configure</command> and
|
||||
<command>make</command> that contain whitespace. Previously, for
|
||||
example, you could say in a builder,
|
||||
|
||||
<programlisting>
|
||||
configureFlags="CFLAGS=-O0"</programlisting>
|
||||
|
||||
but not
|
||||
|
||||
<programlisting>
|
||||
configureFlags="CFLAGS=-O0 -g"</programlisting>
|
||||
|
||||
since the <literal>-g</literal> would be interpreted as a separate
|
||||
argument to <command>configure</command>. Now you can say
|
||||
|
||||
<programlisting>
|
||||
configureFlagsArray=("CFLAGS=-O0 -g")</programlisting>
|
||||
|
||||
or similarly
|
||||
|
||||
<programlisting>
|
||||
configureFlagsArray=("CFLAGS=-O0 -g" "LDFLAGS=-L/foo -L/bar")</programlisting>
|
||||
|
||||
which does the right thing. Idem for <literal>makeFlags</literal>,
|
||||
<literal>installFlags</literal>, <literal>checkFlags</literal> and
|
||||
<literal>distFlags</literal>.</para>
|
||||
|
||||
<para>Unfortunately you can't pass arrays to Bash through the
|
||||
environment, so you can't put the array above in a Nix expression,
|
||||
e.g.,
|
||||
|
||||
<programlisting>
|
||||
configureFlagsArray = ["CFLAGS=-O0 -g"];</programlisting>
|
||||
|
||||
since it would just be flattened to a since string. However, you
|
||||
<emphasis>can</emphasis> use the inline hooks described above:
|
||||
|
||||
<programlisting>
|
||||
preConfigure = "configureFlagsArray=(\"CFLAGS=-O0 -g\")";</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>The function <function>fetchurl</function> now has
|
||||
support for two different kinds of mirroring of files. First, it
|
||||
has support for <emphasis>content-addressable mirrors</emphasis>.
|
||||
For example, given the <function>fetchurl</function> call
|
||||
|
||||
<programlisting>
|
||||
fetchurl {
|
||||
url = http://releases.mozilla.org/<replaceable>...</replaceable>/firefox-2.0.0.6-source.tar.bz2;
|
||||
sha1 = "eb72f55e4a8bf08e8c6ef227c0ade3d068ba1082";
|
||||
}</programlisting>
|
||||
|
||||
<function>fetchurl</function> will first try to download this file
|
||||
from <link
|
||||
xlink:href="http://tarballs.nixos.org/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
|
||||
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
|
||||
to a whitespace-separated list of URLs.</para>
|
||||
|
||||
<para>Second, <function>fetchurl</function> has support for
|
||||
widely-mirrored distribution sites such as SourceForge or the Linux
|
||||
kernel archives. Given a URL of the form
|
||||
<literal>mirror://<replaceable>site</replaceable>/<replaceable>path</replaceable></literal>,
|
||||
it will try to download <replaceable>path</replaceable> from a
|
||||
configurable list of mirrors for <replaceable>site</replaceable>.
|
||||
(This idea was borrowed from Gentoo Linux.) Example:
|
||||
<programlisting>
|
||||
fetchurl {
|
||||
url = mirror://gnu/gcc/gcc-4.2.0/gcc-core-4.2.0.tar.bz2;
|
||||
sha256 = "0ykhzxhr8857dr97z0j9wyybfz1kjr71xk457cfapfw5fjas4ny1";
|
||||
}</programlisting>
|
||||
Currently <replaceable>site</replaceable> can be
|
||||
<literal>sourceforge</literal>, <literal>gnu</literal> and
|
||||
<literal>kernel</literal>. The list of mirrors is defined in
|
||||
<filename>pkgs/build-support/fetchurl/mirrors.nix</filename>. You
|
||||
can override the list of mirrors for a particular site by setting
|
||||
the environment variable
|
||||
<envar>NIX_MIRRORS_<replaceable>site</replaceable></envar>, e.g.
|
||||
<programlisting>
|
||||
export NIX_MIRRORS_sourceforge=http://osdn.dl.sourceforge.net/sourceforge/</programlisting>
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem><para>Important updates:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Glibc 2.5.</para></listitem>
|
||||
|
||||
<listitem><para>GCC 4.1.2.</para></listitem>
|
||||
|
||||
<listitem><para>Gnome 2.16.3.</para></listitem>
|
||||
|
||||
<listitem><para>X11R7.2.</para></listitem>
|
||||
|
||||
<listitem><para>Linux 2.6.21.7 and 2.6.22.6.</para></listitem>
|
||||
|
||||
<listitem><para>Emacs 22.1.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>Major new packages:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>KDE 3.5.6 Base.</para></listitem>
|
||||
|
||||
<listitem><para>Wine 0.9.43.</para></listitem>
|
||||
|
||||
<listitem><para>OpenOffice 2.2.1.</para></listitem>
|
||||
|
||||
<listitem><para>Many Linux system packages to support
|
||||
NixOS.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The following people contributed to this release:
|
||||
|
||||
Andres Löh,
|
||||
Arie Middelkoop,
|
||||
Armijn Hemel,
|
||||
Eelco Dolstra,
|
||||
Marc Weber,
|
||||
Mart Kolthof,
|
||||
Martin Bravenboer,
|
||||
Michael Raskin,
|
||||
Wouter den Breejen and
|
||||
Yury G. Kudryashov.
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Release 0.10 (October 12, 2006)</title>
|
||||
|
||||
<note><para>This release of Nixpkgs requires <link
|
||||
xlink:href='http://nixos.org/releases/nix/nix-0.10/'>Nix
|
||||
0.10</link> or higher.</para></note>
|
||||
|
||||
<para>This release has the following improvements:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para><filename>pkgs/system/all-packages-generic.nix</filename>
|
||||
is gone, we now just have
|
||||
<filename>pkgs/top-level/all-packages.nix</filename> that contains
|
||||
all available packages. This should cause much less confusion with
|
||||
users. <filename>all-packages.nix</filename> is a function that by
|
||||
default returns packages for the current platform, but you can
|
||||
override this by specifying a different <varname>system</varname>
|
||||
argument.</para></listitem>
|
||||
|
||||
<listitem><para>Certain packages in Nixpkgs are now
|
||||
user-configurable through a configuration file, i.e., without having
|
||||
to edit the Nix expressions in Nixpkgs. For instance, the Firefox
|
||||
provided in the Nixpkgs channel is built without the RealPlayer
|
||||
plugin (for legal reasons). Previously, you could easily enable
|
||||
RealPlayer support by editing the call to the Firefox function in
|
||||
<filename>all-packages.nix</filename>, but such changes are not
|
||||
respected when Firefox is subsequently updated through the Nixpkgs
|
||||
channel.</para>
|
||||
|
||||
<para>The Nixpkgs configuration file (found in
|
||||
<filename>~/.nixpkgs/config.nix</filename> or through the
|
||||
<envar>NIXPKGS_CONFIG</envar> environment variable) is an attribute
|
||||
set that contains configuration options that
|
||||
<filename>all-packages.nix</filename> reads and uses for certain
|
||||
packages. For instance, the following configuration file:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
firefox = {
|
||||
enableRealPlayer = true;
|
||||
};
|
||||
}</programlisting>
|
||||
|
||||
persistently enables RealPlayer support in the Firefox
|
||||
build.</para>
|
||||
|
||||
<para>(Actually, <literal>firefox.enableRealPlayer</literal> is the
|
||||
<emphasis>only</emphasis> configuration option currently available,
|
||||
but more are sure to be added.)</para></listitem>
|
||||
|
||||
<listitem><para>Support for new platforms:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para><literal>i686-cygwin</literal>, i.e., Windows
|
||||
(using <link xlink:href="http://www.cygwin.com/">Cygwin</link>).
|
||||
The standard environment on <literal>i686-cygwin</literal> by
|
||||
default builds binaries for the Cygwin environment (i.e., it
|
||||
uses Cygwin tools and produces executables that use the Cygwin
|
||||
library). However, there is also a standard environment that
|
||||
produces binaries that use <link
|
||||
xlink:href="http://www.mingw.org/">MinGW</link>. You can use it
|
||||
by calling <filename>all-package.nix</filename> with the
|
||||
<varname>stdenvType</varname> argument set to
|
||||
<literal>"i686-mingw"</literal>.</para></listitem>
|
||||
|
||||
<listitem><para><literal>i686-darwin</literal>, i.e., Mac OS X
|
||||
on Intel CPUs.</para></listitem>
|
||||
|
||||
<listitem><para><literal>powerpc-linux</literal>.</para></listitem>
|
||||
|
||||
<listitem><para><literal>x86_64-linux</literal>, i.e., Linux on
|
||||
64-bit AMD/Intel CPUs. Unlike <literal>i686-linux</literal>,
|
||||
this platform doesn’t have a pure <literal>stdenv</literal>
|
||||
yet.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem><para>The default compiler is now GCC 4.1.1.</para></listitem>
|
||||
|
||||
<listitem><para>X11 updated to X.org’s X11R7.1.</para></listitem>
|
||||
|
||||
<listitem><para>Notable new packages:
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Opera.</para></listitem>
|
||||
|
||||
<listitem><para>Microsoft Visual C++ 2005 Express Edition and
|
||||
the Windows SDK.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
In total there are now around 809 packages in Nixpkgs.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem><para>It is now <emphasis>much</emphasis> easier to
|
||||
override the default C compiler and other tools in
|
||||
<literal>stdenv</literal> for specific packages.
|
||||
<filename>all-packages.nix</filename> provides two utility
|
||||
functions for this purpose: <function>overrideGCC</function> and
|
||||
<function>overrideInStdenv</function>. Both take a
|
||||
<literal>stdenv</literal> and return an augmented
|
||||
<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>
|
||||
|
||||
<para>For instance, the package <varname>strategoxt</varname>
|
||||
doesn’t build with the GNU Make in <literal>stdenv</literal>
|
||||
(version 3.81), so we call it with an augmented
|
||||
<literal>stdenv</literal> that uses GNU Make 3.80:
|
||||
|
||||
<programlisting>
|
||||
strategoxt = (import ../development/compilers/strategoxt) {
|
||||
inherit fetchurl pkgconfig sdf aterm;
|
||||
stdenv = overrideInStdenv stdenv [gnumake380];
|
||||
};
|
||||
|
||||
gnumake380 = <replaceable>...</replaceable>;</programlisting>
|
||||
|
||||
Likewise, there are many packages that don’t compile with the
|
||||
default GCC (4.1.1), but that’s easily fixed:
|
||||
|
||||
<programlisting>
|
||||
exult = import ../games/exult {
|
||||
inherit fetchurl SDL SDL_mixer zlib libpng unzip;
|
||||
stdenv = overrideGCC stdenv gcc34;
|
||||
};</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>It has also become much easier to experiment with
|
||||
changes to the <literal>stdenv</literal> setup script (which notably
|
||||
contains the generic builder). Since edits to
|
||||
<filename>pkgs/stdenv/generic/setup.sh</filename> trigger a rebuild
|
||||
of <emphasis>everything</emphasis>, this was formerly quite painful.
|
||||
But now <literal>stdenv</literal> contains a function to
|
||||
“regenerate” <literal>stdenv</literal> with a different setup
|
||||
script, allowing the use of a different setup script for specific
|
||||
packages:
|
||||
|
||||
<programlisting>
|
||||
pkg = import <replaceable>...</replaceable> {
|
||||
stdenv = stdenv.regenerate ./my-setup.sh;
|
||||
<replaceable>...</replaceable>
|
||||
}</programlisting>
|
||||
|
||||
</para></listitem>
|
||||
|
||||
|
||||
<listitem><para>Packages can now have a human-readable
|
||||
<emphasis>description</emphasis> field. Package descriptions are
|
||||
shown by <literal>nix-env -qa --description</literal>. In addition,
|
||||
they’re shown on the Nixpkgs release page. A description can be
|
||||
added to a package as follows:
|
||||
|
||||
<programlisting>
|
||||
stdenv.mkDerivation {
|
||||
name = "exult-1.2";
|
||||
<replaceable>...</replaceable>
|
||||
meta = {
|
||||
description = "A reimplementation of the Ultima VII game engine";
|
||||
};
|
||||
}</programlisting>
|
||||
|
||||
The <varname>meta</varname> attribute is not passed to the builder,
|
||||
so changes to the description do not trigger a rebuild. Additional
|
||||
<varname>meta</varname> attributes may be defined in the future
|
||||
(such as the URL of the package’s homepage, the license,
|
||||
etc.).</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
|
||||
<para>The following people contributed to this release:
|
||||
|
||||
Andres Löh,
|
||||
Armijn Hemel,
|
||||
Christof Douma,
|
||||
Eelco Dolstra,
|
||||
Eelco Visser,
|
||||
Mart Kolthof,
|
||||
Martin Bravenboer,
|
||||
Merijn de Jonge,
|
||||
Rob Vermaas and
|
||||
Roy van den Broek.
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book
|
||||
PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.docbook.org/xml/4.3/docbook-xml-4.3.zip"
|
||||
[
|
||||
]>
|
||||
|
||||
<article><title>Nixpkgs Release Notes</title>
|
||||
|
||||
|
||||
<section><title>Release 0.9 (January 31, 2006)</title>
|
||||
@@ -542,8 +16,8 @@ some of the more notable changes:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Distribution files have been moved to <link
|
||||
xlink:href="http://nixos.org/" />.</para></listitem>
|
||||
<listitem><para>Distribution files have been moved to <ulink
|
||||
url="http://nix.cs.uu.nl/" />.</para></listitem>
|
||||
|
||||
<listitem><para>The C library on Linux, Glibc, has been updated to
|
||||
version 2.3.6.</para></listitem>
|
||||
@@ -558,7 +32,7 @@ some of the more notable changes:</para>
|
||||
working X server (previously we only had X client libraries). We
|
||||
use a fully Nixified X server on NixOS.</para></listitem>
|
||||
|
||||
<listitem><para>The Sun JDK 5 has been purified, i.e., it doesn’t
|
||||
<listitem><para>The Sun JDK 5 has been purified, i.e., it doesn't
|
||||
require any non-Nix components such as
|
||||
<filename>/lib/ld-linux.so.2</filename>. This means that Java
|
||||
applications such as Eclipse and Azureus can run on
|
||||
@@ -675,10 +149,9 @@ hashing scheme in Nix 0.8.</para>
|
||||
<listitem>
|
||||
|
||||
<para>Tarballs used by Nixpkgs are now obtained from the same server
|
||||
that hosts Nixpkgs (<link
|
||||
xlink:href="http://catamaran.labs.cs.uu.nl/" />). This reduces the
|
||||
risk of packages being unbuildable due to moved or deleted files on
|
||||
various servers.</para>
|
||||
that hosts Nixpkgs (<ulink url="http://catamaran.labs.cs.uu.nl/" />).
|
||||
This reduces the risk of packages being unbuildable due to moved or
|
||||
deleted files on various servers.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
|
||||
1217
doc/stdenv.xml
1217
doc/stdenv.xml
File diff suppressed because it is too large
Load Diff
169
doc/style.css
169
doc/style.css
@@ -8,14 +8,16 @@
|
||||
|
||||
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 */
|
||||
@@ -32,33 +34,16 @@ h2 /* chapters, appendices, subtitle */
|
||||
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
|
||||
{
|
||||
margin-top: 1.5em;
|
||||
/* border-top: solid #005aa0; */
|
||||
}
|
||||
|
||||
div.section > div.titlepage h2 /* sections */
|
||||
div.sect1 h2 /* sections */
|
||||
{
|
||||
font-size: 150%;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
h3 /* subsections */
|
||||
{
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
div.simplesect h2
|
||||
{
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
div.appendix h3
|
||||
{
|
||||
font-size: 150%;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
div.refnamediv h2, div.refsynopsisdiv h2, div.refsection h2 /* refentry parts */
|
||||
{
|
||||
margin-top: 1.4em;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
@@ -67,30 +52,30 @@ div.refsection h3
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
h3 /* subsections */
|
||||
{
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Examples:
|
||||
Program listings:
|
||||
***************************************************************************/
|
||||
|
||||
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;
|
||||
margin-left: 3em;
|
||||
margin-right: 3em;
|
||||
background: #eeeeee;
|
||||
}
|
||||
|
||||
div.example p.title
|
||||
pre.programlisting
|
||||
{
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
div.example pre
|
||||
{
|
||||
box-shadow: none;
|
||||
color: #600000;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,24 +83,16 @@ div.example pre
|
||||
Screen dumps:
|
||||
***************************************************************************/
|
||||
|
||||
pre.screen, pre.programlisting
|
||||
pre.screen
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
border: 1px solid #6185a0;
|
||||
padding: 6px 6px;
|
||||
margin-left: 3em;
|
||||
margin-right: 3em;
|
||||
color: #600000;
|
||||
background: #f4f4f8;
|
||||
background: #eeeeee;
|
||||
font-family: monospace;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.example pre.programlisting
|
||||
{
|
||||
border: 0px;
|
||||
padding: 0 0;
|
||||
margin: 0 0 0 0;
|
||||
/* font-size: 90%; */
|
||||
}
|
||||
|
||||
|
||||
@@ -123,40 +100,24 @@ div.example pre.programlisting
|
||||
Notes, warnings etc:
|
||||
***************************************************************************/
|
||||
|
||||
.note, .warning
|
||||
.note,.warning
|
||||
{
|
||||
border: 1px solid #b0b0b0;
|
||||
padding: 3px 3px;
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.3em 0.3em 0.3em 0.3em;
|
||||
border: 1px solid #6185a0;
|
||||
padding: 0px 1em;
|
||||
background: #fffff5;
|
||||
border-radius: 0.4em;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
}
|
||||
|
||||
div.note, div.warning
|
||||
div.note,div.warning
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.note h3, div.warning h3
|
||||
div.warning h3
|
||||
{
|
||||
color: red;
|
||||
font-size: 100%;
|
||||
padding-right: 0.5em;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.note p, div.warning p
|
||||
{
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
div.note h3 + p, div.warning h3 + p
|
||||
{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.note h3
|
||||
@@ -175,26 +136,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;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
@@ -212,17 +167,17 @@ tt, code
|
||||
|
||||
}
|
||||
|
||||
div.variablelist dd p, div.glosslist dd p
|
||||
div.variablelist dd
|
||||
{
|
||||
margin-top: 0em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.variablelist dd, div.glosslist dd
|
||||
.default
|
||||
{
|
||||
margin-left: 1.5em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.glosslist dt
|
||||
.availability
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -232,24 +187,48 @@ div.glosslist dt
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
span.command strong
|
||||
|
||||
div.informaltable table
|
||||
{
|
||||
font-weight: normal;
|
||||
color: #400000;
|
||||
border: 1px solid #6185a0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.calloutlist table
|
||||
div.informaltable td
|
||||
{
|
||||
box-shadow: none;
|
||||
border: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
table
|
||||
div.informaltable td.default
|
||||
{
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.affiliation
|
||||
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;
|
||||
}
|
||||
|
||||
328
lib/attrsets.nix
328
lib/attrsets.nix
@@ -1,328 +0,0 @@
|
||||
# Operations on attribute sets.
|
||||
|
||||
with {
|
||||
inherit (builtins) head tail;
|
||||
inherit (import ./trivial.nix) or;
|
||||
inherit (import ./default.nix) fold;
|
||||
inherit (import ./strings.nix) concatStringsSep;
|
||||
inherit (import ./lists.nix) concatMap concatLists all deepSeqList;
|
||||
inherit (import ./misc.nix) maybeAttr;
|
||||
};
|
||||
|
||||
rec {
|
||||
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr;
|
||||
|
||||
|
||||
/* Return an attribute from nested attribute sets. For instance
|
||||
["x" "y"] applied to some set e returns e.x.y, if it exists. The
|
||||
default value is returned otherwise. */
|
||||
attrByPath = attrPath: default: e:
|
||||
let attr = head attrPath;
|
||||
in
|
||||
if attrPath == [] then e
|
||||
else if e ? ${attr}
|
||||
then attrByPath (tail attrPath) default e.${attr}
|
||||
else default;
|
||||
|
||||
|
||||
/* Return nested attribute set in which an attribute is set. For instance
|
||||
["x" "y"] applied with some value v returns `x.y = v;' */
|
||||
setAttrByPath = attrPath: value:
|
||||
if attrPath == [] then value
|
||||
else listToAttrs
|
||||
[ { name = head attrPath; value = setAttrByPath (tail attrPath) value; } ];
|
||||
|
||||
|
||||
getAttrFromPath = attrPath: set:
|
||||
let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'";
|
||||
in attrByPath attrPath (abort errorMsg) set;
|
||||
|
||||
|
||||
/* Return the specified attributes from a set.
|
||||
|
||||
Example:
|
||||
attrVals ["a" "b" "c"] as
|
||||
=> [as.a as.b as.c]
|
||||
*/
|
||||
attrVals = nameList: set: map (x: set.${x}) nameList;
|
||||
|
||||
|
||||
/* Return the values of all attributes in the given set, sorted by
|
||||
attribute name.
|
||||
|
||||
Example:
|
||||
attrValues {c = 3; a = 1; b = 2;}
|
||||
=> [1 2 3]
|
||||
*/
|
||||
attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
|
||||
|
||||
|
||||
/* Collect each attribute named `attr' from a list of attribute
|
||||
sets. Sets that don't contain the named attribute are ignored.
|
||||
|
||||
Example:
|
||||
catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
|
||||
=> [1 2]
|
||||
*/
|
||||
catAttrs = builtins.catAttrs or
|
||||
(attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
|
||||
|
||||
|
||||
/* Filter an attribute set by removing all attributes for which the
|
||||
given predicate return false.
|
||||
|
||||
Example:
|
||||
filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
|
||||
=> { foo = 1; }
|
||||
*/
|
||||
filterAttrs = pred: set:
|
||||
listToAttrs (fold (n: ys: let v = set.${n}; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (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} (maybeAttr name nul a); }])
|
||||
) a (attrNames n)
|
||||
) {} list_of_attrs;
|
||||
|
||||
|
||||
/* Recursively collect sets that verify a given predicate named `pred'
|
||||
from the set `attrs'. The recursion is stopped when the predicate is
|
||||
verified.
|
||||
|
||||
Type:
|
||||
collect ::
|
||||
(AttrSet -> Bool) -> AttrSet -> AttrSet
|
||||
|
||||
Example:
|
||||
collect isList { a = { b = ["b"]; }; c = [1]; }
|
||||
=> [["b"] [1]]
|
||||
|
||||
collect (x: x ? outPath)
|
||||
{ a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
|
||||
=> [{ outPath = "a/"; } { outPath = "b/"; }]
|
||||
*/
|
||||
collect = pred: attrs:
|
||||
if pred attrs then
|
||||
[ attrs ]
|
||||
else if isAttrs attrs then
|
||||
concatMap (collect pred) (attrValues attrs)
|
||||
else
|
||||
[];
|
||||
|
||||
|
||||
/* Utility function that creates a {name, value} pair as expected by
|
||||
builtins.listToAttrs. */
|
||||
nameValuePair = name: value: { inherit name value; };
|
||||
|
||||
|
||||
/* Apply a function to each element in an attribute set. The
|
||||
function takes two arguments --- the attribute name and its value
|
||||
--- and returns the new value for the attribute. The result is a
|
||||
new attribute set.
|
||||
|
||||
Example:
|
||||
mapAttrs (name: value: name + "-" + value)
|
||||
{ x = "foo"; y = "bar"; }
|
||||
=> { x = "x-foo"; y = "y-bar"; }
|
||||
*/
|
||||
mapAttrs = f: set:
|
||||
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set));
|
||||
|
||||
|
||||
/* Like `mapAttrs', but allows the name of each attribute to be
|
||||
changed in addition to the value. The applied function should
|
||||
return both the new name and value as a `nameValuePair'.
|
||||
|
||||
Example:
|
||||
mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
|
||||
{ x = "a"; y = "b"; }
|
||||
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
|
||||
*/
|
||||
mapAttrs' = f: set:
|
||||
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
||||
|
||||
|
||||
/* Call a function for each attribute in the given set and return
|
||||
the result in a list.
|
||||
|
||||
Example:
|
||||
mapAttrsToList (name: value: name + value)
|
||||
{ x = "a"; y = "b"; }
|
||||
=> [ "xa" "yb" ]
|
||||
*/
|
||||
mapAttrsToList = f: attrs:
|
||||
map (name: f name attrs.${name}) (attrNames attrs);
|
||||
|
||||
|
||||
/* Like `mapAttrs', except that it recursively applies itself to
|
||||
attribute sets. Also, the first argument of the argument
|
||||
function is a *list* of the names of the containing attributes.
|
||||
|
||||
Type:
|
||||
mapAttrsRecursive ::
|
||||
([String] -> a -> b) -> AttrSet -> AttrSet
|
||||
|
||||
Example:
|
||||
mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
|
||||
{ n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
|
||||
=> { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
|
||||
*/
|
||||
mapAttrsRecursive = mapAttrsRecursiveCond (as: true);
|
||||
|
||||
|
||||
/* Like `mapAttrsRecursive', but it takes an additional predicate
|
||||
function that tells it whether to recursive into an attribute
|
||||
set. If it returns false, `mapAttrsRecursiveCond' does not
|
||||
recurse, but does apply the map function. It is returns true, it
|
||||
does recurse, and does not apply the map function.
|
||||
|
||||
Type:
|
||||
mapAttrsRecursiveCond ::
|
||||
(AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
|
||||
|
||||
Example:
|
||||
# To prevent recursing into derivations (which are attribute
|
||||
# sets with the attribute "type" equal to "derivation"):
|
||||
mapAttrsRecursiveCond
|
||||
(as: !(as ? "type" && as.type == "derivation"))
|
||||
(x: ... do something ...)
|
||||
attrs
|
||||
*/
|
||||
mapAttrsRecursiveCond = cond: f: set:
|
||||
let
|
||||
recurse = path: set:
|
||||
let
|
||||
g =
|
||||
name: value:
|
||||
if isAttrs value && cond value
|
||||
then recurse (path ++ [name]) value
|
||||
else f (path ++ [name]) value;
|
||||
in mapAttrs g set;
|
||||
in recurse [] set;
|
||||
|
||||
|
||||
/* Generate an attribute set by mapping a function over a list of
|
||||
attribute names.
|
||||
|
||||
Example:
|
||||
genAttrs [ "foo" "bar" ] (name: "x_" + name)
|
||||
=> { foo = "x_foo"; bar = "x_bar"; }
|
||||
*/
|
||||
genAttrs = names: f:
|
||||
listToAttrs (map (n: nameValuePair n (f n)) names);
|
||||
|
||||
|
||||
/* Check whether the argument is a derivation. */
|
||||
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
|
||||
|
||||
|
||||
/* 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,118 +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 { }));
|
||||
|
||||
|
||||
# usage: (you can use override multiple times)
|
||||
# let d = makeOverridable stdenv.mkDerivation { name = ..; buildInputs; }
|
||||
# noBuildInputs = d.override { buildInputs = []; }
|
||||
# additionalBuildInputs = d.override ( args : args // { buildInputs = args.buildInputs ++ [ additional ]; } )
|
||||
makeOverridable = f: origArgs:
|
||||
let
|
||||
ff = f origArgs;
|
||||
in
|
||||
if builtins.isAttrs ff then (ff //
|
||||
{ override = newArgs:
|
||||
makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs));
|
||||
deepOverride = newArgs:
|
||||
makeOverridable f (lib.overrideExisting (lib.mapAttrs (deepOverrider newArgs) origArgs) newArgs);
|
||||
overrideDerivation = fdrv:
|
||||
makeOverridable (args: overrideDerivation (f args) fdrv) origArgs;
|
||||
})
|
||||
else ff;
|
||||
|
||||
deepOverrider = newArgs: name: x: if builtins.isAttrs x then (
|
||||
if x ? deepOverride then (x.deepOverride newArgs) else
|
||||
if x ? override then (x.override newArgs) else
|
||||
x) else x;
|
||||
|
||||
|
||||
/* 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; in
|
||||
makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) autoArgs) // args);
|
||||
|
||||
/* 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};
|
||||
}
|
||||
111
lib/debug.nix
111
lib/debug.nix
@@ -1,111 +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);
|
||||
|
||||
|
||||
traceVal = x: builtins.trace x x;
|
||||
traceXMLVal = x: builtins.trace (builtins.toXML x) x;
|
||||
traceXMLValMarked = str: x: builtins.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));
|
||||
|
||||
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 builtins.trace "${str}\n result:\n${builtins.toXML r}" r
|
||||
);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
let
|
||||
|
||||
trivial = import ./trivial.nix;
|
||||
lists = import ./lists.nix;
|
||||
strings = import ./strings.nix;
|
||||
stringsWithDeps = import ./strings-with-deps.nix;
|
||||
attrsets = import ./attrsets.nix;
|
||||
sources = import ./sources.nix;
|
||||
modules = import ./modules.nix;
|
||||
options = import ./options.nix;
|
||||
types = import ./types.nix;
|
||||
meta = import ./meta.nix;
|
||||
debug = import ./debug.nix;
|
||||
misc = import ./misc.nix;
|
||||
maintainers = import ./maintainers.nix;
|
||||
platforms = import ./platforms.nix;
|
||||
systems = import ./systems.nix;
|
||||
customisation = import ./customisation.nix;
|
||||
licenses = import ./licenses.nix;
|
||||
|
||||
in
|
||||
{ inherit trivial lists strings stringsWithDeps attrsets sources options
|
||||
modules types meta debug maintainers licenses platforms systems;
|
||||
}
|
||||
# !!! don't include everything at top-level; perhaps only the most
|
||||
# commonly used functions.
|
||||
// trivial // lists // strings // stringsWithDeps // attrsets // sources
|
||||
// options // types // meta // debug // misc // modules
|
||||
// systems
|
||||
// customisation
|
||||
411
lib/licenses.nix
411
lib/licenses.nix
@@ -1,411 +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-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";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
epl10 = spdx {
|
||||
spdxId = "EPL-1.0";
|
||||
fullName = "Eclipse Public License 1.0";
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
ofl = spdx {
|
||||
spdxId = "OFL-1.1";
|
||||
fullName = "SIL Open Font License 1.1";
|
||||
};
|
||||
|
||||
openssl = spdx {
|
||||
spdxId = "OpenSSL";
|
||||
fullName = "OpenSSL License";
|
||||
};
|
||||
|
||||
php301 = spdx {
|
||||
spdxId = "PHP-3.01";
|
||||
fullName = "PHP License v3.01";
|
||||
};
|
||||
|
||||
postgresql = spdx {
|
||||
spdxId = "PostgreSQL";
|
||||
fullName = "PostgreSQL License";
|
||||
};
|
||||
|
||||
psfl = spdx {
|
||||
spdxId = "Python-2.0";
|
||||
fullName = "Python Software Foundation License version 2";
|
||||
#url = http://docs.python.org/license.html;
|
||||
};
|
||||
|
||||
publicDomain = {
|
||||
fullName = "Public Domain";
|
||||
};
|
||||
|
||||
qpl = spdx {
|
||||
spdxId = "QPL-1.0";
|
||||
fullName = "Q Public License 1.0";
|
||||
};
|
||||
|
||||
qwt = {
|
||||
fullName = "Qwt License, Version 1.0";
|
||||
url = http://qwt.sourceforge.net/qwtlicense.html;
|
||||
};
|
||||
|
||||
ruby = spdx {
|
||||
spdxId = "Ruby";
|
||||
fullName = "Ruby License";
|
||||
};
|
||||
|
||||
sgi-b-20 = spdx {
|
||||
spdxId = "SGI-B-2.0";
|
||||
fullName = "SGI Free Software License B v2.0";
|
||||
};
|
||||
|
||||
sleepycat = spdx {
|
||||
spdxId = "Sleepycat";
|
||||
fullName = "Sleepycat License";
|
||||
};
|
||||
|
||||
tcltk = spdx {
|
||||
spdxId = "TCL";
|
||||
fullName = "TCL/TK License";
|
||||
};
|
||||
|
||||
unfree = {
|
||||
fullName = "Unfree";
|
||||
free = false;
|
||||
};
|
||||
|
||||
unfreeRedistributable = {
|
||||
fullName = "Unfree redistributable";
|
||||
free = false;
|
||||
};
|
||||
|
||||
unfreeRedistributableFirmware = {
|
||||
fullName = "Unfree redistributable firmware";
|
||||
# Note: we currently consider these "free" for inclusion in the
|
||||
# channel and NixOS images.
|
||||
};
|
||||
|
||||
unlicense = spdx {
|
||||
spdxId = "Unlicense";
|
||||
fullName = "The Unlicense";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
}
|
||||
236
lib/lists.nix
236
lib/lists.nix
@@ -1,236 +0,0 @@
|
||||
# General list operations.
|
||||
|
||||
with import ./trivial.nix;
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) head tail length isList elemAt concatLists filter elem;
|
||||
|
||||
|
||||
# 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);
|
||||
|
||||
|
||||
# map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
|
||||
# ["a-1" "b-2"]'
|
||||
imap = 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 fold (x: y: (flatten x) ++ 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 = 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 = 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: fold (x: c: 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 = 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 = f: fst: snd:
|
||||
let
|
||||
len1 = length fst;
|
||||
len2 = length snd;
|
||||
len = if len1 < len2 then len1 else len2;
|
||||
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. FIXME: O(n^2)!
|
||||
reverseList = 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 = 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 = 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 = 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 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;
|
||||
|
||||
|
||||
# Zip two lists together.
|
||||
zipTwoLists = xs: ys:
|
||||
let
|
||||
len1 = length xs;
|
||||
len2 = length ys;
|
||||
len = if len1 < len2 then len1 else len2;
|
||||
zipTwoLists' = n:
|
||||
if n != len then
|
||||
[ { first = elemAt xs n; second = elemAt ys n; } ]
|
||||
++ zipTwoLists' (n + 1)
|
||||
else [];
|
||||
in zipTwoLists' 0;
|
||||
|
||||
|
||||
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
|
||||
unique = list:
|
||||
if list == [] then
|
||||
[]
|
||||
else
|
||||
let
|
||||
x = head list;
|
||||
xs = unique (drop 1 list);
|
||||
in [x] ++ remove x xs;
|
||||
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
/* -*- coding: utf-8; -*- */
|
||||
|
||||
{
|
||||
/* Add your name and email address here. Keep the list
|
||||
alphabetically sorted. */
|
||||
|
||||
_1126 = "Christian Lask <mail@elfsechsundzwanzig.de>";
|
||||
abbradar = "Nikolay Amiantov <ab@fmap.me>";
|
||||
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
|
||||
aherrmann = "Andreas Herrmann <andreash87@gmx.ch>";
|
||||
ak = "Alexander Kjeldaas <ak@formalprivacy.com>";
|
||||
akc = "Anders Claesson <akc@akc.is>";
|
||||
algorith = "Dries Van Daele <dries_van_daele@telenet.be>";
|
||||
all = "Nix Committers <nix-commits@lists.science.uu.nl>";
|
||||
amiddelk = "Arie Middelkoop <amiddelk@gmail.com>";
|
||||
amorsillo = "Andrew Morsillo <andrew.morsillo@gmail.com>";
|
||||
AndersonTorres = "Anderson Torres <torres.anderson.85@gmail.com>";
|
||||
andres = "Andres Loeh <ksnixos@andres-loeh.de>";
|
||||
antono = "Antono Vasiljev <self@antono.info>";
|
||||
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>";
|
||||
aycanirican = "Aycan iRiCAN <iricanaycan@gmail.com>";
|
||||
balajisivaraman = "Balaji Sivaraman<sivaraman.balaji@gmail.com>";
|
||||
bbenoist = "Baptist BENOIST <return_0@live.com>";
|
||||
bdimcheff = "Brandon Dimcheff <brandon@dimcheff.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>";
|
||||
bosu = "Boris Sukholitko <boriss@gmail.com>";
|
||||
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>";
|
||||
christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>";
|
||||
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
|
||||
codyopel = "Cody Opel <codyopel@gmail.com>";
|
||||
copumpkin = "Dan Peebles <pumpkingod@gmail.com>";
|
||||
coroa = "Jonas Hörsch <jonas@chaoflow.net>";
|
||||
cstrahan = "Charles Strahan <charles.c.strahan@gmail.com>";
|
||||
DamienCassou = "Damien Cassou <damien.cassou@gmail.com>";
|
||||
davidrusu = "David Rusu <davidrusu.me@gmail.com>";
|
||||
dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>";
|
||||
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
|
||||
devhell = "devhell <\"^\"@regexmail.net>";
|
||||
dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>";
|
||||
doublec = "Chris Double <chris.double@double.co.nz>";
|
||||
ederoyd46 = "Matthew Brown <matt@ederoyd.co.uk>";
|
||||
eduarrrd = "Eduard Bachmakov <e.bachmakov@gmail.com>";
|
||||
edwtjo = "Edward Tjörnhammar <ed@cflags.cc>";
|
||||
eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
|
||||
eikek = "Eike Kettner <eike.kettner@posteo.de>";
|
||||
ellis = "Ellis Whitehead <nixos@ellisw.net>";
|
||||
emery = "Emery Hemingway <emery@vfemail.net>";
|
||||
ertes = "Ertugrul Söylemez <ertesx@gmx.de>";
|
||||
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
||||
falsifian = "James Cook <james.cook@utoronto.ca>";
|
||||
flosse = "Markus Kohlhase <mail@markus-kohlhase.de>";
|
||||
fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>";
|
||||
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
|
||||
ftrvxmtrx = "Siarhei Zirukin <ftrvxmtrx@gmail.com>";
|
||||
funfunctor = "Edward O'Callaghan <eocallaghan@alterapraxis.com>";
|
||||
fuuzetsu = "Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>";
|
||||
gal_bolle = "Florent Becker <florent.becker@ens-lyon.org>";
|
||||
garbas = "Rok Garbas <rok@garbas.si>";
|
||||
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
|
||||
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
|
||||
guibert = "David Guibert <david.guibert@gmail.com>";
|
||||
henrytill = "Henry Till <henrytill@gmail.com>";
|
||||
hinton = "Tom Hinton <t@larkery.com>";
|
||||
hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>";
|
||||
ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>";
|
||||
iElectric = "Domen Kozar <domen@dev.si>";
|
||||
iyzsong = "Song Wenwu <iyzsong@gmail.com>";
|
||||
jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>";
|
||||
jcumming = "Jack Cummings <jack@mudshark.org>";
|
||||
jgeerds = "Jascha Geerds <jg@ekby.de>";
|
||||
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
|
||||
joachifm = "Joachim Fasting <joachifm@fastmail.fm>";
|
||||
joamaki = "Jussi Maki <joamaki@gmail.com>";
|
||||
joelteon = "Joel Taylor <me@joelt.io>";
|
||||
jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>";
|
||||
jwiegley = "John Wiegley <johnw@newartisans.com>";
|
||||
jzellner = "Jeff Zellner <jeffz@eml.cc>";
|
||||
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
|
||||
koral = "Koral <koral@mailoo.org>";
|
||||
kovirobi = "Kovacsics Robert <kovirobi@gmail.com>";
|
||||
kragniz = "Louis Taylor <kragniz@gmail.com>";
|
||||
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
|
||||
lethalman = "Luca Bruno <lucabru@src.gnome.org>";
|
||||
lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>";
|
||||
linquize = "Linquize <linquize@yahoo.com.hk>";
|
||||
lovek323 = "Jason O'Conal <jason@oconal.id.au>";
|
||||
ludo = "Ludovic Courtès <ludo@gnu.org>";
|
||||
madjar = "Georges Dubus <georges.dubus@compiletoi.net>";
|
||||
magnetophon = "Bart Brouns <bart@magnetophon.nl>";
|
||||
manveru = "Michael Fellinger <m.fellinger@gmail.com>";
|
||||
marcweber = "Marc Weber <marco-oweber@gmx.de>";
|
||||
matejc = "Matej Cotman <cotman.matej@gmail.com>";
|
||||
meditans = "Carlo Nucera <meditans@gmail.com>";
|
||||
meisternu = "Matt Miemiec <meister@krutt.org>";
|
||||
michelk = "Michel Kuhlmann <michel@kuhlmanns.info>";
|
||||
modulistic = "Pablo Costa <modulistic@gmail.com>";
|
||||
mornfall = "Petr Ročkai <me@mornfall.net>";
|
||||
MP2E = "Cray Elliott <MP2E@archlinux.us>";
|
||||
msackman = "Matthew Sackman <matthew@wellquite.org>";
|
||||
mtreskin = "Max Treskin <zerthurd@gmail.com>";
|
||||
muflax = "Stefan Dorn <mail@muflax.com>";
|
||||
nathan-gs = "Nathan Bijnens <nathan@nathan.gs>";
|
||||
nckx = "Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>";
|
||||
notthemessiah = "Brian Cohen <brian.cohen.88@gmail.com>";
|
||||
nslqqq = "Nikita Mikhailov <nslqqq@gmail.com>";
|
||||
ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
|
||||
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
|
||||
olcai = "Erik Timan <dev@timan.info>";
|
||||
orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
|
||||
page = "Carles Pagès <page@cubata.homelinux.net>";
|
||||
pashev = "Igor Pashev <pashev.igor@gmail.com>";
|
||||
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
|
||||
pierron = "Nicolas B. Pierron <nixos@nbp.name>";
|
||||
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
|
||||
pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>";
|
||||
plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>";
|
||||
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
||||
pSub = "Pascal Wittmann <mail@pascal-wittmann.de>";
|
||||
puffnfresh = "Brian McKenna <brian@brianmckenna.org>";
|
||||
qknight = "Joachim Schiele <js@lastlog.de>";
|
||||
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>";
|
||||
rickynils = "Rickard Nilsson <rickynils@gmail.com>";
|
||||
rob = "Rob Vermaas <rob.vermaas@gmail.com>";
|
||||
robberer = "Longrin Wischnewski <robberer@freakmail.de>";
|
||||
roconnor = "Russell O'Connor <roconnor@theorem.ca>";
|
||||
roelof = "Roelof Wobben <rwobben@hotmail.com>";
|
||||
romildo = "José Romildo Malaquias <malaquias@gmail.com>";
|
||||
rszibele = "Richard Szibele <richard_szibele@hotmail.com>";
|
||||
rycee = "Robert Helgesson <robert@rycee.net>";
|
||||
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
|
||||
schristo = "Scott Christopher <schristopher@konputa.com>";
|
||||
sepi = "Raffael Mancini <raffael@mancini.lu>";
|
||||
shell = "Shell Turner <cam.turn@gmail.com>";
|
||||
shlevy = "Shea Levy <shea@shealevy.com>";
|
||||
simons = "Peter Simons <simons@cryp.to>";
|
||||
sjmackenzie = "Stewart Mackenzie <setori88@gmail.com>";
|
||||
skeidel = "Sven Keidel <svenkeidel@gmail.com>";
|
||||
smironov = "Sergey Mironov <ierton@gmail.com>";
|
||||
sprock = "Roger Mason <rmason@mun.ca>";
|
||||
spwhitt = "Spencer Whitt <sw@swhitt.me>";
|
||||
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
|
||||
tailhook = "Paul Colomiets <paul@colomiets.name>";
|
||||
thammers = "Tobias Hammerschmidt <jawr@gmx.de>";
|
||||
the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>";
|
||||
thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
|
||||
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
|
||||
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
|
||||
tstrobel = "Thomas Strobel <ts468@cam.ac.uk>";
|
||||
ttuegel = "Thomas Tuegel <ttuegel@gmail.com>";
|
||||
tv = "Tomislav Viljetić <tv@shackspace.de>";
|
||||
twey = "James ‘Twey’ Kay <twey@twey.co.uk>";
|
||||
urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>";
|
||||
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
||||
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
||||
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
||||
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
||||
viric = "Lluís Batlle i Rossell <viric@viric.name>";
|
||||
vizanto = "Danny Wilson <danny@prime.vc>";
|
||||
vlstill = "Vladimír Štill <xstill@fi.muni.cz>";
|
||||
vozz = "Oliver Hunt <oliver.huntuk@gmail.com>";
|
||||
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
|
||||
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
|
||||
wjlroe = "William Roe <willroe@gmail.com>";
|
||||
wkennington = "William A. Kennington III <william@wkennington.com>";
|
||||
wmertens = "Wout Mertens <Wout.Mertens@gmail.com>";
|
||||
wscott = "Wayne Scott <wsc9tt@gmail.com>";
|
||||
wyvie = "Elijah Rum <elijahrum@gmail.com>";
|
||||
yarr = "Dmitry V. <savraz@gmail.com>";
|
||||
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
|
||||
zef = "Zef Hemel <zef@zef.me>";
|
||||
zimbatm = "zimbatm <zimbatm@zimbatm.com>";
|
||||
zoomulator = "Kim Simmons <zoomulator@gmail.com>";
|
||||
Gonzih = "Max Gonzih <gonzih@gmail.com>";
|
||||
}
|
||||
66
lib/meta.nix
66
lib/meta.nix
@@ -1,66 +0,0 @@
|
||||
/* Some functions for manipulating meta attributes, as well as the
|
||||
name attribute. */
|
||||
|
||||
let lib = import ./default.nix;
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
|
||||
/* Add to or override the meta attributes of the given
|
||||
derivation.
|
||||
|
||||
Example:
|
||||
addMetaAttrs {description = "Bla blah";} somePkg
|
||||
*/
|
||||
addMetaAttrs = newAttrs: drv:
|
||||
drv // { meta = (drv.meta or {}) // newAttrs; };
|
||||
|
||||
|
||||
/* Change the symbolic name of a package for presentation purposes
|
||||
(i.e., so that nix-env users can tell them apart).
|
||||
*/
|
||||
setName = name: drv: drv // {inherit name;};
|
||||
|
||||
|
||||
/* Like `setName', but takes the previous name as an argument.
|
||||
|
||||
Example:
|
||||
updateName (oldName: oldName + "-experimental") somePkg
|
||||
*/
|
||||
updateName = updater: drv: drv // {name = updater (drv.name);};
|
||||
|
||||
|
||||
/* Append a suffix to the name of a package (before the version
|
||||
part). */
|
||||
appendToName = suffix: updateName (name:
|
||||
let x = builtins.parseDrvName name; in "${x.name}-${suffix}-${x.version}");
|
||||
|
||||
|
||||
/* Apply a function to each derivation and only to derivations in an attrset
|
||||
*/
|
||||
mapDerivationAttrset = f: set: lib.mapAttrs (name: pkg: if lib.isDerivation pkg then (f pkg) else pkg) set;
|
||||
|
||||
|
||||
/* Decrease the nix-env priority of the package, i.e., other
|
||||
versions/variants of the package will be preferred.
|
||||
*/
|
||||
lowPrio = drv: addMetaAttrs { priority = "10"; } drv;
|
||||
|
||||
|
||||
/* Apply lowPrio to an attrset with derivations
|
||||
*/
|
||||
lowPrioSet = set: mapDerivationAttrset lowPrio set;
|
||||
|
||||
|
||||
/* Increase the nix-env priority of the package, i.e., this
|
||||
version/variant of the package will be preferred.
|
||||
*/
|
||||
hiPrio = drv: addMetaAttrs { priority = "-10"; } drv;
|
||||
|
||||
|
||||
/* Apply hiPrio to an attrset with derivations
|
||||
*/
|
||||
hiPrioSet = set: mapDerivationAttrset hiPrio set;
|
||||
|
||||
}
|
||||
426
lib/misc.nix
426
lib/misc.nix
@@ -1,426 +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;
|
||||
deepOverride = a : (base.passthru.function ((lib.mapAttrs (lib.deepOverrider a) base.passthru.args) // a));
|
||||
} ;
|
||||
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 [] [];
|
||||
|
||||
genericClosure = builtins.genericClosure or lazyGenericClosure;
|
||||
|
||||
innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else
|
||||
innerModifySumArgs f x (a // b);
|
||||
modifySumArgs = f: x: innerModifySumArgs f x {};
|
||||
|
||||
|
||||
innerClosePropagation = acc : xs :
|
||||
if xs == []
|
||||
then acc
|
||||
else let y = head xs;
|
||||
ys = tail xs;
|
||||
in if ! isAttrs y
|
||||
then innerClosePropagation acc ys
|
||||
else let acc' = [y] ++ acc;
|
||||
in innerClosePropagation
|
||||
acc'
|
||||
(uniqList { inputList = (maybeAttrNullable "propagatedBuildInputs" [] y)
|
||||
++ (maybeAttrNullable "propagatedNativeBuildInputs" [] y)
|
||||
++ ys;
|
||||
acc = acc';
|
||||
}
|
||||
);
|
||||
|
||||
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
|
||||
|
||||
# calls a function (f attr value ) for each record item. returns a list
|
||||
mapAttrsFlatten = f : r : map (attr: f attr r.${attr}) (attrNames r);
|
||||
|
||||
# attribute set containing one attribute
|
||||
nvs = name : value : listToAttrs [ (nameValuePair name value) ];
|
||||
# adds / replaces an attribute of an attribute set
|
||||
setAttr = set : name : v : set // (nvs name v);
|
||||
|
||||
# setAttrMerge (similar to mergeAttrsWithFunc but only merges the values of a particular name)
|
||||
# setAttrMerge "a" [] { a = [2];} (x : x ++ [3]) -> { a = [2 3]; }
|
||||
# setAttrMerge "a" [] { } (x : x ++ [3]) -> { a = [ 3]; }
|
||||
setAttrMerge = name : default : attrs : f :
|
||||
setAttr attrs name (f (maybeAttr name default attrs));
|
||||
|
||||
# Using f = a : b = b the result is similar to //
|
||||
# merge attributes with custom function handling the case that the attribute
|
||||
# exists in both sets
|
||||
mergeAttrsWithFunc = f : set1 : set2 :
|
||||
fold (n: set : if set ? ${n}
|
||||
then setAttr set n (f set.${n} set2.${n})
|
||||
else set )
|
||||
(set2 // set1) (attrNames set2);
|
||||
|
||||
# merging two attribute set concatenating the values of same attribute names
|
||||
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
|
||||
mergeAttrsConcatenateValues = mergeAttrsWithFunc ( a : b : (toList a) ++ (toList b) );
|
||||
|
||||
# merges attributes using //, if a name exisits in both attributes
|
||||
# an error will be triggered unless its listed in mergeLists
|
||||
# so you can mergeAttrsNoOverride { buildInputs = [a]; } { buildInputs = [a]; } {} to get
|
||||
# { buildInputs = [a b]; }
|
||||
# merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs?
|
||||
# in these cases the first buildPhase will override the second one
|
||||
# ! deprecated, use mergeAttrByFunc instead
|
||||
mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
|
||||
overrideSnd ? [ "buildPhase" ]
|
||||
} : attrs1 : attrs2 :
|
||||
fold (n: set :
|
||||
setAttr set n ( if set ? ${n}
|
||||
then # merge
|
||||
if elem n mergeLists # attribute contains list, merge them by concatenating
|
||||
then attrs2.${n} ++ attrs1.${n}
|
||||
else if elem n overrideSnd
|
||||
then attrs1.${n}
|
||||
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
|
||||
else attrs2.${n} # add attribute not existing in attr1
|
||||
)) attrs1 (attrNames attrs2);
|
||||
|
||||
|
||||
# example usage:
|
||||
# mergeAttrByFunc {
|
||||
# inherit mergeAttrBy; # defined below
|
||||
# buildInputs = [ a b ];
|
||||
# } {
|
||||
# buildInputs = [ c d ];
|
||||
# };
|
||||
# will result in
|
||||
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
|
||||
# is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using
|
||||
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
|
||||
mergeAttrByFunc = x : y :
|
||||
let
|
||||
mergeAttrBy2 = { mergeAttrBy=lib.mergeAttrs; }
|
||||
// (maybeAttr "mergeAttrBy" {} x)
|
||||
// (maybeAttr "mergeAttrBy" {} y); in
|
||||
fold lib.mergeAttrs {} [
|
||||
x y
|
||||
(mapAttrs ( a : v : # merge special names using given functions
|
||||
if x ? ${a}
|
||||
then if y ? ${a}
|
||||
then v x.${a} y.${a} # both have attr, use merge func
|
||||
else x.${a} # only x has attr
|
||||
else y.${a} # only y has attr)
|
||||
) (removeAttrs mergeAttrBy2
|
||||
# don't merge attrs which are neither in x nor y
|
||||
(filter (a: ! x ? ${a} && ! y ? ${a})
|
||||
(attrNames mergeAttrBy2))
|
||||
)
|
||||
)
|
||||
];
|
||||
mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
|
||||
mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"];
|
||||
|
||||
# merge attrs based on version key into mkDerivation args, see mergeAttrBy to learn about smart merge defaults
|
||||
#
|
||||
# This function is best explained by an example:
|
||||
#
|
||||
# {version ? "2.x"} :
|
||||
#
|
||||
# mkDerivation (mergeAttrsByVersion "package-name" version
|
||||
# { # version specific settings
|
||||
# "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool]; };
|
||||
# "2.x" = { src = ..; };
|
||||
# }
|
||||
# { // shared settings
|
||||
# buildInputs = [ common build inputs ];
|
||||
# meta = { .. }
|
||||
# }
|
||||
# )
|
||||
#
|
||||
# Please note that e.g. Eelco Dolstra usually prefers having one file for
|
||||
# each version. On the other hand there are valuable additional design goals
|
||||
# - readability
|
||||
# - do it once only
|
||||
# - try to avoid duplication
|
||||
#
|
||||
# Marc Weber and Michael Raskin sometimes prefer keeping older
|
||||
# versions around for testing and regression tests - as long as its cheap to
|
||||
# do so.
|
||||
#
|
||||
# Very often it just happens that the "shared" code is the bigger part.
|
||||
# Then using this function might be appropriate.
|
||||
#
|
||||
# Be aware that its easy to cause recompilations in all versions when using
|
||||
# this function - also if derivations get too complex splitting into multiple
|
||||
# files is the way to go.
|
||||
#
|
||||
# See misc.nix -> versionedDerivation
|
||||
# discussion: nixpkgs: pull/310
|
||||
mergeAttrsByVersion = name: version: attrsByVersion: base:
|
||||
mergeAttrsByFuncDefaultsClean [ { name = "${name}-${version}"; } base (maybeAttr version (throw "bad version ${version} for ${name}") attrsByVersion)];
|
||||
|
||||
# sane defaults (same name as attr name so that inherit can be used)
|
||||
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
|
||||
listToAttrs (map (n : nameValuePair n lib.concat)
|
||||
[ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ])
|
||||
// listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
|
||||
// listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
|
||||
;
|
||||
|
||||
# prepareDerivationArgs tries to make writing configurable derivations easier
|
||||
# example:
|
||||
# prepareDerivationArgs {
|
||||
# mergeAttrBy = {
|
||||
# myScript = x : y : x ++ "\n" ++ y;
|
||||
# };
|
||||
# cfg = {
|
||||
# readlineSupport = true;
|
||||
# };
|
||||
# flags = {
|
||||
# readline = {
|
||||
# set = {
|
||||
# configureFlags = [ "--with-compiler=${compiler}" ];
|
||||
# buildInputs = [ compiler ];
|
||||
# pass = { inherit compiler; READLINE=1; };
|
||||
# assertion = compiler.dllSupport;
|
||||
# myScript = "foo";
|
||||
# };
|
||||
# unset = { configureFlags = ["--without-compiler"]; };
|
||||
# };
|
||||
# };
|
||||
# src = ...
|
||||
# buildPhase = '' ... '';
|
||||
# name = ...
|
||||
# myScript = "bar";
|
||||
# };
|
||||
# if you don't have need for unset you can omit the surrounding set = { .. } attr
|
||||
# all attrs except flags cfg and mergeAttrBy will be merged with the
|
||||
# additional data from flags depending on config settings
|
||||
# It's used in composableDerivation in all-packages.nix. It's also used
|
||||
# heavily in the new python and libs implementation
|
||||
#
|
||||
# should we check for misspelled cfg options?
|
||||
# TODO use args.mergeFun here as well?
|
||||
prepareDerivationArgs = args:
|
||||
let args2 = { cfg = {}; flags = {}; } // args;
|
||||
flagName = name : "${name}Support";
|
||||
cfgWithDefaults = (listToAttrs (map (n : nameValuePair (flagName n) false) (attrNames args2.flags)))
|
||||
// args2.cfg;
|
||||
opts = attrValues (mapAttrs (a : v :
|
||||
let v2 = if v ? set || v ? unset then v else { set = v; };
|
||||
n = if cfgWithDefaults.${flagName a} then "set" else "unset";
|
||||
attr = maybeAttr n {} v2; in
|
||||
if (maybeAttr "assertion" true attr)
|
||||
then attr
|
||||
else throw "assertion of flag ${a} of derivation ${args.name} failed"
|
||||
) args2.flags );
|
||||
in removeAttrs
|
||||
(mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
|
||||
["flags" "cfg" "mergeAttrBy" ];
|
||||
|
||||
|
||||
nixType = x:
|
||||
if isAttrs x then
|
||||
if x ? outPath then "derivation"
|
||||
else "aattrs"
|
||||
else if isFunction x then "function"
|
||||
else if isList x then "list"
|
||||
else if x == true then "bool"
|
||||
else if x == false then "bool"
|
||||
else if x == null then "null"
|
||||
else if isInt x then "int"
|
||||
else "string";
|
||||
|
||||
}
|
||||
363
lib/modules.nix
363
lib/modules.nix
@@ -1,363 +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. */
|
||||
evalModules = { modules, prefix ? [], args ? {}, check ? true }:
|
||||
let
|
||||
args' = args // { lib = import ./.; } // result;
|
||||
closed = closeModules modules args';
|
||||
# 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.
|
||||
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 check && set ? _definedNames then
|
||||
fold (m: res:
|
||||
fold (name: res:
|
||||
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
|
||||
unifyModuleSyntax file "${parentKey}:anon-${toString n}" (applyIfFunction x args)
|
||||
else
|
||||
unifyModuleSyntax (toString x) (toString x) (applyIfFunction (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 = f: arg: if isFunction f then f arg else f;
|
||||
|
||||
/* 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 = concatLists (map (m:
|
||||
if m.options ? ${name}
|
||||
then [ { inherit (m) file; options = m.options.${name}; } ]
|
||||
else []
|
||||
) options);
|
||||
# Get all submodules that define ‘name’.
|
||||
defns = concatLists (map (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;
|
||||
# Process mkMerge and mkIf properties.
|
||||
defns' = concatMap (m:
|
||||
if m.config ? ${name}
|
||||
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties m.config.${name})
|
||||
else []
|
||||
) 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:
|
||||
fold (opt: res:
|
||||
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;
|
||||
addModuleFile = m:
|
||||
if isFunction m then args: { _file = opt.file; } // (m args)
|
||||
else { _file = opt.file; } // m;
|
||||
coerceOption = file: opt:
|
||||
if isFunction opt then args: { _file = file; } // (opt args)
|
||||
else { _file = file; options = opt; };
|
||||
getSubModules = opt.options.type.getSubModules or null;
|
||||
submodules =
|
||||
if getSubModules != null then map addModuleFile getSubModules ++ res.options
|
||||
else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options
|
||||
else res.options;
|
||||
in opt.options // res //
|
||||
{ declarations = [opt.file] ++ res.declarations;
|
||||
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
|
||||
# Process mkOverride properties, adding in the default
|
||||
# value specified in the option declaration (if any).
|
||||
defsFinal' = filterOverrides
|
||||
((if opt ? default then [{ file = head opt.declarations; value = mkOptionDefault opt.default; }] else []) ++ defs);
|
||||
# Sort mkOrder properties.
|
||||
defsFinal =
|
||||
# Avoid sorting if we don't have to.
|
||||
if any (def: def.value._type or "" == "order") defsFinal'
|
||||
then sortProperties defsFinal'
|
||||
else defsFinal';
|
||||
files = map (def: def.file) defsFinal;
|
||||
# Type-check the remaining definitions, and merge them if
|
||||
# possible.
|
||||
merged =
|
||||
if defsFinal == [] then
|
||||
throw "The option `${showOption loc}' is used but not defined."
|
||||
else
|
||||
fold (def: res:
|
||||
if opt.type.check def.value then res
|
||||
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.")
|
||||
(opt.type.merge loc defsFinal) defsFinal;
|
||||
# Finally, apply the ‘apply’ function to the merged
|
||||
# value. This allows options to yield a value computed
|
||||
# from the definitions.
|
||||
value = (opt.apply or id) merged;
|
||||
in opt //
|
||||
{ value = addErrorContext "while evaluating the option `${showOption loc}':" value;
|
||||
definitions = map (def: def.value) defsFinal;
|
||||
isDefined = defsFinal != [];
|
||||
inherit files;
|
||||
};
|
||||
|
||||
/* 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;
|
||||
min = x: y: if x < y then x else y;
|
||||
highestPrio = fold (def: prio: 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;
|
||||
|
||||
|
||||
/* Compatibility. */
|
||||
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
|
||||
|
||||
}
|
||||
137
lib/options.nix
137
lib/options.nix
@@ -1,137 +0,0 @@
|
||||
# Nixpkgs/NixOS option handling.
|
||||
|
||||
let lib = import ./default.nix; in
|
||||
|
||||
with import ./trivial.nix;
|
||||
with import ./lists.nix;
|
||||
with import ./misc.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.
|
||||
, 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 fold lib.mergeAttrs {} list
|
||||
else if all isBool list then fold 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)}.";
|
||||
|
||||
/* Obsolete, will remove soon. Specify an option type or apply
|
||||
function instead. */
|
||||
mergeTypedOption = typeName: predicate: merge: loc: list:
|
||||
let list' = map (x: x.value) list; in
|
||||
if all predicate list then merge list'
|
||||
else throw "Expected a ${typeName}.";
|
||||
|
||||
mergeEnableOption = mergeTypedOption "boolean"
|
||||
(x: true == x || false == x) (fold lib.or false);
|
||||
|
||||
mergeListOption = mergeTypedOption "list" isList concatLists;
|
||||
|
||||
mergeStringOption = mergeTypedOption "string" isString lib.concatStrings;
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
fold (opt: rest:
|
||||
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;
|
||||
}
|
||||
// (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
|
||||
# FIXME: expensive, O(n^2)
|
||||
[ docOption ] ++ subOptions ++ rest) [] (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,16 +0,0 @@
|
||||
let lists = import ./lists.nix; in
|
||||
|
||||
rec {
|
||||
gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */
|
||||
linux = ["i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "mips64el-linux"];
|
||||
darwin = ["x86_64-darwin"];
|
||||
freebsd = ["i686-freebsd" "x86_64-freebsd"];
|
||||
openbsd = ["i686-openbsd" "x86_64-openbsd"];
|
||||
netbsd = ["i686-netbsd" "x86_64-netbsd"];
|
||||
cygwin = ["i686-cygwin" "x86_64-cygwin"];
|
||||
unix = linux ++ darwin ++ freebsd ++ openbsd;
|
||||
all = linux ++ darwin ++ cygwin ++ freebsd ++ openbsd;
|
||||
none = [];
|
||||
allBut = platforms: lists.filter (x: !(builtins.elem x platforms)) all;
|
||||
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux"];
|
||||
}
|
||||
@@ -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; };
|
||||
|
||||
}
|
||||
211
lib/strings.nix
211
lib/strings.nix
@@ -1,211 +0,0 @@
|
||||
/* String manipulation functions. */
|
||||
|
||||
let lib = import ./default.nix;
|
||||
|
||||
inherit (builtins) length;
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
inherit (builtins) stringLength substring head tail isString;
|
||||
|
||||
|
||||
# Concatenate a list of strings.
|
||||
concatStrings = lib.fold (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 [(head list) separator]
|
||||
++ (intersperse separator (tail list));
|
||||
|
||||
|
||||
# Concatenate a list of strings with a separator between each element, e.g.
|
||||
# concatStringsSep " " ["foo" "bar" "xyzzy"] == "foo bar xyzzy"
|
||||
concatStringsSep = separator: list:
|
||||
concatStrings (intersperse separator list);
|
||||
|
||||
concatMapStringsSep = sep: f: list: concatStringsSep sep (map f list);
|
||||
concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap f list);
|
||||
|
||||
|
||||
# Construct a Unix-style search path consisting of each `subDir"
|
||||
# directory of the given list of packages. For example,
|
||||
# `makeSearchPath "bin" ["x" "y" "z"]' returns "x/bin:y/bin:z/bin".
|
||||
makeSearchPath = subDir: packages:
|
||||
concatStringsSep ":" (map (path: path + "/" + subDir) packages);
|
||||
|
||||
|
||||
# Construct a library search path (such as RPATH) containing the
|
||||
# libraries for a set of packages, e.g. "${pkg1}/lib:${pkg2}/lib:...".
|
||||
makeLibraryPath = makeSearchPath "lib";
|
||||
|
||||
|
||||
# Idem for Perl search paths.
|
||||
makePerlPath = makeSearchPath "lib/perl5/site_perl";
|
||||
|
||||
|
||||
# Dependening on the boolean `cond', return either the given string
|
||||
# or the empty string.
|
||||
optionalString = cond: string: if cond then string else "";
|
||||
|
||||
|
||||
# Determine whether a string has given prefix/suffix.
|
||||
hasPrefix = pref: str:
|
||||
eqStrings (substring 0 (stringLength pref) str) pref;
|
||||
hasSuffix = suff: str:
|
||||
let
|
||||
lenStr = stringLength str;
|
||||
lenSuff = stringLength suff;
|
||||
in lenStr >= lenSuff &&
|
||||
eqStrings (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: let l = stringLength s; in
|
||||
if l == 0
|
||||
then []
|
||||
else map (p: substring p 1 s) (lib.range 0 (l - 1));
|
||||
|
||||
|
||||
# Manipulate a string charcater by character and replace them by strings
|
||||
# before concatenating the results.
|
||||
stringAsChars = f: s:
|
||||
concatStrings (
|
||||
map f (stringToCharacters s)
|
||||
);
|
||||
|
||||
|
||||
# same as vim escape function.
|
||||
# Each character contained in list is prefixed by "\"
|
||||
escape = list : string :
|
||||
stringAsChars (c: if lib.elem c list then "\\${c}" else c) string;
|
||||
|
||||
|
||||
# still ugly slow. But more correct now
|
||||
# [] for zsh
|
||||
escapeShellArg = lib.escape (stringToCharacters "\\ ';$`()|<>\t*[]");
|
||||
|
||||
|
||||
# replace characters by their substitutes. This function is equivalent to
|
||||
# the `tr' command except that one character can be replace by multiple
|
||||
# ones. e.g.,
|
||||
# replaceChars ["<" ">"] ["<" ">"] "<foo>" returns "<foo>".
|
||||
replaceChars = del: new: s:
|
||||
let
|
||||
subst = c:
|
||||
(lib.fold
|
||||
(sub: res: if sub.fst == c then sub else res)
|
||||
{fst = c; snd = c;} (lib.zipLists del new)
|
||||
).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;
|
||||
|
||||
# Compares strings not requiring context equality
|
||||
# Obviously, a workaround but works on all Nix versions
|
||||
eqStrings = a: b: addContextFrom b a == addContextFrom 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 && eqStrings suf (substring (sLen - sufLen) sufLen s) then
|
||||
substring 0 (sLen - sufLen) s
|
||||
else
|
||||
s;
|
||||
|
||||
# Return true iff string v1 denotes a version older than v2.
|
||||
versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1;
|
||||
|
||||
|
||||
# Return true iff string v1 denotes a version equal to or newer than v2.
|
||||
versionAtLeast = v1: v2: !versionOlder v1 v2;
|
||||
|
||||
|
||||
# Get the version of the specified derivation, as specified in its
|
||||
# ‘name’ attribute.
|
||||
getVersion = drv: (builtins.parseDrvName drv.name).version;
|
||||
|
||||
|
||||
# Extract name with version from URL. Ask for separator which is
|
||||
# supposed to start extension
|
||||
nameFromURL = url: sep: let
|
||||
components = splitString "/" url;
|
||||
filename = lib.last components;
|
||||
name = builtins.head (splitString sep filename);
|
||||
in
|
||||
assert ! eqStrings 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}";
|
||||
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
isDarwin = matchAttrs { kernel = kernels.darwin; };
|
||||
isLinux = matchAttrs { kernel = kernels.linux; };
|
||||
isi686 = matchAttrs { cpu = cpuTypes.i686; };
|
||||
is64Bit = matchAttrs { cpu = { bits = 64; }; };
|
||||
|
||||
|
||||
# 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;
|
||||
}
|
||||
113
lib/tests.nix
113
lib/tests.nix
@@ -1,113 +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];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
with {
|
||||
inherit (import ./lists.nix) deepSeqList;
|
||||
inherit (import ./attrsets.nix) deepSeqAttrs;
|
||||
};
|
||||
|
||||
rec {
|
||||
|
||||
# Identity function.
|
||||
id = x: x;
|
||||
|
||||
# Constant function.
|
||||
const = x: y: x;
|
||||
|
||||
# Named versions corresponding to some builtin operators.
|
||||
concat = x: y: x ++ y;
|
||||
or = x: y: x || y;
|
||||
and = x: y: x && y;
|
||||
mergeAttrs = x: y: x // y;
|
||||
|
||||
# Take a function and evaluate it with its own returned value.
|
||||
fix = f: let result = f result; in result;
|
||||
|
||||
# Flip the order of the arguments of a binary function.
|
||||
flip = f: a: b: f b a;
|
||||
|
||||
# `seq x y' evaluates x, then returns y. That is, it forces strict
|
||||
# evaluation of its first argument.
|
||||
seq = x: y: if x == null then y else y;
|
||||
|
||||
# Like `seq', but recurses into lists and attribute sets to force evaluation
|
||||
# of all list elements/attributes.
|
||||
deepSeq = x: y:
|
||||
if builtins.isList x
|
||||
then deepSeqList x y
|
||||
else if builtins.isAttrs x
|
||||
then deepSeqAttrs x y
|
||||
else seq x y;
|
||||
|
||||
# Pull in some builtins not included elsewhere.
|
||||
inherit (builtins)
|
||||
pathExists readFile isBool isFunction
|
||||
isInt add sub lessThan;
|
||||
|
||||
# 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. This is useful to
|
||||
inNixShell = builtins.getEnv "IN_NIX_SHELL" == "1";
|
||||
|
||||
}
|
||||
230
lib/types.nix
230
lib/types.nix
@@ -1,230 +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;
|
||||
|
||||
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 = loc: fold (x: y: x.value || y) false;
|
||||
};
|
||||
|
||||
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: fold (def: mergeAttrs def.value) {};
|
||||
};
|
||||
|
||||
# derivation is a reserved keyword.
|
||||
package = mkOptionType {
|
||||
name = "derivation";
|
||||
check = isDerivation;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
path = mkOptionType {
|
||||
name = "path";
|
||||
# Hacky: there is no ‘isPath’ primop.
|
||||
check = x: builtins.unsafeDiscardStringContext (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 = value: isList value && all elemType.check value;
|
||||
merge = loc: defs:
|
||||
concatLists (imap (n: def: imap (m: def':
|
||||
elemType.merge (loc ++ ["[${toString n}-${toString m}]"])
|
||||
[{ inherit (def) file; value = def'; }]) 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 = x: isAttrs x && all elemType.check (attrValues x);
|
||||
merge = loc: defs:
|
||||
zipAttrsWith (name: elemType.merge (loc ++ [name]))
|
||||
# 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:
|
||||
if isList x then listOnly.check x
|
||||
else if isAttrs x then attrOnly.check x
|
||||
else false;
|
||||
merge = loc: defs: attrOnly.merge loc (imap convertIfList defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: loaOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
uniq = elemType: mkOptionType {
|
||||
inherit (elemType) name check;
|
||||
merge = mergeOneOption;
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: uniq (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
nullOr = elemType: mkOptionType {
|
||||
name = "null or ${elemType.name}";
|
||||
check = x: builtins.isNull x || elemType.check x;
|
||||
merge = loc: defs:
|
||||
let nrNulls = count (def: isNull def.value) defs; in
|
||||
if nrNulls == length defs then null
|
||||
else if nrNulls != 0 then
|
||||
throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}."
|
||||
else elemType.merge loc defs;
|
||||
getSubOptions = elemType.getSubOptions;
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: nullOr (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
submodule = opts:
|
||||
let
|
||||
opts' = toList opts;
|
||||
inherit (import ./modules.nix) evalModules;
|
||||
in
|
||||
mkOptionType rec {
|
||||
name = "submodule";
|
||||
check = x: isAttrs x || isFunction x;
|
||||
merge = loc: defs:
|
||||
let
|
||||
coerce = def: if isFunction def then def else { config = def; };
|
||||
modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
|
||||
in (evalModules { inherit modules; args.name = last loc; prefix = loc; }).config;
|
||||
getSubOptions = prefix: (evalModules
|
||||
{ modules = opts'; inherit prefix;
|
||||
# FIXME: hack to get shit to evaluate.
|
||||
args = { name = ""; }; }).options;
|
||||
getSubModules = opts';
|
||||
substSubModules = m: submodule m;
|
||||
};
|
||||
|
||||
enum = values: mkOptionType {
|
||||
name = "one of ${concatStringsSep ", " values}";
|
||||
check = flip elem values;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
either = t1: t2: mkOptionType {
|
||||
name = "${t1.name} or ${t2.name}";
|
||||
check = x: t1.check x || t2.check x;
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
# Obsolete alternative to configOf. It takes its option
|
||||
# declarations from the ‘options’ attribute of containing option
|
||||
# declaration.
|
||||
optionSet = mkOptionType {
|
||||
name = /* builtins.trace "types.optionSet is deprecated; use types.submodule instead" */ "option set";
|
||||
};
|
||||
|
||||
# Augment the given type with an additional type check function.
|
||||
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
*~
|
||||
,*
|
||||
.*.swp
|
||||
.*.swo
|
||||
result
|
||||
result-*
|
||||
/doc/NEWS.html
|
||||
/doc/NEWS.txt
|
||||
/doc/manual.html
|
||||
/doc/manual.pdf
|
||||
.version-suffix
|
||||
|
||||
.DS_Store
|
||||
.git
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM busybox
|
||||
|
||||
RUN dir=`mktemp -d` && trap 'rm -rf "$dir"' EXIT && \
|
||||
wget -O- https://nixos.org/releases/nix/nix-1.7/nix-1.7-x86_64-linux.tar.bz2 | bzcat | tar x -C $dir && \
|
||||
mkdir -m 0755 /nix && USER=root sh $dir/*/install && \
|
||||
echo ". /root/.nix-profile/etc/profile.d/nix.sh" >> /etc/profile
|
||||
|
||||
ADD . /root/nix/nixpkgs
|
||||
ONBUILD ENV NIX_PATH nixpkgs=/root/nix/nixpkgs:nixos=/root/nix/nixpkgs/nixos
|
||||
ONBUILD ENV PATH /root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin
|
||||
ONBUILD ENV ENV /etc/profile
|
||||
ENV ENV /etc/profile
|
||||
62
maintainers/docs/bugs.txt
Normal file
62
maintainers/docs/bugs.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
* 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)
|
||||
|
||||
|
||||
* `ld' on Mac OS X barfs if the timestamp on static libraries has
|
||||
changed (which happens if they are installed through a substitute).
|
||||
|
||||
Typical error:
|
||||
|
||||
/usr/bin/ld: table of contents for archive: libATerm.a is out of
|
||||
date; rerun ranlib(1) (can't load from it)
|
||||
|
||||
Solution: patch ld.
|
||||
|
||||
Non-solution: extend NAR file format to include timestamps. We
|
||||
don't want that because they introduce a source of non-determinism.
|
||||
To catch problems like this one determistically, we should change
|
||||
the timestamp on store objects to 0.
|
||||
|
||||
|
||||
* 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
|
||||
@@ -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
|
||||
32
maintainers/docs/static-initial-env
Normal file
32
maintainers/docs/static-initial-env
Normal file
@@ -0,0 +1,32 @@
|
||||
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
|
||||
|
||||
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.
|
||||
14
maintainers/docs/todo.txt
Normal file
14
maintainers/docs/todo.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
* Patch development/tools/misc/libtool not to search standard
|
||||
directories for libraries (like setup.sh does now). [do we want
|
||||
this?]
|
||||
|
||||
* In setup.sh: add configureFlagsArray or something
|
||||
|
||||
* 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,97 +0,0 @@
|
||||
#! /run/current-system/sw/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use XML::Simple;
|
||||
use File::Basename;
|
||||
use File::Path;
|
||||
use File::Copy 'cp';
|
||||
use IPC::Open2;
|
||||
use Nix::Store;
|
||||
|
||||
my $myDir = dirname($0);
|
||||
|
||||
my $tarballsCache = $ENV{'NIX_TARBALLS_CACHE'} // "/tarballs";
|
||||
|
||||
my $xml = `nix-instantiate --eval-only --xml --strict '<nixpkgs/maintainers/scripts/find-tarballs.nix>'`;
|
||||
die "$0: evaluation failed\n" if $? != 0;
|
||||
|
||||
my $data = XMLin($xml) or die;
|
||||
|
||||
mkpath($tarballsCache);
|
||||
mkpath("$tarballsCache/md5");
|
||||
mkpath("$tarballsCache/sha1");
|
||||
mkpath("$tarballsCache/sha256");
|
||||
|
||||
foreach my $file (@{$data->{list}->{attrs}}) {
|
||||
my $url = $file->{attr}->{url}->{string}->{value};
|
||||
my $algo = $file->{attr}->{type}->{string}->{value};
|
||||
my $hash = $file->{attr}->{hash}->{string}->{value};
|
||||
|
||||
if ($url !~ /^http:/ && $url !~ /^https:/ && $url !~ /^ftp:/ && $url !~ /^mirror:/) {
|
||||
print STDERR "skipping $url (unsupported scheme)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
$url =~ /([^\/]+)$/;
|
||||
my $fn = $1;
|
||||
|
||||
if (!defined $fn) {
|
||||
print STDERR "skipping $url (no file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn =~ /[&?=%]/ || $fn =~ /^\./) {
|
||||
print STDERR "skipping $url (bad character in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn !~ /[a-zA-Z]/) {
|
||||
print STDERR "skipping $url (no letter in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn !~ /[0-9]/) {
|
||||
print STDERR "skipping $url (no digit in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($fn !~ /[-_\.]/) {
|
||||
print STDERR "skipping $url (no dash/dot/underscore in file name)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $dstPath = "$tarballsCache/$fn";
|
||||
|
||||
next if -e $dstPath;
|
||||
|
||||
print "downloading $url to $dstPath...\n";
|
||||
|
||||
next if $ENV{DRY_RUN};
|
||||
|
||||
$ENV{QUIET} = 1;
|
||||
$ENV{PRINT_PATH} = 1;
|
||||
my $fh;
|
||||
my $pid = open($fh, "-|", "nix-prefetch-url", "--type", $algo, $url, $hash) or die;
|
||||
waitpid($pid, 0) or die;
|
||||
if ($? != 0) {
|
||||
print STDERR "failed to fetch $url: $?\n";
|
||||
next;
|
||||
}
|
||||
<$fh>; my $storePath = <$fh>; chomp $storePath;
|
||||
|
||||
die unless -e $storePath;
|
||||
|
||||
cp($storePath, $dstPath) or die;
|
||||
|
||||
my $md5 = hashFile("md5", 0, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/md5/$md5");
|
||||
|
||||
my $sha1 = hashFile("sha1", 0, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/sha1/$sha1");
|
||||
|
||||
my $sha256 = hashFile("sha256", 0, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/sha256/$sha256");
|
||||
|
||||
$sha256 = hashFile("sha256", 1, $storePath) or die;
|
||||
symlink("../$fn", "$tarballsCache/sha256/$sha256");
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Download patches from debian project
|
||||
# Usage $0 debian-patches.txt debian-patches.nix
|
||||
# An example input and output files can be found in applications/graphics/xara/
|
||||
|
||||
DEB_URL=http://patch-tracker.debian.org/patch/series/dl
|
||||
declare -a deb_patches
|
||||
mapfile -t deb_patches < $1
|
||||
|
||||
prefix="${DEB_URL}/${deb_patches[0]}"
|
||||
|
||||
if [[ -n "$2" ]]; then
|
||||
exec 1> $2
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
# Generated by $(basename $0) from $(basename $1)
|
||||
let
|
||||
prefix = "${prefix}";
|
||||
in
|
||||
[
|
||||
EOF
|
||||
for ((i=1;i < ${#deb_patches[@]}; ++i)); do
|
||||
url="${prefix}/${deb_patches[$i]}"
|
||||
sha256=$(nix-prefetch-url $url)
|
||||
echo " {"
|
||||
echo " url = \"\${prefix}/${deb_patches[$i]}\";"
|
||||
echo " sha256 = \"$sha256\";"
|
||||
echo " }"
|
||||
done
|
||||
echo "]"
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
attr=$1
|
||||
|
||||
: ${NIXPKGS=/etc/nixos/nixpkgs}
|
||||
|
||||
tmp=$(mktemp --tmpdir -d nixpkgs-dep-license.XXXXXX)
|
||||
|
||||
exitHandler() {
|
||||
exitCode=$?
|
||||
rm -rf "$tmp"
|
||||
exit $exitCode
|
||||
}
|
||||
|
||||
trap "exitHandler" EXIT
|
||||
|
||||
# fetch the trace and the drvPath of the attribute.
|
||||
nix-instantiate $NIXPKGS -A $attr --show-trace > "$tmp/drvPath" 2> "$tmp/trace" || {
|
||||
cat 1>&2 - "$tmp/trace" <<EOF
|
||||
An error occured while evaluating $attr.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# generate a sed script based on the trace output.
|
||||
sed '
|
||||
\,@:.*:@, {
|
||||
# \1 *.drv file
|
||||
# \2 License terms
|
||||
s,.*@:drv:\(.*\):\(.*\):@.*,s!\1!\1: \2!; t;,
|
||||
s!Str(\\\"\([^,]*\)\\\",\[\])!\1!g
|
||||
b
|
||||
}
|
||||
d
|
||||
' "$tmp/trace" > "$tmp/filter.sed"
|
||||
|
||||
if test $(wc -l "$tmp/filter.sed" | sed 's/ .*//') == 0; then
|
||||
echo 1>&2 "
|
||||
No derivation mentionned in the stack trace. Either your derivation does
|
||||
not use stdenv.mkDerivation or you forgot to use the stdenv adapter named
|
||||
traceDrvLicenses.
|
||||
|
||||
- defaultStdenv = allStdenvs.stdenv;
|
||||
+ defaultStdenv = traceDrvLicenses allStdenvs.stdenv;
|
||||
"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# remove all dependencies which are using stdenv.mkDerivation
|
||||
echo '
|
||||
d
|
||||
' >> "$tmp/filter.sed"
|
||||
|
||||
nix-store -q --tree $(cat "$tmp/drvPath") | sed -f "$tmp/filter.sed"
|
||||
|
||||
exit 0;
|
||||
36
maintainers/scripts/evacuate-urls.sh
Executable file
36
maintainers/scripts/evacuate-urls.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#! /bin/sh -e
|
||||
|
||||
find . -name "*.nix" | while read fn; do
|
||||
|
||||
grep -E '^ *url = ' "$fn" | while read line; do
|
||||
|
||||
if oldURL=$(echo "$line" | sed 's^url = \(.*\);^\1^'); then
|
||||
|
||||
if ! echo "$oldURL" | grep -q -E "www.cs.uu.nl|nix.cs.uu.nl|.stratego-language.org|java.sun.com|ut2004|linuxq3a|RealPlayer|Adbe"; then
|
||||
base=$(basename $oldURL)
|
||||
newURL="http://nix.cs.uu.nl/dist/tarballs/$base"
|
||||
newPath="/data/webserver/dist/tarballs/$base"
|
||||
echo "$fn: $oldURL -> $newURL"
|
||||
|
||||
# if test -e "$newPath"; then
|
||||
# echo "WARNING: $newPath exists!"
|
||||
# else
|
||||
|
||||
if ! test -e "$newPath"; then
|
||||
curl --fail --location --max-redirs 20 "$oldURL" > "$newPath".tmp
|
||||
mv -f "$newPath".tmp "$newPath"
|
||||
|
||||
fi
|
||||
|
||||
sed "s^$oldURL^$newURL^" < "$fn" > "$fn".tmp
|
||||
mv -f "$fn".tmp "$fn"
|
||||
|
||||
# fi
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
done
|
||||
@@ -1,24 +0,0 @@
|
||||
# Evaluate `release.nix' like Hydra would. Too bad nix-instantiate
|
||||
# can't to do this.
|
||||
|
||||
with import ../../lib;
|
||||
|
||||
let
|
||||
trace = if builtins.getEnv "VERBOSE" == "1" then builtins.trace else (x: y: y);
|
||||
|
||||
rel = removeAttrs (import ../../pkgs/top-level/release.nix { }) [ "tarball" "unstable" "xbursttools" ];
|
||||
|
||||
# Add the ‘recurseForDerivations’ attribute to ensure that
|
||||
# nix-instantiate recurses into nested attribute sets.
|
||||
recurse = path: attrs:
|
||||
if (builtins.tryEval attrs).success then
|
||||
if isDerivation attrs
|
||||
then
|
||||
if (builtins.tryEval attrs.drvPath).success
|
||||
then { inherit (attrs) name drvPath; }
|
||||
else { failed = true; }
|
||||
else { recurseForDerivations = true; } //
|
||||
mapAttrs (n: v: let path' = path ++ [n]; in trace path' (recurse path' v)) attrs
|
||||
else { };
|
||||
|
||||
in recurse [] rel
|
||||
@@ -1,45 +0,0 @@
|
||||
# This expression returns a list of all fetchurl calls used by all
|
||||
# packages reachable from release.nix.
|
||||
|
||||
with import ../.. { };
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
root = removeAttrs (import ../../pkgs/top-level/release.nix { }) [ "tarball" "unstable" ];
|
||||
|
||||
uniqueUrls = map (x: x.file) (genericClosure {
|
||||
startSet = map (file: { key = file.url; inherit file; }) urls;
|
||||
operator = const [ ];
|
||||
});
|
||||
|
||||
urls = map (drv: { url = head drv.urls; hash = drv.outputHash; type = drv.outputHashAlgo; }) fetchurlDependencies;
|
||||
|
||||
fetchurlDependencies = filter (drv: drv.outputHash or "" != "" && drv ? urls) dependencies;
|
||||
|
||||
dependencies = map (x: x.value) (genericClosure {
|
||||
startSet = map keyDrv (derivationsIn' root);
|
||||
operator = { key, value }: map keyDrv (immediateDependenciesOf value);
|
||||
});
|
||||
|
||||
derivationsIn' = x:
|
||||
if !canEval x then []
|
||||
else if isDerivation x then optional (canEval x.drvPath) x
|
||||
else if isList x then concatLists (map derivationsIn' x)
|
||||
else if isAttrs x then concatLists (mapAttrsToList (n: v: derivationsIn' v) x)
|
||||
else [ ];
|
||||
|
||||
keyDrv = drv: if canEval drv.drvPath then { key = drv.drvPath; value = drv; } else { };
|
||||
|
||||
immediateDependenciesOf = drv:
|
||||
concatLists (mapAttrsToList (n: v: derivationsIn v) (removeAttrs drv ["meta" "passthru"]));
|
||||
|
||||
derivationsIn = x:
|
||||
if !canEval x then []
|
||||
else if isDerivation x then optional (canEval x.drvPath) x
|
||||
else if isList x then concatLists (map derivationsIn x)
|
||||
else [ ];
|
||||
|
||||
canEval = val: (builtins.tryEval val).success;
|
||||
|
||||
in uniqueUrls
|
||||
@@ -1,95 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
GNOME_FTP="ftp.gnome.org/pub/GNOME/sources"
|
||||
|
||||
project=$1
|
||||
|
||||
if [ "$project" == "--help" ]; then
|
||||
echo "Usage: $0 project [major.minor]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
baseVersion=$2
|
||||
|
||||
if [ -z "$project" ]; then
|
||||
echo "No project specified, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# curl -l ftp://... doesn't work from my office in HSE, and I don't want to have
|
||||
# any conversations with sysadmin. Somehow lftp works.
|
||||
if [ "$FTP_CLIENT" = "lftp" ]; then
|
||||
ls_ftp() {
|
||||
lftp -c "open $1; cls"
|
||||
}
|
||||
else
|
||||
ls_ftp() {
|
||||
curl -l "$1"/
|
||||
}
|
||||
fi
|
||||
|
||||
if [ -z "$baseVersion" ]; then
|
||||
echo "Looking for available versions..." >&2
|
||||
available_baseversions=( `ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n` )
|
||||
echo -e "The following versions are available:\n ${available_baseversions[@]}" >&2
|
||||
echo -en "Choose one of them: " >&2
|
||||
read baseVersion
|
||||
fi
|
||||
|
||||
FTPDIR="${GNOME_FTP}/${project}/${baseVersion}"
|
||||
|
||||
#version=`curl -l ${FTPDIR}/ 2>/dev/null | grep LATEST-IS | sed -e s/LATEST-IS-//`
|
||||
# gnome's LATEST-IS is broken. Do not trust it.
|
||||
|
||||
files=$(ls_ftp "${FTPDIR}")
|
||||
declare -A versions
|
||||
|
||||
for f in $files; do
|
||||
case $f in
|
||||
(LATEST-IS-*|*.news|*.changes|*.sha256sum|*.diff*):
|
||||
;;
|
||||
($project-*.*.9*.tar.*):
|
||||
tmp=${f#$project-}
|
||||
tmp=${tmp%.tar*}
|
||||
echo "Ignored unstable version ${tmp}" >&2
|
||||
;;
|
||||
($project-*.tar.*):
|
||||
tmp=${f#$project-}
|
||||
tmp=${tmp%.tar*}
|
||||
versions[${tmp}]=1
|
||||
;;
|
||||
(*):
|
||||
echo "UNKNOWN FILE $f"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "Found versions ${!versions[@]}" >&2
|
||||
version=`echo ${!versions[@]} | sed -e 's/ /\n/g' | sort -t. -k1,1n -k 2,2n -k 3,3n | tail -n1`
|
||||
echo "Latest version is: ${version}" >&2
|
||||
|
||||
name=${project}-${version}
|
||||
echo "Fetching .sha256 file" >&2
|
||||
curl -O http://${FTPDIR}/${name}.sha256sum
|
||||
|
||||
extensions=( "xz" "bz2" "gz" )
|
||||
echo "Choosing archive extension (known are ${extensions[@]})..." >&2
|
||||
for ext in ${extensions[@]}; do
|
||||
if grep "\\.tar\\.${ext}$" ${name}.sha256sum >& /dev/null; then
|
||||
ext_pref=$ext
|
||||
sha256=$(grep "\\.tar\\.${ext}$" ${name}.sha256sum | cut -f1 -d\ )
|
||||
break
|
||||
fi
|
||||
done
|
||||
sha256=`nix-hash --to-base32 --type sha256 $sha256`
|
||||
echo "Chosen ${ext_pref}, hash is ${sha256}" >&2
|
||||
|
||||
cat <<EOF
|
||||
name = "${project}-${version}";
|
||||
|
||||
src = fetchurl {
|
||||
url = mirror://gnome/sources/${project}/${baseVersion}/${project}-${version}.tar.${ext_pref};
|
||||
sha256 = "${sha256}";
|
||||
};
|
||||
EOF
|
||||
|
||||
rm -v ${name}.sha256sum >&2
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# give absolute path of release.nix as argument
|
||||
hydra_eval_jobs \
|
||||
--argstr system x86_64-linux \
|
||||
--argstr system i686-linux \
|
||||
--argstr system x86_64-darwin \
|
||||
--argstr system i686-cygwin \
|
||||
--argstr system i686-freebsd \
|
||||
--arg officialRelease false \
|
||||
--arg nixpkgs "{ outPath = builtins.storePath ./. ; rev = 1234; }" \
|
||||
$@
|
||||
@@ -1,22 +0,0 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
|
||||
my %map;
|
||||
open LIST1, "<$ARGV[0]" or die;
|
||||
while (<LIST1>) {
|
||||
/^(\S+)\s+(.*)$/;
|
||||
$map{$1} = $2;
|
||||
}
|
||||
|
||||
open LIST1, "<$ARGV[1]" or die;
|
||||
while (<LIST1>) {
|
||||
/^(\S+)\s+(.*)$/;
|
||||
if (!defined $map{$1}) {
|
||||
print STDERR "missing file: $2\n";
|
||||
next;
|
||||
}
|
||||
print "$2\n";
|
||||
print "$map{$1}\n";
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
echo "let pkgs = import /etc/nixos/nixpkgs$2 {}; x = pkgs.callPackage $1 { $3 }; in ${4:-x}" |
|
||||
nix-instantiate --show-trace - |
|
||||
xargs nix-store -r -K
|
||||
@@ -1,22 +0,0 @@
|
||||
{ stdenv, makeWrapper, perl, perlPackages }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nix-generate-from-cpan-1";
|
||||
|
||||
buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON perlPackages.CPANPLUS ];
|
||||
|
||||
unpackPhase = "true";
|
||||
buildPhase = "true";
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${./nix-generate-from-cpan.pl} $out/bin/nix-generate-from-cpan
|
||||
wrapProgram $out/bin/nix-generate-from-cpan --set PERL5LIB $PERL5LIB
|
||||
'';
|
||||
|
||||
meta = {
|
||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||
description = "Utility to generate a Nix expression for a Perl package from CPAN";
|
||||
};
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
#! /run/current-system/sw/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use CPANPLUS::Backend;
|
||||
use YAML::XS;
|
||||
use JSON;
|
||||
|
||||
my $module_name = $ARGV[0];
|
||||
die "syntax: $0 <MODULE-NAME>\n" unless defined $module_name;
|
||||
|
||||
my $cb = CPANPLUS::Backend->new;
|
||||
|
||||
my @modules = $cb->search(type => "name", allow => [$module_name]);
|
||||
die "module $module_name not found\n" if scalar @modules == 0;
|
||||
die "multiple packages that match module $module_name\n" if scalar @modules > 1;
|
||||
my $module = $modules[0];
|
||||
|
||||
sub pkg_to_attr {
|
||||
my ($pkg_name) = @_;
|
||||
my $attr_name = $pkg_name;
|
||||
$attr_name =~ s/-\d.*//; # strip version
|
||||
return "LWP" if $attr_name eq "libwww-perl";
|
||||
$attr_name =~ s/-//g;
|
||||
return $attr_name;
|
||||
}
|
||||
|
||||
sub get_pkg_name {
|
||||
my ($module) = @_;
|
||||
my $pkg_name = $module->package;
|
||||
$pkg_name =~ s/\.tar.*//;
|
||||
$pkg_name =~ s/\.zip//;
|
||||
return $pkg_name;
|
||||
}
|
||||
|
||||
my $pkg_name = get_pkg_name $module;
|
||||
my $attr_name = pkg_to_attr $pkg_name;
|
||||
|
||||
print STDERR "attribute name: ", $attr_name, "\n";
|
||||
print STDERR "module: ", $module->module, "\n";
|
||||
print STDERR "version: ", $module->version, "\n";
|
||||
print STDERR "package: ", $module->package, , " (", $pkg_name, ", ", $attr_name, ")\n";
|
||||
print STDERR "path: ", $module->path, "\n";
|
||||
|
||||
my $tar_path = $module->fetch();
|
||||
print STDERR "downloaded to: $tar_path\n";
|
||||
print STDERR "sha-256: ", $module->status->checksum_value, "\n";
|
||||
|
||||
my $pkg_path = $module->extract();
|
||||
print STDERR "unpacked to: $pkg_path\n";
|
||||
|
||||
my $meta;
|
||||
if (-e "$pkg_path/META.yml") {
|
||||
eval {
|
||||
$meta = YAML::XS::LoadFile("$pkg_path/META.yml");
|
||||
};
|
||||
if ($@) {
|
||||
system("iconv -f windows-1252 -t utf-8 '$pkg_path/META.yml' > '$pkg_path/META.yml.tmp'");
|
||||
$meta = YAML::XS::LoadFile("$pkg_path/META.yml.tmp");
|
||||
}
|
||||
} elsif (-e "$pkg_path/META.json") {
|
||||
local $/;
|
||||
open(my $fh, '<', "$pkg_path/META.json") or die;
|
||||
$meta = decode_json(<$fh>);
|
||||
} else {
|
||||
warn "package has no META.yml or META.json\n";
|
||||
}
|
||||
|
||||
print STDERR "metadata: ", encode_json($meta), "\n" if defined $meta;
|
||||
|
||||
# Map a module to the attribute corresponding to its package
|
||||
# (e.g. HTML::HeadParser will be mapped to HTMLParser, because that
|
||||
# module is in the HTML-Parser package).
|
||||
sub module_to_pkg {
|
||||
my ($module_name) = @_;
|
||||
my @modules = $cb->search(type => "name", allow => [$module_name]);
|
||||
if (scalar @modules == 0) {
|
||||
# Fallback.
|
||||
$module_name =~ s/:://g;
|
||||
return $module_name;
|
||||
}
|
||||
my $module = $modules[0];
|
||||
my $attr_name = pkg_to_attr(get_pkg_name $module);
|
||||
print STDERR "mapped dep $module_name to $attr_name\n";
|
||||
return $attr_name;
|
||||
}
|
||||
|
||||
sub get_deps {
|
||||
my ($type) = @_;
|
||||
my $deps;
|
||||
if (defined $meta->{prereqs}) {
|
||||
die "unimplemented";
|
||||
} elsif ($type eq "runtime") {
|
||||
$deps = $meta->{requires};
|
||||
} elsif ($type eq "configure") {
|
||||
$deps = $meta->{configure_requires};
|
||||
} elsif ($type eq "build") {
|
||||
$deps = $meta->{build_requires};
|
||||
}
|
||||
my @res;
|
||||
foreach my $n (keys %{$deps}) {
|
||||
next if $n eq "perl";
|
||||
# Hacky way to figure out if this module is part of Perl.
|
||||
if ($n !~ /^JSON/ && $n !~ /^YAML/ && $n !~ /^Module::Pluggable/) {
|
||||
eval "use $n;";
|
||||
if (!$@) {
|
||||
print STDERR "skipping Perl-builtin module $n\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
push @res, module_to_pkg($n);
|
||||
}
|
||||
return @res;
|
||||
}
|
||||
|
||||
sub uniq {
|
||||
return keys %{{ map { $_ => 1 } @_ }};
|
||||
}
|
||||
|
||||
my @build_deps = sort(uniq(get_deps("configure"), get_deps("build"), get_deps("test")));
|
||||
print STDERR "build deps: @build_deps\n";
|
||||
|
||||
my @runtime_deps = sort(uniq(get_deps("runtime")));
|
||||
print STDERR "runtime deps: @runtime_deps\n";
|
||||
|
||||
my $homepage = $meta->{resources}->{homepage};
|
||||
print STDERR "homepage: $homepage\n" if defined $homepage;
|
||||
|
||||
my $description = $meta->{abstract};
|
||||
if (defined $description) {
|
||||
$description = uc(substr($description, 0, 1)) . substr($description, 1); # capitalise first letter
|
||||
$description =~ s/\.$//; # remove period at the end
|
||||
$description =~ s/\s*$//;
|
||||
$description =~ s/^\s*//;
|
||||
print STDERR "description: $description\n";
|
||||
}
|
||||
|
||||
my $license = $meta->{license};
|
||||
if (defined $license) {
|
||||
$license = "perl5" if $license eq "perl_5";
|
||||
print STDERR "license: $license\n";
|
||||
}
|
||||
|
||||
my $build_fun = -e "$pkg_path/Build.PL" && ! -e "$pkg_path/Makefile.PL" ? "buildPerlModule" : "buildPerlPackage";
|
||||
|
||||
print STDERR "===\n";
|
||||
|
||||
print <<EOF;
|
||||
$attr_name = $build_fun {
|
||||
name = "$pkg_name";
|
||||
src = fetchurl {
|
||||
url = mirror://cpan/${\$module->path}/${\$module->package};
|
||||
sha256 = "${\$module->status->checksum_value}";
|
||||
};
|
||||
EOF
|
||||
print <<EOF if scalar @build_deps > 0;
|
||||
buildInputs = [ @build_deps ];
|
||||
EOF
|
||||
print <<EOF if scalar @runtime_deps > 0;
|
||||
propagatedBuildInputs = [ @runtime_deps ];
|
||||
EOF
|
||||
print <<EOF;
|
||||
meta = {
|
||||
EOF
|
||||
print <<EOF if defined $homepage;
|
||||
homepage = $homepage;
|
||||
EOF
|
||||
print <<EOF if defined $description;
|
||||
description = "$description";
|
||||
EOF
|
||||
print <<EOF if defined $license;
|
||||
license = "$license";
|
||||
EOF
|
||||
print <<EOF;
|
||||
};
|
||||
};
|
||||
EOF
|
||||
@@ -1,22 +0,0 @@
|
||||
{ stdenv, makeWrapper, perl, perlPackages }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixpkgs-lint-1";
|
||||
|
||||
buildInputs = [ makeWrapper perl perlPackages.XMLSimple ];
|
||||
|
||||
unpackPhase = "true";
|
||||
buildPhase = "true";
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${./nixpkgs-lint.pl} $out/bin/nixpkgs-lint
|
||||
wrapProgram $out/bin/nixpkgs-lint --set PERL5LIB $PERL5LIB
|
||||
'';
|
||||
|
||||
meta = {
|
||||
maintainers = [ stdenv.lib.maintainers.eelco ];
|
||||
description = "A utility for Nixpkgs contributors to check Nixpkgs for common errors";
|
||||
};
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
#! /run/current-system/sw/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use List::Util qw(min);
|
||||
use XML::Simple qw(:strict);
|
||||
use Getopt::Long qw(:config gnu_getopt);
|
||||
|
||||
# Parse the command line.
|
||||
my $path = "<nixpkgs>";
|
||||
my $filter = "*";
|
||||
my $maintainer;
|
||||
|
||||
sub showHelp {
|
||||
print <<EOF;
|
||||
Usage: $0 [--package=NAME] [--maintainer=REGEXP] [--file=PATH]
|
||||
|
||||
Check Nixpkgs for common errors/problems.
|
||||
|
||||
-p, --package filter packages by name (default is ‘*’)
|
||||
-m, --maintainer filter packages by maintainer (case-insensitive regexp)
|
||||
-f, --file path to Nixpkgs (default is ‘<nixpkgs>’)
|
||||
|
||||
Examples:
|
||||
\$ nixpkgs-lint -f /my/nixpkgs -p firefox
|
||||
\$ nixpkgs-lint -f /my/nixpkgs -m eelco
|
||||
EOF
|
||||
exit 0;
|
||||
}
|
||||
|
||||
GetOptions("package|p=s" => \$filter,
|
||||
"maintainer|m=s" => \$maintainer,
|
||||
"file|f=s" => \$path,
|
||||
"help" => sub { showHelp() }
|
||||
) or exit 1;
|
||||
|
||||
# Evaluate Nixpkgs into an XML representation.
|
||||
my $xml = `nix-env -f '$path' -qa '$filter' --xml --meta --drv-path`;
|
||||
die "$0: evaluation of ‘$path’ failed\n" if $? != 0;
|
||||
|
||||
my $info = XMLin($xml, KeyAttr => { 'item' => '+attrPath', 'meta' => 'name' }, ForceArray => 1, SuppressEmpty => '' ) or die "cannot parse XML output";
|
||||
|
||||
# Check meta information.
|
||||
print "=== Package meta information ===\n\n";
|
||||
my $nrBadNames = 0;
|
||||
my $nrMissingMaintainers = 0;
|
||||
my $nrMissingPlatforms = 0;
|
||||
my $nrMissingDescriptions = 0;
|
||||
my $nrBadDescriptions = 0;
|
||||
my $nrMissingLicenses = 0;
|
||||
|
||||
foreach my $attr (sort keys %{$info->{item}}) {
|
||||
my $pkg = $info->{item}->{$attr};
|
||||
|
||||
my $pkgName = $pkg->{name};
|
||||
my $pkgVersion = "";
|
||||
if ($pkgName =~ /(.*)(-[0-9].*)$/) {
|
||||
$pkgName = $1;
|
||||
$pkgVersion = $2;
|
||||
}
|
||||
|
||||
# Check the maintainers.
|
||||
my @maintainers;
|
||||
my $x = $pkg->{meta}->{maintainers};
|
||||
if (defined $x && $x->{type} eq "strings") {
|
||||
@maintainers = map { $_->{value} } @{$x->{string}};
|
||||
} elsif (defined $x->{value}) {
|
||||
@maintainers = ($x->{value});
|
||||
}
|
||||
|
||||
if (defined $maintainer && scalar(grep { $_ =~ /$maintainer/i } @maintainers) == 0) {
|
||||
delete $info->{item}->{$attr};
|
||||
next;
|
||||
}
|
||||
|
||||
if (scalar @maintainers == 0) {
|
||||
print "$attr: Lacks a maintainer\n";
|
||||
$nrMissingMaintainers++;
|
||||
}
|
||||
|
||||
# Check the platforms.
|
||||
if (!defined $pkg->{meta}->{platforms}) {
|
||||
print "$attr: Lacks a platform\n";
|
||||
$nrMissingPlatforms++;
|
||||
}
|
||||
|
||||
# Package names should not be capitalised.
|
||||
if ($pkgName =~ /^[A-Z]/) {
|
||||
print "$attr: package name ‘$pkgName’ should not be capitalised\n";
|
||||
$nrBadNames++;
|
||||
}
|
||||
|
||||
if ($pkgVersion eq "") {
|
||||
print "$attr: package has no version\n";
|
||||
$nrBadNames++;
|
||||
}
|
||||
|
||||
# Check the license.
|
||||
if (!defined $pkg->{meta}->{license}) {
|
||||
print "$attr: Lacks a license\n";
|
||||
$nrMissingLicenses++;
|
||||
}
|
||||
|
||||
# Check the description.
|
||||
my $description = $pkg->{meta}->{description}->{value};
|
||||
if (!$description) {
|
||||
print "$attr: Lacks a description\n";
|
||||
$nrMissingDescriptions++;
|
||||
} else {
|
||||
my $bad = 0;
|
||||
if ($description =~ /^\s/) {
|
||||
print "$attr: Description starts with whitespace\n";
|
||||
$bad = 1;
|
||||
}
|
||||
if ($description =~ /\s$/) {
|
||||
print "$attr: Description ends with whitespace\n";
|
||||
$bad = 1;
|
||||
}
|
||||
if ($description =~ /\.$/) {
|
||||
print "$attr: Description ends with a period\n";
|
||||
$bad = 1;
|
||||
}
|
||||
if (index(lc($description), lc($attr)) != -1) {
|
||||
print "$attr: Description contains package name\n";
|
||||
$bad = 1;
|
||||
}
|
||||
$nrBadDescriptions++ if $bad;
|
||||
}
|
||||
}
|
||||
|
||||
print "\n";
|
||||
|
||||
# Find packages that have the same name.
|
||||
print "=== Package name collisions ===\n\n";
|
||||
|
||||
my %pkgsByName;
|
||||
|
||||
foreach my $attr (sort keys %{$info->{item}}) {
|
||||
my $pkg = $info->{item}->{$attr};
|
||||
#print STDERR "attr = $attr, name = $pkg->{name}\n";
|
||||
$pkgsByName{$pkg->{name}} //= [];
|
||||
push @{$pkgsByName{$pkg->{name}}}, $pkg;
|
||||
}
|
||||
|
||||
my $nrCollisions = 0;
|
||||
foreach my $name (sort keys %pkgsByName) {
|
||||
my @pkgs = @{$pkgsByName{$name}};
|
||||
|
||||
# Filter attributes that are aliases of each other (e.g. yield the
|
||||
# same derivation path).
|
||||
my %drvsSeen;
|
||||
@pkgs = grep { my $x = $drvsSeen{$_->{drvPath}}; $drvsSeen{$_->{drvPath}} = 1; !defined $x } @pkgs;
|
||||
|
||||
# Filter packages that have a lower priority.
|
||||
my $highest = min (map { $_->{meta}->{priority}->{value} // 0 } @pkgs);
|
||||
@pkgs = grep { ($_->{meta}->{priority}->{value} // 0) == $highest } @pkgs;
|
||||
|
||||
next if scalar @pkgs == 1;
|
||||
|
||||
$nrCollisions++;
|
||||
print "The following attributes evaluate to a package named ‘$name’:\n";
|
||||
print " ", join(", ", map { $_->{attrPath} } @pkgs), "\n\n";
|
||||
}
|
||||
|
||||
print "=== Bottom line ===\n";
|
||||
print "Number of packages: ", scalar(keys %{$info->{item}}), "\n";
|
||||
print "Number of bad names: $nrBadNames\n";
|
||||
print "Number of missing maintainers: $nrMissingMaintainers\n";
|
||||
print "Number of missing platforms: $nrMissingPlatforms\n";
|
||||
print "Number of missing licenses: $nrMissingLicenses\n";
|
||||
print "Number of missing descriptions: $nrMissingDescriptions\n";
|
||||
print "Number of bad descriptions: $nrBadDescriptions\n";
|
||||
print "Number of name collisions: $nrCollisions\n";
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
usage() {
|
||||
echo "
|
||||
$0 <path to unpacked binary distribution directory>
|
||||
|
||||
This program return the list of libraries and where to find them based on
|
||||
your currently installed programs.
|
||||
";
|
||||
exit 1
|
||||
}
|
||||
|
||||
if test $# -ne 1; then
|
||||
usage
|
||||
fi
|
||||
|
||||
binaryDist=$1
|
||||
|
||||
hasBinaries=false
|
||||
for bin in $(find $binaryDist -executable -type f) :; do
|
||||
if test $bin = ":"; then
|
||||
$hasBinaries || \
|
||||
echo "No patchable found in this directory."
|
||||
break
|
||||
fi
|
||||
hasBinaries=true
|
||||
|
||||
echo ""
|
||||
echo "$bin:"
|
||||
hasLibraries=false
|
||||
unset interpreter
|
||||
unset addRPath
|
||||
for lib in $(strings $bin | grep '^\(/\|\)lib.*\.so' | sort | uniq) :; do
|
||||
if test $lib = ":"; then
|
||||
$hasLibraries || \
|
||||
echo " This program is a script or it is statically linked."
|
||||
break
|
||||
fi
|
||||
hasLibraries=true
|
||||
|
||||
echo " $lib:";
|
||||
|
||||
libPath=$lib
|
||||
lib=$(basename $lib)
|
||||
|
||||
#versionLessLib=$(echo $lib | sed 's,[.][.0-9]*$,,')
|
||||
|
||||
libs="$(
|
||||
find /nix/store/*/lib* \( -type f -or -type l \) -name $lib |
|
||||
grep -v '\(bootstrap-tools\|system-path\|user-environment\|extra-utils\)'
|
||||
)"
|
||||
|
||||
echo "$libs" |
|
||||
sed 's,^/nix/store/[a-z0-9]*-\([^/]*\)/.*/\([^/]*\)$, \1 -> \2,' |
|
||||
sort |
|
||||
uniq;
|
||||
|
||||
names=$(
|
||||
echo "$libs" |
|
||||
sed 's,^/nix/store/[a-z0-9]*-\([^/]*\)-[.0-9]*/.*$,\1,' |
|
||||
sort |
|
||||
uniq;
|
||||
)
|
||||
|
||||
if test "$names" = "glibc"; then names="stdenv.glibc"; fi
|
||||
if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.cc.gcc"; fi
|
||||
|
||||
if test $lib != $libPath; then
|
||||
interpreter="--interpreter \${$names}/lib/$lib"
|
||||
elif echo $addRPath | grep -c "$names" &> /dev/null; then
|
||||
:
|
||||
else
|
||||
addRPath=${addRPath+$addRPath:}"\${$names}/lib"
|
||||
fi
|
||||
done;
|
||||
$hasLibraries && \
|
||||
echo "
|
||||
Patchelf command:
|
||||
|
||||
patchelf $interpreter \\
|
||||
${addRPath+--set-rpath $addRPath \\
|
||||
} \$out/$bin
|
||||
|
||||
"
|
||||
done;
|
||||
@@ -1,260 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
usage () {
|
||||
echo 1>&2 "
|
||||
usage:
|
||||
$0
|
||||
[--git commit..commit | --git commit]
|
||||
[--svn rev:rev | --svn rev]
|
||||
[--path path[:path]*]
|
||||
[--help]
|
||||
|
||||
This program is used to investigate how any changes inside your nixpkgs
|
||||
repository may hurt. With these kind of information you may choose wisely
|
||||
where you should commit your changes.
|
||||
|
||||
This program adapts it-self to your versionning system to avoid too much
|
||||
effort on your Internet bandwidth. If you need to check more than one
|
||||
commits / revisions, you may use the following commands:
|
||||
|
||||
--git remotes/trunk..master
|
||||
--svn 17670:17677
|
||||
|
||||
Check the differences between each commit separating the first and the
|
||||
last commit.
|
||||
|
||||
--path /etc/nixos/nixpkgs:/tmp/nixpkgs_1:/tmp/nixpkgs_2
|
||||
|
||||
Check the differences between multiple directories containing different
|
||||
versions of nixpkgs.
|
||||
|
||||
All these options exist with one commit / revision argument. Such options
|
||||
are used to compare your \$NIXPKGS path with the specified version.
|
||||
|
||||
If you omit to mention any other commit / revision, then your \$NIXPKGS path
|
||||
is compared with its last update. This command is useful to test code from
|
||||
a dirty repository.
|
||||
|
||||
"
|
||||
|
||||
exit 1;
|
||||
}
|
||||
|
||||
#####################
|
||||
# Process Arguments #
|
||||
#####################
|
||||
|
||||
: ${NIXPKGS=/etc/nixos/nixpkgs/}
|
||||
|
||||
vcs=""
|
||||
gitCommits=""
|
||||
svnRevisions=""
|
||||
pathLocations=""
|
||||
verbose=false
|
||||
|
||||
argfun=""
|
||||
for arg; do
|
||||
if test -z "$argfun"; then
|
||||
case $arg in
|
||||
--git) vcs="git"; argfun="set_gitCommits";;
|
||||
--svn) vcs="svn"; argfun="set_svnRevisions";;
|
||||
--path) vcs="path"; argfun="set_pathLocations";;
|
||||
--verbose) verbose=true;;
|
||||
--help) usage;;
|
||||
*) usage;;
|
||||
esac
|
||||
else
|
||||
case $argfun in
|
||||
set_*)
|
||||
var=$(echo $argfun | sed 's,^set_,,')
|
||||
eval $var=$arg
|
||||
;;
|
||||
esac
|
||||
argfun=""
|
||||
fi
|
||||
done
|
||||
|
||||
if $verbose; then
|
||||
set -x
|
||||
else
|
||||
set +x
|
||||
fi
|
||||
|
||||
############################
|
||||
# Find the repository type #
|
||||
############################
|
||||
|
||||
if test -z "$vcs"; then
|
||||
if test -x "$NIXPKGS/.git"; then
|
||||
if git --git-dir="$NIXPKGS/.git" branch > /dev/null 2>&1; then
|
||||
vcs="git"
|
||||
gitCommits=$(git --git-dir="$NIXPKGS/.git" log -n 1 --pretty=format:%H 2> /dev/null)
|
||||
fi
|
||||
elif test -x "$NIXPKGS/.svn"; then
|
||||
cd "$NIXPKGS"
|
||||
if svn info > /dev/null 2>&1; then
|
||||
vcs="svn";
|
||||
svnRevisions=$(svn info | sed -n 's,Revision: ,,p')
|
||||
fi
|
||||
cd -
|
||||
else
|
||||
usage
|
||||
fi
|
||||
fi
|
||||
|
||||
###############################
|
||||
# Define a storage directory. #
|
||||
###############################
|
||||
|
||||
pkgListDir=""
|
||||
exitCode=1
|
||||
cleanup(){
|
||||
test -e "$pkgListDir" && rm -rf "$pkgListDir"
|
||||
exit $exitCode;
|
||||
}
|
||||
|
||||
trap cleanup EXIT SIGINT SIGQUIT ERR
|
||||
|
||||
pkgListDir=$(mktemp --tmpdir -d rebuild-amount-XXXXXXXX)
|
||||
vcsDir="$pkgListDir/.vcs"
|
||||
|
||||
###########################
|
||||
# Versionning for Dummies #
|
||||
###########################
|
||||
|
||||
path_init() {
|
||||
if test "${pathLocations#*:}" = "$pathLocations"; then
|
||||
pathLocations="$NIXPKGS:$pathLocations"
|
||||
fi
|
||||
pathLocations="${pathLocations}:"
|
||||
}
|
||||
|
||||
path_getNext() {
|
||||
pathLoc="${pathLocations%%:*}"
|
||||
pathLocations="${pathLocations#*:}"
|
||||
}
|
||||
|
||||
path_setPath() {
|
||||
path="$pathLoc"
|
||||
}
|
||||
|
||||
path_setName() {
|
||||
name=$(echo "$pathLoc" | tr '/' '_')
|
||||
}
|
||||
|
||||
################
|
||||
# Git Commands #
|
||||
################
|
||||
|
||||
git_init() {
|
||||
git clone "$NIXPKGS/.git" "$vcsDir" > /dev/null 2>&1
|
||||
if echo "gitCommits" | grep -c "\.\." > /dev/null 2>&1; then
|
||||
gitCommits=$(git --git-dir="$vcsDir/.git" log --reverse --pretty=format:%H $gitCommits 2> /dev/null)
|
||||
else
|
||||
pathLocations="$vcsDir:$NIXPKGS"
|
||||
vcs="path"
|
||||
path_init
|
||||
fi
|
||||
}
|
||||
|
||||
git_getNext() {
|
||||
git --git-dir="$vcsDir/.git" checkout $(echo "$gitCommits" | head -n 1) > /dev/null 2>&1
|
||||
gitCommits=$(echo "$gitCommits" | sed '1 d')
|
||||
}
|
||||
|
||||
git_setPath() {
|
||||
path="$vcsDir"
|
||||
}
|
||||
|
||||
git_setName() {
|
||||
name=$(git --git-dir="$vcsDir/.git" log -n 1 --pretty=format:%H 2> /dev/null)
|
||||
}
|
||||
|
||||
#######################
|
||||
# Subversion Commands #
|
||||
#######################
|
||||
|
||||
svn_init() {
|
||||
cp -r "$NIXPKGS" "$vcsDir" > /dev/null 2>&1
|
||||
if echo "svnRevisions" | grep -c ":" > /dev/null 2>&1; then
|
||||
svnRevisions=$(seq ${svnRevisions%:*} ${svnRevisions#*:})
|
||||
else
|
||||
pathLocations="$vcsDir:$NIXPKGS"
|
||||
vcs="path"
|
||||
path_init
|
||||
fi
|
||||
}
|
||||
|
||||
svn_getNext() {
|
||||
cd "$vcsDir"
|
||||
svn checkout $(echo "$svnRevisions" | head -n 1) > /dev/null 2>&1
|
||||
cd -
|
||||
svnRevisions=$(echo "$svnRevisions" | sed '1 d')
|
||||
}
|
||||
|
||||
svn_setPath() {
|
||||
path="$vcsDir"
|
||||
}
|
||||
|
||||
svn_setName() {
|
||||
name=$(svn info 2> /dev/null | sed -n 's,Revision: ,,p')
|
||||
}
|
||||
|
||||
####################
|
||||
# Logical Commands #
|
||||
####################
|
||||
|
||||
init () { ${vcs}_init; }
|
||||
getNext () { ${vcs}_getNext; }
|
||||
setPath () { ${vcs}_setPath; }
|
||||
setName () { ${vcs}_setName; }
|
||||
|
||||
|
||||
#####################
|
||||
# Check for Rebuild #
|
||||
#####################
|
||||
|
||||
# Generate the list of all derivations that could be build from a nixpkgs
|
||||
# respository. This list of derivation hashes is compared with previous
|
||||
# lists and a brief summary is produced on the output.
|
||||
|
||||
compareNames () {
|
||||
nb=$(diff -y --suppress-common-lines --speed-large-files "$pkgListDir/$1.drvs" "$pkgListDir/$2.drvs" 2> /dev/null | wc -l)
|
||||
echo "$1 -> $2: $nb"
|
||||
}
|
||||
|
||||
echo "Please wait, this may take some minutes ..."
|
||||
|
||||
init
|
||||
first=""
|
||||
oldPrev=""
|
||||
|
||||
prev=""
|
||||
curr=""
|
||||
|
||||
while true; do
|
||||
getNext
|
||||
setPath # set path=...
|
||||
setName # set name=...
|
||||
curr="$name"
|
||||
|
||||
test -z "$curr" && break || true
|
||||
|
||||
nix-instantiate "$path" > "$pkgListDir/$curr.drvs" > /dev/null 2>&1 || true
|
||||
|
||||
if test -n "$prev"; then
|
||||
compareNames "$prev" "$curr"
|
||||
else
|
||||
echo "Number of package to rebuild:"
|
||||
first="$curr"
|
||||
fi
|
||||
oldPrev="$prev"
|
||||
prev="$curr"
|
||||
done
|
||||
|
||||
if test "$first" != "$oldPrev"; then
|
||||
echo "Number of package to rebuild (first -> last):"
|
||||
compareNames "$first" "$curr"
|
||||
fi
|
||||
|
||||
exitCode=0
|
||||
@@ -1,7 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
if [[ -z "$VERBOSE" ]]; then
|
||||
echo "You may set VERBOSE=1 to see debug output or to any other non-empty string to make this script completely silent"
|
||||
fi
|
||||
unset HOME NIXPKGS_CONFIG # Force empty config
|
||||
nix-instantiate --strict --eval-only --xml --show-trace "$(dirname "$0")"/eval-release.nix 2>&1 > /dev/null
|
||||
@@ -1,40 +0,0 @@
|
||||
#! /usr/bin/env bash
|
||||
set -e
|
||||
|
||||
export NIX_CURL_FLAGS=-sS
|
||||
|
||||
if [[ $1 == nix ]]; then
|
||||
echo "=== Installing Nix..."
|
||||
# Install Nix
|
||||
bash <(curl -sS https://nixos.org/nix/install)
|
||||
source $HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
# Make sure we can use hydra's binary cache
|
||||
sudo mkdir /etc/nix
|
||||
sudo tee /etc/nix/nix.conf <<EOF >/dev/null
|
||||
binary-caches = http://cache.nixos.org http://hydra.nixos.org
|
||||
trusted-binary-caches = http://hydra.nixos.org
|
||||
build-max-jobs = 4
|
||||
EOF
|
||||
|
||||
# Verify evaluation
|
||||
echo "=== Verifying that nixpkgs evaluates..."
|
||||
nix-env -f. -qa --json >/dev/null
|
||||
elif [[ $1 == nox ]]; then
|
||||
echo "=== Installing nox..."
|
||||
git clone -q https://github.com/madjar/nox
|
||||
pip --quiet install -e nox
|
||||
elif [[ $1 == build ]]; then
|
||||
source $HOME/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
if [[ $TRAVIS_PULL_REQUEST == false ]]; then
|
||||
echo "===> Not a pull request, checking evaluation"
|
||||
nix-build pkgs/top-level/release.nix -A tarball
|
||||
else
|
||||
echo "=== Checking PR"
|
||||
nox-review pr ${TRAVIS_PULL_REQUEST}
|
||||
fi
|
||||
else
|
||||
echo "$0: Unknown option $1" >&2
|
||||
false
|
||||
fi
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
: ${NIXOS_CHANNELS:=https://nixos.org/channels/}
|
||||
: ${CHANNELS_NAMESPACE:=refs/heads/channels/}
|
||||
|
||||
# List all channels which are currently in the repository which we would
|
||||
# have to remove if they are not found again.
|
||||
deadChannels=$(git for-each-ref --format="%(refname)" $CHANNELS_NAMESPACE)
|
||||
|
||||
function updateRef() {
|
||||
local channelName=$1
|
||||
local newRev=$2
|
||||
|
||||
# if the inputs are not valid, then we do not update any branch.
|
||||
test -z "$newRev" -o -z "$channelName" && return;
|
||||
|
||||
# Update the local refs/heads/channels/* branches to be in-sync with the
|
||||
# channel references.
|
||||
local branch=$CHANNELS_NAMESPACE$channelName
|
||||
oldRev=$(git rev-parse --short $branch 2>/dev/null || true)
|
||||
if test "$oldRev" != "$newRev"; then
|
||||
if git update-ref $branch $newRev 2>/dev/null; then
|
||||
if test -z "$oldRev"; then
|
||||
echo " * [new branch] $newRev -> ${branch#refs/heads/}"
|
||||
else
|
||||
echo " $oldRev..$newRev -> ${branch#refs/heads/}"
|
||||
fi
|
||||
else
|
||||
if test -z "$oldRev"; then
|
||||
echo " * [missing rev] $newRev -> ${branch#refs/heads/}"
|
||||
else
|
||||
echo " [missing rev] $oldRev..$newRev -> ${branch#refs/heads/}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Filter out the current channel from the list of dead channels.
|
||||
deadChannels=$(grep -v $CHANNELS_NAMESPACE$channelName <<EOF
|
||||
$deadChannels
|
||||
EOF
|
||||
)
|
||||
}
|
||||
|
||||
# Find the name of all channels which are listed in the directory.
|
||||
echo "Fetching channels from $NIXOS_CHANNELS:"
|
||||
for channelName in : $(curl -s $NIXOS_CHANNELS | sed -n '/folder/ { s,.*href=",,; s,/".*,,; p }'); do
|
||||
test "$channelName" = : && continue;
|
||||
|
||||
# Do not follow redirections, such that we can extract the
|
||||
# short-changeset from the name of the directory where we are
|
||||
# redirected to.
|
||||
sha1=$(curl -sI $NIXOS_CHANNELS$channelName | sed -n '/Location/ { s,.*\.\([a-f0-9]*\)[ \r]*$,\1,; p; }')
|
||||
|
||||
updateRef "remotes/$channelName" "$sha1"
|
||||
done
|
||||
|
||||
echo "Fetching channels from nixos-version:"
|
||||
if currentSystem=$(nixos-version 2>/dev/null); then
|
||||
# If the system is entirely build from a custom nixpkgs version,
|
||||
# then the version is not annotated in git version. This sed
|
||||
# expression is basically matching that the expressions end with
|
||||
# ".<sha1> (Name)" to extract the sha1.
|
||||
sha1=$(echo $currentSystem | sed -n 's,^.*\.\([a-f0-9]*\) *(.*)$,\1,; T skip; p; :skip;')
|
||||
|
||||
updateRef current-system "$sha1"
|
||||
fi
|
||||
|
||||
echo "Fetching channels from ~/.nix-defexpr:"
|
||||
for revFile in : $(find -L ~/.nix-defexpr/ -maxdepth 4 -name svn-revision); do
|
||||
test "$revFile" = : && continue;
|
||||
|
||||
# Deconstruct a path such as, into:
|
||||
#
|
||||
# /home/luke/.nix-defexpr/channels_root/nixos/nixpkgs/svn-revision
|
||||
# channelName = root/nixos
|
||||
#
|
||||
# /home/luke/.nix-defexpr/channels/nixpkgs/svn-revision
|
||||
# channelName = nixpkgs
|
||||
#
|
||||
user=${revFile#*.nix-defexpr/channels}
|
||||
repo=${user#*/}
|
||||
repo=${repo%%/*}
|
||||
user=${user%%/*}
|
||||
user=${user#_}
|
||||
test -z "$user" && user=$USER
|
||||
channelName="$user${user:+/}$repo"
|
||||
|
||||
sha1=$(cat $revFile | sed -n 's,^.*\.\([a-f0-9]*\)$,\1,; T skip; p; :skip;')
|
||||
|
||||
updateRef "$channelName" "$sha1"
|
||||
done
|
||||
|
||||
# Suggest to remove channel branches which are no longer found by this
|
||||
# script. This is to handle the cases where a local/remote channel
|
||||
# disappear. We should not attempt to remove manually any branches, as they
|
||||
# might be user branches.
|
||||
if test -n "$deadChannels"; then
|
||||
|
||||
echo "
|
||||
Some old channel branches are still in your repository, if you
|
||||
want to remove them, run the following command(s):
|
||||
"
|
||||
|
||||
while read branch; do
|
||||
echo " git update-ref -d $branch"
|
||||
done <<EOF
|
||||
$deadChannels
|
||||
EOF
|
||||
|
||||
echo
|
||||
fi
|
||||
@@ -1,6 +0,0 @@
|
||||
viric viriketo@gmail.com
|
||||
Pjotr Prins pjotr.public01@thebird.nl
|
||||
Pjotr Prins pjotr.public05@thebird.nl
|
||||
Wouter den Breejen wbreejen
|
||||
MarcWeber marcweber
|
||||
Ricardo Correia Ricardo M. Correia
|
||||
@@ -1,122 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
export LANG=C LC_ALL=C LC_COLLATE=C
|
||||
|
||||
# Load git log
|
||||
raw_git_log="$(git log)"
|
||||
git_data="$(echo "$raw_git_log" | grep 'Author:' |
|
||||
sed -e 's/^ *Author://; s/\\//g; s/^ *//; s/ *$//;
|
||||
s/ @ .*//; s/ *[<]/\t/; s/[>]//')"
|
||||
|
||||
# Name - nick - email correspondence from log and from maintainer list
|
||||
# Also there are a few manual entries
|
||||
maintainers="$(cat "$(dirname "$0")/../../lib/maintainers.nix" |
|
||||
grep '=' | sed -re 's/\\"/''/g;
|
||||
s/ *([^ =]*) *= *" *(.*[^ ]) *[<](.*)[>] *".*/\1\t\2\t\3/')"
|
||||
git_lines="$( ( echo "$git_data";
|
||||
cat "$(dirname "$0")/vanity-manual-equalities.txt") | sort |uniq)"
|
||||
|
||||
emails="$(
|
||||
( echo "$maintainers" | cut -f 3; echo "$git_data" | cut -f 2 ) |
|
||||
sort | uniq | grep -E ".+@.+[.].+"
|
||||
)"
|
||||
|
||||
fetchGithubName () {
|
||||
commitid="$(
|
||||
echo "$raw_git_log" | grep -B3 "Author: .*[<]$1[>]" | head -n 3 |
|
||||
grep '^commit ' | tail -n 1 | sed -e 's/^commit //'
|
||||
)"
|
||||
userid="$(
|
||||
curl https://github.com/NixOS/nixpkgs/commit/"$commitid" 2>/dev/null |
|
||||
grep authored -B10 | grep 'href="/' |
|
||||
sed -re 's@.* href="/@@; s@".*@@' |
|
||||
grep -v "/commit/"
|
||||
)";
|
||||
echo "$userid"
|
||||
}
|
||||
|
||||
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && {
|
||||
echo "$emails" | while read email; do
|
||||
line="$(grep "$email " "$NIXPKGS_GITHUB_NAME_CACHE")"
|
||||
[ -z "$line" ] && {
|
||||
echo "$email $(fetchGithubName "$email")" >> \
|
||||
"$NIXPKGS_GITHUB_NAME_CACHE"
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
# For RDF
|
||||
normalize_name () {
|
||||
sed -e 's/%/%25/g; s/ /%20/g; s/'\''/%27/g; s/"/%22/g; s/`/%60/g'
|
||||
}
|
||||
|
||||
denormalize_name () {
|
||||
sed -e 's/%20/ /g; s/%27/'\''/g; s/%22/"/g; s/%60/`/g; s/%25/%/g;';
|
||||
}
|
||||
|
||||
n3="$(mktemp --suffix .n3)"
|
||||
|
||||
# «The same person» relation and a sorting hint
|
||||
# Full name is something with a space
|
||||
(
|
||||
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
|
||||
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\1>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\3>.@'
|
||||
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\3> <my://can-be> <my://name/\1>.@'
|
||||
echo "$git_lines" | grep ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
|
||||
echo "$git_lines" | grep -v ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://1>.@'
|
||||
echo "$maintainers" | cut -f 2 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
|
||||
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && cat "$NIXPKGS_GITHUB_NAME_CACHE" |
|
||||
grep -v " $" |
|
||||
sed -re 's@(.*)\t(.*)@<my://name/\1> <my://at-github> <my://github/\2>.@'
|
||||
) | normalize_name | grep -E '<my://[-a-z]+>' | sort | uniq > "$n3"
|
||||
|
||||
# Get transitive closure
|
||||
sparql="$(nix-build '<nixpkgs>' -Q -A apache-jena --no-out-link)/bin/sparql"
|
||||
name_list="$(
|
||||
"$sparql" --results=TSV --data="$n3" "
|
||||
select ?x ?y ?g where {
|
||||
?x <my://can-be>+ ?y.
|
||||
?x <my://is-name> ?g.
|
||||
}
|
||||
" | tail -n +2 |
|
||||
sed -re 's@<my://name/@@g; s@<my://@@g; s@>@@g;' |
|
||||
sort -k 2,3 -t ' '
|
||||
)"
|
||||
github_name_list="$(
|
||||
"$sparql" --results=TSV --data="$n3" "
|
||||
select ?x ?y where {
|
||||
?x (<my://can-be>+ / <my://at-github>) ?y.
|
||||
}
|
||||
" | tail -n +2 |
|
||||
sed -re 's@<my://(name|github)/@@g; s@<my://@@g; s@>@@g;'
|
||||
)"
|
||||
|
||||
# Take first spelling option for every person
|
||||
name_list_canonical="$(echo "$name_list" | cut -f 1,2 | uniq -f1)"
|
||||
|
||||
cleaner_script="$(echo "$name_list_canonical" | denormalize_name |
|
||||
sed -re 's/(.*)\t(.*)/s#^\2$#\1#g/g')"
|
||||
|
||||
# Add github usernames
|
||||
if [ -n "$NIXPKGS_GITHUB_NAME_CACHE" ]; then
|
||||
github_adder_script="$(echo "$github_name_list" |
|
||||
grep -E "$(echo "$name_list_canonical" | cut -f 2 |
|
||||
tr '\n' '|' )" |
|
||||
sort | uniq |
|
||||
sed -re 's/(.*)\t(.*)/s| \1$| \1\t\2|g;/' |
|
||||
denormalize_name
|
||||
)"
|
||||
else
|
||||
github_adder_script=''
|
||||
fi
|
||||
|
||||
echo "$name_list" | denormalize_name
|
||||
|
||||
echo
|
||||
|
||||
echo "$git_data" | cut -f 1 |
|
||||
sed -e "$cleaner_script" |
|
||||
sort | uniq -c | sort -k1n | sed -re "$github_adder_script" |
|
||||
sed -re 's/^ *([0-9]+) /\1\t/'
|
||||
@@ -1,18 +0,0 @@
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,5 +0,0 @@
|
||||
*** NixOS ***
|
||||
|
||||
NixOS is a Linux distribution based on the purely functional package
|
||||
management system Nix. More information can be found at
|
||||
http://nixos.org/nixos and in the manual in doc/manual.
|
||||
@@ -1,43 +0,0 @@
|
||||
{ configuration ? import ./lib/from-env.nix "NIXOS_CONFIG" <nixos-config>
|
||||
, system ? builtins.currentSystem
|
||||
}:
|
||||
|
||||
let
|
||||
|
||||
eval = import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules = [ configuration ];
|
||||
};
|
||||
|
||||
inherit (eval) pkgs;
|
||||
|
||||
# This is for `nixos-rebuild build-vm'.
|
||||
vmConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules = [ configuration ./modules/virtualisation/qemu-vm.nix ];
|
||||
}).config;
|
||||
|
||||
# This is for `nixos-rebuild build-vm-with-bootloader'.
|
||||
vmWithBootLoaderConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules =
|
||||
[ configuration
|
||||
./modules/virtualisation/qemu-vm.nix
|
||||
{ virtualisation.useBootLoader = true; }
|
||||
];
|
||||
}).config;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
inherit (eval) config options;
|
||||
|
||||
system = eval.config.system.build.toplevel;
|
||||
|
||||
vm = vmConfig.system.build.vm;
|
||||
|
||||
vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm;
|
||||
|
||||
# The following are used by nixos-rebuild.
|
||||
nixFallback = pkgs.nixUnstable;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
To build the manual, you need Nix installed on your system (no need
|
||||
for NixOS). To install Nix, follow the instructions at
|
||||
|
||||
https://nixos.org/nix/download.html
|
||||
|
||||
When you have Nix on your system, in the root directory of the project
|
||||
(i.e., `nixpkgs`), run:
|
||||
|
||||
nix-build nixos/release.nix -A manual.x86_64-linux
|
||||
|
||||
When this command successfully finishes, it will tell you where the
|
||||
manual got generated.
|
||||
@@ -1,65 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-boot-problems">
|
||||
|
||||
<title>Boot Problems</title>
|
||||
|
||||
<para>If NixOS fails to boot, there are a number of kernel command
|
||||
line parameters that may help you to identify or fix the issue. You
|
||||
can add these parameters in the GRUB boot menu by pressing “e” to
|
||||
modify the selected boot entry and editing the line starting with
|
||||
<literal>linux</literal>. The following are some useful kernel command
|
||||
line parameters that are recognised by the NixOS boot scripts or by
|
||||
systemd:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>boot.shell_on_fail</literal></term>
|
||||
<listitem><para>Start a root shell if something goes wrong in
|
||||
stage 1 of the boot process (the initial ramdisk). This is
|
||||
disabled by default because there is no authentication for the
|
||||
root shell.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>boot.debug1</literal></term>
|
||||
<listitem><para>Start an interactive shell in stage 1 before
|
||||
anything useful has been done. That is, no modules have been
|
||||
loaded and no file systems have been mounted, except for
|
||||
<filename>/proc</filename> and
|
||||
<filename>/sys</filename>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>boot.trace</literal></term>
|
||||
<listitem><para>Print every shell command executed by the stage 1
|
||||
and 2 boot scripts.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>single</literal></term>
|
||||
<listitem><para>Boot into rescue mode (a.k.a. single user mode).
|
||||
This will cause systemd to start nothing but the unit
|
||||
<literal>rescue.target</literal>, which runs
|
||||
<command>sulogin</command> to prompt for the root password and
|
||||
start a root login shell. Exiting the shell causes the system to
|
||||
continue with the normal boot process.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>systemd.log_level=debug systemd.log_target=console</literal></term>
|
||||
<listitem><para>Make systemd very verbose and send log messages to
|
||||
the console instead of the journal.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
For more parameters recognised by systemd, see
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>If no login prompts or X11 login screens appear (e.g. due to
|
||||
hanging dependencies), you can press Alt+ArrowUp. If you’re lucky,
|
||||
this will start rescue mode (described above). (Also note that since
|
||||
most units have a 90-second timeout before systemd gives up on them,
|
||||
the <command>agetty</command> login prompts should appear eventually
|
||||
unless something is very wrong.)</para>
|
||||
|
||||
</section>
|
||||
@@ -1,62 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-gc">
|
||||
|
||||
<title>Cleaning the Nix Store</title>
|
||||
|
||||
<para>Nix has a purely functional model, meaning that packages are
|
||||
never upgraded in place. Instead new versions of packages end up in a
|
||||
different location in the Nix store (<filename>/nix/store</filename>).
|
||||
You should periodically run Nix’s <emphasis>garbage
|
||||
collector</emphasis> to remove old, unreferenced packages. This is
|
||||
easy:
|
||||
|
||||
<screen>
|
||||
$ nix-collect-garbage
|
||||
</screen>
|
||||
|
||||
Alternatively, you can use a systemd unit that does the same in the
|
||||
background:
|
||||
|
||||
<screen>
|
||||
$ systemctl start nix-gc.service
|
||||
</screen>
|
||||
|
||||
You can tell NixOS in <filename>configuration.nix</filename> to run
|
||||
this unit automatically at certain points in time, for instance, every
|
||||
night at 03:15:
|
||||
|
||||
<programlisting>
|
||||
nix.gc.automatic = true;
|
||||
nix.gc.dates = "03:15";
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The commands above do not remove garbage collector roots, such
|
||||
as old system configurations. Thus they do not remove the ability to
|
||||
roll back to previous configurations. The following command deletes
|
||||
old roots, removing the ability to roll back to them:
|
||||
<screen>
|
||||
$ nix-collect-garbage -d
|
||||
</screen>
|
||||
You can also do this for specific profiles, e.g.
|
||||
<screen>
|
||||
$ nix-env -p /nix/var/nix/profiles/per-user/eelco/profile --delete-generations old
|
||||
</screen>
|
||||
Note that NixOS system configurations are stored in the profile
|
||||
<filename>/nix/var/nix/profiles/system</filename>.</para>
|
||||
|
||||
<para>Another way to reclaim disk space (often as much as 40% of the
|
||||
size of the Nix store) is to run Nix’s store optimiser, which seeks
|
||||
out identical files in the store and replaces them with hard links to
|
||||
a single copy.
|
||||
<screen>
|
||||
$ nix-store --optimise
|
||||
</screen>
|
||||
Since this command needs to read the entire Nix store, it can take
|
||||
quite a while to finish.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,50 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-container-networking">
|
||||
|
||||
|
||||
<title>Container Networking</title>
|
||||
|
||||
<para>When you create a container using <literal>nixos-container
|
||||
create</literal>, it gets it own private IPv4 address in the range
|
||||
<literal>10.233.0.0/16</literal>. You can get the container’s IPv4
|
||||
address as follows:
|
||||
|
||||
<screen>
|
||||
$ nixos-container show-ip foo
|
||||
10.233.4.2
|
||||
|
||||
$ ping -c1 10.233.4.2
|
||||
64 bytes from 10.233.4.2: icmp_seq=1 ttl=64 time=0.106 ms
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Networking is implemented using a pair of virtual Ethernet
|
||||
devices. The network interface in the container is called
|
||||
<literal>eth0</literal>, while the matching interface in the host is
|
||||
called <literal>ve-<replaceable>container-name</replaceable></literal>
|
||||
(e.g., <literal>ve-foo</literal>). The container has its own network
|
||||
namespace and the <literal>CAP_NET_ADMIN</literal> capability, so it
|
||||
can perform arbitrary network configuration such as setting up
|
||||
firewall rules, without affecting or having access to the host’s
|
||||
network.</para>
|
||||
|
||||
<para>By default, containers cannot talk to the outside network. If
|
||||
you want that, you should set up Network Address Translation (NAT)
|
||||
rules on the host to rewrite container traffic to use your external
|
||||
IP address. This can be accomplished using the following configuration
|
||||
on the host:
|
||||
|
||||
<programlisting>
|
||||
networking.nat.enable = true;
|
||||
networking.nat.internalInterfaces = ["ve-+"];
|
||||
networking.nat.externalInterface = "eth0";
|
||||
</programlisting>
|
||||
where <literal>eth0</literal> should be replaced with the desired
|
||||
external interface. Note that <literal>ve-+</literal> is a wildcard
|
||||
that matches all container interfaces.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,34 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-containers">
|
||||
|
||||
<title>Container Management</title>
|
||||
|
||||
<para>NixOS allows you to easily run other NixOS instances as
|
||||
<emphasis>containers</emphasis>. Containers are a light-weight
|
||||
approach to virtualisation that runs software in the container at the
|
||||
same speed as in the host system. NixOS containers share the Nix store
|
||||
of the host, making container creation very efficient.</para>
|
||||
|
||||
<warning><para>Currently, NixOS containers are not perfectly isolated
|
||||
from the host system. This means that a user with root access to the
|
||||
container can do things that affect the host. So you should not give
|
||||
container root access to untrusted users.</para></warning>
|
||||
|
||||
<para>NixOS containers can be created in two ways: imperatively, using
|
||||
the command <command>nixos-container</command>, and declaratively, by
|
||||
specifying them in your <filename>configuration.nix</filename>. The
|
||||
declarative approach implies that containers get upgraded along with
|
||||
your host system when you run <command>nixos-rebuild</command>, which
|
||||
is often not what you want. By contrast, in the imperative approach,
|
||||
containers are configured and updated independently from the host
|
||||
system.</para>
|
||||
|
||||
<xi:include href="imperative-containers.xml" />
|
||||
<xi:include href="declarative-containers.xml" />
|
||||
<xi:include href="container-networking.xml" />
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-cgroups">
|
||||
|
||||
<title>Control Groups</title>
|
||||
|
||||
<para>To keep track of the processes in a running system, systemd uses
|
||||
<emphasis>control groups</emphasis> (cgroups). A control group is a
|
||||
set of processes used to allocate resources such as CPU, memory or I/O
|
||||
bandwidth. There can be multiple control group hierarchies, allowing
|
||||
each kind of resource to be managed independently.</para>
|
||||
|
||||
<para>The command <command>systemd-cgls</command> lists all control
|
||||
groups in the <literal>systemd</literal> hierarchy, which is what
|
||||
systemd uses to keep track of the processes belonging to each service
|
||||
or user session:
|
||||
|
||||
<screen>
|
||||
$ systemd-cgls
|
||||
├─user
|
||||
│ └─eelco
|
||||
│ └─c1
|
||||
│ ├─ 2567 -:0
|
||||
│ ├─ 2682 kdeinit4: kdeinit4 Running...
|
||||
│ ├─ <replaceable>...</replaceable>
|
||||
│ └─10851 sh -c less -R
|
||||
└─system
|
||||
├─httpd.service
|
||||
│ ├─2444 httpd -f /nix/store/3pyacby5cpr55a03qwbnndizpciwq161-httpd.conf -DNO_DETACH
|
||||
│ └─<replaceable>...</replaceable>
|
||||
├─dhcpcd.service
|
||||
│ └─2376 dhcpcd --config /nix/store/f8dif8dsi2yaa70n03xir8r653776ka6-dhcpcd.conf
|
||||
└─ <replaceable>...</replaceable>
|
||||
</screen>
|
||||
|
||||
Similarly, <command>systemd-cgls cpu</command> shows the cgroups in
|
||||
the CPU hierarchy, which allows per-cgroup CPU scheduling priorities.
|
||||
By default, every systemd service gets its own CPU cgroup, while all
|
||||
user sessions are in the top-level CPU cgroup. This ensures, for
|
||||
instance, that a thousand run-away processes in the
|
||||
<literal>httpd.service</literal> cgroup cannot starve the CPU for one
|
||||
process in the <literal>postgresql.service</literal> cgroup. (By
|
||||
contrast, it they were in the same cgroup, then the PostgreSQL process
|
||||
would get 1/1001 of the cgroup’s CPU time.) You can limit a service’s
|
||||
CPU share in <filename>configuration.nix</filename>:
|
||||
|
||||
<programlisting>
|
||||
systemd.services.httpd.serviceConfig.CPUShares = 512;
|
||||
</programlisting>
|
||||
|
||||
By default, every cgroup has 1024 CPU shares, so this will halve the
|
||||
CPU allocation of the <literal>httpd.service</literal> cgroup.</para>
|
||||
|
||||
<para>There also is a <literal>memory</literal> hierarchy that
|
||||
controls memory allocation limits; by default, all processes are in
|
||||
the top-level cgroup, so any service or session can exhaust all
|
||||
available memory. Per-cgroup memory limits can be specified in
|
||||
<filename>configuration.nix</filename>; for instance, to limit
|
||||
<literal>httpd.service</literal> to 512 MiB of RAM (excluding swap)
|
||||
and 640 MiB of RAM (including swap):
|
||||
|
||||
<programlisting>
|
||||
systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
|
||||
systemd.services.httpd.serviceConfig.ControlGroupAttribute = [ "memory.memsw.limit_in_bytes 640M" ];
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The command <command>systemd-cgtop</command> shows a
|
||||
continuously updated list of all cgroups with their CPU and memory
|
||||
usage.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,52 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-declarative-containers">
|
||||
|
||||
<title>Declarative Container Specification</title>
|
||||
|
||||
<para>You can also specify containers and their configuration in the
|
||||
host’s <filename>configuration.nix</filename>. For example, the
|
||||
following specifies that there shall be a container named
|
||||
<literal>database</literal> running PostgreSQL:
|
||||
|
||||
<programlisting>
|
||||
containers.database =
|
||||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql92;
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
If you run <literal>nixos-rebuild switch</literal>, the container will
|
||||
be built and started. If the container was already running, it will be
|
||||
updated in place, without rebooting.</para>
|
||||
|
||||
<para>By default, declarative containers share the network namespace
|
||||
of the host, meaning that they can listen on (privileged)
|
||||
ports. However, they cannot change the network configuration. You can
|
||||
give a container its own network as follows:
|
||||
|
||||
<programlisting>
|
||||
containers.database =
|
||||
{ privateNetwork = true;
|
||||
hostAddress = "192.168.100.10";
|
||||
localAddress = "192.168.100.11";
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
This gives the container a private virtual Ethernet interface with IP
|
||||
address <literal>192.168.100.11</literal>, which is hooked up to a
|
||||
virtual Ethernet interface on the host with IP address
|
||||
<literal>192.168.100.10</literal>. (See the next section for details
|
||||
on container networking.)</para>
|
||||
|
||||
<para>To disable the container, just remove it from
|
||||
<filename>configuration.nix</filename> and run <literal>nixos-rebuild
|
||||
switch</literal>. Note that this will not delete the root directory of
|
||||
the container in <literal>/var/lib/containers</literal>.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,124 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-imperative-containers">
|
||||
|
||||
<title>Imperative Container Management</title>
|
||||
|
||||
<para>We’ll cover imperative container management using
|
||||
<command>nixos-container</command> first. You create a container with
|
||||
identifier <literal>foo</literal> as follows:
|
||||
|
||||
<screen>
|
||||
$ nixos-container create foo
|
||||
</screen>
|
||||
|
||||
This creates the container’s root directory in
|
||||
<filename>/var/lib/containers/foo</filename> and a small configuration
|
||||
file in <filename>/etc/containers/foo.conf</filename>. It also builds
|
||||
the container’s initial system configuration and stores it in
|
||||
<filename>/nix/var/nix/profiles/per-container/foo/system</filename>. You
|
||||
can modify the initial configuration of the container on the command
|
||||
line. For instance, to create a container that has
|
||||
<command>sshd</command> running, with the given public key for
|
||||
<literal>root</literal>:
|
||||
|
||||
<screen>
|
||||
$ nixos-container create foo --config 'services.openssh.enable = true; \
|
||||
users.extraUsers.root.openssh.authorizedKeys.keys = ["ssh-dss AAAAB3N…"];'
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Creating a container does not start it. To start the container,
|
||||
run:
|
||||
|
||||
<screen>
|
||||
$ nixos-container start foo
|
||||
</screen>
|
||||
|
||||
This command will return as soon as the container has booted and has
|
||||
reached <literal>multi-user.target</literal>. On the host, the
|
||||
container runs within a systemd unit called
|
||||
<literal>container@<replaceable>container-name</replaceable>.service</literal>.
|
||||
Thus, if something went wrong, you can get status info using
|
||||
<command>systemctl</command>:
|
||||
|
||||
<screen>
|
||||
$ systemctl status container@foo
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>If the container has started succesfully, you can log in as
|
||||
root using the <command>root-login</command> operation:
|
||||
|
||||
<screen>
|
||||
$ nixos-container root-login foo
|
||||
[root@foo:~]#
|
||||
</screen>
|
||||
|
||||
Note that only root on the host can do this (since there is no
|
||||
authentication). You can also get a regular login prompt using the
|
||||
<command>login</command> operation, which is available to all users on
|
||||
the host:
|
||||
|
||||
<screen>
|
||||
$ nixos-container login foo
|
||||
foo login: alice
|
||||
Password: ***
|
||||
</screen>
|
||||
|
||||
With <command>nixos-container run</command>, you can execute arbitrary
|
||||
commands in the container:
|
||||
|
||||
<screen>
|
||||
$ nixos-container run foo -- uname -a
|
||||
Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>There are several ways to change the configuration of the
|
||||
container. First, on the host, you can edit
|
||||
<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>,
|
||||
and run
|
||||
|
||||
<screen>
|
||||
$ nixos-container update foo
|
||||
</screen>
|
||||
|
||||
This will build and activate the new configuration. You can also
|
||||
specify a new configuration on the command line:
|
||||
|
||||
<screen>
|
||||
$ nixos-container update foo --config 'services.httpd.enable = true; \
|
||||
services.httpd.adminAddr = "foo@example.org";'
|
||||
|
||||
$ curl http://$(nixos-container show-ip foo)/
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">…
|
||||
</screen>
|
||||
|
||||
However, note that this will overwrite the container’s
|
||||
<filename>/etc/nixos/configuration.nix</filename>.</para>
|
||||
|
||||
<para>Alternatively, you can change the configuration from within the
|
||||
container itself by running <command>nixos-rebuild switch</command>
|
||||
inside the container. Note that the container by default does not have
|
||||
a copy of the NixOS channel, so you should run <command>nix-channel
|
||||
--update</command> first.</para>
|
||||
|
||||
<para>Containers can be stopped and started using
|
||||
<literal>nixos-container stop</literal> and <literal>nixos-container
|
||||
start</literal>, respectively, or by using
|
||||
<command>systemctl</command> on the container’s service unit. To
|
||||
destroy a container, including its file system, do
|
||||
|
||||
<screen>
|
||||
$ nixos-container destroy foo
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,52 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-logging">
|
||||
|
||||
<title>Logging</title>
|
||||
|
||||
<para>System-wide logging is provided by systemd’s
|
||||
<emphasis>journal</emphasis>, which subsumes traditional logging
|
||||
daemons such as syslogd and klogd. Log entries are kept in binary
|
||||
files in <filename>/var/log/journal/</filename>. The command
|
||||
<literal>journalctl</literal> allows you to see the contents of the
|
||||
journal. For example,
|
||||
|
||||
<screen>
|
||||
$ journalctl -b
|
||||
</screen>
|
||||
|
||||
shows all journal entries since the last reboot. (The output of
|
||||
<command>journalctl</command> is piped into <command>less</command> by
|
||||
default.) You can use various options and match operators to restrict
|
||||
output to messages of interest. For instance, to get all messages
|
||||
from PostgreSQL:
|
||||
|
||||
<screen>
|
||||
$ journalctl -u postgresql.service
|
||||
-- Logs begin at Mon, 2013-01-07 13:28:01 CET, end at Tue, 2013-01-08 01:09:57 CET. --
|
||||
...
|
||||
Jan 07 15:44:14 hagbard postgres[2681]: [2-1] LOG: database system is shut down
|
||||
-- Reboot --
|
||||
Jan 07 15:45:10 hagbard postgres[2532]: [1-1] LOG: database system was shut down at 2013-01-07 15:44:14 CET
|
||||
Jan 07 15:45:13 hagbard postgres[2500]: [1-1] LOG: database system is ready to accept connections
|
||||
</screen>
|
||||
|
||||
Or to get all messages since the last reboot that have at least a
|
||||
“critical” severity level:
|
||||
|
||||
<screen>
|
||||
$ journalctl -b -p crit
|
||||
Dec 17 21:08:06 mandark sudo[3673]: pam_unix(sudo:auth): auth could not identify password for [alice]
|
||||
Dec 29 01:30:22 mandark kernel[6131]: [1053513.909444] CPU6: Core temperature above threshold, cpu clock throttled (total events = 1)
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The system journal is readable by root and by users in the
|
||||
<literal>wheel</literal> and <literal>systemd-journal</literal>
|
||||
groups. All users have a private journal that can be read using
|
||||
<command>journalctl</command>.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,18 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-maintenance-mode">
|
||||
|
||||
<title>Maintenance Mode</title>
|
||||
|
||||
<para>You can enter rescue mode by running:
|
||||
|
||||
<screen>
|
||||
$ systemctl rescue</screen>
|
||||
|
||||
This will eventually give you a single-user root shell. Systemd will
|
||||
stop (almost) all system services. To get out of maintenance mode,
|
||||
just exit from the rescue shell.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,33 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-network-issues">
|
||||
|
||||
<title>Network Problems</title>
|
||||
|
||||
<para>Nix uses a so-called <emphasis>binary cache</emphasis> to
|
||||
optimise building a package from source into downloading it as a
|
||||
pre-built binary. That is, whenever a command like
|
||||
<command>nixos-rebuild</command> needs a path in the Nix store, Nix
|
||||
will try to download that path from the Internet rather than build it
|
||||
from source. The default binary cache is
|
||||
<uri>https://cache.nixos.org/</uri>. If this cache is unreachable,
|
||||
Nix operations may take a long time due to HTTP connection timeouts.
|
||||
You can disable the use of the binary cache by adding <option>--option
|
||||
use-binary-caches false</option>, e.g.
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --option use-binary-caches false
|
||||
</screen>
|
||||
|
||||
If you have an alternative binary cache at your disposal, you can use
|
||||
it instead:
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --option binary-caches http://my-cache.example.org/
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,44 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-rebooting">
|
||||
|
||||
<title>Rebooting and Shutting Down</title>
|
||||
|
||||
<para>The system can be shut down (and automatically powered off) by
|
||||
doing:
|
||||
|
||||
<screen>
|
||||
$ shutdown
|
||||
</screen>
|
||||
|
||||
This is equivalent to running <command>systemctl
|
||||
poweroff</command>.</para>
|
||||
|
||||
<para>To reboot the system, run
|
||||
|
||||
<screen>
|
||||
$ reboot
|
||||
</screen>
|
||||
|
||||
which is equivalent to <command>systemctl reboot</command>.
|
||||
Alternatively, you can quickly reboot the system using
|
||||
<literal>kexec</literal>, which bypasses the BIOS by directly loading
|
||||
the new kernel into memory:
|
||||
|
||||
<screen>
|
||||
$ systemctl kexec
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The machine can be suspended to RAM (if supported) using
|
||||
<command>systemctl suspend</command>, and suspended to disk using
|
||||
<command>systemctl hibernate</command>.</para>
|
||||
|
||||
<para>These commands can be run by any user who is logged in locally,
|
||||
i.e. on a virtual console or in X11; otherwise, the user is asked for
|
||||
authentication.</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,48 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-rollback">
|
||||
|
||||
<title>Rolling Back Configuration Changes</title>
|
||||
|
||||
<para>After running <command>nixos-rebuild</command> to switch to a
|
||||
new configuration, you may find that the new configuration doesn’t
|
||||
work very well. In that case, there are several ways to return to a
|
||||
previous configuration.</para>
|
||||
|
||||
<para>First, the GRUB boot manager allows you to boot into any
|
||||
previous configuration that hasn’t been garbage-collected. These
|
||||
configurations can be found under the GRUB submenu “NixOS - All
|
||||
configurations”. This is especially useful if the new configuration
|
||||
fails to boot. After the system has booted, you can make the selected
|
||||
configuration the default for subsequent boots:
|
||||
|
||||
<screen>
|
||||
$ /run/current-system/bin/switch-to-configuration boot</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Second, you can switch to the previous configuration in a running
|
||||
system:
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --rollback</screen>
|
||||
|
||||
This is equivalent to running:
|
||||
|
||||
<screen>
|
||||
$ /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen>
|
||||
|
||||
where <replaceable>N</replaceable> is the number of the NixOS system
|
||||
configuration. To get a list of the available configurations, do:
|
||||
|
||||
<screen>
|
||||
$ ls -l /nix/var/nix/profiles/system-*-link
|
||||
<replaceable>...</replaceable>
|
||||
lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> /nix/store/202b...-nixos-13.07pre4932_5a676e4-4be1055
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,24 +0,0 @@
|
||||
<part xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-running">
|
||||
|
||||
<title>Administration</title>
|
||||
|
||||
<partintro>
|
||||
<para>This chapter describes various aspects of managing a running
|
||||
NixOS system, such as how to use the <command>systemd</command>
|
||||
service manager.</para>
|
||||
</partintro>
|
||||
|
||||
<xi:include href="service-mgmt.xml" />
|
||||
<xi:include href="rebooting.xml" />
|
||||
<xi:include href="user-sessions.xml" />
|
||||
<xi:include href="control-groups.xml" />
|
||||
<xi:include href="logging.xml" />
|
||||
<xi:include href="cleaning-store.xml" />
|
||||
<xi:include href="containers.xml" />
|
||||
<xi:include href="troubleshooting.xml" />
|
||||
|
||||
</part>
|
||||
@@ -1,83 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-systemctl">
|
||||
|
||||
<title>Service Management</title>
|
||||
|
||||
<para>In NixOS, all system services are started and monitored using
|
||||
the systemd program. Systemd is the “init” process of the system
|
||||
(i.e. PID 1), the parent of all other processes. It manages a set of
|
||||
so-called “units”, which can be things like system services
|
||||
(programs), but also mount points, swap files, devices, targets
|
||||
(groups of units) and more. Units can have complex dependencies; for
|
||||
instance, one unit can require that another unit must be successfully
|
||||
started before the first unit can be started. When the system boots,
|
||||
it starts a unit named <literal>default.target</literal>; the
|
||||
dependencies of this unit cause all system services to be started,
|
||||
file systems to be mounted, swap files to be activated, and so
|
||||
on.</para>
|
||||
|
||||
<para>The command <command>systemctl</command> is the main way to
|
||||
interact with <command>systemd</command>. Without any arguments, it
|
||||
shows the status of active units:
|
||||
|
||||
<screen>
|
||||
$ systemctl
|
||||
-.mount loaded active mounted /
|
||||
swapfile.swap loaded active active /swapfile
|
||||
sshd.service loaded active running SSH Daemon
|
||||
graphical.target loaded active active Graphical Interface
|
||||
<replaceable>...</replaceable>
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>You can ask for detailed status information about a unit, for
|
||||
instance, the PostgreSQL database service:
|
||||
|
||||
<screen>
|
||||
$ systemctl status postgresql.service
|
||||
postgresql.service - PostgreSQL Server
|
||||
Loaded: loaded (/nix/store/pn3q73mvh75gsrl8w7fdlfk3fq5qm5mw-unit/postgresql.service)
|
||||
Active: active (running) since Mon, 2013-01-07 15:55:57 CET; 9h ago
|
||||
Main PID: 2390 (postgres)
|
||||
CGroup: name=systemd:/system/postgresql.service
|
||||
├─2390 postgres
|
||||
├─2418 postgres: writer process
|
||||
├─2419 postgres: wal writer process
|
||||
├─2420 postgres: autovacuum launcher process
|
||||
├─2421 postgres: stats collector process
|
||||
└─2498 postgres: zabbix zabbix [local] idle
|
||||
|
||||
Jan 07 15:55:55 hagbard postgres[2394]: [1-1] LOG: database system was shut down at 2013-01-07 15:55:05 CET
|
||||
Jan 07 15:55:57 hagbard postgres[2390]: [1-1] LOG: database system is ready to accept connections
|
||||
Jan 07 15:55:57 hagbard postgres[2420]: [1-1] LOG: autovacuum launcher started
|
||||
Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
|
||||
</screen>
|
||||
|
||||
Note that this shows the status of the unit (active and running), all
|
||||
the processes belonging to the service, as well as the most recent log
|
||||
messages from the service.
|
||||
|
||||
</para>
|
||||
|
||||
<para>Units can be stopped, started or restarted:
|
||||
|
||||
<screen>
|
||||
$ systemctl stop postgresql.service
|
||||
$ systemctl start postgresql.service
|
||||
$ systemctl restart postgresql.service
|
||||
</screen>
|
||||
|
||||
These operations are synchronous: they wait until the service has
|
||||
finished starting or stopping (or has failed). Starting a unit will
|
||||
cause the dependencies of that unit to be started as well (if
|
||||
necessary).</para>
|
||||
|
||||
<!-- - cgroups: each service and user session is a cgroup
|
||||
|
||||
- cgroup resource management -->
|
||||
|
||||
</chapter>
|
||||
@@ -1,37 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-nix-store-corruption">
|
||||
|
||||
<title>Nix Store Corruption</title>
|
||||
|
||||
<para>After a system crash, it’s possible for files in the Nix store
|
||||
to become corrupted. (For instance, the Ext4 file system has the
|
||||
tendency to replace un-synced files with zero bytes.) NixOS tries
|
||||
hard to prevent this from happening: it performs a
|
||||
<command>sync</command> before switching to a new configuration, and
|
||||
Nix’s database is fully transactional. If corruption still occurs,
|
||||
you may be able to fix it automatically.</para>
|
||||
|
||||
<para>If the corruption is in a path in the closure of the NixOS
|
||||
system configuration, you can fix it by doing
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch --repair
|
||||
</screen>
|
||||
|
||||
This will cause Nix to check every path in the closure, and if its
|
||||
cryptographic hash differs from the hash recorded in Nix’s database,
|
||||
the path is rebuilt or redownloaded.</para>
|
||||
|
||||
<para>You can also scan the entire Nix store for corrupt paths:
|
||||
|
||||
<screen>
|
||||
$ nix-store --verify --check-contents --repair
|
||||
</screen>
|
||||
|
||||
Any corrupt paths will be redownloaded if they’re available in a
|
||||
binary cache; otherwise, they cannot be repaired.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,18 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-troubleshooting">
|
||||
|
||||
<title>Troubleshooting</title>
|
||||
|
||||
<para>This chapter describes solutions to common problems you might
|
||||
encounter when you manage your NixOS system.</para>
|
||||
|
||||
<xi:include href="boot-problems.xml" />
|
||||
<xi:include href="maintenance-mode.xml" />
|
||||
<xi:include href="rollback.xml" />
|
||||
<xi:include href="store-corruption.xml" />
|
||||
<xi:include href="network-problems.xml" />
|
||||
|
||||
</chapter>
|
||||
@@ -1,53 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-user-sessions">
|
||||
|
||||
<title>User Sessions</title>
|
||||
|
||||
<para>Systemd keeps track of all users who are logged into the system
|
||||
(e.g. on a virtual console or remotely via SSH). The command
|
||||
<command>loginctl</command> allows querying and manipulating user
|
||||
sessions. For instance, to list all user sessions:
|
||||
|
||||
<screen>
|
||||
$ loginctl
|
||||
SESSION UID USER SEAT
|
||||
c1 500 eelco seat0
|
||||
c3 0 root seat0
|
||||
c4 500 alice
|
||||
</screen>
|
||||
|
||||
This shows that two users are logged in locally, while another is
|
||||
logged in remotely. (“Seats” are essentially the combinations of
|
||||
displays and input devices attached to the system; usually, there is
|
||||
only one seat.) To get information about a session:
|
||||
|
||||
<screen>
|
||||
$ loginctl session-status c3
|
||||
c3 - root (0)
|
||||
Since: Tue, 2013-01-08 01:17:56 CET; 4min 42s ago
|
||||
Leader: 2536 (login)
|
||||
Seat: seat0; vc3
|
||||
TTY: /dev/tty3
|
||||
Service: login; type tty; class user
|
||||
State: online
|
||||
CGroup: name=systemd:/user/root/c3
|
||||
├─ 2536 /nix/store/10mn4xip9n7y9bxqwnsx7xwx2v2g34xn-shadow-4.1.5.1/bin/login --
|
||||
├─10339 -bash
|
||||
└─10355 w3m nixos.org
|
||||
</screen>
|
||||
|
||||
This shows that the user is logged in on virtual console 3. It also
|
||||
lists the processes belonging to this session. Since systemd keeps
|
||||
track of this, you can terminate a session in a way that ensures that
|
||||
all the session’s processes are gone:
|
||||
|
||||
<screen>
|
||||
$ loginctl terminate-session c3
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
@@ -1,166 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-module-abstractions">
|
||||
|
||||
<title>Abstractions</title>
|
||||
|
||||
<para>If you find yourself repeating yourself over and over, it’s time
|
||||
to abstract. Take, for instance, this Apache HTTP Server configuration:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
[ { hostName = "example.org";
|
||||
documentRoot = "/webroot";
|
||||
adminAddr = "alice@example.org";
|
||||
enableUserDir = true;
|
||||
}
|
||||
{ hostName = "example.org";
|
||||
documentRoot = "/webroot";
|
||||
adminAddr = "alice@example.org";
|
||||
enableUserDir = true;
|
||||
enableSSL = true;
|
||||
sslServerCert = "/root/ssl-example-org.crt";
|
||||
sslServerKey = "/root/ssl-example-org.key";
|
||||
}
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
It defines two virtual hosts with nearly identical configuration; the
|
||||
only difference is that the second one has SSL enabled. To prevent
|
||||
this duplication, we can use a <literal>let</literal>:
|
||||
|
||||
<programlisting>
|
||||
let
|
||||
exampleOrgCommon =
|
||||
{ hostName = "example.org";
|
||||
documentRoot = "/webroot";
|
||||
adminAddr = "alice@example.org";
|
||||
enableUserDir = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
[ exampleOrgCommon
|
||||
(exampleOrgCommon // {
|
||||
enableSSL = true;
|
||||
sslServerCert = "/root/ssl-example-org.crt";
|
||||
sslServerKey = "/root/ssl-example-org.key";
|
||||
})
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
The <literal>let exampleOrgCommon =
|
||||
<replaceable>...</replaceable></literal> defines a variable named
|
||||
<literal>exampleOrgCommon</literal>. The <literal>//</literal>
|
||||
operator merges two attribute sets, so the configuration of the second
|
||||
virtual host is the set <literal>exampleOrgCommon</literal> extended
|
||||
with the SSL options.</para>
|
||||
|
||||
<para>You can write a <literal>let</literal> wherever an expression is
|
||||
allowed. Thus, you also could have written:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
let exampleOrgCommon = <replaceable>...</replaceable>; in
|
||||
[ exampleOrgCommon
|
||||
(exampleOrgCommon // { <replaceable>...</replaceable> })
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
but not <literal>{ let exampleOrgCommon =
|
||||
<replaceable>...</replaceable>; in <replaceable>...</replaceable>;
|
||||
}</literal> since attributes (as opposed to attribute values) are not
|
||||
expressions.</para>
|
||||
|
||||
<para><emphasis>Functions</emphasis> provide another method of
|
||||
abstraction. For instance, suppose that we want to generate lots of
|
||||
different virtual hosts, all with identical configuration except for
|
||||
the host name. This can be done as follows:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
let
|
||||
makeVirtualHost = name:
|
||||
{ hostName = name;
|
||||
documentRoot = "/webroot";
|
||||
adminAddr = "alice@example.org";
|
||||
};
|
||||
in
|
||||
[ (makeVirtualHost "example.org")
|
||||
(makeVirtualHost "example.com")
|
||||
(makeVirtualHost "example.gov")
|
||||
(makeVirtualHost "example.nl")
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
Here, <varname>makeVirtualHost</varname> is a function that takes a
|
||||
single argument <literal>name</literal> and returns the configuration
|
||||
for a virtual host. That function is then called for several names to
|
||||
produce the list of virtual host configurations.</para>
|
||||
|
||||
<para>We can further improve on this by using the function
|
||||
<varname>map</varname>, which applies another function to every
|
||||
element in a list:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
let
|
||||
makeVirtualHost = <replaceable>...</replaceable>;
|
||||
in map makeVirtualHost
|
||||
[ "example.org" "example.com" "example.gov" "example.nl" ];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
(The function <literal>map</literal> is called a
|
||||
<emphasis>higher-order function</emphasis> because it takes another
|
||||
function as an argument.)</para>
|
||||
|
||||
<para>What if you need more than one argument, for instance, if we
|
||||
want to use a different <literal>documentRoot</literal> for each
|
||||
virtual host? Then we can make <varname>makeVirtualHost</varname> a
|
||||
function that takes a <emphasis>set</emphasis> as its argument, like this:
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
services.httpd.virtualHosts =
|
||||
let
|
||||
makeVirtualHost = { name, root }:
|
||||
{ hostName = name;
|
||||
documentRoot = root;
|
||||
adminAddr = "alice@example.org";
|
||||
};
|
||||
in map makeVirtualHost
|
||||
[ { name = "example.org"; root = "/sites/example.org"; }
|
||||
{ name = "example.com"; root = "/sites/example.com"; }
|
||||
{ name = "example.gov"; root = "/sites/example.gov"; }
|
||||
{ name = "example.nl"; root = "/sites/example.nl"; }
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
But in this case (where every root is a subdirectory of
|
||||
<filename>/sites</filename> named after the virtual host), it would
|
||||
have been shorter to define <varname>makeVirtualHost</varname> as
|
||||
<programlisting>
|
||||
makeVirtualHost = name:
|
||||
{ hostName = name;
|
||||
documentRoot = "/sites/${name}";
|
||||
adminAddr = "alice@example.org";
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
Here, the construct
|
||||
<literal>${<replaceable>...</replaceable>}</literal> allows the result
|
||||
of an expression to be spliced into a string.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,24 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ad-hoc-network-config">
|
||||
|
||||
<title>Ad-Hoc Configuration</title>
|
||||
|
||||
<para>You can use <option>networking.localCommands</option> to specify
|
||||
shell commands to be run at the end of
|
||||
<literal>network-setup.service</literal>. This is useful for doing
|
||||
network configuration not covered by the existing NixOS modules. For
|
||||
instance, to statically configure an IPv6 address:
|
||||
|
||||
<programlisting>
|
||||
networking.localCommands =
|
||||
''
|
||||
ip -6 addr add 2001:610:685:1::1/64 dev eth0
|
||||
'';
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,63 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-ad-hoc-packages">
|
||||
|
||||
<title>Ad-Hoc Package Management</title>
|
||||
|
||||
<para>With the command <command>nix-env</command>, you can install and
|
||||
uninstall packages from the command line. For instance, to install
|
||||
Mozilla Thunderbird:
|
||||
|
||||
<screen>
|
||||
$ nix-env -iA nixos.pkgs.thunderbird</screen>
|
||||
|
||||
If you invoke this as root, the package is installed in the Nix
|
||||
profile <filename>/nix/var/nix/profiles/default</filename> and visible
|
||||
to all users of the system; otherwise, the package ends up in
|
||||
<filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/profile</filename>
|
||||
and is not visible to other users. The <option>-A</option> flag
|
||||
specifies the package by its attribute name; without it, the package
|
||||
is installed by matching against its package name
|
||||
(e.g. <literal>thunderbird</literal>). The latter is slower because
|
||||
it requires matching against all available Nix packages, and is
|
||||
ambiguous if there are multiple matching packages.</para>
|
||||
|
||||
<para>Packages come from the NixOS channel. You typically upgrade a
|
||||
package by updating to the latest version of the NixOS channel:
|
||||
<screen>
|
||||
$ nix-channel --update nixos
|
||||
</screen>
|
||||
and then running <literal>nix-env -i</literal> again. Other packages
|
||||
in the profile are <emphasis>not</emphasis> affected; this is the
|
||||
crucial difference with the declarative style of package management,
|
||||
where running <command>nixos-rebuild switch</command> causes all
|
||||
packages to be updated to their current versions in the NixOS channel.
|
||||
You can however upgrade all packages for which there is a newer
|
||||
version by doing:
|
||||
<screen>
|
||||
$ nix-env -u '*'
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>A package can be uninstalled using the <option>-e</option>
|
||||
flag:
|
||||
<screen>
|
||||
$ nix-env -e thunderbird
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>Finally, you can roll back an undesirable
|
||||
<command>nix-env</command> action:
|
||||
<screen>
|
||||
$ nix-env --rollback
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para><command>nix-env</command> has many more flags. For details,
|
||||
see the
|
||||
<citerefentry><refentrytitle>nix-env</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
manpage or the Nix manual.</para>
|
||||
|
||||
</section>
|
||||
@@ -1,84 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-custom-packages">
|
||||
|
||||
<title>Adding Custom Packages</title>
|
||||
|
||||
<para>It’s possible that a package you need is not available in NixOS.
|
||||
In that case, you can do two things. First, you can clone the Nixpkgs
|
||||
repository, add the package to your clone, and (optionally) submit a
|
||||
patch or pull request to have it accepted into the main Nixpkgs
|
||||
repository. This is described in detail in the <link
|
||||
xlink:href="http://nixos.org/nixpkgs/manual">Nixpkgs manual</link>.
|
||||
In short, you clone Nixpkgs:
|
||||
|
||||
<screen>
|
||||
$ git clone git://github.com/NixOS/nixpkgs.git
|
||||
$ cd nixpkgs
|
||||
</screen>
|
||||
|
||||
Then you write and test the package as described in the Nixpkgs
|
||||
manual. Finally, you add it to
|
||||
<literal>environment.systemPackages</literal>, e.g.
|
||||
|
||||
<programlisting>
|
||||
environment.systemPackages = [ pkgs.my-package ];
|
||||
</programlisting>
|
||||
|
||||
and you run <command>nixos-rebuild</command>, specifying your own
|
||||
Nixpkgs tree:
|
||||
|
||||
<screen>
|
||||
$ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The second possibility is to add the package outside of the
|
||||
Nixpkgs tree. For instance, here is how you specify a build of the
|
||||
<link xlink:href="http://www.gnu.org/software/hello/">GNU Hello</link>
|
||||
package directly in <filename>configuration.nix</filename>:
|
||||
|
||||
<programlisting>
|
||||
environment.systemPackages =
|
||||
let
|
||||
my-hello = with pkgs; stdenv.mkDerivation rec {
|
||||
name = "hello-2.8";
|
||||
src = fetchurl {
|
||||
url = "mirror://gnu/hello/${name}.tar.gz";
|
||||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
|
||||
};
|
||||
};
|
||||
in
|
||||
[ my-hello ];
|
||||
</programlisting>
|
||||
|
||||
Of course, you can also move the definition of
|
||||
<literal>my-hello</literal> into a separate Nix expression, e.g.
|
||||
<programlisting>
|
||||
environment.systemPackages = [ (import ./my-hello.nix) ];
|
||||
</programlisting>
|
||||
where <filename>my-hello.nix</filename> contains:
|
||||
<programlisting>
|
||||
with import <nixpkgs> {}; # bring all of Nixpkgs into scope
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "hello-2.8";
|
||||
src = fetchurl {
|
||||
url = "mirror://gnu/hello/${name}.tar.gz";
|
||||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
This allows testing the package easily:
|
||||
<screen>
|
||||
$ nix-build my-hello.nix
|
||||
$ ./result/bin/hello
|
||||
Hello, world!
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,213 +0,0 @@
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-configuration-file">
|
||||
|
||||
<title>NixOS Configuration File</title>
|
||||
|
||||
<para>The NixOS configuration file generally looks like this:
|
||||
|
||||
<programlisting>
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{ <replaceable>option definitions</replaceable>
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
The first line (<literal>{ config, pkgs, ... }:</literal>) denotes
|
||||
that this is actually a function that takes at least the two arguments
|
||||
<varname>config</varname> and <varname>pkgs</varname>. (These are
|
||||
explained later.) The function returns a <emphasis>set</emphasis> of
|
||||
option definitions (<literal>{ <replaceable>...</replaceable> }</literal>). These definitions have the
|
||||
form <literal><replaceable>name</replaceable> =
|
||||
<replaceable>value</replaceable></literal>, where
|
||||
<replaceable>name</replaceable> is the name of an option and
|
||||
<replaceable>value</replaceable> is its value. For example,
|
||||
|
||||
<programlisting>
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{ services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "alice@example.org";
|
||||
services.httpd.documentRoot = "/webroot";
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
defines a configuration with three option definitions that together
|
||||
enable the Apache HTTP Server with <filename>/webroot</filename> as
|
||||
the document root.</para>
|
||||
|
||||
<para>Sets can be nested, and in fact dots in option names are
|
||||
shorthand for defining a set containing another set. For instance,
|
||||
<option>services.httpd.enable</option> defines a set named
|
||||
<varname>services</varname> that contains a set named
|
||||
<varname>httpd</varname>, which in turn contains an option definition
|
||||
named <varname>enable</varname> with value <literal>true</literal>.
|
||||
This means that the example above can also be written as:
|
||||
|
||||
<programlisting>
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{ services = {
|
||||
httpd = {
|
||||
enable = true;
|
||||
adminAddr = "alice@example.org";
|
||||
documentRoot = "/webroot";
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
which may be more convenient if you have lots of option definitions
|
||||
that share the same prefix (such as
|
||||
<literal>services.httpd</literal>).</para>
|
||||
|
||||
<para>NixOS checks your option definitions for correctness. For
|
||||
instance, if you try to define an option that doesn’t exist (that is,
|
||||
doesn’t have a corresponding <emphasis>option declaration</emphasis>),
|
||||
<command>nixos-rebuild</command> will give an error like:
|
||||
<screen>
|
||||
The option `services.httpd.enabl' defined in `/etc/nixos/configuration.nix' does not exist.
|
||||
</screen>
|
||||
Likewise, values in option definitions must have a correct type. For
|
||||
instance, <option>services.httpd.enable</option> must be a Boolean
|
||||
(<literal>true</literal> or <literal>false</literal>). Trying to give
|
||||
it a value of another type, such as a string, will cause an error:
|
||||
<screen>
|
||||
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>Options have various types of values. The most important are:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Strings</term>
|
||||
<listitem>
|
||||
<para>Strings are enclosed in double quotes, e.g.
|
||||
|
||||
<programlisting>
|
||||
networking.hostName = "dexter";
|
||||
</programlisting>
|
||||
|
||||
Special characters can be escaped by prefixing them with a
|
||||
backslash (e.g. <literal>\"</literal>).</para>
|
||||
|
||||
<para>Multi-line strings can be enclosed in <emphasis>double
|
||||
single quotes</emphasis>, e.g.
|
||||
|
||||
<programlisting>
|
||||
networking.extraHosts =
|
||||
''
|
||||
127.0.0.2 other-localhost
|
||||
10.0.0.1 server
|
||||
'';
|
||||
</programlisting>
|
||||
|
||||
The main difference is that preceding whitespace is
|
||||
automatically stripped from each line, and that characters like
|
||||
<literal>"</literal> and <literal>\</literal> are not special
|
||||
(making it more convenient for including things like shell
|
||||
code).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Booleans</term>
|
||||
<listitem>
|
||||
<para>These can be <literal>true</literal> or
|
||||
<literal>false</literal>, e.g.
|
||||
|
||||
<programlisting>
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = false;
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Integers</term>
|
||||
<listitem>
|
||||
<para>For example,
|
||||
|
||||
<programlisting>
|
||||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
|
||||
</programlisting>
|
||||
|
||||
(Note that here the attribute name
|
||||
<literal>net.ipv4.tcp_keepalive_time</literal> is enclosed in
|
||||
quotes to prevent it from being interpreted as a set named
|
||||
<literal>net</literal> containing a set named
|
||||
<literal>ipv4</literal>, and so on. This is because it’s not a
|
||||
NixOS option but the literal name of a Linux kernel
|
||||
setting.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Sets</term>
|
||||
<listitem>
|
||||
<para>Sets were introduced above. They are name/value pairs
|
||||
enclosed in braces, as in the option definition
|
||||
|
||||
<programlisting>
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/sda1";
|
||||
fsType = "ext4";
|
||||
options = "rw,data=ordered,relatime";
|
||||
};
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Lists</term>
|
||||
<listitem>
|
||||
<para>The important thing to note about lists is that list
|
||||
elements are separated by whitespace, like this:
|
||||
|
||||
<programlisting>
|
||||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
||||
</programlisting>
|
||||
|
||||
List elements can be any other type, e.g. sets:
|
||||
|
||||
<programlisting>
|
||||
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Packages</term>
|
||||
<listitem>
|
||||
<para>Usually, the packages you need are already part of the Nix
|
||||
Packages collection, which is a set that can be accessed through
|
||||
the function argument <varname>pkgs</varname>. Typical uses:
|
||||
|
||||
<programlisting>
|
||||
environment.systemPackages =
|
||||
[ pkgs.thunderbird
|
||||
pkgs.emacs
|
||||
];
|
||||
|
||||
postgresql.package = pkgs.postgresql90;
|
||||
</programlisting>
|
||||
|
||||
The latter option definition changes the default PostgreSQL
|
||||
package used by NixOS’s PostgreSQL service to 9.0. For more
|
||||
information on packages, including how to add new ones, see
|
||||
<xref linkend="sec-custom-packages"/>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
@@ -1,27 +0,0 @@
|
||||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-configuration-syntax">
|
||||
|
||||
<title>Configuration Syntax</title>
|
||||
|
||||
<para>The NixOS configuration file
|
||||
<filename>/etc/nixos/configuration.nix</filename> is actually a
|
||||
<emphasis>Nix expression</emphasis>, which is the Nix package
|
||||
manager’s purely functional language for describing how to build
|
||||
packages and configurations. This means you have all the expressive
|
||||
power of that language at your disposal, including the ability to
|
||||
abstract over common patterns, which is very useful when managing
|
||||
complex systems. The syntax and semantics of the Nix language are
|
||||
fully described in the <link
|
||||
xlink:href="http://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
|
||||
manual</link>, but here we give a short overview of the most important
|
||||
constructs useful in NixOS configuration files.</para>
|
||||
|
||||
<xi:include href="config-file.xml" />
|
||||
<xi:include href="abstractions.xml" />
|
||||
<xi:include href="modularity.xml" />
|
||||
<xi:include href="summary.xml" />
|
||||
|
||||
</chapter>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user