Compare commits

..

1 Commits

Author SHA1 Message Date
Eelco Dolstra
129a56627f svn path=/nixpkgs/branches/0.10-release/; revision=6722 2006-10-12 20:35:23 +00:00
7428 changed files with 38671 additions and 347420 deletions

10
.gitignore vendored
View File

@@ -1,10 +0,0 @@
*~
,*
.*.swp
.*.swo
result
doc/NEWS.html
doc/NEWS.txt
doc/manual.html
doc/manual.pdf
.version-suffix

View File

@@ -1 +0,0 @@
13.10

1
STABLE Normal file
View File

@@ -0,0 +1 @@
1

1
VERSION Normal file
View File

@@ -0,0 +1 @@
0.10

View File

@@ -1 +0,0 @@
import ./pkgs/top-level/all-packages.nix

View File

@@ -1,7 +1,3 @@
# You may need to override this.
docbookxsl = $(HOME)/.nix-profile/xml/xsl/docbook
dblatex = dblatex
XMLLINT = xmllint --catalogs
XSLTPROC = xsltproc --catalogs \
--param section.autolabel 1 \
@@ -17,7 +13,7 @@ NEWS_OPTS = \
--stringparam section.autolabel.max.depth 0 \
--stringparam header.rule 0
all: NEWS.html NEWS.txt manual.html manual.pdf
all: NEWS.html NEWS.txt
NEWS.html: release-notes.xml
$(XSLTPROC) --nonet --xinclude --output $@ $(NEWS_OPTS) \
@@ -29,13 +25,3 @@ NEWS.txt: release-notes.xml
$(docbookxsl)/html/docbook.xsl -
LANG=en_US w3m -dump $@.tmp.html > $@
rm $@.tmp.html
manual.html: *.xml
$(XSLTPROC) --nonet --xinclude --output manual.html \
$(docbookxsl)/html/docbook.xsl manual.xml
manual.pdf: *.xml
$(dblatex) \
-P doc.collab.show=0 \
-P latex.output.revhistory=0 \
manual.xml

View File

