295 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
<chapter xmlns="http://docbook.org/ns/docbook"
 | 
						||
	 xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
						||
	 xml:id="chap-functions">
 | 
						||
 | 
						||
<title>Functions reference</title>
 | 
						||
 | 
						||
<para>
 | 
						||
  The nixpkgs repository has several utility functions to manipulate Nix expressions.
 | 
						||
</para>
 | 
						||
 | 
						||
<section xml:id="sec-pkgs-overridePackages">
 | 
						||
  <title>pkgs.overridePackages</title>
 | 
						||
 | 
						||
  <para>
 | 
						||
    This function inside the nixpkgs expression (<varname>pkgs</varname>)
 | 
						||
    can be used to override the set of packages itself.
 | 
						||
  </para>
 | 
						||
  <para>
 | 
						||
    Warning: this function is expensive and must not be used from within
 | 
						||
    the nixpkgs repository.
 | 
						||
  </para>
 | 
						||
  <para>
 | 
						||
    Example usage:
 | 
						||
 | 
						||
    <programlisting>let
 | 
						||
  pkgs = import <nixpkgs> {};
 | 
						||
  newpkgs = pkgs.overridePackages (self: super: {
 | 
						||
    foo = super.foo.override { ... };
 | 
						||
  };
 | 
						||
in ...</programlisting>
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The resulting <varname>newpkgs</varname> will have the new <varname>foo</varname>
 | 
						||
    expression, and all other expressions depending on <varname>foo</varname> will also
 | 
						||
    use the new <varname>foo</varname> expression.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The behavior of this function is similar to <link 
 | 
						||
    linkend="sec-modify-via-packageOverrides">config.packageOverrides</link>.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The <varname>self</varname> parameter refers to the final package set with the
 | 
						||
    applied overrides. Using this parameter may lead to infinite recursion if not
 | 
						||
    used consciously.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The <varname>super</varname> parameter refers to the old package set.
 | 
						||
    It's equivalent to <varname>pkgs</varname> in the above example.
 | 
						||
  </para>
 | 
						||
 | 
						||
</section>
 | 
						||
 | 
						||
<section xml:id="sec-pkg-override">
 | 
						||
  <title><pkg>.override</title>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The function <varname>override</varname> is usually available for all the
 | 
						||
    derivations in the nixpkgs expression (<varname>pkgs</varname>).
 | 
						||
  </para>
 | 
						||
  <para>
 | 
						||
    It is used to override the arguments passed to a function.
 | 
						||
  </para>
 | 
						||
  <para>
 | 
						||
    Example usages:
 | 
						||
 | 
						||
    <programlisting>pkgs.foo.override { arg1 = val1; arg2 = val2; ... }</programlisting>
 | 
						||
    <programlisting>pkgs.overridePackages (self: super: {
 | 
						||
  foo = super.foo.override { barSupport = true ; };
 | 
						||
})</programlisting>
 | 
						||
    <programlisting>mypkg = pkgs.callPackage ./mypkg.nix {
 | 
						||
  mydep = pkgs.mydep.override { ... };
 | 
						||
})</programlisting>
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    In the first example, <varname>pkgs.foo</varname> is the result of a function call
 | 
						||
    with some default arguments, usually a derivation.
 | 
						||
    Using <varname>pkgs.foo.override</varname> will call the same function with
 | 
						||
    the given new arguments.
 | 
						||
  </para>
 | 
						||
 | 
						||
</section>
 | 
						||
 | 
						||
<section xml:id="sec-pkg-overrideDerivation">
 | 
						||
  <title><pkg>.overrideDerivation</title>
 | 
						||
 | 
						||
  <warning>
 | 
						||
    <para>Do not use this function in Nixpkgs. Because it breaks
 | 
						||
    package abstraction and doesn’t provide error checking for
 | 
						||
    function arguments, it is only intended for ad-hoc customisation
 | 
						||
    (such as in <filename>~/.nixpkgs/config.nix</filename>).</para>
 | 
						||
  </warning>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The function <varname>overrideDerivation</varname> is usually available for all the
 | 
						||
    derivations in the nixpkgs expression (<varname>pkgs</varname>).
 | 
						||
  </para> 
 | 
						||
  <para>
 | 
						||
    It is used to create a new derivation by overriding the attributes of
 | 
						||
    the original derivation according to the given function.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    Example usage:
 | 
						||
 | 
						||
    <programlisting>mySed = pkgs.gnused.overrideDerivation (oldAttrs: {
 | 
						||
  name = "sed-4.2.2-pre";
 | 
						||
  src = fetchurl {
 | 
						||
    url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
 | 
						||
    sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
 | 
						||
  };
 | 
						||
  patches = [];
 | 
						||
});</programlisting>
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    In the above example, the name, src and patches of the derivation
 | 
						||
    will be overridden, while all other attributes will be retained from the
 | 
						||
    original derivation.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The argument <varname>oldAttrs</varname> is used to refer to the attribute set of
 | 
						||
    the original derivation.
 | 
						||
  </para>
 | 
						||
 | 
						||