@@ -1,605 +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 its asking for trouble.</para></listitem>
<listitem><para>Use <literal>lowerCamelCase</literal> for variable
names, not <literal>UpperCamelCase</literal>. TODO: naming of
attributes in
<filename>all-packages.nix</filename>?</para></listitem>
<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 &amp;&amp; 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>.
However, identifiers in the Nix language dont allow certain
characters (e.g. dashes), so sometimes a different variable name
should be used. For instance, the
<literal>module-init-tools</literal> package is bound to the
<literal>module_init_tools</literal> variable in
<filename>all-packages.nix</filename>.</para>
<para>There are a few naming guidelines:
<itemizedlist>
<listitem><para>Generally, try to stick to the upstream package
name.</para></listitem>
<listitem><para>Dont 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 changed to
underscores in variable names, rather than to camel case — e.g.,
<varname>module_init_tools</varname> instead of
<varname>moduleInitTools</varname>.</para></listitem>
<listitem><para>If there are multiple versions of a package, this
should be reflected in the variable names in
<filename>all-packages.nix</filename>,
e.g. <varname>hello_0_3</varname> and <varname>hello_0_4</varname>.
If there is an obvious “default” version, make an attribute like
<literal>hello = hello_0_4;</literal>.</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>Hierachy</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 its 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 its used to support <emphasis>software development</emphasis>:</term>
<listitem>
<variablelist>
<varlistentry>
<term>If its 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 its a <emphasis>compiler</emphasis>:</term>
<listitem>
<para><filename>development/compilers</filename> (e.g. <filename>gcc</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its an <emphasis>interpreter</emphasis>:</term>
<listitem>
<para><filename>development/interpreters</filename> (e.g. <filename>guile</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its a (set of) development <emphasis>tool(s)</emphasis>:</term>
<listitem>
<variablelist>
<varlistentry>
<term>If its 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 its 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 its 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 its for <emphasis>networking</emphasis>:</term>
<listitem>
<para><filename>tools/networking</filename> (e.g. <filename>wget</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its for <emphasis>text processing</emphasis>:</term>
<listitem>
<para><filename>tools/text</filename> (e.g. <filename>diffutils</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its 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 its 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 its 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 its 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 its a <emphasis>shell</emphasis>:</term>
<listitem>
<para><filename>shells</filename> (e.g. <filename>bash</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its a <emphasis>server</emphasis>:</term>
<listitem>
<variablelist>
<varlistentry>
<term>If its a web server:</term>
<listitem>
<para><filename>servers/http</filename> (e.g. <filename>apache-httpd</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its 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 its 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 its an <emphasis>application</emphasis>:</term>
<listitem>
<para>A (typically large) program with a distinct user
interface, primarily used interactively.</para>
<variablelist>
<varlistentry>
<term>If its 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 its for <emphasis>video playback / editing</emphasis>:</term>
<listitem>
<para><filename>applications/video</filename> (e.g. <filename>vlc</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its for <emphasis>graphics viewing / editing</emphasis>:</term>
<listitem>
<para><filename>applications/graphics</filename> (e.g. <filename>gimp</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its for <emphasis>networking</emphasis>:</term>
<listitem>
<variablelist>
<varlistentry>
<term>If its a <emphasis>mailreader</emphasis>:</term>
<listitem>
<para><filename>applications/networking/mailreaders</filename> (e.g. <filename>thunderbird</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its a <emphasis>newsreader</emphasis>:</term>
<listitem>
<para><filename>applications/networking/newsreaders</filename> (e.g. <filename>pan</filename>)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its 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 its <emphasis>data</emphasis> (i.e., does not have a
straight-forward executable semantics):</term>
<listitem>
<variablelist>
<varlistentry>
<term>If its a <emphasis>font</emphasis>:</term>
<listitem>
<para><filename>data/fonts</filename></para>
</listitem>
</varlistentry>
<varlistentry>
<term>If its related to <emphasis>SGML/XML processing</emphasis>:</term>
<listitem>
<variablelist>
<varlistentry>
<term>If its 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 its 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 its 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><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 dont 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>

View File

@@ -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 its 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>

View File

@@ -1,260 +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>. Its 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 were actually
downloading. Perl packages are made available in
<filename>all-packages.nix</filename> through the variable
<varname>perlPackages</varname>. For instance, if you have a package
that needs <varname>ClassC3</varname>, you would typically write
<programlisting>
foo = import ../path/to/foo.nix {
inherit stdenv fetchurl ...;
inherit (perlPackages) ClassC3;
};
</programlisting>
in <filename>all-packages.nix</filename>. You can test building a
Perl package as follows:
<screen>
$ nix-build -A perlPackages.ClassC3
</screen>
<varname>buildPerlPackage</varname> adds <literal>perl-</literal> to
the start of the name attribute, so the package above is actually
called <literal>perl-Class-C3-0.21</literal>. So to install it, you
can say:
<screen>
$ nix-env -i perl-Class-C3
</screen>
(Of course you can also install using the attribute name:
<literal>nix-env -i -A perlPackages.ClassC3</literal>.)</para>
<para>So what does <varname>buildPerlPackage</varname> do? It does
the following:
<orderedlist>
<listitem><para>In the configure phase, it calls <literal>perl
Makefile.PL</literal> to generate a Makefile. You can set the
variable <varname>makeMakerFlags</varname> to pass flags to
<filename>Makefile.PL</filename></para></listitem>
<listitem><para>It adds the contents of the <envar>PERL5LIB</envar>
environment variable to <literal>#! .../bin/perl</literal> line of
Perl scripts as <literal>-I<replaceable>dir</replaceable></literal>
flags. This ensures that a script can find its
dependencies.</para></listitem>
<listitem><para>In the fixup phase, it writes the propagated build
inputs (<varname>propagatedBuildInputs</varname>) to the file
<filename>$out/nix-support/propagated-user-env-packages</filename>.
<command>nix-env</command> recursively installs all packages listed
in this file when you install a package that has it. This ensures
that a Perl package can find its dependencies.</para></listitem>
</orderedlist>
</para>
<para><varname>buildPerlPackage</varname> is built on top of
<varname>stdenv</varname>, so everything can be customised in the
usual way. For instance, the <literal>BerkeleyDB</literal> module has
a <varname>preConfigure</varname> hook to generate a configuration
file used by <filename>Makefile.PL</filename>:
<programlisting>
{buildPerlPackage, fetchurl, db4}:
buildPerlPackage rec {
name = "BerkeleyDB-0.36";
src = fetchurl {
url = "mirror://cpan/authors/id/P/PM/PMQS/${name}.tar.gz";
sha256 = "07xf50riarb60l1h6m2dqmql8q5dij619712fsgw7ach04d8g3z1";
};
preConfigure = ''
echo "LIB = ${db4}/lib" > config.in
echo "INCLUDE = ${db4}/include" >> config.in
'';
}
</programlisting>
</para>
<para>Dependencies on other Perl packages can be specified in the
<varname>buildInputs</varname> and
<varname>propagatedBuildInputs</varname> attributes. If something is
exclusively a build-time dependency, use
<varname>buildInputs</varname>; if its (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><title>Python</title>
<para>
Python packages that
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link>,
which many Python packages do nowadays, can be built very simply using
the <varname>buildPythonPackage</varname> function. This function is
implemented
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix"><filename>pkgs/development/python-modules/generic/default.nix</filename></link>
and works similarly to <varname>buildPerlPackage</varname>. (See
<xref linkend="ssec-language-perl"/> for details.)
</para>
<para>
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>.
Most of them are simple. For example:
<programlisting>
twisted = buildPythonPackage {
name = "twisted-8.1.0";
src = fetchurl {
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
};
propagatedBuildInputs = [ pkgs.ZopeInterface ];
meta = {
homepage = http://twistedmatrix.com/;
description = "Twisted, an event-driven networking engine written in Python";
license = "MIT";
};
};
</programlisting>
</para>
</section>
<section><title>Java</title>
<para>Java packages should install JAR files in
<filename>$out/lib/java</filename>.</para>
</section>
<!--
<section><title>Haskell</title>
<para>TODO</para>
</section>
<section><title>TeX / LaTeX</title>
<para>* Special support for building TeX documents</para>
</section>
-->
</chapter>

View File

@@ -1,37 +0,0 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude">
<info>
<title>Nixpkgs Manual</title>
<subtitle>Draft (Version <xi:include href="../.version"
parse="text" />)</subtitle>
<author>
<personname>
<firstname>Eelco</firstname>
<surname>Dolstra</surname>
</personname>
<affiliation>
<orgname>LogicBlox</orgname>
</affiliation>
</author>
<copyright>
<year>2008-2012</year>
<holder>Eelco Dolstra</holder>
</copyright>
</info>
<xi:include href="introduction.xml" />
<xi:include href="quick-start.xml" />
<xi:include href="stdenv.xml" />
<xi:include href="meta.xml" />
<xi:include href="language-support.xml" />
<xi:include href="package-notes.xml" />
<xi:include href="coding-conventions.xml" />
</book>

View File

@@ -1,244 +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 = "GPLv3+";
};
</programlisting>
</para>
<para>Meta-attributes are not passed to the builder of the package.
Thus, a change to a meta-attribute doesnt trigger a recompilation of
the package. The value of a meta-attribute must a string.</para>
<para>The meta-attributes of a package can be queried from the
command-line using <command>nix-env</command>:
<screen>
$ nix-env -qa hello --meta --xml
&lt;?xml version='1.0' encoding='utf-8'?>
&lt;items>
&lt;item attrPath="hello" name="hello-2.3" system="i686-linux">
&lt;meta name="description" value="A program that produces a familiar, friendly greeting" />
&lt;meta name="homepage" value="http://www.gnu.org/software/hello/manual/" />
&lt;meta name="license" value="GPLv3+" />
&lt;meta name="longDescription" value="GNU Hello is a program that prints &amp;quot;Hello, world!&amp;quot; when you run it.&amp;#xA;It is fully customizable.&amp;#xA;" />
&lt;/item>
&lt;/items>
</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>The following meta-attributes have a standard
interpretation:</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>Dont include a period at the end. Dont include newline
characters. Capitalise the first character. For brevity, dont
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>homepage</varname></term>
<listitem><para>The packages homepage. Example:
<literal>http://www.gnu.org/software/hello/manual/</literal></para></listitem>
</varlistentry>
<varlistentry>
<term><varname>license</varname></term>
<listitem><para>The license for the package. See below for the
allowed values.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>maintainers</varname></term>
<listitem><para>A list of names and e-mail addresses of the
maintainers of this Nix expression, e.g. <literal>["Alice
&lt;alice@example.org>" "Bob &lt;bob@example.com>"]</literal>. If
you are the maintainer of multiple packages, you may want to add
yourself to <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/lib/maintainers.nix"><filename>pkgs/lib/maintainers.nix</filename></link>
and write something like <literal>[stdenv.lib.maintainers.alice
stdenv.lib.maintainers.bob]</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<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>
</variablelist>
</section>
<section xml:id="sec-meta-license"><title>Licenses</title>
<note><para>This is just a first attempt at standardising the license
attribute.</para></note>
<para>The <varname>meta.license</varname> attribute must be one of the
following:
<variablelist>
<varlistentry>
<term><varname>GPL</varname></term>
<listitem><para>GNU General Public License; version not
specified.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>GPLv2</varname></term>
<listitem><para>GNU General Public License, version
2.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>GPLv2+</varname></term>
<listitem><para>GNU General Public License, version
2 or higher.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>GPLv3</varname></term>
<listitem><para>GNU General Public License, version
3.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>GPLv3+</varname></term>
<listitem><para>GNU General Public License, version
3 or higher.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>bsd</varname></term>
<listitem><para>Catch-all for licenses that are essentially
similar to <link
xlink:href="http://www.gnu.org/licenses/license-list.html#ModifiedBSD">the
original BSD license with the advertising clause removed</link>,
i.e. permissive non-copyleft free software licenses. This
includes the <link
xlink:href="http://www.gnu.org/licenses/license-list.html#X11License">X11
(“MIT”) License</link>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>perl5</varname></term>
<listitem><para>The Perl 5 license (Artistic License, version 1
and GPL, version 1 or later).</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>free</varname></term>
<listitem><para>Catch-all for free software licenses not listed
above.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>free-copyleft</varname></term>
<listitem><para>Catch-all for free, copyleft software licenses not
listed above.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>free-non-copyleft</varname></term>
<listitem><para>Catch-all for free, non-copyleft software licenses
not listed above.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>unfree-redistributable</varname></term>
<listitem><para>Unfree package that can be redistributed in binary
form. That is, its 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 doesnt actually modify the
original binaries; otherwise were 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>

View File

@@ -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.

View File

@@ -1,158 +0,0 @@
- The standard environment
(Some of this can be moved from the Nix manual)
- Special attributes
- Generic builder
- Helper functions
- GCC / ld wrapper (+ env vars)
- Phases (+ how to add phases) and hooks
- Override functions for stdenv
- Overriding GCC
- Overriding the setup script
- Predefined override functions in all-packages.nix: static binary
stdenv, dietlibc stdenv
- Stdenv bootstrap; how to update the Linux bootstrap binaries
- Specific platform notes (Linux, Native, Cygwin, Mingw)
- Support for specific languages
- Perl
- Generic Perl builder
- Python
- Wrapper generation
- Haskell
- TODO
- Java
- TODO; Java needs lots of improvement
- TeX/LaTeX
- Special support for building TeX documents
- Special kinds of applications
- OpenGL apps
- Binary-only apps
- Linux kernel modules
- Mozilla plugins/extensions
- X apps
- KDE apps
- GConf-based apps
- Programs that need wrappers
- makeWrapper etc.
- Initial ramdisks
- Library functions
- i.e. in lib/default.nix
- Specific package notes
- Linux kernel; how to update; feature tests
- X.org; how to update
- Gnome; how to update
- GCC?
- GHC?
- ...
- Meta attributes
- License attr; possible values
- Virtual machine support (for the build farm)
- vmtools
- KVM notes
- Performing a build in a VM
- In the host FS
- In a disk image
- RPM builds
- RPM image creation
- Deb builds
- Deb image creation
- Debugging VM builds
- Guidelines for Nixpkgs contributions
- File naming conventions
- Versioning of packages
- Tree organisation
- Variable naming
- Layout / indentations style
- Output FS hierarchy (e.g. $out/share/man instead of $out/man)
- Misc
- Building outside of the Nixpkgs tree
- Config options
- Downloading stuff
- fetchurl
- mirror:// scheme
- fetchsvn
- fetchcvs
- fetchdarcs
- Appendix: Nixpkgs config options

View File

@@ -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 kernels <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 isnt 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 doesnt 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 were 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. dont
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 arent 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 (&lt;>) { if (/(href|HREF)="([^"]*.bz2)"/) { print "$ENV{'i'}$2\n"; }; }' \
| sort > tarballs-7.4.list
</screen>
<filename>extra.list</filename> contains libraries that arent 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>

View File

@@ -1,239 +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 its 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.1.nix"><filename>pkgs/development/libraries/gmp/5.1.1.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>BitTorrent (wxPython-based): <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/networking/p2p/bittorrent/default.nix"><filename>pkgs/tools/networking/p2p/bittorrent/default.nix</filename></link>.
Uses an external <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/networking/p2p/bittorrent/builder.sh">build
script</link>, which can be useful if you have lots of code
that you dont want cluttering up the Nix expression. But
external builders are mostly obsolete.
</para>
</listitem>
<listitem>
<para>Thunderbird: <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/mailreaders/thunderbird/default.nix"><filename>pkgs/applications/networking/mailreaders/thunderbird/default.nix</filename></link>.
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 doesnt 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 its 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>
<replaceable>url</replaceable> to get the SHA-256 hash of
source distributions.</para>
</listitem>
<listitem>
<para>A list of schemes for <literal>mirror://</literal>
URLs can be found in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/fetchurl/mirrors.nix"><filename>pkgs/build-support/fetchurl/mirrors.nix</filename></link>.</para>
</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>Test whether the package builds:
<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, or send a patch to
<literal>nix-dev@cs.uu.nl</literal>.</para>
</listitem>
<listitem>
<para>If you want the TU Delft build farm to build binaries of the
package and make them available in the <link
xlink:href="http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable/"><literal>nixpkgs</literal>
channel</link>, add it to <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/release.nix"><filename>pkgs/top-level/release.nix</filename></link>.</para>
</listitem>
</orderedlist>
</para>
</chapter>

View File

@@ -5,339 +5,10 @@
<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 doesnt 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 doesnt 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
xlink:href='http://nix.cs.uu.nl/dist/nix/nix-0.10/'>Nix
0.10</link> or higher.</para></note>
<para>This release has the following improvements:</para>
@@ -543,7 +214,7 @@ some of the more notable changes:</para>
<itemizedlist>
<listitem><para>Distribution files have been moved to <link
xlink:href="http://nixos.org/" />.</para></listitem>
xlink:href="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>

File diff suppressed because it is too large Load Diff

View File

@@ -8,14 +8,15 @@
body
{
font-family: "Nimbus Sans L", sans-serif;
font-family: sans-serif;
background: white;
margin: 2em 1em 2em 1em;
}
h1, h2, h3, h4
h1,h2,h3
{
color: #005aa0;
text-align: left;
}
h1 /* title */
@@ -45,11 +46,6 @@ h3 /* subsections */
font-size: 125%;
}
div.simplesect h2
{
font-size: 110%;
}
div.appendix h3
{
font-size: 150%;
@@ -74,13 +70,11 @@ div.refsection h3
div.example
{
border: 1px solid #b0b0b0;
border: 1px solid #6185a0;
padding: 6px 6px;
margin-left: 1.5em;
margin-right: 1.5em;
background: #f4f4f8;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example p.title
@@ -88,11 +82,6 @@ div.example p.title
margin-top: 0em;
}
div.example pre
{
box-shadow: none;
}
/***************************************************************************
Screen dumps:
@@ -100,15 +89,14 @@ div.example pre
pre.screen, pre.programlisting
{
border: 1px solid #b0b0b0;
border: 1px solid #6185a0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
color: #600000;
background: #f4f4f8;
font-family: monospace;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
/* font-size: 90%; */
}
div.example pre.programlisting
@@ -125,15 +113,13 @@ div.example pre.programlisting
.note, .warning
{
border: 1px solid #b0b0b0;
border: 1px solid #6185a0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
margin-bottom: 1em;
padding: 0.3em 0.3em 0.3em 0.3em;
background: #fffff5;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.note, div.warning
@@ -145,6 +131,7 @@ div.note h3, div.warning h3
{
color: red;
font-size: 100%;
// margin: 0 0 0 0;
padding-right: 0.5em;
display: inline;
}
@@ -175,26 +162,20 @@ div.navfooter *
Links colors and highlighting:
***************************************************************************/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
a:link { color: #0048b3; }
a:visited { color: #002a6a; }
a:hover { background: #ffffcd; }
/***************************************************************************
Table of contents:
***************************************************************************/
div.toc
.toc
{
font-size: 90%;
}
div.toc dl
{
margin-top: 0em;
margin-bottom: 0em;
}
/***************************************************************************
@@ -227,29 +208,76 @@ div.glosslist dt
font-style: italic;
}
.default
{
font-style: italic;
}
.availability
{
font-style: italic;
}
.varname
{
color: #400000;
}
span.command strong
div.informaltable table
{
font-weight: normal;
border: 1px solid #6185a0;
width: 100%;
}
div.informaltable td
{
border: 0;
padding: 5px;
}
div.informaltable td.default
{
text-align: right;
}
div.informaltable th
{
text-align: left;
color: #005aa0;
border: 0;
padding: 5px;
background: #fffff5;
font-weight: normal;
font-style: italic;
}
td.varname, td.tagname, td.paramname
{
font-weight: bold;
vertical-align: top;
}
div.epigraph
{
font-style: italic;
text-align: right;
}
table.productionset table.productionset
{
font-family: monospace;
}
strong.command
{
// font-family: monospace;
// font-style: italic;
// font-weight: normal;
color: #400000;
}
div.calloutlist table
div.calloutlist td
{
box-shadow: none;
padding-bottom: 1em;
}
table
{
border-collapse: collapse;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.affiliation
{
font-style: italic;
}

View File

@@ -1,328 +0,0 @@
# Operations on attribute sets.
with {
inherit (builtins) head tail isString;
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 builtins ? hasAttr && hasAttr attr e
then attrByPath (tail attrPath) default (getAttr attr e)
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: getAttr x set) 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 = 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 = attr: l: concatLists (map (s: if hasAttr attr s then [(getAttr attr s)] 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 = getAttr n set; 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 (getAttr name n) (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 builtins.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 builtins.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 (getAttr attr set); }) (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 (getAttr attr set)) (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 (getAttr name attrs)) (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] (getAttr attr old) new)) (attrNames old));
deepSeqAttrs = x: y: deepSeqList (attrValues x) y;
}

View File

@@ -1,54 +0,0 @@
{lib, pkgs} :
let inherit (lib) nv nvs; in
{
# see for example:
# - development/interpreters/php_configurable/default.nix
# - .. search composableDerivation in all-packages.nix ..
#
# You should be able to override anything you like easily
# grep the mailinglist by title "python proposal" (dec 08)
# -> http://mail.cs.uu.nl/pipermail/nix-dev/2008-December/001571.html
# to see why this got complicated when using all its features
# TODO add newer example using new syntax (kernel derivation proposal -> mailinglist)
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;
};
};
}

View File

@@ -1,116 +0,0 @@
let lib = import ./default.nix;
inherit (builtins) getAttr 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);
})
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 (builtins.getAttr outputName drv) outPath drvPath type outputName;
};
};
outputsList = map outputToAttrListElement outputs;
in builtins.getAttr drv.outputName commonAttrs;
}

View File

@@ -1,119 +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 {
# Wrapper aroung the primop `addErrorContext', which shouldn't used
# directly. It evaluates and returns `val', but if an evaluation
# error occurs, the text in `msg' is added to the error context
# (stack trace) printed by Nix.
addErrorContext =
if builtins ? addErrorContext
then builtins.addErrorContext
else msg: val: val;
addErrorContextToAttrs = lib.mapAttrs (a : v : lib.addErrorContext "while evaluating ${a}" v);
traceVal = if builtins ? trace then x: (builtins.trace x x) else x: x;
traceXMLVal = if builtins ? trace then x: (builtins.trace (builtins.toXML x) x) else x: x;
traceXMLValMarked = str: if builtins ? trace then x: (builtins.trace ( str + builtins.toXML x) x) else 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
);
}

View File

@@ -1,32 +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;
# Pull in some builtins not included elsewhere.
inherit (builtins) pathExists readFile;
}
# !!! 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

View File

@@ -1,241 +0,0 @@
{
/* License identifiers loosely based on: http://fedoraproject.org/wiki/Licensing
* 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.
*/
artistic2 = {
shortName = "Artistic 2.0";
fullName = "Artistic 2.0";
url = "http://opensource.org/licenses/artistic-license-2.0.php";
};
agpl3 = {
shortName = "AGPLv3";
fullName = "GNU Affero General Public License version 3 only";
url = https://www.gnu.org/licenses/agpl.html;
};
agpl3Plus = {
shortName = "AGPLv3+";
fullName = "GNU Affero General Public License version 3 or later";
url = https://www.gnu.org/licenses/agpl.html;
};
amd = {
shortName = "amd";
fullName = "AMD License Agreement";
url = "http://developer.amd.com/amd-license-agreement/";
};
amdadl = {
shortName = "amd-adl";
fullName = "amd-adl license";
url = "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/AMD-ADL?revision=1.1";
};
# Apple Public Source License 2.0;
# http://opensource.org/licenses/APSL-2.0
apsl20 = "APSL 2.0";
asl20 = {
shortName = "ASL2.0";
fullName = "Apache Software License 2.0";
url = http://www.apache.org/licenses/LICENSE-2.0;
};
boost = {
shortName = "boost";
fullName = "Boost Software License";
url = http://www.boost.org/LICENSE_1_0.txt;
};
bsd2 = {
shortName = "BSD-2";
fullName = "BSD license (2 clause)";
url = http://opensource.org/licenses/BSD-2-Clause;
};
bsd3 = {
shortName = "BSD-3";
fullName = "BSD license (3 clause)";
url = http://opensource.org/licenses/BSD-3-Clause;
};
bsdOriginal = {
shortName = "BSD-original";
fullName = "Original BSD license with advertising clause";
url = https://fedoraproject.org/wiki/Licensing/BSD;
};
cddl = {
shortName = "CDDL";
fullName = "Common Development Distribution License ";
url = http://www.opensolaris.org/os/licensing/cddllicense.txt;
};
cpl10 = {
shortName = "CPL 1.0";
fullName = "Common Public License version 1.0";
url = http://www.eclipse.org/legal/cpl-v10.html;
};
epl10 = {
shortName = "EPL 1.0";
fullName = "Eclipse Public License version 1.0";
url = http://www.eclipse.org/legal/epl-v10.html;
};
gpl2 = "GPLv2";
gpl2Oss = {
shortName = "GPLv2+OSS";
fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)";
url = http://www.mysql.com/about/legal/licensing/foss-exception;
};
# GNU General Public License version 2 or later;
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
gpl2Plus = "GPLv2+";
gpl3 = {
shortName = "GPLv3";
fullName = "GNU General Public License version 3 only";
url = http://www.fsf.org/licensing/licenses/gpl.html;
};
gpl3Plus = {
shortName = "GPLv3+";
fullName = "GNU General Public License version 3 or later";
url = http://www.fsf.org/licensing/licenses/gpl.html;
};
gpl3ClasspathPlus = {
shortName = "GPLv3+classpath+";
fullName = "GNU General Public License version 3 or later (with Classpath exception)";
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
};
isc = {
shortName = "ISC";
fullName = "Internet Systems Consortium License";
url = http://www.opensource.org/licenses/ISC;
};
ipl10 = {
shortName = "IPL 1.0";
fullName = "IBM Public License Version 1.0";
url = http://www.ibm.com/developerworks/opensource/library/os-i18n2/os-ipl.html;
};
ijg = {
shortName = "IJG";
fullName = "Independent JPEG Group License";
url = https://fedoraproject.org/wiki/Licensing/IJG;
};
libtiff = {
shortName = "libtiff";
fullName = "libtiff license";
url = https://fedoraproject.org/wiki/Licensing/libtiff;
};
lgpl2 = "LGPLv2";
lgpl2Plus = {
shortName = "LGPLv2+";
fullName = "GNU Library General Public License version 2 or later";
url = http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html;
};
lgpl21 = "LGPLv2.1";
lgpl21Plus = {
shortName = "LGPLv2.1+";
fullName = "GNU Lesser General Public License version 2.1 or later";
url = http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html;
};
llgpl21 = {
shortName = "LLGPLv2.1";
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;
};
lgpl3 = {
shortName = "LGPLv3";
fullName = "GNU Lesser General Public License version 3 only";
url = http://www.fsf.org/licensing/licenses/lgpl.html;
};
lgpl3Plus = {
shortName = "LGPLv3+";
fullName = "GNU Lesser General Public License version 3 or later";
url = http://www.fsf.org/licensing/licenses/lgpl.html;
};
mit = {
shortName = "MIT";
fullName = "MIT/X11 license";
url = http://www.opensource.org/licenses/mit-license.php;
};
mpl11 = {
shortName = "MPL1.1";
fullName = "Mozilla Public License version 1.1";
url = http://www.mozilla.org/MPL/MPL-1.1.html;
};
mpl20 = {
shortName = "MPL2.0";
fullName = "Mozilla Public License version 2.0";
url = https://www.mozilla.org/MPL/2.0;
};
openssl = {
shortName = "openssl";
fullName = "OpenSSL license";
url = http://www.openssl.org/source/license.html;
};
publicDomain = {
shortName = "Public Domain";
fullname = "Public Domain";
};
psfl = {
shortName = "PSFL";
fullName = "Python Software Foundation License";
url = http://docs.python.org/license.html;
};
tcltk = {
shortName = "Tcl/Tk";
fullName = "Tcl/Tk license";
url = http://www.tcl.tk/software/tcltk/license.html;
};
unfree = "unfree";
unfreeRedistributable = "unfree-redistributable";
unfreeRedistributableFirmware = "unfree-redistributable-firmware";
zlib = {
shortName = "zlib";
fullName = "zlib license";
url = http://www.gzip.org/zlib/zlib_license.html;
};
zpt20 = {
shortName = "ZPT2.0";
fullName = "Zope Public License 2.0";
url = "http://old.zope.org/Resources/License/ZPL-2.0";
};
zpt21 = {
shortName = "ZPT2.1";
fullName = "Zope Public License 2.1";
url = "http://old.zope.org/Resources/License/ZPL-2.1";
};
}

View File

@@ -1,243 +0,0 @@
# General list operations.
let
inherit (import ./trivial.nix) deepSeq;
inc = builtins.add 1;
dec = n: builtins.sub n 1;
in rec {
inherit (builtins) head tail length isList add sub lessThan elemAt;
# 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' (inc n));
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 == minus1
then nul
else op (foldl' (dec n)) (elemAt list n);
in foldl' (dec (length list));
minus1 = dec 0;
# 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 (inc n) (elemAt list n)) ] ++ imap' (inc n);
in imap' 0;
# Concatenate a list of lists.
concatLists = builtins.concatLists or (fold (x: y: x ++ y) []);
# 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];
# Filter a list using a predicate; that is, return a list containing
# every element from `list' for which `pred' returns true.
filter =
builtins.filter or
(pred: list:
fold (x: y: if pred x then [x] ++ y else y) [] list);
# Remove elements equal to 'e' from a list. Useful for buildInputs.
remove = e: filter (x: x != e);
# Return true if `list' has an element `x'.
elem =
builtins.elem or
(x: list: fold (a: bs: x == a || bs) false list);
# 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 inc c 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 builtins.isList x then x else [x];
# Return a list of integers from `first' up to and including `last'.
range = first: last:
if builtins.lessThan last first
then []
else [first] ++ range (builtins.add 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 builtins.lessThan len1 len2 then len1 else len2;
zipListsWith' = n:
if n != len then
[ (f (elemAt fst n) (elemAt snd n)) ]
++ zipListsWith' (inc n)
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' (inc n); 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 lessThan 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' (inc n);
in take' 0;
# Remove the first (at most) N elements of a list.
drop = count: list:
let
len = length list;
drop' = n:
if n == minus1 || lessThan n count
then []
else
drop' (dec n) ++ [ (elemAt list n) ];
in drop' (dec len);
last = list:
assert list != []; elemAt list (dec (length list));
# Zip two lists together.
zipTwoLists = xs: ys:
let
len1 = length xs;
len2 = length ys;
len = if lessThan len1 len2 then len1 else len2;
zipTwoLists' = n:
if n != len then
[ { first = elemAt xs n; second = elemAt ys n; } ]
++ zipTwoLists' (inc n)
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];
}

View File

@@ -1,66 +0,0 @@
/* -*- coding: utf-8; -*- */
{
/* Add your name and email address here. Keep the list
alphabetically sorted. */
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
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>";
andres = "Andres Loeh <ksnixos@andres-loeh.de>";
antono = "Antono Vasiljev <self@antono.info>";
astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>";
aszlig = "aszlig <aszlig@redmoonstudios.org>";
bbenoist = "Baptist BENOIST <return_0@live.com>";
bjg = "Brian Gough <bjg@gnu.org>";
bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>";
bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>";
bodil = "Bodil Stokke <nix@bodil.org>";
chaoflow = "Florian Friesdorf <flo@chaoflow.net>";
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
coroa = "Jonas Hörsch <jonas@chaoflow.net>";
edwtjo = "Edward Tjörnhammar <ed@cflags.cc>";
eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
ertes = "Ertugrul Söylemez <es@ertes.de>";
garbas = "Rok Garbas <rok@garbas.si>";
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
guibert = "David Guibert <david.guibert@gmail.com>";
iElectric = "Domen Kozar <domen@dev.si>";
iyzsong = "Song Wenwu <iyzsong@gmail.com>";
jcumming = "Jack Cummings <jack@mudshark.org>";
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
lovek323 = "Jason O'Conal <jason@oconal.id.au>";
ludo = "Ludovic Courtès <ludo@gnu.org>";
marcweber = "Marc Weber <marco-oweber@gmx.de>";
modulistic = "Pablo Costa <modulistic@gmail.com>";
mornfall = "Petr Ročkai <me@mornfall.net>";
ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
page = "Carles Pagès <page@cubata.homelinux.net>";
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
pierron = "Nicolas B. Pierron <nixos@nbp.name>";
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
pSub = "Pascal Wittmann <mail@pascal-wittmann.de>";
qknight = "Joachim Schiele <js@lastlog.de>";
raskin = "Michael Raskin <7c6f434c@mail.ru>";
rickynils = "Rickard Nilsson <rickynils@gmail.com>";
rob = "Rob Vermaas <rob.vermaas@gmail.com>";
roconnor = "Russell O'Connor <roconnor@theorem.ca>";
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
shlevy = "Shea Levy <shea@shealevy.com>";
simons = "Peter Simons <simons@cryp.to>";
smironov = "Sergey Mironov <ierton@gmail.com>";
thammers = "Tobias Hammerschmidt <jawr@gmx.de>";
the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>";
urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>";
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>";
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
zef = "Zef Hemel <zef@zef.me>";
}

View File

@@ -1,48 +0,0 @@
/* Some functions for manipulating meta attributes, as well as the
name attribute. */
rec {
/* Add to or override the meta attributes of the given
derivation.
Example:
addMetaAttrs {description = "Bla blah";} somePkg
*/
addMetaAttrs = newAttrs: drv:
drv // { meta = (if drv ? meta then drv.meta else {}) // 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. !!! the suffix should
really be appended *before* the version, at least most of the
time.
*/
appendToName = suffix: updateName (name: "${name}-${suffix}");
/* 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;
/* 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;
}

View File

@@ -1,429 +0,0 @@
let lib = import ./default.nix;
inherit (builtins) isFunction hasAttr getAttr 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 = getAttr n args;
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 = name: default: attrs:
if attrs == null then default else
if __hasAttr name attrs then (__getAttr name attrs) else default;
# shortcut for attrByPath ["name"] default attrs
maybeAttr = name: default: attrs:
if __hasAttr name attrs then (__getAttr name attrs) else 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 (builtins.getAttr attr r) ) (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 (__hasAttr n set)
then setAttr set n (f (__getAttr n set) (__getAttr n set2))
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 (__hasAttr n set)
then # merge
if elem n mergeLists # attribute contains list, merge them by concatenating
then (__getAttr n attrs2) ++ (__getAttr n attrs1)
else if elem n overrideSnd
then __getAttr n attrs1
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
else __getAttr n attrs2 # 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 (hasAttr a x)
then if (hasAttr a y)
then v (getAttr a x) (getAttr a y) # both have attr, use merge func
else (getAttr a x) # only x has attr
else (getAttr a y) # only y has attr)
) (removeAttrs mergeAttrBy2
# don't merge attrs which are neither in x nor y
(filter (a : (! hasAttr a x) && (! hasAttr a y) )
(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 (getAttr (flagName a) cfgWithDefaults) 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";
}

View File

@@ -1,314 +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 hasAttr name set 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 || builtins.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)}'."
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 builtins.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 hasAttr name m.options
then [ { inherit (m) file; options = getAttr name m.options; } ]
else []
) options);
# Get all submodules that define name.
defns = concatLists (map (m:
if hasAttr name m.config
then map (config: { inherit (m) file; inherit config; })
(pushDownProperties (getAttr name m.config))
else []
) configs);
nrOptions = count (m: isOption m.options) decls;
# Process mkMerge and mkIf properties.
defns' = concatMap (m:
if hasAttr name m.config
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties (getAttr name m.config))
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). */
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 ||
opt.options ? type && res ? type
then
throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}."
else
opt.options // res //
{ declarations = [opt.file] ++ res.declarations;
options = if opt.options ? options then [(toList opt.options.options ++ res.options)] else [];
}
) { 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);
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
mkIf 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
[ 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 builtins.lessThan 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;
/* Hack for backward compatibility: convert options of type
optionSet to configOf. FIXME: remove eventually. */
fixupOptionType = loc: opt:
let
options' = opt.options or
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute.");
coerce = x:
if builtins.isFunction x then x
else { config, ... }: { options = x; };
options = map coerce (flatten options');
f = tp:
if tp.name == "option set" then types.submodule options
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 opt // { type = f (opt.type or types.unspecified); };
/* 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
# FIXME: Add mkOrder back in. It's not currently used anywhere in
# NixOS, but it should be useful.
/* Compatibility. */
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
}

View File

@@ -1,120 +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;
};
mergeDefaultOption = loc: defs:
let list = getValues defs; in
if length list == 1 then head list
else if all builtins.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 builtins.isBool list then fold lib.or false list
else if all builtins.isString list then lib.concatStrings list
else if all builtins.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" builtins.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;
}
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; };
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>";
}

View File

@@ -1,16 +0,0 @@
let lists = import ./lists.nix; in
rec {
gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */
linux = ["i686-linux" "x86_64-linux" "powerpc-linux" "armv5tel-linux" "armv7l-linux" "mips64el-linux"];
darwin = ["x86_64-darwin"];
freebsd = ["i686-freebsd" "x86_64-freebsd" "powerpc-freebsd"];
openbsd = ["i686-openbsd" "x86_64-openbsd"];
netbsd = ["i686-netbsd" "x86_64-netbsd"];
cygwin = ["i686-cygwin"];
unix = linux ++ darwin ++ freebsd ++ openbsd;
all = linux ++ darwin ++ cygwin ++ freebsd ++ openbsd;
none = [];
allBut = platform: lists.filter (x: platform != x) all;
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux"];
}

View File

@@ -1,29 +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")) ||
# Filter out backup files.
(lib.hasSuffix "~" baseName)
);
in src: builtins.filterSource filter src;
# Get all files ending with the specified suffices from the given
# directory. 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;
}

View File

@@ -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 hasAttr entry done then f done (tail todo)
else f (done // listToAttrs [{name = entry; value = 1;}]) ([(builtins.getAttr entry predefined)] ++ 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; };
}

View File

@@ -1,190 +0,0 @@
/* String manipulation functions. */
let lib = import ./default.nix;
inherit (builtins) add sub lessThan length;
in
rec {
inherit (builtins) stringLength substring head tail;
# 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);
# 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 filename ends in the given suffix.
hasSuffix = ext: fileName:
let lenFileName = stringLength fileName;
lenExt = stringLength ext;
in !(lessThan lenFileName lenExt) &&
substring (sub lenFileName lenExt) lenFileName fileName == ext;
# 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 (sub 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 ["<" ">"] ["&lt;" "&gt;"] "<foo>" returns "&lt;foo&gt;".
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;
# Compares strings not requiring context equality
# Obviously, a workaround but works on all Nix versions
eqStrings = a: b: (a+(substring 0 0 b)) == ((substring 0 0 a)+b);
# Cut a string with a separator and produces a list of strings which were
# separated by this separator. e.g.,
# `splitString "." "foo.bar.baz"' returns ["foo" "bar" "baz"].
splitString = sep: s:
let
sepLen = stringLength sep;
sLen = stringLength s;
lastSearch = sub sLen sepLen;
startWithSep = startAt:
substring startAt sepLen s == sep;
recurse = index: startAt:
let cutUntil = i: [(substring startAt (sub i startAt) s)]; in
if lessThan index lastSearch then
if startWithSep index then
let restartAt = add index sepLen; in
cutUntil index ++ recurse restartAt restartAt
else
recurse (add 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 pre == substring 0 preLen s then
substring preLen (sub sLen preLen) 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}";
}

View File

@@ -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]
&& (builtins.lessThan 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;
}

View File

@@ -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];
};
}

View File

@@ -1,38 +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;
}

View File

@@ -1,210 +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;
typeOf = x: x._type or "";
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: {}
}:
{ _type = "option-type";
inherit name check merge getSubOptions;
};
types = rec {
unspecified = mkOptionType {
name = "unspecified";
};
bool = mkOptionType {
name = "boolean";
check = builtins.isBool;
merge = loc: fold (x: y: x.value || y) false;
};
int = mkOptionType {
name = "integer";
check = builtins.isInt;
merge = mergeOneOption;
};
str = mkOptionType {
name = "string";
check = builtins.isString;
merge = mergeOneOption;
};
# Merge multiple definitions by concatenating them (with the given
# separator between the values).
separatedString = sep: mkOptionType {
name = "string";
check = builtins.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 ++ ["*"]);
};
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>"]);
};
# 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 = "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?>"]);
};
uniq = elemType: mkOptionType {
inherit (elemType) name check;
merge = mergeOneOption;
getSubOptions = elemType.getSubOptions;
};
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;
};
functionTo = elemType: mkOptionType {
name = "function that evaluates to a(n) ${elemType.name}";
check = builtins.isFunction;
merge = loc: defs:
fnArgs: elemType.merge loc (map (fn: { inherit (fn) file; value = fn.value fnArgs; }) defs);
getSubOptions = elemType.getSubOptions;
};
submodule = opts:
let
opts' = toList opts;
inherit (import ./modules.nix) evalModules;
in
mkOptionType rec {
name = "submodule";
check = x: isAttrs x || builtins.isFunction x;
merge = loc: defs:
let
coerce = def: if builtins.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;
};
# 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; };
};
}

62
maintainers/docs/bugs.txt Normal file
View 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.

View 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

View File

@@ -0,0 +1,31 @@
Creating a new static stdenv
----------------------------
When Nix is ported to a new (Linux) platform and you want to have a completely
pure setup for the stdenv (for example for NixOS) it is necessary to rebuild
the static tools.
The challenge is that there is no Nix environment yet, for bootstrapping.
The first task is to create all the tools that are necessary. For most tools
there are ready made Nix expressions.
GCC
There is an expression gcc-static-3.4. Depending on whether or not you already
have an environment built with Nix (x86-linux: yes, rest: not yet) you should
set the noSysDirs parameter in all-packages.nix. If there is an environment,
leave it, but if the system is still impure (like most systems), set noSysDirs
to false.
bash
There is an expression for bash-static. Simply build it.
bzip2
There is an expression for bzip2-static. Simply build it.
findutils
There is an expression for findutils-static. Simply build it.

View File

@@ -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!
@@ -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

View File

@@ -0,0 +1,35 @@
Upgrading the standard initial environment
For Nix on i686-linux we make use of an environment of statically linked
tools (see $nixpkgs/stdenv/linux). The first version of these tools were
compiled outside of Nix, in an impure environment. They are used as some
magical ingredient to make everything work. To keep these tools more in
synchronization with the rest of nixpkgs and to make porting of nixpkgs
to other platforms easier the static versions are now also built with Nix
and nixpkgs.
The tools can be found in nixpkgs in:
- shells/bash-static
- tools/networking/curl-diet
- tools/archivers/gnutar-diet
- tools/compression/gzip-diet
- tools/compression/bzip2-static
- tools/text/gnused-diet
- tools/text/diffutils-diet
- tools/text/gnupatch-diet
- tools/misc/findutils-static
and
- development/compilers/gcc-static-3.4
Most packages are compiled with dietlibc, an alternate C library, apart
from bash and findutils, which are statically linked to glibc. The reason
we chose dietlibc has various reasons. First of all, curl cannot be built
statically with glibc. If we do, we get a static binary, but it cannot resolve
hostnames to IP addresses. glibc dynamically loads functionality at runtime
to do resolving. When linking with dietlibc this doesn't happen.
The static tools are not used as part of the input hashing (see Eelco's
PhD thesis, paragraph 5.4.1), so changing them does not change anything and
will not force a massive rebuild.

16
maintainers/docs/todo.txt Normal file
View File

@@ -0,0 +1,16 @@
* 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]
* Fix the bzip2 build generically.

View 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

View File

@@ -1,95 +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";
last if $? >> 8 == 255;
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");
}

View File

@@ -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 "]"

View File

@@ -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;

View File

@@ -0,0 +1,44 @@
#! /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|belastingdienst|microsoft|armijn/.nix|sun.com|archive.eclipse.org"; then
base=$(basename $oldURL)
newURL="http://nix.cs.uu.nl/dist/tarballs/$base"
newPath="/data/webserver/dist/tarballs/$base"
echo "$fn: $oldURL -> $newURL"
isSafe=1
if test -e "$newPath"; then
hash=$(fgrep -A 1 "$oldURL" "$fn" | grep md5 | sed 's^.*md5 = \"\(.*\)\";.*^\1^')
echo "HASH = $hash"
if ! test "$(nix-hash --type md5 --flat "$newPath")" = "$hash"; then
echo "WARNING: $newPath exists and differs!"
isSafe=
fi
fi
if test -n "$doMove" -a -n "$isSafe"; then
if ! test -e "$newPath"; then
curl --disable-epsv --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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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; }" \
$@

View File

@@ -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

View File

@@ -1,22 +0,0 @@
{ stdenv, makeWrapper, perl, perlPackages }:
stdenv.mkDerivation {
name = "nix-generate-from-cpan-1";
buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON ];
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";
};
}

View File

@@ -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/) {
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

View File

@@ -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";
};
}

View File

@@ -1,173 +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 die("syntax: $0 ...\n");
# 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";

View File

@@ -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.gcc.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;

View File

@@ -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

View File