</section>
 | 
						||
 | 
						||
<section xml:id="sec-lib-makeOverridable">
 | 
						||
  <title>lib.makeOverridable</title>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The function <varname>lib.makeOverridable</varname> is used to make the result
 | 
						||
    of a function easily customizable. This utility only makes sense for functions
 | 
						||
    that accept an argument set and return an attribute set.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    Example usage:
 | 
						||
 | 
						||
    <programlisting>f = { a, b }: { result = a+b; }
 | 
						||
c = lib.makeOverridable f { a = 1; b = 2; }</programlisting>
 | 
						||
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The variable <varname>c</varname> is the value of the <varname>f</varname> function
 | 
						||
    applied with some default arguments. Hence the value of <varname>c.result</varname>
 | 
						||
    is <literal>3</literal>, in this example.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    The variable <varname>c</varname> however also has some additional functions, like
 | 
						||
    <link linkend="sec-pkg-override">c.override</link> which can be used to
 | 
						||
    override the default arguments. In this example the value of
 | 
						||
    <varname>(c.override { a = 4; }).result</varname> is 6.
 | 
						||
  </para>
 | 
						||
 | 
						||
</section>
 | 
						||
 | 
						||
 | 
						||
<section xml:id="sec-fhs-environments">
 | 
						||
  <title>buildFHSChrootEnv/buildFHSUserEnv</title>
 | 
						||
 | 
						||
  <para>
 | 
						||
    <function>buildFHSChrootEnv</function> and
 | 
						||
    <function>buildFHSUserEnv</function> provide a way to build and run
 | 
						||
    FHS-compatible lightweight sandboxes. They get their own isolated root with
 | 
						||
    binded <filename>/nix/store</filename>, so their footprint in terms of disk
 | 
						||
    space needed is quite small. This allows one to run software which is hard or
 | 
						||
    unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions,
 | 
						||
    games distributed as tarballs, software with integrity checking and/or external
 | 
						||
    self-updated binaries.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    <function>buildFHSChrootEnv</function> allows to create persistent
 | 
						||
    environments, which can be constructed, deconstructed and entered by
 | 
						||
    multiple users at once. A downside is that it requires
 | 
						||
    <literal>root</literal> access for both those who create and destroy and
 | 
						||
    those who enter it. It can be useful to create environments for daemons that
 | 
						||
    one can enter and observe.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    <function>buildFHSUserEnv</function> uses Linux namespaces feature to create
 | 
						||
    temporary lightweight environments which are destroyed after all child
 | 
						||
    processes exit. It does not require root access, and can be useful to create
 | 
						||
    sandboxes and wrap applications.
 | 
						||
  </para>
 | 
						||
 | 
						||
  <para>
 | 
						||
    Those functions both rely on <function>buildFHSEnv</function>, which creates
 | 
						||
    an actual directory structure given a list of necessary packages and extra
 | 
						||
    build commands.
 | 
						||
    <function>buildFHSChrootEnv</function> and <function>buildFHSUserEnv</function>
 | 
						||
    both accept those arguments which are passed to
 | 
						||
    <function>buildFHSEnv</function>:
 | 
						||
  </para>
 | 
						||
 | 
						||
  <variablelist>
 | 
						||
    <varlistentry>
 | 
						||
    <term><literal>name</literal></term>
 | 
						||
 | 
						||
    <listitem><para>Environment name.</para></listitem>
 | 
						||
    </varlistentry>
 | 
						||
 | 
						||
    <varlistentry>
 | 
						||
    <term><literal>targetPkgs</literal></term>
 | 
						||
 | 
						||
    <listitem><para>Packages to be installed for the main host's architecture
 | 
						||
    (i.e. x86_64 on x86_64 installations).</para></listitem>
 | 
						||
    </varlistentry>
 | 
						||
 | 
						||
    <varlistentry>
 | 
						||
    <term><literal>multiPkgs</literal></term>
 | 
						||
 | 
						||
    <listitem><para>Packages to be installed for all architectures supported by
 | 
						||
    a host (i.e. i686 and x86_64 on x86_64 installations).</para></listitem>
 | 
						||
    </varlistentry>
 | 
						||
 | 
						||
    <varlistentry>
 | 
						||
    <term><literal>extraBuildCommands</literal></term>
 | 
						||
 | 
						||
    <listitem><para>Additional commands to be executed for finalizing the
 | 
						||
    directory structure.</para></listitem>
 | 
						||
    </varlistentry>
 | 
						||
 | 
						||
    <varlistentry>
 | 
						||
    <term><literal>extraBuildCommandsMulti</literal></term>
 | 
						||
 | 
						||
    <listitem><para>Like <literal>extraBuildCommandsMulti</literal>, but
 | 
						||
    executed only on multilib architectures.</para></listitem>
 | 
						||
    </varlistentry>
 | 
						||
  </variablelist>
 | 
						||
 | 
						||
  <para>
 | 
						||
    Additionally, <function>buildFHSUserEnv</function> accepts
 | 
						||
    <literal>runScript</literal> parameter, which is a command that would be
 | 
						||
    executed inside the sandbox and passed all the command line arguments. It
 | 
						||
    default to <literal>bash</literal>.
 | 
						||
  </para>
 | 
						||
  <para>
 | 
						||
    It also uses <literal>CHROOTENV_EXTRA_BINDS</literal> environment variable
 | 
						||
    for binding extra directories in the sandbox to outside places. The format of
 | 
						||
    the variable is <literal>/mnt=test-mnt:/data</literal>, where
 | 
						||
    <literal>/mnt</literal> would be mounted as <literal>/test-mnt</literal>
 | 
						||
    and <literal>/data</literal> would be mounted as <literal>/data</literal>.
 | 
						||
    <literal>extraBindMounts</literal> array argument to
 | 
						||
    <function>buildFHSUserEnv</function> function is prepended to this variable.
 | 
						||
    Latter entries take priority if defined several times -- i.e. in case of
 | 
						||
    <literal>/data=data1:/data=data2</literal> the actual bind path would be
 | 
						||
    <literal>/data2</literal>.
 | 
						||
  </para>
 | 
						||
  <para>
 | 
						||
    One can create a simple environment using a <literal>shell.nix</literal>
 | 
						||
    like that:
 | 
						||
  </para>
 | 
						||
 | 
						||