@@ -61,7 +61,7 @@ rules
<map({x', x'', x''', xs', starts, starts': \[x | xs] -> [x''' | xs']
where
<remove-section-start> x => (x', starts);
<map(regularise-empty-lines); if !starts; debug; sortable-section; debug then qsort(compare-attrs) else id end> [x' | xs] => [x'' | xs'];
<map(regularise-empty-lines); qsort(compare-attrs)> [x' | xs] => [x'' | xs'];
<[] <+ \x -> ["\n\n\n" | x]\ > starts => starts';
<prepend-layout> (starts', x'') => x'''
\ })> groups => attrs';
@@ -79,12 +79,9 @@ strategies
<implode-string; is-substring(!"###")> cs;
!x
rules
sortable-section = ?[s]; !s; explode-string; not(fetch({x: ?x; !(x, 97); geq}))
rules
remove-section-start:
(appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs), attr) ->
((appl(prod([cf(layout())], cf(opt(layout())), no-attrs()), cs'), attr), starts)

View File

@@ -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

View File

@@ -1 +0,0 @@
improvements to vsftpd module

View File

@@ -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.

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -1,21 +0,0 @@
{
boot = {
loader.grub.device = "/dev/sda";
};
fileSystems = [
{ mountPoint = "/";
device = "/dev/sda1";
}
];
swapDevices = [
{ device = "/dev/sdb1"; }
];
services = {
openssh = {
enable = true;
};
};
}

View File

@@ -1,32 +0,0 @@
{
boot = {
loader.grub.device = "/dev/sda";
copyKernels = true;
bootMount = "(hd0,0)";
};
fileSystems = [
{ mountPoint = "/";
device = "/dev/sda3";
}
{ mountPoint = "/boot";
device = "/dev/sda1";
neededForBoot = true;
}
];
swapDevices = [
{ device = "/dev/sda2"; }
];
services = {
sshd = {
enable = true;
};
};
fonts = {
enableFontConfig = false;
};
}

View File

@@ -1,27 +0,0 @@
# This configuration has / on a LVM volume. Since Grub
# doesn't know about LVM, a separate /boot is therefore
# needed.
#
# In this example, labels are used for file systems and
# swap devices: "boot" might be /dev/sda1, "root" might be
# /dev/my-volume-group/root, and "swap" might be /dev/sda2.
# In particular there is no specific reference to the fact
# that / is on LVM; that's figured out automatically.
{
boot.loader.grub.device = "/dev/sda";
boot.initrd.kernelModules = ["ata_piix"];
fileSystems = [
{ mountPoint = "/";
label = "root";
}
{ mountPoint = "/boot";
label = "boot";
}
];
swapDevices = [
{ label = "swap"; }
];
}

View File

@@ -1,36 +0,0 @@
{
boot = {
loader.grub.device = "/dev/sda";
};
fileSystems = [
{ mountPoint = "/";
device = "/dev/sda1";
}
];
services = {
sshd = {
enable = true;
};
httpd = {
enable = true;
adminAddr = "admin@example.org";
subservices = {
subversion = {
enable = true;
dataDir = "/data/subversion";
notificationSender = "svn@example.org";
};
};
};
};
}

View File

@@ -1,20 +0,0 @@
# Configuration file used to install NixOS-x86_64 on a USB stick.
{
boot = {
loader.grub.device = "/dev/sda";
initrd = {
kernelModules = ["usb_storage" "ehci_hcd" "ohci_hcd"];
};
};
fileSystems = [
{ mountPoint = "/";
label = "nixos-usb";
}
];
fonts = {
enableFontConfig = false;
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,117 +0,0 @@
{ pkgs, options, version, revision }:
with pkgs.lib;
let
# Remove invisible and internal options.
options' = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options);
# Clean up declaration sites to not refer to the NixOS source tree.
options'' = flip map options' (opt: opt // {
declarations = map (fn: stripPrefix fn) opt.declarations;
});
prefix = toString pkgs.path;
stripPrefix = fn:
if substring 0 (stringLength prefix) fn == prefix then
substring (add (stringLength prefix) 1) 1000 fn
else
fn;
optionsXML = builtins.toFile "options.xml" (builtins.unsafeDiscardStringContext (builtins.toXML options''));
optionsDocBook = pkgs.runCommand "options-db.xml" {} ''
if grep /nixpkgs/nixos/modules ${optionsXML}; then
echo "The manual appears to depend on the location of Nixpkgs, which is bad"
echo "since this prevents sharing via the NixOS channel. This is typically"
echo "caused by an option default that refers to a relative path (see above"
echo "for hints about the offending path)."
exit 1
fi
${pkgs.libxslt}/bin/xsltproc \
--stringparam revision '${revision}' \
-o $out ${./options-to-docbook.xsl} ${optionsXML}
'';
in rec {
# Generate the NixOS manual.
manual = pkgs.stdenv.mkDerivation {
name = "nixos-manual";
sources = sourceFilesBySuffices ./. [".xml"];
buildInputs = [ pkgs.libxml2 pkgs.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 . # */
ln -s ${optionsDocBook} options-db.xml
echo "${version}" > version
# Check the validity of the manual sources.
xmllint --noout --nonet --xinclude --noxincludenode \
--relaxng ${pkgs.docbook5}/xml/rng/docbook/docbook.rng \
manual.xml
# Generate the HTML manual.
dst=$out/share/doc/nixos
ensureDir $dst
xsltproc $xsltFlags --nonet --xinclude \
--output $dst/manual.html \
${pkgs.docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \
./manual.xml
mkdir -p $dst/images/callouts
cp ${pkgs.docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/images/callouts/
cp ${./style.css} $dst/style.css
mkdir -p $out/nix-support
echo "nix-build out $out" >> $out/nix-support/hydra-build-products
echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products
''; # */
meta.description = "The NixOS manual in HTML format";
};
# Generate the NixOS manpages.
manpages = pkgs.stdenv.mkDerivation {
name = "nixos-manpages";
sources = sourceFilesBySuffices ./. [".xml"];
buildInputs = [ pkgs.libxml2 pkgs.libxslt ];
buildCommand = ''
ln -s $sources/*.xml . # */
ln -s ${optionsDocBook} options-db.xml
# Check the validity of the manual sources.
xmllint --noout --nonet --xinclude --noxincludenode \
--relaxng ${pkgs.docbook5}/xml/rng/docbook/docbook.rng \
./man-pages.xml
# Generate manpages.
mkdir -p $out/share/man
xsltproc --nonet --xinclude \
--param man.output.in.separate.dir 1 \
--param man.output.base.dir "'$out/share/man/'" \
--param man.endnotes.are.numbered 0 \
${pkgs.docbook5_xsl}/xml/xsl/docbook/manpages/docbook.xsl \
./man-pages.xml
'';
};
}

View File

@@ -1,853 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Development</title>
<para>This chapter describes how you can modify and extend
NixOS.</para>
<!--===============================================================-->
<section>
<title>Getting the sources</title>
<para>By default, NixOSs <command>nixos-rebuild</command> command
uses the NixOS and Nixpkgs sources provided by the
<literal>nixos-unstable</literal> channel (kept in
<filename>/nix/var/nix/profiles/per-user/root/channels/nixos</filename>).
To modify NixOS, however, you should check out the latest sources from
Git. This is done using the following command:
<screen>
$ nixos-checkout <replaceable>/my/sources</replaceable>
</screen>
or
<screen>
$ mkdir -p <replaceable>/my/sources</replaceable>
$ cd <replaceable>/my/sources</replaceable>
$ nix-env -i git
$ git clone git://github.com/NixOS/nixpkgs.git
</screen>
This will check out the latest NixOS sources to
<filename><replaceable>/my/sources</replaceable>/nixpkgs/nixos</filename>
and the Nixpkgs sources to
<filename><replaceable>/my/sources</replaceable>/nixpkgs</filename>.
(The NixOS source tree lives in a subdirectory of the Nixpkgs
repository.) If you want to rebuild your system using your (modified)
sources, you need to tell <command>nixos-rebuild</command> about them
using the <option>-I</option> flag:
<screen>
$ nixos-rebuild switch -I nixpkgs=<replaceable>/my/sources</replaceable>/nixpkgs
</screen>
</para>
<para>If you want <command>nix-env</command> to use the expressions in
<replaceable>/my/sources</replaceable>, use <command>nix-env -f
<replaceable>/my/sources</replaceable>/nixpkgs</command>, or change
the default by adding a symlink in
<filename>~/.nix-defexpr</filename>:
<screen>
$ ln -s <replaceable>/my/sources</replaceable>/nixpkgs ~/.nix-defexpr/nixpkgs
</screen>
You may want to delete the symlink
<filename>~/.nix-defexpr/channels_root</filename> to prevent roots
NixOS channel from clashing with your own tree.</para>
<!-- FIXME: not sure what this means.
<para>You should not pass the base directory
<filename><replaceable>/my/sources</replaceable></filename>
to <command>nix-env</command>, as it will break after interpreting expressions
in <filename>nixos/</filename> as packages.</para>
-->
</section>
<!--===============================================================-->
<section>
<title>Writing NixOS modules</title>
<para>NixOS has a modular system for declarative configuration. This
system combines multiple <emphasis>modules</emphasis> to produce the
full system configuration. One of the modules that constitute the
configuration is <filename>/etc/nixos/configuration.nix</filename>.
Most of the others live in the <link
xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><filename>nixos/modules</filename></link>
subdirectory of the Nixpkgs tree.</para>
<para>Each NixOS module is a file that handles one logical aspect of
the configuration, such as a specific kind of hardware, a service, or
network settings. A module configuration does not have to handle
everything from scratch; it can use the functionality provided by
other modules for its implementation. Thus a module can
<emphasis>declare</emphasis> options that can be used by other
modules, and conversely can <emphasis>define</emphasis> options
provided by other modules in its own implementation. For example, the
module <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/pam.nix"><filename>pam.nix</filename></link>
declares the option <option>security.pam.services</option> that allows
other modules (e.g. <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><filename>sshd.nix</filename></link>)
to define PAM services; and it defines the option
<option>environment.etc</option> (declared by <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><filename>etc.nix</filename></link>)
to cause files to be created in
<filename>/etc/pam.d</filename>.</para>
<para xml:id="para-module-syn">In <xref
linkend="sec-configuration-syntax"/>, we saw the following structure
of NixOS modules:
<programlisting>
{ config, pkgs, ... }:
{ <replaceable>option definitions</replaceable>
}
</programlisting>
This is actually an <emphasis>abbreviated</emphasis> form of module
that only defines options, but does not declare any. The structure of
full NixOS modules is shown in <xref linkend='ex-module-syntax' />.</para>
<example xml:id='ex-module-syntax'><title>Structure of NixOS modules</title>
<programlisting>
{ config, pkgs, ... }: <co xml:id='module-syntax-1' />
{
imports =
[ <replaceable>paths of other modules</replaceable> <co xml:id='module-syntax-2' />
];
options = {
<replaceable>option declarations</replaceable> <co xml:id='module-syntax-3' />
};
config = {
<replaceable>option definitions</replaceable> <co xml:id='module-syntax-4' />
};
}</programlisting>
</example>
<para>The meaning of each part is as follows.
<calloutlist>
<callout arearefs='module-syntax-1'>
<para>This line makes the current Nix expression a function. The
variable <varname>pkgs</varname> contains Nixpkgs, while
<varname>config</varname> contains the full system configuration.
This line can be omitted if there is no reference to
<varname>pkgs</varname> and <varname>config</varname> inside the
module.</para>
</callout>
<callout arearefs='module-syntax-2'>
<para>This list enumerates the paths to other NixOS modules that
should be included in the evaluation of the system configuration.
A default set of modules is defined in the file
<filename>modules/module-list.nix</filename>. These don't need to
be added in the import list.</para>
</callout>
<callout arearefs='module-syntax-3'>
<para>The attribute <varname>options</varname> is a nested set of
<emphasis>option declarations</emphasis> (described below).</para>
</callout>
<callout arearefs='module-syntax-4'>
<para>The attribute <varname>config</varname> is a nested set of
<emphasis>option definitions</emphasis> (also described
below).</para>
</callout>
</calloutlist>
</para>
<para><xref linkend='locate-example' /> shows a module that handles
the regular update of the “locate” database, an index of all files in
the file system. This module declares two options that can be defined
by other modules (typically the users
<filename>configuration.nix</filename>):
<option>services.locate.enable</option> (whether the database should
be updated) and <option>services.locate.period</option> (when the
update should be done). It implements its functionality by defining
two options declared by other modules:
<option>systemd.services</option> (the set of all systemd services)
and <option>services.cron.systemCronJobs</option> (the list of
commands to be executed periodically by <command>cron</command>).</para>
<example xml:id='locate-example'><title>NixOS module for the “locate” service</title>
<programlisting>
{ config, pkgs, ... }:
with pkgs.lib;
let locatedb = "/var/cache/locatedb"; in
{
options = {
services.locate = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
If enabled, NixOS will periodically update the database of
files used by the <command>locate</command> command.
'';
};
period = mkOption {
type = types.str;
default = "15 02 * * *";
description = ''
This option defines (in the format used by cron) when the
locate database is updated. The default is to update at
02:15 at night every day.
'';
};
};
};
config = {
systemd.services.update-locatedb =
{ description = "Update Locate Database";
path = [ pkgs.su ];
script =
''
mkdir -m 0755 -p $(dirname ${locatedb})
exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /media /run'
'';
};
services.cron.systemCronJobs = optional config.services.locate.enable
"${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service";
};
}</programlisting>
</example>
<section><title>Option declarations</title>
<para>An option declaration specifies the name, type and description
of a NixOS configuration option. It is illegal to define an option
that hasnt been declared in any module. A option declaration
generally looks like this:
<programlisting>
options = {
<replaceable>name</replaceable> = mkOption {
type = <replaceable>type specification</replaceable>;
default = <replaceable>default value</replaceable>;
example = <replaceable>example value</replaceable>;
description = "<replaceable>Description for use in the NixOS manual.</replaceable>";
};
};
</programlisting>
</para>
<para>The function <varname>mkOption</varname> accepts the following arguments.
<variablelist>
<varlistentry>
<term><varname>type</varname></term>
<listitem>
<para>The type of the option (see below). It may be omitted,
but thats not advisable since it may lead to errors that are
hard to diagnose.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>default</varname></term>
<listitem>
<para>The default value used if no value is defined by any
module. A default is not required; in that case, if the option
value is ever used, an error will be thrown.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>example</varname></term>
<listitem>
<para>An example value that will be shown in the NixOS manual.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>description</varname></term>
<listitem>
<para>A textual description of the option, in DocBook format,
that will be included in the NixOS manual.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>Here is a non-exhaustive list of option types:
<variablelist>
<varlistentry>
<term><varname>types.bool</varname></term>
<listitem>
<para>A Boolean.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.int</varname></term>
<listitem>
<para>An integer.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.str</varname></term>
<listitem>
<para>A string.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.lines</varname></term>
<listitem>
<para>A string. If there are multiple definitions, they are
concatenated, with newline characters in between.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.path</varname></term>
<listitem>
<para>A path, defined as anything that, when coerced to a
string, starts with a slash. This includes derivations.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
<listitem>
<para>A list of elements of type <replaceable>t</replaceable>
(e.g., <literal>types.listOf types.str</literal> is a list of
strings). Multiple definitions are concatenated together.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
<listitem>
<para>A set of elements of type <replaceable>t</replaceable>
(e.g., <literal>types.attrsOf types.int</literal> is a set of
name/value pairs, the values being integers).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
<listitem>
<para>Either the value <literal>null</literal> or something of
type <replaceable>t</replaceable>.</para>
</listitem>
</varlistentry>
</variablelist>
You can also create new types using the function
<varname>mkOptionType</varname>. See
<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
</section>
<section><title>Option definitions</title>
<para>Option definitions are generally straight-forward bindings of values to option names, like
<programlisting>
config = {
services.httpd.enable = true;
};
</programlisting>
However, sometimes you need to wrap an option definition or set of
option definitions in a <emphasis>property</emphasis> to achieve
certain effects:</para>
<simplesect><title>Delaying conditionals</title>
<para>If a set of option definitions is conditional on the value of
another option, you may need to use <varname>mkIf</varname>.
Consider, for instance:
<programlisting>
config = if config.services.httpd.enable then {
environment.systemPackages = [ <replaceable>...</replaceable> ];
<replaceable>...</replaceable>
} else {};
</programlisting>
This definition will cause Nix to fail with an “infinite recursion”
error. Why? Because the value of
<option>config.services.httpd.enable</option> depends on the value
being constructed here. After all, you could also write the clearly
circular and contradictory:
<programlisting>
config = if config.services.httpd.enable then {
services.httpd.enable = false;
} else {
services.httpd.enable = true;
};
</programlisting>
The solution is to write:
<programlisting>
config = mkIf config.services.httpd.enable {
environment.systemPackages = [ <replaceable>...</replaceable> ];
<replaceable>...</replaceable>
};
</programlisting>
The special function <varname>mkIf</varname> causes the evaluation of
the conditional to be “pushed down” into the individual definitions,
as if you had written:
<programlisting>
config = {
environment.systemPackages = if config.services.httpd.enable then [ <replaceable>...</replaceable> ] else [];
<replaceable>...</replaceable>
};
</programlisting>
</para>
</simplesect>
<simplesect><title>Setting priorities</title>
<para>A module can override the definitions of an option in other
modules by setting a <emphasis>priority</emphasis>. All option
definitions that do not have the lowest priority value are discarded.
By default, option definitions have priority 1000. You can specify an
explicit priority by using <varname>mkOverride</varname>, e.g.
<programlisting>
services.openssh.enable = mkOverride 10 false;
</programlisting>
This definition causes all other definitions with priorities above 10
to be discarded. The function <varname>mkForce</varname> is
equal to <varname>mkOverride 50</varname>.</para>
</simplesect>
<simplesect><title>Merging configurations</title>
<para>In conjunction with <literal>mkIf</literal>, it is sometimes
useful for a module to return multiple sets of option definitions, to
be merged together as if they were declared in separate modules. This
can be done using <varname>mkMerge</varname>:
<programlisting>
config = mkMerge
[ # Unconditional stuff.
{ environment.systemPackages = [ <replaceable>...</replaceable> ];
}
# Conditional stuff.
(mkIf config.services.bla.enable {
environment.systemPackages = [ <replaceable>...</replaceable> ];
})
];
</programlisting>
</para>
</simplesect>
</section>
<section><title>Important options</title>
<para>NixOS has many options, but some are of particular importance to
module writers.</para>
<variablelist>
<varlistentry>
<term><option>etc.environment</option></term>
<listitem>
<para>This set defines files in <filename>/etc</filename>. A
typical use is:
<programlisting>
environment.etc."os-release".text =
''
NAME=NixOS
<replaceable>...</replaceable>
'';
</programlisting>
which causes a file named <filename>/etc/os-release</filename>
to be created with the given contents.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>system.activationScripts</option></term>
<listitem>
<para>A set of shell script fragments that must be executed
whenever the configuration is activated (i.e., at boot time, or
after running <command>nixos-rebuild switch</command>). For instance,
<programlisting>
system.activationScripts.media =
''
mkdir -m 0755 -p /media
'';
</programlisting>
causes the directory <filename>/media</filename> to be created.
Activation scripts must be idempotent. They should not start
background processes such as daemons; use
<option>systemd.services</option> for that.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>systemd.services</option></term>
<listitem>
<para>This is the set of systemd services. Example:
<programlisting>
systemd.services.dhcpcd =
{ description = "DHCP Client";
wantedBy = [ "multi-user.target" ];
after = [ "systemd-udev-settle.service" ];
path = [ dhcpcd pkgs.nettools pkgs.openresolv ];
serviceConfig =
{ Type = "forking";
PIDFile = "/run/dhcpcd.pid";
ExecStart = "${dhcpcd}/sbin/dhcpcd --config ${dhcpcdConf}";
Restart = "always";
};
};
</programlisting>
which creates the systemd unit
<literal>dhcpcd.service</literal>. The option
<option>wantedBy</option> determined which other units pull this
one in; <literal>multi-user.target</literal> is the default
target of the system, so <literal>dhcpcd.service</literal> will
always be started. The option
<option>serviceConfig.ExecStart</option> provides the main
command for the service; its also possible to provide pre-start
actions, stop scripts, and so on.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>users.extraUsers</option></term>
<term><option>users.extraGroups</option></term>
<listitem>
<para>If your service requires special UIDs or GIDs, you can
define them with these options. See <xref
linkend="sec-user-management"/> for details.</para>
</listitem>
</varlistentry>
</variablelist>
</section>
</section>
<!--===============================================================-->
<section>
<title>Building specific parts of NixOS</title>
<para>With the command <command>nix-build</command>, you can build
specific parts of your NixOS configuration. This is done as follows:
<screen>
$ cd <replaceable>/path/to/nixpkgs/nixos</replaceable>
$ nix-build -A config.<replaceable>option</replaceable></screen>
where <replaceable>option</replaceable> is a NixOS option with type
“derivation” (i.e. something that can be built). Attributes of
interest include:
<variablelist>
<varlistentry>
<term><varname>system.build.toplevel</varname></term>
<listitem>
<para>The top-level option that builds the entire NixOS system.
Everything else in your configuration is indirectly pulled in by
this option. This is what <command>nixos-rebuild</command>
builds and what <filename>/run/current-system</filename> points
to afterwards.</para>
<para>A shortcut to build this is:
<screen>
$ nix-build -A system</screen>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>system.build.manual.manual</varname></term>
<listitem><para>The NixOS manual.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>system.build.etc</varname></term>
<listitem><para>A tree of symlinks that form the static parts of
<filename>/etc</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>system.build.initialRamdisk</varname></term>
<term><varname>system.build.kernel</varname></term>
<listitem>
<para>The initial ramdisk and kernel of the system. This allows
a quick way to test whether the kernel and the initial ramdisk
boot correctly, by using QEMUs <option>-kernel</option> and
<option>-initrd</option> options:
<screen>
$ nix-build -A config.system.build.initialRamdisk -o initrd
$ nix-build -A config.system.build.kernel -o kernel
$ qemu-system-x86_64 -kernel ./kernel/bzImage -initrd ./initrd/initrd -hda /dev/null
</screen>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>system.build.nixos-rebuild</varname></term>
<term><varname>system.build.nixos-install</varname></term>
<term><varname>system.build.nixos-generate-config</varname></term>
<listitem>
<para>These build the corresponding NixOS commands.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<!--===============================================================-->
<section>
<title>Building your own NixOS CD</title>
<para>Building a NixOS CD is as easy as configuring your own computer. The
idea is to use another module which will replace
your <filename>configuration.nix</filename> to configure the system that
would be installed on the CD.</para>
<para>Default CD/DVD configurations are available
inside <filename>nixos/modules/installer/cd-dvd</filename>. To build them
you have to set <envar>NIXOS_CONFIG</envar> before
running <command>nix-build</command> to build the ISO.
<screen>
$ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-minimal.nix</screen>
</para>
<para>Before burning your CD/DVD, you can check the content of the image by mounting anywhere like
suggested by the following command:
<screen>
$ mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso</screen>
</para>
</section>
<!--===============================================================-->
<section>
<title>Testing the installer</title>
<para>Building, burning, and
booting from an installation CD is rather
tedious, so here is a quick way to see if the installer works
properly:
<screen>
$ nix-build -A config.system.build.nixos-install
$ dd if=/dev/zero of=diskimage seek=2G count=0 bs=1
$ yes | mke2fs -j diskimage
$ mount -o loop diskimage /mnt
$ ./result/bin/nixos-install</screen>
</para>
</section>
<!--===============================================================-->
<section><title>Whole-system testing using virtual machines</title>
<para>Complete NixOS GNU/Linux systems can be tested in virtual
machines (VMs). This makes it possible to test a system upgrade or
configuration change before rebooting into it, using the
<command>nixos-rebuild build-vm</command> or <command>nixos-rebuild
build-vm-with-bootloader</command> command.</para>
<!-- The following is adapted from
http://wiki.nixos.org/wiki/NixOS_VM_tests, by Eelco Dolstra. -->
<para>The <filename>tests/</filename> directory in the NixOS source
tree contains several <emphasis>whole-system unit tests</emphasis>.
These tests can be run<footnote><para>NixOS tests can be run both from
NixOS and from a non-NixOS GNU/Linux distribution, provided the Nix
package manager is installed.</para></footnote> from the NixOS source
tree as follows:
<screen>
$ nix-build tests/ -A nfs.test
</screen>
This performs an automated test of the NFS client and server
functionality in the Linux kernel, including file locking semantics
(e.g., whether locks are maintained across server crashes). It will
first build or download all the dependencies of the test (e.g., all
packages needed to run a NixOS VM). The test is defined in <link
xlink:href="https://nixos.org/repos/nix/nixos/trunk/tests/nfs.nix">
<filename>tests/nfs.nix</filename></link>. If the test succeeds,
<command>nix-build</command> will place a symlink
<filename>./result</filename> in the current directory pointing at the
location in the Nix store of the test results (e.g., screenshots, test
reports, and so on). In particular, a pretty-printed log of the test
is written to <filename>log.html</filename>, which can be viewed using
a web browser like this:
<screen>
$ firefox result/log.html
</screen>
</para>
<para>It is also possible to run the test environment interactively,
allowing you to experiment with the VMs. For example:
<screen>
$ nix-build tests/ -A nfs.driver
$ ./result/bin/nixos-run-vms
</screen>
The script <command>nixos-run-vms</command> starts the three virtual
machines defined in the NFS test using QEMU/KVM. The root file system
of the VMs is created on the fly and kept across VM restarts in
<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
<para>Finally, the test itself can be run interactively. This is
particularly useful when developing or debugging a test:
<screen>
$ nix-build tests/ -A nfs.driver
$ ./result/bin/nixos-test-driver
starting VDE switch for network 1
&gt;
</screen>
Perl statements can now be typed in to start or manipulate the VMs:
<screen>
&gt; startAll;
(the VMs start booting)
&gt; $server-&gt;waitForJob("nfs-kernel-nfsd");
&gt; $client1-&gt;succeed("flock -x /data/lock -c 'sleep 100000' &amp;");
&gt; $client2-&gt;fail("flock -n -s /data/lock true");
&gt; $client1-&gt;shutdown;
(this releases client1's lock)
&gt; $client2-&gt;succeed("flock -n -s /data/lock true");
</screen>
The function <command>testScript</command> executes the entire test
script and drops you back into the test driver command line upon its
completion. This allows you to inspect the state of the VMs after the
test (e.g. to debug the test script).</para>
<para>This and other tests are continuously run on <link
xlink:href="http://hydra.nixos.org/jobset/nixos/trunk">the Hydra
instance at <literal>nixos.org</literal></link>, which allows
developers to be notified of any regressions introduced by a NixOS or
Nixpkgs change.</para>
<para>The actual Nix programming interface to VM testing is in NixOS,
under <link
xlink:href="https://nixos.org/repos/nix/nixos/trunk/lib/testing.nix">
<filename>lib/testing.nix</filename></link>. This file defines a
function which takes an attribute set containing a
<literal>nixpkgs</literal> attribute (the path to a Nixpkgs checkout),
and a <literal>system</literal> attribute (the system type). It
returns an attribute set containing several utility functions, among
which the main entry point is <literal>makeTest</literal>.
</para>
<para>The <literal>makeTest</literal> function takes a function
similar to that found in <link
xlink:href="https://nixos.org/repos/nix/nixos/trunk/tests/nfs.nix">
<filename>tests/nfs.nix</filename></link> (discussed above). It
returns an attribute set containing (among others):
<variablelist>
<varlistentry>
<term><varname>test</varname></term>
<listitem><para>A derivation containing the test log as an HTML
file, as seen above, suitable for presentation in the Hydra
continuous build system.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>report</varname></term>
<listitem><para>A derivation containing a code coverage report, with
meta-data suitable for Hydra.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>driver</varname></term>
<listitem><para>A derivation containing scripts to run the VM test or
interact with the VM network interactively, as seen above.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
</chapter>

View File

@@ -1,469 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Installing NixOS</title>
<!--===============================================================-->
<section>
<title>Obtaining NixOS</title>
<para>NixOS ISO images can be downloaded from the <link
xlink:href="http://nixos.org/nixos/download.html">NixOS
homepage</link>. These can be burned onto a CD. It is also possible
to copy them onto a USB stick and install NixOS from there. For
details, see the <link
xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS
Wiki</link>.</para>
<para>As an alternative to installing NixOS yourself, you can get a
running NixOS system through several other means:
<itemizedlist>
<listitem>
<para>Using virtual appliances in Open Virtualization Format (OVF)
that can be imported into VirtualBox. These are available from
the <link xlink:href="http://nixos.org/nixos/download.html">NixOS
homepage</link>.</para>
</listitem>
<listitem>
<para>Using AMIs for Amazons EC2. To find one for your region
and instance type, please refer to the <link
xlink:href="https://github.com/NixOS/nixops/blob/master/nix/ec2-amis.nix">list
of most recent AMIs</link>.</para>
</listitem>
<listitem>
<para>Using NixOps, the NixOS-based cloud deployment tool, which
allows you to provision VirtualBox and EC2 NixOS instances from
declarative specifications. Check out the <link
xlink:href="https://github.com/NixOS/nixops">NixOps
homepage</link> for details.</para>
</listitem>
</itemizedlist>
</para>
</section>
<!--===============================================================-->
<section>
<title>Installation</title>
<orderedlist>
<listitem><para>Boot from the CD.</para></listitem>
<listitem><para>The CD contains a basic NixOS installation. (It
also contains Memtest86+, useful if you want to test new hardware.)
When its finished booting, it should have detected most of your
hardware and brought up networking (check
<command>ifconfig</command>). Networking is necessary for the
installer, since it will download lots of stuff (such as source
tarballs or Nixpkgs channel binaries). Its best if you have a DHCP
server on your network. Otherwise configure networking manually
using <command>ifconfig</command>.</para></listitem>
<listitem><para>The NixOS manual is available on virtual console 8
(press Alt+F8 to access).</para></listitem>
<listitem><para>Login as <literal>root</literal> and the empty
password.</para></listitem>
<listitem><para>If you downloaded the graphical ISO image, you can
run <command>start display-manager</command> to start KDE.</para></listitem>
<listitem><para>The NixOS installer doesnt do any partitioning or
formatting yet, so you need to that yourself. Use the following
commands:
<itemizedlist>
<listitem><para>For partitioning:
<command>fdisk</command>.</para></listitem>
<listitem><para>For initialising Ext4 partitions:
<command>mkfs.ext4</command>. It is recommended that you assign a
unique symbolic label to the file system using the option
<option>-L <replaceable>label</replaceable></option>, since this
makes the file system configuration independent from device
changes. For example:
<screen>
$ mkfs.ext4 -L nixos /dev/sda1</screen>
</para></listitem>
<listitem><para>For creating swap partitions:
<command>mkswap</command>. Again its recommended to assign a
label to the swap partition: <option>-L
<replaceable>label</replaceable></option>.</para></listitem>
<listitem><para>For creating LVM volumes, the LVM commands, e.g.,
<screen>
$ pvcreate /dev/sda1 /dev/sdb1
$ vgcreate MyVolGroup /dev/sda1 /dev/sdb1
$ lvcreate --size 2G --name bigdisk MyVolGroup
$ lvcreate --size 1G --name smalldisk MyVolGroup</screen>
</para></listitem>
<listitem><para>For creating software RAID devices, use
<command>mdadm</command>.</para></listitem>
</itemizedlist>
</para></listitem>
<listitem><para>Mount the target file system on which NixOS should
be installed on <filename>/mnt</filename>, e.g.
<screen>
$ mount /dev/disk/by-label/nixos /mnt
</screen>
</para></listitem>
<listitem><para>If your machine has a limited amount of memory, you
may want to activate swap devices now (<command>swapon
<replaceable>device</replaceable></command>). The installer (or
rather, the build actions that it may spawn) may need quite a bit of
RAM, depending on your configuration.</para></listitem>
<listitem>
<para>You now need to create a file
<filename>/mnt/etc/nixos/configuration.nix</filename> that
specifies the intended configuration of the system. This is
because NixOS has a <emphasis>declarative</emphasis> configuration
model: you create or edit a description of the desired
configuration of your system, and then NixOS takes care of making
it happen. The syntax of the NixOS configuration file is
described in <xref linkend="sec-configuration-syntax"/>, while a
list of available configuration options appears in <xref
linkend="ch-options"/>. A minimal example is shown in <xref
linkend="ex-config"/>.</para>
<para>The command <command>nixos-generate-config</command> can
generate an initial configuration file for you:
<screen>
$ nixos-generate-config --root /mnt</screen>
You should then edit
<filename>/mnt/etc/nixos/configuration.nix</filename> to suit your
needs:
<screen>
$ nano /mnt/etc/nixos/configuration.nix
</screen>
The <command>vim</command> text editor is also available.</para>
<para>You <emphasis>must</emphasis> set the option
<option>boot.loader.grub.device</option> to specify on which disk
the GRUB boot loader is to be installed. Without it, NixOS cannot
boot.</para>
<para>Another critical option is <option>fileSystems</option>,
specifying the file systems that need to be mounted by NixOS.
However, you typically dont need to set it yourself, because
<command>nixos-generate-config</command> sets it automatically in
<filename>/mnt/etc/nixos/hardware-configuration.nix</filename>
from your currently mounted file systems. (The configuration file
<filename>hardware-configuration.nix</filename> is included from
<filename>configuration.nix</filename> and will be overwritten by
future invocations of <command>nixos-generate-config</command>;
thus, you generally should not modify it.)</para>
<note><para>Depending on your hardware configuration or type of
file system, you may need to set the option
<option>boot.initrd.kernelModules</option> to include the kernel
modules that are necessary for mounting the root file system,
otherwise the installed system will not be able to boot. (If this
happens, boot from the CD again, mount the target file system on
<filename>/mnt</filename>, fix
<filename>/mnt/etc/nixos/configuration.nix</filename> and rerun
<filename>nixos-install</filename>.) In most cases,
<command>nixos-generate-config</command> will figure out the
required modules.</para></note>
<para>Examples of real-world NixOS configuration files can be
found at <link
xlink:href="https://nixos.org/repos/nix/configurations/trunk/"/>.</para>
</listitem>
<listitem><para>Do the installation:
<screen>
$ nixos-install</screen>
Cross fingers. If this fails due to a temporary problem (such as
a network issue while downloading binaries from the NixOS binary
cache), you can just re-run <command>nixos-install</command>.
Otherwise, fix your <filename>configuration.nix</filename> and
then re-run <command>nixos-install</command>.</para></listitem>
<listitem><para>If everything went well:
<screen>
$ reboot</screen>
</para></listitem>
<listitem>
<para>You should now be able to boot into the installed NixOS.
The GRUB boot menu shows a list of <emphasis>available
configurations</emphasis> (initially just one). Every time you
change the NixOS configuration (see <xref
linkend="sec-changing-config" />), a new item appears in the menu.
This allows you to easily roll back to another configuration if
something goes wrong.</para>
<para>You should log in and change the <literal>root</literal>
password with <command>passwd</command>.</para>
<para>Youll probably want to create some user accounts as well,
which can be done with <command>useradd</command>:
<screen>
$ useradd -c 'Eelco Dolstra' -m eelco
$ passwd eelco</screen>
</para>
<para>You may also want to install some software. For instance,
<screen>
$ nix-env -qa \*</screen>
shows what packages are available, and
<screen>
$ nix-env -i w3m</screen>
install the <literal>w3m</literal> browser.</para>
</listitem>
</orderedlist>
<para>To summarise, <xref linkend="ex-install-sequence" /> shows a
typical sequence of commands for installing NixOS on an empty hard
drive (here <filename>/dev/sda</filename>). <xref linkend="ex-config"
/> shows a corresponding configuration Nix expression.</para>
<example xml:id='ex-install-sequence'><title>Commands for installing NixOS on <filename>/dev/sda</filename></title>
<screen>
$ fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
$ mkfs.ext4 -L nixos /dev/sda1
$ mkswap -L swap /dev/sda2
$ swapon /dev/sda2
$ mount /dev/disk/by-label/nixos /mnt
$ nixos-generate-config --root /mnt
$ nano /mnt/etc/nixos/configuration.nix
$ nixos-install
$ reboot</screen>
</example>
<example xml:id='ex-config'><title>NixOS configuration</title>
<screen>
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
boot.loader.grub.device = "/dev/sda";
# Note: setting fileSystems is generally not
# necessary, since nixos-generate-config figures them out
# automatically in hardware-configuration.nix.
#fileSystems."/".device = "/dev/disk/by-label/nixos";
# Enable the OpenSSH server.
services.sshd.enable = true;
}</screen>
</example>
</section>
<!--===============================================================-->
<section xml:id="sec-changing-config">
<title>Changing the configuration</title>
<para>The file <filename>/etc/nixos/configuration.nix</filename>
contains the current configuration of your machine. Whenever youve
changed something to that file, you should do
<screen>
$ nixos-rebuild switch</screen>
to build the new configuration, make it the default configuration for
booting, and try to realise the configuration in the running system
(e.g., by restarting system services).</para>
<warning><para>These commands must be executed as root, so you should
either run them from a root shell or by prefixing them with
<literal>sudo -i</literal>.</para></warning>
<para>You can also do
<screen>
$ nixos-rebuild test</screen>
to build the configuration and switch the running system to it, but
without making it the boot default. So if (say) the configuration
locks up your machine, you can just reboot to get back to a working
configuration.</para>
<para>There is also
<screen>
$ nixos-rebuild boot</screen>
to build the configuration and make it the boot default, but not
switch to it now (so it will only take effect after the next
reboot).</para>
<para>You can make your configuration show up in a different submenu
of the GRUB 2 boot screen by giving it a different <emphasis>profile
name</emphasis>, e.g.
<screen>
$ nixos-rebuild switch -p test </screen>
which causes the new configuration (and previous ones created using
<literal>-p test</literal>) to show up in the GRUB submenu “NixOS -
Profile 'test'”. This can be useful to separate test configurations
from “stable” configurations.</para>
<para>Finally, you can do
<screen>
$ nixos-rebuild build</screen>
to build the configuration but nothing more. This is useful to see
whether everything compiles cleanly.</para>
<para>If you have a machine that supports hardware virtualisation, you
can also test the new configuration in a sandbox by building and
running a QEMU <emphasis>virtual machine</emphasis> that contains the
desired configuration. Just do
<screen>
$ nixos-rebuild build-vm
$ ./result/bin/run-*-vm
</screen>
The VM does not have use any data from your host system, so your
existing user accounts and home directories will not be
available.</para>
</section>
<!--===============================================================-->
<section xml:id="sec-upgrading">
<title>Upgrading NixOS</title>
<para>The best way to keep your NixOS installation up to date is to
use one of the NixOS <emphasis>channels</emphasis>. A channel is a
Nix mechanism for distributing Nix expressions and associated
binaries. The NixOS channels are updated automatically from NixOSs
Git repository after certain tests have passed and all packages have
been built. These channels are:
<itemizedlist>
<listitem>
<para>Stable channels, such as <literal
xlink:href="http://nixos.org/channels/nixos-13.10">nixos-13.10</literal>.
These only get conservative bug fixes and package upgrades. For
instance, a channel update may cause the Linux kernel on your
system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but
not from 3.4.<replaceable>x</replaceable> to
3.11.<replaceable>x</replaceable> (a major change that has the
potential to break things). Stable channels are generally
maintained until the next stable branch is created.</para>
</listitem>
<listitem>
<para>The unstable channel, <literal
xlink:href="http://nixos.org/channels/nixos-unstable">nixos-unstable</literal>.
This corresponds to NixOSs main development branch, and may thus
see radical changes between channel updates. Its not recommended
for production systems.</para>
</listitem>
</itemizedlist>
To see what channels are available, go to <link
xlink:href="http://nixos.org/channels"/>. (Note that the URIs of the
various channels redirect to a directory that contains the channels
latest version and includes ISO images and VirtualBox
appliances.)</para>
<para>When you first install NixOS, youre automatically subscribed to
the NixOS channel that corresponds to your installation source. For
instance, if you installed from a 13.10 ISO, you will be subscribed to
the <literal>nixos-13.10</literal> channel. To see which NixOS
channel youre subscribed to, run the following as root:
<screen>
$ nix-channel --list | grep nixos
nixos https://nixos.org/channels/nixos-unstable
</screen>
To switch to a different NixOS channel, do
<screen>
$ nix-channel --add http://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
</screen>
(Be sure to include the <literal>nixos</literal> parameter at the
end.) For instance, to use the NixOS 13.10 stable channel:
<screen>
$ nix-channel --add http://nixos.org/channels/nixos-13.10 nixos
</screen>
But it you want to live on the bleeding edge:
<screen>
$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos
</screen>
</para>
<para>You can then upgrade NixOS to the latest version in your chosen
channel by running
<screen>
$ nixos-rebuild switch --upgrade
</screen>
which is equivalent to the more verbose <literal>nix-channel --update
nixos; nixos-rebuild switch</literal>.</para>
<warning><para>It is generally safe to switch back and forth between
channels. The only exception is that a newer NixOS may also have a
newer Nix version, which may involve an upgrade of Nixs database
schema. This cannot be undone easily, so in that case you will not be
able to go back to your original channel.</para></warning>
</section>
</chapter>

View File

@@ -1,38 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><filename>configuration.nix</filename></refentrytitle>
<manvolnum>5</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><filename>configuration.nix</filename></refname>
<refpurpose>NixOS system configuration specification</refpurpose>
</refnamediv>
<refsection><title>Description</title>
<para>The file <filename>/etc/nixos/configuration.nix</filename>
contains the declarative specification of your NixOS system
configuration. The command <command>nixos-rebuild</command> takes
this file and realises the system configuration specified
therein.</para>
</refsection>
<refsection><title>Options</title>
<para>You can use the following options in
<filename>configuration.nix</filename>.</para>
<xi:include href="options-db.xml" />
</refsection>
</refentry>

View File

@@ -1,110 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-build-vms</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-build-vms</command></refname>
<refpurpose>build a network of virtual machines from a network of NixOS configurations</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-build-vms</command>
<arg><option>--show-trace</option></arg>
<arg><option>--no-out-link</option></arg>
<arg><option>--help</option></arg>
<arg choice="plain"><replaceable>network.nix</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command builds a network of QEMU-KVM virtual machines of a Nix expression
specifying a network of NixOS machines. The virtual network can be started by
executing the <filename>bin/run-vms</filename> shell script that is generated by
this command. By default, a <filename>result</filename> symlink is produced that
points to the generated virtual network.
</para>
<para>A network Nix expression has the following structure:
<screen>
{
test1 = {pkgs, config, ...}:
{
services.openssh.enable = true;
nixpkgs.system = "i686-linux";
deployment.targetHost = "test1.example.net";
# Other NixOS options
};
test2 = {pkgs, config, ...}:
{
services.openssh.enable = true;
services.httpd.enable = true;
environment.systemPackages = [ pkgs.lynx ];
nixpkgs.system = "x86_64-linux";
deployment.targetHost = "test2.example.net";
# Other NixOS options
};
}
</screen>
Each attribute in the expression represents a machine in the network
(e.g. <varname>test1</varname> and <varname>test2</varname>)
referring to a function defining a NixOS configuration.
In each NixOS configuration, two attributes have a special meaning.
The <varname>deployment.targetHost</varname> specifies the address
(domain name or IP address)
of the system which is used by <command>ssh</command> to perform
remote deployment operations. The <varname>nixpkgs.system</varname>
attribute can be used to specify an architecture for the target machine,
such as <varname>i686-linux</varname> which builds a 32-bit NixOS
configuration. Omitting this property will build the configuration
for the same architecture as the host system.
</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--show-trace</option></term>
<listitem>
<para>Shows a trace of the output.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--no-out-link</option></term>
<listitem>
<para>Do not create a 'result' symlink.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem>
<para>Shows the usage of this command to the user.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
</refentry>

View File

@@ -1,208 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-generate-config</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-generate-config</command></refname>
<refpurpose>generate NixOS configuration modules</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-generate-config</command>
<arg><option>--force</option></arg>
<arg>
<arg choice='plain'><option>--root</option></arg>
<replaceable>root</replaceable>
</arg>
<arg>
<arg choice='plain'><option>--dir</option></arg>
<replaceable>dir</replaceable>
</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command writes two NixOS configuration modules:
<variablelist>
<varlistentry>
<term><option>/etc/nixos/hardware-configuration.nix</option></term>
<listitem>
<para>This module sets NixOS configuration options based on your
current hardware configuration. In particular, it sets the
<option>fileSystem</option> option to reflect all currently
mounted file systems, the <option>swapDevices</option> option to
reflect active swap devices, and the
<option>boot.initrd.*</option> options to ensure that the
initial ramdisk contains any kernel modules necessary for
mounting the root file system.</para>
<para>If this file already exists, it is overwritten. Thus, you
should not modify it manually. Rather, you should include it
from your <filename>/etc/nixos/configuration.nix</filename>, and
re-run <command>nixos-generate-config</command> to update it
whenever your hardware configuration changes.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>/etc/nixos/configuration.nix</option></term>
<listitem>
<para>This is the main NixOS system configuration module. If it
already exists, its left unchanged. Otherwise,
<command>nixos-generate-config</command> will write a template
for you to customise.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--root</option></term>
<listitem>
<para>If this option is given, treat the directory
<replaceable>root</replaceable> as the root of the file system.
This means that configuration files will be written to
<filename><replaceable>root</replaceable>/etc/nixos</filename>,
and that any file systems outside of
<replaceable>root</replaceable> are ignored for the purpose of
generating the <option>fileSystems</option> option.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--dir</option></term>
<listitem>
<para>If this option is given, write the configuration files to
the directory <replaceable>dir</replaceable> instead of
<filename>/etc/nixos</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--force</option></term>
<listitem>
<para>Overwrite
<filename>/etc/nixos/configuration.nix</filename> if it already
exists.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--no-filesystems</option></term>
<listitem>
<para>Omit everything concerning file system information
(which includes swap devices) from the hardware configuration.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--show-hardware-config</option></term>
<listitem>
<para>Don't generate <filename>configuration.nix</filename> or
<filename>hardware-configuration.nix</filename> and print the
hardware configuration to stdout only.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Examples</title>
<para>This command is typically used during NixOS installation to
write initial configuration modules. For example, if you created and
mounted the target file systems on <filename>/mnt</filename> and
<filename>/mnt/boot</filename>, you would run:
<screen>
$ nixos-generate-config --root /mnt
</screen>
The resulting file
<filename>/mnt/etc/nixos/hardware-configuration.nix</filename> might
look like this:
<programlisting>
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, pkgs, ... }:
{
imports =
[ &lt;nixos/modules/installer/scan/not-detected.nix>
];
boot.initrd.availableKernelModules = [ "ehci_hcd" "ahci" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-label/nixos";
fsType = "ext3";
options = "rw,data=ordered,relatime";
};
fileSystems."/boot" =
{ device = "/dev/sda1";
fsType = "ext3";
options = "rw,errors=continue,user_xattr,acl,barrier=1,data=writeback,relatime";
};
swapDevices =
[ { device = "/dev/sda2"; }
];
nix.maxJobs = 8;
}
</programlisting>
It will also create a basic
<filename>/mnt/etc/nixos/configuration.nix</filename>, which you
should edit to customise the logical configuration of your system.
This file includes the result of the hardware scan as follows:
<programlisting>
imports = [ ./hardware-configuration.nix ];
</programlisting>
</para>
<para>After installation, if your hardware configuration changes, you
can run:
<screen>
$ nixos-generate-config
</screen>
to update <filename>/etc/nixos/hardware-configuration.nix</filename>.
Your <filename>/etc/nixos/configuration.nix</filename> will
<emphasis>not</emphasis> be overwritten.</para>
</refsection>
</refentry>

View File

@@ -1,78 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-install</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-install</command></refname>
<refpurpose>install NixOS</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-install</command>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command installs NixOS in the file system mounted on
<filename>/mnt</filename>, based on the NixOS configuration specified
in <filename>/mnt/etc/nixos/configuration.nix</filename>. It performs
the following steps:
<itemizedlist>
<listitem><para>It copies Nix and its dependencies to
<filename>/mnt/nix/store</filename>.</para></listitem>
<listitem><para>It runs Nix in <filename>/mnt</filename> to build
the NixOS configuration specified in
<filename>/mnt/etc/nixos/configuration.nix</filename>.</para></listitem>
<listitem><para>It installs the GRUB boot loader on the device
specified in the option <option>boot.loader.grub.device</option>,
and generates a GRUB configuration file that boots into the NixOS
configuration just installed.</para></listitem>
</itemizedlist>
</para>
<para>This command is idempotent: if it is interrupted or fails due to
a temporary problem (e.g. a network issue), you can safely re-run
it.</para>
</refsection>
<refsection><title>Examples</title>
<para>A typical NixOS installation is done by creating and mounting a
file system on <filename>/mnt</filename>, generating a NixOS
configuration in
<filename>/mnt/etc/nixos/configuration.nix</filename>, and running
<command>nixos-install</command>. For instance, if we want to install
NixOS on an <literal>ext4</literal> file system created in
<filename>/dev/sda1</filename>:
<screen>
$ mkfs.ext4 /dev/sda1
$ mount /dev/sda1 /mnt
$ nixos-generate-config --root /mnt
$ # edit /mnt/etc/nixos/configuration.nix
$ nixos-install
</screen>
</para>
</refsection>
</refentry>

View File

@@ -1,138 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-option</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-option</command></refname>
<refpurpose>inspect a NixOS configuration</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-option</command>
<group choice="opt">
<option>-v</option>
<option>-d</option>
<option>-l</option>
</group>
<arg choice='plain'><replaceable>option.name</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command evaluates the configuration specified in
<filename>/etc/nixos/configuration.nix</filename> and returns the properties
of the option name given as argument. By default, it returns the value of
the option.</para>
<para>When the option name is not an option, the command prints the list of
attributes contained in the attribute set.</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--value</option>, <option>-v</option></term>
<listitem>
<para>Returns the value of the option. This is the default operation
if no other options are defined.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--description</option>, <option>-d</option></term>
<listitem>
<para>Return the default value, the example and the description of the
option when available.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--lookup</option>, <option>-l</option></term>
<listitem>
<para>Return the locations where the option is declared and where it
is defined. This is extremely useful to find sources of errors in
your configuration.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Environment</title>
<variablelist>
<varlistentry>
<term><envar>NIXOS_CONFIG</envar></term>
<listitem>
<para>Path to the main NixOS configuration module. Defaults to
<filename>/etc/nixos/configuration.nix</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Examples</title>
<para>Investigate option values:
<screen>$ nixos-option boot.loader
This attribute set contains:
generationsDir
grub
initScript
$ nixos-option boot.loader.grub.enable
true</screen></para>
<para>Prints option information:
<screen>$ nixos-option -d networking.hostName
Default: "nixos"
Description:
The name of the machine. Leave it empty if you want to obtain
it from a DHCP server (if using DHCP).</screen></para>
<para>Find the locations which are declaring and defining an option:
<screen>$ nixos-option -l hardware.firmware
Declared by:
/mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix
Defined by:
/path/to/nixpkgs/nixos/modules/system/boot/kernel.nix
/path/to/nixpkgs/nixos/modules/hardware/network/rt73.nix
/path/to/nixpkgs/nixos/modules/hardware/network/intel-3945abg.nix
/path/to/nixpkgs/nixos/modules/hardware/network/intel-2200bg.nix</screen></para>
</refsection>
<refsection><title>Bugs</title>
<para>The author listed in the following section is wrong. If there is any
other bug, please report to Nicolas Pierron.</para>
</refsection>
</refentry>

View File

@@ -1,335 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-rebuild</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><command>nixos-rebuild</command></refname>
<refpurpose>reconfigure a NixOS machine</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-rebuild</command>
<group choice='req'>
<arg choice='plain'><option>switch</option></arg>
<arg choice='plain'><option>boot</option></arg>
<arg choice='plain'><option>test</option></arg>
<arg choice='plain'><option>build</option></arg>
<arg choice='plain'><option>dry-run</option></arg>
<arg choice='plain'><option>build-vm</option></arg>
<arg choice='plain'><option>build-vm-with-bootloader</option></arg>
</group>
<sbr />
<arg><option>--upgrade</option></arg>
<arg><option>--install-grub</option></arg>
<arg><option>--no-build-nix</option></arg>
<arg><option>--fast</option></arg>
<arg><option>--rollback</option></arg>
<sbr />
<arg>
<group choice='req'>
<arg choice='plain'><option>--profile-name</option></arg>
<arg choice='plain'><option>-p</option></arg>
</group>
<replaceable>name</replaceable>
</arg>
<sbr />
<arg><option>--show-trace</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command updates the system so that it corresponds to the
configuration specified in
<filename>/etc/nixos/configuration.nix</filename>. Thus, every time
you modify <filename>/etc/nixos/configuration.nix</filename> or any
NixOS module, you must run <command>nixos-rebuild</command> to make
the changes take effect. It builds the new system in
<filename>/nix/store</filename>, runs its activation script, and stop
and (re)starts any system services if needed.</para>
<para>This command has one required argument, which specifies the
desired operation. It must be one of the following:
<variablelist>
<varlistentry>
<term><option>switch</option></term>
<listitem>
<para>Build and activate the new configuration, and make it the
boot default. That is, the configuration is added to the GRUB
boot menu as the default meny entry, so that subsequent reboots
will boot the system into the new configuration. Previous
configurations activated with <command>nixos-rebuild
switch</command> or <command>nixos-rebuild boot</command> remain
available in the GRUB menu.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>boot</option></term>
<listitem>
<para>Build the new configuration and make it the boot default
(as with <command>nixos-rebuild switch</command>), but do not
activate it. That is, the system continues to run the previous
configuration until the next reboot.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>test</option></term>
<listitem>
<para>Build and activate the new configuration, but do not add
it to the GRUB boot menu. Thus, if you reboot the system (or if
it crashes), you will automatically revert to the default
configuration (i.e. the configuration resulting from the last
call to <command>nixos-rebuild switch</command> or
<command>nixos-rebuild boot</command>).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>build</option></term>
<listitem>
<para>Build the new configuration, but neither activate it nor
add it to the GRUB boot menu. It leaves a symlink named
<filename>result</filename> in the current directory, which
points to the output of the top-level “system” derivation. This
is essentially the same as doing
<screen>
$ nix-build /path/to/nixpkgs/nixos -A system
</screen>
Note that you do not need to be <literal>root</literal> to run
<command>nixos-rebuild build</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>dry-run</option></term>
<listitem>
<para>Simply show what store paths would be built or downloaded
by any of the operations above.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>build-vm</option></term>
<listitem>
<para>Build a script that starts a NixOS virtual machine with
the desired configuration. It leaves a symlink
<filename>result</filename> in the current directory that points
(under
<filename>result/bin/run-<replaceable>hostname</replaceable>-vm</filename>)
at the script that starts the VM. Thus, to test a NixOS
configuration in a virtual machine, you should do the following:
<screen>
$ nixos-rebuild build-vm
$ ./result/bin/run-*-vm
</screen></para>
<para>The VM is implemented using the <literal>qemu</literal>
package. For best performance, you should load the
<literal>kvm-intel</literal> or <literal>kvm-amd</literal>
kernel modules to get hardware virtualisation.</para>
<para>The VM mounts the Nix store of the host through the 9P
file system. The host Nix store is read-only, so Nix commands
that modify the Nix store will not work in the VM. This
includes commands such as <command>nixos-rebuild</command>; to
change the VMs configuration, you must halt the VM and re-run
the commands above.
</para>
<para>The VM has its own <literal>ext3</literal> root file
system, which is automatically created when the VM is first
started, and is persistent across reboots of the VM. It is
stored in
<literal>./<replaceable>hostname</replaceable>.qcow2</literal>.
<!-- The entire file system hierarchy of the host is available in
the VM under <filename>/hostfs</filename>.--></para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>build-vm-with-bootloader</option></term>
<listitem>
<para>Like <option>build-vm</option>, but boots using the
regular boot loader of your configuration (e.g., GRUB 1 or 2),
rather than booting directly into the kernel and initial ramdisk
of the system. This allows you to test whether the boot loader
works correctly. However, it does not guarantee that your NixOS
configuration will boot successfully on the host hardware (i.e.,
after running <command>nixos-rebuild switch</command>), because
the hardware and boot loader configuration in the VM are
different. The boot loader is installed on an automatically
generated virtual disk containing a <filename>/boot</filename>
partition, which is mounted read-only in the VM.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--upgrade</option></term>
<listitem>
<para>Fetch the latest version of NixOS from the NixOS
channel.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--install-grub</option></term>
<listitem>
<para>Causes the GRUB boot loader to be (re)installed on the
device specified by the
<varname>boot.loader.grub.device</varname> configuration
option.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--no-build-nix</option></term>
<listitem>
<para>Normally, <command>nixos-rebuild</command> first builds
the <varname>nixUnstable</varname> attribute in Nixpkgs, and
uses the resulting instance of the Nix package manager to build
the new system configuration. This is necessary if the NixOS
modules use features not provided by the currently installed
version of Nix. This option disables building a new Nix.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--fast</option></term>
<listitem>
<para>Equivalent to <option>--no-build-nix</option>
<option>--show-trace</option>. This option is useful if you
call <command>nixos-rebuild</command> frequently (e.g. if youre
hacking on a NixOS module).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--rollback</option></term>
<listitem>
<para>Instead of building a new configuration as specified by
<filename>/etc/nixos/configuration.nix</filename>, roll back to
the previous configuration. (The previous configuration is
defined as the one before the “current” generation of the
Nix profile <filename>/nix/var/nix/profiles/system</filename>.)</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--profile-name</option></term>
<term><option>-p</option></term>
<listitem>
<para>Instead of using the Nix profile
<filename>/nix/var/nix/profiles/system</filename> to keep track
of the current and previous system configurations, use
<filename>/nix/var/nix/profiles/system-profiles/<replaceable>name</replaceable></filename>.
When you use GRUB 2, for every system profile created with this
flag, NixOS will create a submenu named “NixOS - Profile
'<replaceable>name</replaceable>'” in GRUBs boot menu,
containing the current and previous configurations of this
profile.</para>
<para>For instance, if you want to test a configuration file
named <filename>test.nix</filename> without affecting the
default system profile, you would do:
<screen>
$ nixos-rebuild switch -p test -I nixos-config=./test.nix
</screen>
The new configuration will appear in the GRUB 2 submenu “NixOS - Profile
'test'”.</para>
</listitem>
</varlistentry>
</variablelist>
<para>In addition, <command>nixos-rebuild</command> accepts various
Nix-related flags, including <option>--max-jobs</option> /
<option>-j</option>, <option>--show-trace</option>,
<option>--keep-failed</option>, <option>--keep-going</option> and
<option>--verbose</option> / <option>-v</option>. See
the Nix manual for details.</para>
</refsection>
<refsection><title>Environment</title>
<variablelist>
<varlistentry>
<term><envar>NIXOS_CONFIG</envar></term>
<listitem>
<para>Path to the main NixOS configuration module. Defaults to
<filename>/etc/nixos/configuration.nix</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Files</title>
<variablelist>
<varlistentry>
<term><filename>/run/current-system</filename></term>
<listitem>
<para>A symlink to the currently active system configuration in
the Nix store.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>/nix/var/nix/profiles/system</filename></term>
<listitem>
<para>The Nix profile that contains the current and previous
system configurations. Used to generate the GRUB boot
menu.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Bugs</title>
<para>This command should be renamed to something more
descriptive.</para>
</refsection>
</refentry>

View File

@@ -1,31 +0,0 @@
<reference xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>NixOS Reference Pages</title>
<info>
<author>
<personname>
<firstname>Eelco</firstname>
<surname>Dolstra</surname>
</personname>
<contrib>Author</contrib>
</author>
<copyright>
<year>2007-2013</year>
<holder>Eelco Dolstra</holder>
</copyright>
</info>
<xi:include href="man-configuration.xml" />
<xi:include href="man-nixos-build-vms.xml" />
<xi:include href="man-nixos-generate-config.xml" />
<xi:include href="man-nixos-install.xml" />
<xi:include href="man-nixos-option.xml" />
<xi:include href="man-nixos-rebuild.xml" />
</reference>

View File

@@ -1,63 +0,0 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<info>
<title>NixOS Manual</title>
<subtitle>Version <xi:include href="version" parse="text" /></subtitle>
<author>
<personname>
<firstname>Eelco</firstname>
<surname>Dolstra</surname>
</personname>
</author>
<author>
<personname>
<firstname>Nicolas</firstname>
<surname>Pierron</surname>
</personname>
</author>
<copyright>
<year>2007-2013</year>
<holder>Eelco Dolstra</holder>
</copyright>
</info>
<preface>
<title>Preface</title>
<para>This manual describes how to install, use and extend NixOS,
a Linux distribution based on the purely functional package
management system Nix.</para>
<para>If you encounter problems, please report them on the
<literal
xlink:href="http://lists.science.uu.nl/mailman/listinfo/nix-dev">nix-dev@lists.science.uu.nl</literal>
mailing list or on the <link
xlink:href="irc://irc.freenode.net/#nixos">
<literal>#nixos</literal> channel on Freenode</link>. Bugs should
be reported in <link
xlink:href="https://github.com/NixOS/nixpkgs/issues">NixOS GitHub
issue tracker</link>.</para>
</preface>
<xi:include href="installation.xml" />
<xi:include href="configuration.xml" />
<xi:include href="running.xml" />
<!-- <xi:include href="userconfiguration.xml" /> -->
<xi:include href="troubleshooting.xml" />
<xi:include href="development.xml" />
<chapter xml:id="ch-options">
<title>List of options</title>
<xi:include href="options-db.xml" />
</chapter>
</book>

View File

@@ -1,207 +0,0 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://docbook.org/ns/docbook"
extension-element-prefixes="str"
>
<xsl:output method='xml' encoding="UTF-8" />
<xsl:param name="revision" />
<xsl:template match="/expr/list">
<variablelist>
<xsl:for-each select="attrs">
<varlistentry>
<term>
<option>
<xsl:for-each select="attr[@name = 'name']/string">
<xsl:value-of select="@value" />
<xsl:if test="position() != last()">.</xsl:if>
</xsl:for-each>
</option>
</term>
<listitem>
<para>
<xsl:value-of disable-output-escaping="yes"
select="attr[@name = 'description']/string/@value" />
</para>
<xsl:if test="attr[@name = 'default']">
<para>
<emphasis>Default:</emphasis>
<xsl:text> </xsl:text>
<xsl:apply-templates select="attr[@name = 'default']" mode="top" />
</para>
</xsl:if>
<xsl:if test="attr[@name = 'example']">
<para>
<emphasis>Example:</emphasis>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="attr[@name = 'example']/attrs[attr[@name = '_type' and string[@value = 'literalExample']]]">
<programlisting><xsl:value-of select="attr[@name = 'example']/attrs/attr[@name = 'text']/string/@value" /></programlisting>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="attr[@name = 'example']" mode="top" />
</xsl:otherwise>
</xsl:choose>
</para>
</xsl:if>
<xsl:if test="count(attr[@name = 'declarations']/list/*) != 0">
<para>
<emphasis>Declared by:</emphasis>
</para>
<xsl:apply-templates select="attr[@name = 'declarations']" />
</xsl:if>
<xsl:if test="count(attr[@name = 'definitions']/list/*) != 0">
<para>
<emphasis>Defined by:</emphasis>
</para>
<xsl:apply-templates select="attr[@name = 'definitions']" />
</xsl:if>
</listitem>
</varlistentry>
</xsl:for-each>
</variablelist>
</xsl:template>
<xsl:template match="*" mode="top">
<xsl:choose>
<xsl:when test="string[contains(@value, '&#010;')]">
<programlisting>
<xsl:text>''
</xsl:text><xsl:value-of select='str:replace(string/@value, "${", "&apos;&apos;${")' /><xsl:text>''</xsl:text></programlisting>
</xsl:when>
<xsl:otherwise>
<literal><xsl:apply-templates /></literal>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="null">
<xsl:text>null</xsl:text>
</xsl:template>
<xsl:template match="string">
<xsl:choose>
<xsl:when test="(contains(@value, '&quot;') or contains(@value, '\')) and not(contains(@value, '&#010;'))">
<xsl:text>''</xsl:text><xsl:value-of select='str:replace(@value, "${", "&apos;&apos;${")' /><xsl:text>''</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>"</xsl:text><xsl:value-of select="str:replace(str:replace(str:replace(str:replace(@value, '\', '\\'), '&quot;', '\&quot;'), '&#010;', '\n'), '$', '\$')" /><xsl:text>"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="int">
<xsl:value-of select="@value" />
</xsl:template>
<xsl:template match="bool[@value = 'true']">
<xsl:text>true</xsl:text>
</xsl:template>
<xsl:template match="bool[@value = 'false']">
<xsl:text>false</xsl:text>
</xsl:template>
<xsl:template match="list">
[
<xsl:for-each select="*">
<xsl:apply-templates select="." />
<xsl:text> </xsl:text>
</xsl:for-each>
]
</xsl:template>
<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'literalExample']]]">
<xsl:value-of select="attr[@name = 'text']/string/@value" />
</xsl:template>
<xsl:template match="attrs">
{
<xsl:for-each select="attr">
<xsl:value-of select="@name" />
<xsl:text> = </xsl:text>
<xsl:apply-templates select="*" /><xsl:text>; </xsl:text>
</xsl:for-each>
}
</xsl:template>
<xsl:template match="derivation">
<replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
</xsl:template>
<xsl:template match="attr[@name = 'declarations' or @name = 'definitions']">
<simplelist>
<xsl:for-each select="list/string">
<member><filename>
<!-- Hyperlink the filename either to the NixOS Subversion
repository (if its a module and we have a revision number),
or to the local filesystem. -->
<xsl:choose>
<xsl:when test="not(starts-with(@value, '/'))">
<xsl:choose>
<xsl:when test="$revision = 'local'">
<xsl:attribute name="xlink:href">https://github.com/NixOS/nixpkgs/blob/master/<xsl:value-of select="@value"/></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="xlink:href">https://github.com/NixOS/nixpkgs/blob/<xsl:value-of select="$revision"/>/<xsl:value-of select="@value"/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$revision != 'local' and contains(@value, 'nixops') and contains(@value, '/nix/')">
<xsl:attribute name="xlink:href">https://github.com/NixOS/nixops/blob/<xsl:value-of select="$revision"/>/nix/<xsl:value-of select="substring-after(@value, '/nix/')"/></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="xlink:href">file://<xsl:value-of select="@value"/></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<!-- Print the filename and make it user-friendly by replacing the
/nix/store/<hash> prefix by the default location of nixos
sources. -->
<xsl:choose>
<xsl:when test="not(starts-with(@value, '/'))">
&lt;nixpkgs/<xsl:value-of select="@value"/>&gt;
</xsl:when>
<xsl:when test="contains(@value, 'nixops') and contains(@value, '/nix/')">
&lt;nixops/<xsl:value-of select="substring-after(@value, '/nix/')"/>&gt;
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@value" />
</xsl:otherwise>
</xsl:choose>
</filename></member>
</xsl:for-each>
</simplelist>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,369 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="ch-running">
<title>Running NixOS</title>
<para>This chapter describes various aspects of managing a running
NixOS system, such as how to use the <command>systemd</command>
service manager.</para>
<!--===============================================================-->
<section><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 -->
</section>
<!--===============================================================-->
<section><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>
</section>
<!--===============================================================-->
<section><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 sessions processes are gone:
<screen>
$ loginctl terminate-session c3
</screen>
</para>
</section>
<!--===============================================================-->
<section><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 cgroups CPU time.) You can limit a services
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>
</section>
<!--===============================================================-->
<section><title>Logging</title>
<para>System-wide logging is provided by systemds
<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>
</section>
<!--===============================================================-->
<section><title>Cleaning up 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 Nixs <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 Nixs 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>
</section>
</chapter>

View File

@@ -1,268 +0,0 @@
/* Copied from http://bakefile.sourceforge.net/, which appears
licensed under the GNU GPL. */
/***************************************************************************
Basic headers and text:
***************************************************************************/
body
{
font-family: "Nimbus Sans L", sans-serif;
background: white;
margin: 2em 1em 2em 1em;
}
h1, h2, h3, h4
{
color: #005aa0;
}
h1 /* title */
{
font-size: 200%;
}
h2 /* chapters, appendices, subtitle */
{
font-size: 180%;
}
/* Extra space between chapters, appendices. */
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
{
margin-top: 1.5em;
}
div.section > div.titlepage 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%;
}
div.refsection h3
{
font-size: 110%;
}
/***************************************************************************
Examples:
***************************************************************************/
div.example
{
border: 1px solid #b0b0b0;
padding: 6px 6px;
margin-left: 1.5em;
margin-right: 1.5em;
background: #f4f4f8;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example p.title
{
margin-top: 0em;
}
div.example pre
{
box-shadow: none;
}
/***************************************************************************
Screen dumps:
***************************************************************************/
pre.screen, pre.programlisting
{
border: 1px solid #b0b0b0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
color: #600000;
background: #f4f4f8;
font-family: monospace;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.example pre.programlisting
{
border: 0px;
padding: 0 0;
margin: 0 0 0 0;
}
/***************************************************************************
Notes, warnings etc:
***************************************************************************/
.note, .warning
{
border: 1px solid #b0b0b0;
padding: 3px 3px;
margin-left: 1.5em;
margin-right: 1.5em;
margin-bottom: 1em;
padding: 0.3em 0.3em 0.3em 0.3em;
background: #fffff5;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
div.note, div.warning
{
font-style: italic;
}
div.note 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
{
color: blue;
font-size: 100%;
}
div.navfooter *
{
font-size: 90%;
}
/***************************************************************************
Links colors and highlighting:
***************************************************************************/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
a:link { color: #0048b3; }
a:visited { color: #002a6a; }
/***************************************************************************
Table of contents:
***************************************************************************/
div.toc
{
font-size: 90%;
}
div.toc dl
{
margin-top: 0em;
margin-bottom: 0em;
}
/***************************************************************************
Special elements:
***************************************************************************/
tt, code
{
color: #400000;
}
.term
{
font-weight: bold;
}
div.variablelist dd p, div.glosslist dd p
{
margin-top: 0em;
}
div.variablelist dd, div.glosslist dd
{
margin-left: 1.5em;
}
div.glosslist dt
{
font-style: italic;
}
.varname
{
color: #400000;
}
span.command strong
{
font-weight: normal;
color: #400000;
}
div.calloutlist table
{
box-shadow: none;
}
table
{
border-collapse: collapse;
box-shadow: 0.4em 0.4em 0.5em #e0e0e0;
}
table.simplelist
{
text-align: left;
color: #005aa0;
border: 0;
padding: 5px;
background: #fffff5;
font-weight: normal;
font-style: italic;
box-shadow: none;
margin-bottom: 1em;
}
div.affiliation
{
font-style: italic;
}

View File

@@ -1,198 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Troubleshooting</title>
<!--===============================================================-->
<section><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 youre 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>
<!--===============================================================-->
<section><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>
<!--===============================================================-->
<section><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 doesnt
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 hasnt 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>
<!--===============================================================-->
<section><title>Nix store corruption</title>
<para>After a system crash, its 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
Nixs 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 Nixs 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 theyre available in a
binary cache; otherwise, they cannot be repaired.</para>
</section>
<!--===============================================================-->
<section><title>Nix network issues</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>http://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>
</chapter>

View File

@@ -1,16 +0,0 @@
This file should become a nix expression. (see modules/installer/tools/tools.nix)
you need to:
- download the latest jQuery from and copy it to chrome/content:
http://code.jquery.com/jquery-1.5.2.js
- install 'xulrunner' with nix:
nix-env -Ai nixpkgs_sys.firefox40Pkgs.xulrunner
- make sure nixos-option in your path
- have /etc/nixos/nixpkgs
- have /etc/nixos/nixos
run it:
- xulrunner /etc/nixos/nixos/gui/application.ini -jsconsole

View File

@@ -1,36 +0,0 @@
[App]
;
; This field specifies your organization's name. This field is recommended,
; but optional.
Vendor=NixOS
;
; This field specifies your application's name. This field is required.
Name=NixOS-gui
;
; This field specifies your application's version. This field is optional.
Version=0.1
;
; This field specifies your application's build ID (timestamp). This field is
; required.
BuildID=20110424
;
; This field specifies a compact copyright notice for your application. This
; field is optional.
;Copyright=
;
; This ID is just an example. Every XUL app ought to have it's own unique ID.
; You can use the microsoft "guidgen" or "uuidgen" tools, or go on
; irc.mozilla.org and /msg botbot uuid. This field is optional.
;ID=
[Gecko]
;
; This field is required. It specifies the minimum Gecko version that this
; application requires.
MinVersion=1.9a5
;
; This field is optional. It specifies the maximum Gecko version that this
; application requires. It should be specified if your application uses
; unfrozen interfaces.
MaxVersion=2.*

View File

@@ -1 +0,0 @@
manifest chrome/chrome.manifest

View File

@@ -1 +0,0 @@
content nixos-gui content/

View File

@@ -1,137 +0,0 @@
function inspect(obj, maxLevels, level)
{
var str = '', type, msg;
// Start Input Validations
// Don't touch, we start iterating at level zero
if(level == null) level = 0;
// At least you want to show the first level
if(maxLevels == null) maxLevels = 1;
if(maxLevels < 1)
return '<font color="red">Error: Levels number must be > 0</font>';
// We start with a non null object
if(obj == null)
return '<font color="red">Error: Object <b>NULL</b></font>';
// End Input Validations
// Each Iteration must be indented
str += '<ul>';
// Start iterations for all objects in obj
for(property in obj)
{
try
{
// Show "property" and "type property"
type = typeof(obj[property]);
str += '<li>(' + type + ') ' + property +
( (obj[property]==null)?(': <b>null</b>'):('')) + '</li>';
// We keep iterating if this property is an Object, non null
// and we are inside the required number of levels
if((type == 'object') && (obj[property] != null) && (level+1 < maxLevels))
str += inspect(obj[property], maxLevels, level+1);
}
catch(err)
{
// Is there some properties in obj we can't access? Print it red.
if(typeof(err) == 'string') msg = err;
else if(err.message) msg = err.message;
else if(err.description) msg = err.description;
else msg = 'Unknown';
str += '<li><font color="red">(Error) ' + property + ': ' + msg +'</font></li>';
}
}
// Close indent
str += '</ul>';
return str;
}
// Run xulrunner application.ini -jsconsole -console, to see messages.
function log(str)
{
Components.classes['@mozilla.org/consoleservice;1']
.getService(Components.interfaces.nsIConsoleService)
.logStringMessage(str);
}
function makeTempFile(prefix)
{
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsIFile);
file.append(prefix || "xulrunner");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664);
return file;
}
function writeToFile(file, data)
{
// file is nsIFile, data is a string
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
// use 0x02 | 0x10 to open file for appending.
foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
foStream.write(data, data.length);
foStream.close();
}
function readFromFile(file)
{
// |file| is nsIFile
var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(file, -1, 0, 0);
sstream.init(fstream);
var str = sstream.read(4096);
while (str.length > 0) {
data += str;
str = sstream.read(4096);
}
sstream.close();
fstream.close();
return data;
}
function runProgram(commandLine)
{
// create an nsILocalFile for the executable
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath("/bin/sh");
// create an nsIProcess
var process = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
process.init(file);
// Run the process.
// If first param is true, calling thread will be blocked until
// called process terminates.
// Second and third params are used to pass command-line arguments
// to the process.
var args = ["-c", commandLine];
process.run(true, args, args.length);
}
// only for testing...
function testIO()
{
var f = makeTempFile();
writeToFile(f, "essai\ntest");
alert(readFromFile(f));
runProgram("zenity --info");
}

View File

@@ -1,70 +0,0 @@
// global variables.
var gNixOS;
var gOptionView;
/*
var gProgressBar;
function setProgress(current, max)
{
if (gProgressBar) {
gProgressBar.value = 100 * current / max;
log("progress: " + gProgressBar.value + "%");
}
else
log("unknow progress bar");
}
*/
function updateTextbox(id, value)
{
// setting the height cause an overflow which resize the textbox to its
// content due to its onoverflow attribute.
$(id).attr("value", value).attr("height", 1);
};
function updatePanel(options)
{
log("updatePanel: " + options.length);
if (options.length == 0)
return;
// FIXME: ignore the rest of the selection for now.
var o = options[0];
$("#name").attr("label", o.path);
if (o.typename != null)
$("#typename").attr("label", o.typename);
else
$("#typename").attr("label", "");
$("#desc").text(o.description);
if (o.value != null)
updateTextbox("#val", o.value);
else
updateTextbox("#val", "");
if (o.defaultValue != null)
updateTextbox("#def", o.defaultValue);
else
updateTextbox("#def", "");
if (o.example != null)
updateTextbox("#exp", o.example);
else
updateTextbox("#exp", "");
updateTextbox("#decls", o.declarations.join("\n"));
updateTextbox("#defs", o.definitions.join("\n"));
}
function onload()
{
var optionTree = document.getElementById("option-tree");
// gProgressBar = document.getElementById("progress-bar");
// setProgress(0, 1);
gNixOS = new NixOS();
gOptionView = new OptionView(gNixOS.option, updatePanel);
optionTree.view = gOptionView;
}

View File

@@ -1,63 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window>
<!-- To edit this file I recommend you to use:
http://xulfr.org/outils/xulediteur.xul
-->
<window
id = "nixos-gui"
title = "NixOS gui"
width = "800"
height = "600"
xmlns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="jquery-1.5.2.js"/>
<script src="io.js"/>
<script src="nixos.js"/>
<script src="optionView.js"/>
<script src="main.js"/>
<hbox flex="1">
<vbox width="250">
<tree flex="1" id="option-tree" persist="height" onselect="gOptionView.selectionChanged()">
<treecols>
<treecol persist="hidden width" flex="9" id="opt-name"
label="Option" primary="true"/>
<!-- Uncomment the following column to see the number of option
printed below each options. -->
<!--
<treecol persist="hidden width" flex="1" id="dbg-size"
label="sz"/>
-->
</treecols>
<treechildren id="first-child" flex="1"/>
</tree>
</vbox>
<vbox flex="3" style="overflow: auto">
<caption id="name" label=""/>
<caption id="typename" label=""/>
<separator/>
<description id="desc" hidden="false"></description>
<separator/>
<caption label="Value:"/>
<textbox id="val" readonly="true" multiline="true" value=""
class="plain" hidden="false" onoverflow="this.height =
this.inputField.scrollHeight;" />
<separator/>
<caption label="Default:"/>
<textbox id="def" readonly="true" multiline="true" value="" class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
<separator/>
<caption label="Example:"/>
<textbox id="exp" readonly="true" multiline="true" value="" class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
<separator/>
<caption label="Declarations:"/>
<textbox id="decls" readonly="true" multiline="true" value="" class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
<separator/>
<caption label="Definitions:"/>
<textbox id="defs" readonly="true" multiline="true" value=""
class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
</vbox>
</hbox>
<!-- <progressmeter id="progress-bar" value="0%"/> -->
</window>

View File

@@ -1,255 +0,0 @@
function NixOS () {
var env = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
if (env.exists("NIXOS"))
this.nixos = env.get("NIXOS");
if (env.exists("NIXOS_CONFIG"))
this.config = env.get("NIXOS_CONFIG");
if (env.exists("NIXPKGS"))
this.nixpkgs = env.get("NIXPKGS");
if (env.exists("mountPoint"))
this.root = env.get("mountPoint");
if (env.exists("NIXOS_OPTION"))
this.optionBin = env.get("NIXOS_OPTION");
this.option = new Option("options", this, null);
};
NixOS.prototype = {
root: "",
nixos: "/etc/nixos/nixos",
nixpkgs: "/etc/nixos/nixpkgs",
config: "/etc/nixos/configuration.nix",
instantiateBin: "/run/current-system/sw/bin/nix-instantiate",
optionBin: "/run/current-system/sw/bin/nixos-option",
tmpFile: "nixos-gui",
option: null
};
function Option (name, context, parent) {
this.name = name;
this.context_ = context;
if (parent == null)
this.path = "";
else if (parent.path == "")
this.path = name;
else
this.path = parent.path + "." + name;
};
Option.prototype = {
load: function () {
var env = "";
env += "'NIXOS=" + this.context_.root + this.context_.nixos + "' ";
env += "'NIXOS_PKGS=" + this.context_.root + this.context_.nixpkgs + "' ";
env += "'NIXOS_CONFIG=" + this.context_.config + "' ";
var out = makeTempFile(this.context_.tmpFile);
var prog = this.context_.optionBin + " 2>&1 >" + out.path + " ";
var args = " --xml " + this.path;
runProgram(/*env + */ prog + args);
var xml = readFromFile(out);
out.remove(false);
// jQuery does a stack overflow when converting a huge XML to a DOM.
var dom = DOMParser().parseFromString(xml, "text/xml");
var xmlAttrs = $("expr > attrs > attr", dom);
this.isOption = xmlAttrs.first().attr("name") == "_isOption";
if (!this.isOption)
this.loadSubOptions(xmlAttrs);
else
this.loadOption(xmlAttrs);
this.isLoaded = true;
},
loadSubOptions: function (xmlAttrs) {
var cur = this;
var attrs = new Array();
xmlAttrs.each(
function (index) {
var name = $(this).attr("name");
var attr = new Option(name, cur.context_, cur);
attrs.push(attr);
}
);
this.subOptions = attrs;
},
optionAttributeMap: {
_isOption: function (cur, v) { },
value: function (cur, v) { cur.value = xml2nix($(v).children().first()); },
default: function (cur, v) { cur.defaultValue = xml2nix($(v).children().first()); },
example: function (cur, v) { cur.example = xml2nix($(v).children().first()); },
description: function (cur, v) { cur.description = this.string(v); },
typename: function (cur, v) { cur.typename = this.string(v); },
options: function (cur, v) { cur.loadSubOptions($("attrs", v).children()); },
declarations: function (cur, v) { cur.declarations = this.pathList(v); },
definitions: function (cur, v) { cur.definitions = this.pathList(v); },
string: function (v) {
return $(v).children("string").first().attr("value");
},
pathList: function (v) {
var list = [];
$(v).children("list").first().children().each(
function (idx) {
list.push($(this).attr("value"));
}
);
return list;
}
},
loadOption: function (attrs) {
var cur = this;
attrs.each(
function (index) {
var name = $(this).attr("name");
log("loadOption: " + name);
cur.optionAttributeMap[name](cur, this);
}
);
},
// keep the context under which this option has been used.
context_: null,
// name of the option.
name: "",
// result of nixos-option.
value: null,
typename: null,
defaultValue: null,
example: null,
description: "",
declarations: [],
definitions: [],
// path to reach this option
path: "",
// list of options accessible from here.
isLoaded: false,
isOption: false,
subOptions: []
};
var xml2nix_pptable = {
attrs: function (node, depth, pp) {
var children = node.children().not(
function () {
var name = $(this).attr("name");
return name.charAt(0) == "_";
}
);
var c = 0;
var out = "";
out += "{";
depth += 1;
children.each(
function (idx) {
c += 1;
out += pp.indent(depth);
out += pp.dispatch($(this), depth, pp);
}
);
depth -= 1;
if (c > 0)
out += this.indent(depth);
else
out += " ";
out += "}";
return out;
},
list: function (node, depth, pp) {
var children = node.children();
var c = 0;
var out = "";
out += "[";
depth += 1;
children.each(
function (idx) {
c += 1;
out += pp.indent(depth);
out += pp.dispatch($(this), depth, pp);
}
);
depth -= 1;
if (c > 0)
out += this.indent(depth);
else
out += " ";
out += "]";
return out;
},
attr: function (node, depth, pp) {
var name = node.attr("name");
var out = "";
var val = "";
out += name + " = ";
depth += 1;
val = pp.dispatch(node.children().first(), depth, pp);
out += val;
depth -= 1;
out += ";";
return out;
},
string: function (node, depth, pp) {
return "\"" + node.attr("value") + "\"";
},
path: function (node, depth, pp) {
return node.attr("value");
},
bool: function (node, depth, pp) {
return node.attr("value");
},
"int": function (node, depth, pp) {
return node.attr("value");
},
null: function (node, depth, pp) {
return "null";
},
derivation: function (node, depth, pp) {
return "<derivation>";
},
function: function (node, depth, pp) {
return "<function>";
},
unevaluated: function (node, depth, pp) {
return "<unevaluated>";
},
dispatch: function (node, depth, pp) {
for (var key in pp)
{
if(node.is(key))
{
// log(this.indent(depth) + "dispatch: " + key);
var out = pp[key](node, depth, pp);
// log(this.indent(depth) + "dispatch: => " + out);
return out;
}
}
return "<dispatch-error>";
},
indent: function (depth) {
var ret = "\n";
while (depth--)
ret += " ";
return ret;
}
};
function xml2nix(node) {
var depth = 0;
var pp = xml2nix_pptable;
var out = pp.dispatch(node, depth, pp);
// log("pretty:\n" + out);
return out;
}

View File

@@ -1,242 +0,0 @@
// extend NixOS options to handle the Tree View. Should be better to keep a
// separation of concern here.
Option.prototype.tv_opened = false;
Option.prototype.tv_size = 1;
Option.prototype.tv_open = function () {
this.tv_opened = true;
this.tv_size = 1;
// load an option if it is not loaded yet, and initialize them to be
// read by the Option view.
if (!this.isLoaded)
this.load();
// If this is not an option, then add it's lits of sub-options size.
if (!this.isOption)
{
for (var i = 0; i < this.subOptions.length; i++)
this.tv_size += this.subOptions[i].tv_size;
}
};
Option.prototype.tv_close = function () {
this.tv_opened = false;
this.tv_size = 1;
};
function OptionView (root, selCallback) {
root.tv_open();
this.rootOption = root;
this.selCallback = selCallback;
}
OptionView.prototype = {
rootOption: null,
selCallback: null,
// This function returns the path to option which is at the specified row.
reach_cache: null,
reachRow: function (row) {
var o = this.rootOption; // Current option.
var r = 0; // Number of rows traversed.
var c = 0; // Child index.
var path = [{ row: r, opt: o }]; // new Array();
// hypothesis: this.rootOption.tv_size is always open and bigger than
// Use the previous returned value to avoid making to many checks and to
// optimize for frequent access of near rows.
if (this.reach_cache != null)
{
for (var i = this.reach_cache.length - 2; i >= 0; i--) {
var p = this.reach_cache[i];
// If we will have to go the same path.
if (row >= p.row && row < p.row + p.opt.tv_size)
{
path.unshift(p);
r = path[0].row;
o = path[0].opt;
}
else
break;
};
}
while (r != row)
{
// Go deeper in the child which contains the requested row. The
// tv_size contains the size of the tree starting from each option.
c = 0;
while (c < o.subOptions.length && r + o.subOptions[c].tv_size < row)
{
r += o.subOptions[c].tv_size;
c += 1;
}
if (c < o.subOptions.length && r + o.subOptions[c].tv_size >= row)
{
// Count the current option as a row.
o = o.subOptions[c];
r += 1;
}
else
alert("WTF: " + o.name + " ask: " + row + " children: " + o.subOptions + " c: " + c);
path.unshift({ row: r, opt: o });
}
this.reach_cache = path;
return path;
},
// needs to return true if there is a /row/ at the same level /after/ a
// given row.
hasNextSibling: function(row, after) {
log("sibling " + row + " after " + after);
var path = reachRow(row);
if (path.length > 1)
{
var last = path[1].row + path[1].opt.tv_size;
// Has a next sibling if the row is not over the size of the
// parent and if the current one is not the last child.
return after + 1 < last && path[0].row + path[0].opt.tv_size < last;
}
else
// The top-level option has no sibling.
return false;
},
// Does the current row contain any sub-options?
isContainer: function(row) {
return !this.reachRow(row)[0].opt.isOption;
},
isContainerEmpty: function(row) {
return this.reachRow(row)[0].opt.subOptions.length == 0;
},
isContainerOpen: function(row) {
return this.reachRow(row)[0].opt.tv_opened;
},
// Open or close an option.
toggleOpenState: function (row) {
var path = this.reachRow(row);
var delta = -path[0].opt.tv_size;
if (path[0].opt.tv_opened)
path[0].opt.tv_close();
else
path[0].opt.tv_open();
delta += path[0].opt.tv_size;
// Parents are alreay opened, but we need to update the tv_size
// counters. Thus we have to invalidate the reach cache.
this.reach_cache = null;
for (var i = 1; i < path.length; i++)
path[i].opt.tv_open();
this.tree.rowCountChanged(row + 1, delta);
},
// Return the identation level of the option at the line /row/. The
// top-level level is 0.
getLevel: function(row) {
return this.reachRow(row).length - 1;
},
// Obtain the index of a parent row. If there is no parent row,
// returns -1.
getParentIndex: function(row) {
var path = this.reachRow(row);
if (path.length > 1)
return path[1].row;
else
return -1;
},
// Return the content of each row base on the column name.
getCellText: function(row, column) {
if (column.id == "opt-name")
return this.reachRow(row)[0].opt.name;
if (column.id == "dbg-size")
return this.reachRow(row)[0].opt.tv_size;
return "";
},
// We have no column with images.
getCellValue: function(row, column) { },
isSelectable: function(row, column) { return true; },
// Get the selection out of the tree and give options to the call back
// function.
selectionChanged: function() {
if (this.selCallback == null)
return;
var opts = [];
var start = new Object();
var end = new Object();
var numRanges = this.tree.view.selection.getRangeCount();
for (var t = 0; t < numRanges; t++) {
this.tree.view.selection.getRangeAt(t,start,end);
for (var v = start.value; v <= end.value; v++) {
var opt = this.reachRow(v)[0].opt;
if (!opt.isLoaded)
opt.load();
if (opt.isOption)
opts.push(opt);
// FIXME: no need to make things slowing down, because our current
// callback do not handle multiple option display.
if (!opts.empty)
break;
}
// FIXME: no need to make things slowing down, because our current
// callback do not handle multiple option display.
if (!opts.empty)
break;
}
if (!opts.empty)
this.selCallback(opts);
},
set rowCount(c) { throw "rowCount is a readonly property"; },
get rowCount() { return this.rootOption.tv_size; },
// refuse drag-n-drop of options.
canDrop: function (index, orientation, dataTransfer) { return false; },
drop: function (index, orientation, dataTransfer) { },
// ?
getCellProperties: function(row, column, prop) { },
getColumnProperties: function(column, prop) { },
getRowProperties: function(row, prop) { },
getImageSrc: function(row, column) { },
// No progress columns are used.
getProgressMode: function(row, column) { },
// Do not add options yet.
isEditable: function(row, column) { return false; },
setCellValue: function(row, column, value) { },
setCellText: function(row, column, value) { },
// ...
isSeparator: function(index) { return false; },
isSorted: function() { return false; },
performAction: function(action) { },
performActionOnCell: function(action, row, column) { },
performActionOnRow: function(action, row) { }, // ??
// ??
cycleCell: function (row, col) { },
cycleHeader: function(col) { },
selection: null,
tree: null,
setTree: function(tree) { this.tree = tree; }
};

View File

@@ -1,154 +0,0 @@
const nsIAppShellService = Components.interfaces.nsIAppShellService;
const nsISupports = Components.interfaces.nsISupports;
const nsICategoryManager = Components.interfaces.nsICategoryManager;
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
const nsICommandLine = Components.interfaces.nsICommandLine;
const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
const nsIFactory = Components.interfaces.nsIFactory;
const nsIModule = Components.interfaces.nsIModule;
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
// CHANGEME: to the chrome URI of your extension or application
const CHROME_URI = "chrome://nixos-gui/content/myviewer.xul";
// CHANGEME: change the contract id, CID, and category to be unique
// to your application.
const clh_contractID = "@mozilla.org/commandlinehandler/general-startup;1?type=myapp";
// use uuidgen to generate a unique ID
const clh_CID = Components.ID("{2991c315-b871-42cd-b33f-bfee4fcbf682}");
// category names are sorted alphabetically. Typical command-line handlers use a
// category that begins with the letter "m".
const clh_category = "m-myapp";
/**
* Utility functions
*/
/**
* Opens a chrome window.
* @param aChromeURISpec a string specifying the URI of the window to open.
* @param aArgument an argument to pass to the window (may be null)
*/
function openWindow(aChromeURISpec, aArgument)
{
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
getService(Components.interfaces.nsIWindowWatcher);
ww.openWindow(null, aChromeURISpec, "_blank",
"chrome,menubar,toolbar,status,resizable,dialog=no",
aArgument);
}
/**
* The XPCOM component that implements nsICommandLineHandler.
* It also implements nsIFactory to serve as its own singleton factory.
*/
const myAppHandler = {
/* nsISupports */
QueryInterface : function clh_QI(iid)
{
if (iid.equals(nsICommandLineHandler) ||
iid.equals(nsIFactory) ||
iid.equals(nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
/* nsICommandLineHandler */
handle : function clh_handle(cmdLine)
{
openWindow(CHROME_URI, cmdLine);
cmdLine.preventDefault = true;
},
// CHANGEME: change the help info as appropriate, but
// follow the guidelines in nsICommandLineHandler.idl
// specifically, flag descriptions should start at
// character 24, and lines should be wrapped at
// 72 characters with embedded newlines,
// and finally, the string should end with a newline
helpInfo : " <filename> Open the file in the viewer\n",
/* nsIFactory */
createInstance : function clh_CI(outer, iid)
{
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
lockFactory : function clh_lock(lock)
{
/* no-op */
}
};
/**
* The XPCOM glue that implements nsIModule
*/
const myAppHandlerModule = {
/* nsISupports */
QueryInterface : function mod_QI(iid)
{
if (iid.equals(nsIModule) ||
iid.equals(nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
/* nsIModule */
getClassObject : function mod_gch(compMgr, cid, iid)
{
if (cid.equals(clh_CID))
return myAppHandler.QueryInterface(iid);
throw Components.results.NS_ERROR_NOT_REGISTERED;
},
registerSelf : function mod_regself(compMgr, fileSpec, location, type)
{
compMgr.QueryInterface(nsIComponentRegistrar);
compMgr.registerFactoryLocation(clh_CID,
"myAppHandler",
clh_contractID,
fileSpec,
location,
type);
var catMan = Components.classes["@mozilla.org/categorymanager;1"].
getService(nsICategoryManager);
catMan.addCategoryEntry("command-line-handler",
clh_category,
clh_contractID, true, true);
},
unregisterSelf : function mod_unreg(compMgr, location, type)
{
compMgr.QueryInterface(nsIComponentRegistrar);
compMgr.unregisterFactoryLocation(clh_CID, location);
var catMan = Components.classes["@mozilla.org/categorymanager;1"].
getService(nsICategoryManager);
catMan.deleteCategoryEntry("command-line-handler", clh_category);
},
canUnload : function (compMgr)
{
return true;
}
};
/* The NSGetModule function is the magic entry point that XPCOM uses to find what XPCOM objects
* this component provides
*/
function NSGetModule(comMgr, fileSpec)
{
return myAppHandlerModule;
}

View File

@@ -1,11 +0,0 @@
pref("toolkit.defaultChromeURI", "chrome://nixos-gui/content/myviewer.xul");
pref("general.useragent.extra.myviewer", "NixOS gui/0.0");
/* debugging prefs */
pref("browser.dom.window.dump.enabled", true); // enable output to stderr
pref("javascript.options.showInConsole", true); // show javascript errors from chrome: files in the jsconsole
pref("javascript.options.strict", true); // show javascript strict warnings in the jsconsole
/* disable xul cache so that modifications to chrome: files apply without restarting xulrunner */
pref("nglayout.debug.disable_xul_cache", true);
pref("nglayout.debug.disable_xul_fastload", true);

View File

@@ -1,87 +0,0 @@
{ system, minimal ? false }:
let pkgs = import ./nixpkgs.nix { config = {}; inherit system; }; in
with pkgs.lib;
with import ../lib/qemu-flags.nix;
rec {
inherit pkgs;
# Build a virtual network from an attribute set `{ machine1 =
# config1; ... machineN = configN; }', where `machineX' is the
# hostname and `configX' is a NixOS system configuration. Each
# machine is given an arbitrary IP address in the virtual network.
buildVirtualNetwork =
nodes: let nodesOut = mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes); in nodesOut;
buildVM =
nodes: configurations:
import ./eval-config.nix {
inherit system;
modules = configurations ++
[ ../modules/virtualisation/qemu-vm.nix
../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs
{ key = "no-manual"; services.nixosManual.enable = false; }
] ++ optional minimal ../modules/testing/minimal-kernel.nix;
extraArgs = { inherit nodes; };
};
# Given an attribute set { machine1 = config1; ... machineN =
# configN; }, sequentially assign IP addresses in the 192.168.1.0/24
# range to each machine, and set the hostname to the attribute name.
assignIPAddresses = nodes:
let
machines = attrNames nodes;
machinesNumbered = zipTwoLists machines (range 1 254);
nodes_ = flip map machinesNumbered (m: nameValuePair m.first
[ ( { config, pkgs, nodes, ... }:
let
interfacesNumbered = zipTwoLists config.virtualisation.vlans (range 1 255);
interfaces = flip map interfacesNumbered ({ first, second }:
nameValuePair "eth${toString second}"
{ ipAddress = "192.168.${toString first}.${toString m.second}";
subnetMask = "255.255.255.0";
});
in
{ key = "ip-address";
config =
{ networking.hostName = m.first;
networking.interfaces = listToAttrs interfaces;
networking.primaryIPAddress =
optionalString (interfaces != []) (head interfaces).value.ipAddress;
# Put the IP addresses of all VMs in this machine's
# /etc/hosts file. If a machine has multiple
# interfaces, use the IP address corresponding to
# the first interface (i.e. the first network in its
# virtualisation.vlans option).
networking.extraHosts = flip concatMapStrings machines
(m: let config = (getAttr m nodes).config; in
optionalString (config.networking.primaryIPAddress != "")
("${config.networking.primaryIPAddress} " +
"${config.networking.hostName}\n"));
virtualisation.qemu.options =
flip map interfacesNumbered
({ first, second }: qemuNICFlags second first m.second);
};
}
)
(getAttr m.first nodes)
] );
in listToAttrs nodes_;
}

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