<programlisting><![CDATA[
 | 
						||
{ pkgs ? import <nixpkgs> {} }:
 | 
						||
 | 
						||
(pkgs.buildFHSUserEnv {
 | 
						||
  name = "simple-x11-env";
 | 
						||
  targetPkgs = pkgs: (with pkgs;
 | 
						||
    [ udev
 | 
						||
      alsaLib
 | 
						||
    ]) ++ (with pkgs.xorg;
 | 
						||
    [ libX11
 | 
						||
      libXcursor
 | 
						||
      libXrandr
 | 
						||
    ]);
 | 
						||
  multiPkgs = pkgs: (with pkgs;
 | 
						||
    [ udev
 | 
						||
      alsaLib
 | 
						||
    ]) ++ (with [];
 | 
						||
  runScript = "bash";
 | 
						||
}).env
 | 
						||
]]></programlisting>
 | 
						||
 | 
						||
  <para>
 | 
						||
    Running <literal>nix-shell</literal> would then drop you into a shell with
 | 
						||
    these libraries and binaries available. You can use this to run
 | 
						||
    closed-source applications which expect FHS structure without hassles:
 | 
						||
    simply change <literal>runScript</literal> to the application path,
 | 
						||
    e.g. <filename>./bin/start.sh</filename> -- relative paths are supported.
 | 
						||
  </para>
 | 
						||
</section>
 | 
						||
 | 
						||
</chapter>
 |