Merge branch 'staging' into mesa_3

This commit is contained in:
Matthew Bauer 2019-05-02 17:37:20 -04:00 committed by GitHub
commit 296e8fef61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11257 changed files with 487607 additions and 251764 deletions

View File

@ -1,8 +0,0 @@
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((nil
(bug-reference-bug-regexp . "\\(\\(?:[Ii]ssue \\|[Ff]ixe[ds] \\|[Rr]esolve[ds]? \\|[Cc]lose[ds]? \\|[Pp]\\(?:ull [Rr]equest\\|[Rr]\\) \\|(\\)#\\([0-9]+\\))?\\)")
(bug-reference-url-format . "https://github.com/NixOS/nixpkgs/issues/%s"))
(nix-mode
(tab-width . 2)))

66
.github/CODEOWNERS vendored
View File

@ -12,7 +12,7 @@
# Libraries # Libraries
/lib @edolstra @nbp /lib @edolstra @nbp
/lib/systems @nbp @ericson2314 /lib/systems @nbp @ericson2314 @matthewbauer
/lib/generators.nix @edolstra @nbp @Profpatsch /lib/generators.nix @edolstra @nbp @Profpatsch
/lib/debug.nix @edolstra @nbp @Profpatsch /lib/debug.nix @edolstra @nbp @Profpatsch
@ -20,9 +20,11 @@
/default.nix @nbp /default.nix @nbp
/pkgs/top-level/default.nix @nbp @Ericson2314 /pkgs/top-level/default.nix @nbp @Ericson2314
/pkgs/top-level/impure.nix @nbp @Ericson2314 /pkgs/top-level/impure.nix @nbp @Ericson2314
/pkgs/top-level/stage.nix @nbp @Ericson2314 /pkgs/top-level/stage.nix @nbp @Ericson2314 @matthewbauer
/pkgs/stdenv/generic @Ericson2314 /pkgs/top-level/splice.nix @Ericson2314 @matthewbauer
/pkgs/stdenv/cross @Ericson2314 /pkgs/top-level/release-cross.nix @Ericson2314 @matthewbauer
/pkgs/stdenv/generic @Ericson2314 @matthewbauer
/pkgs/stdenv/cross @Ericson2314 @matthewbauer
/pkgs/build-support/cc-wrapper @Ericson2314 @orivej /pkgs/build-support/cc-wrapper @Ericson2314 @orivej
/pkgs/build-support/bintools-wrapper @Ericson2314 @orivej /pkgs/build-support/bintools-wrapper @Ericson2314 @orivej
/pkgs/build-support/setup-hooks @Ericson2314 /pkgs/build-support/setup-hooks @Ericson2314
@ -45,27 +47,35 @@
/nixos/doc/manual/man-nixos-option.xml @nbp /nixos/doc/manual/man-nixos-option.xml @nbp
/nixos/modules/installer/tools/nixos-option.sh @nbp /nixos/modules/installer/tools/nixos-option.sh @nbp
# NixOS modules
/nixos/modules @Infinisil
# Python-related code and docs # Python-related code and docs
/maintainers/scripts/update-python-libraries @FRidh /maintainers/scripts/update-python-libraries @FRidh
/pkgs/top-level/python-packages.nix @FRidh /pkgs/top-level/python-packages.nix @FRidh
/pkgs/development/interpreters/python @FRidh /pkgs/development/interpreters/python @FRidh
/pkgs/development/python-modules @FRidh /pkgs/development/python-modules @FRidh
/doc/languages-frameworks/python.md @FRidh /doc/languages-frameworks/python.section.md @FRidh
# Haskell # Haskell
/pkgs/development/compilers/ghc @peti @ryantm @basvandijk /pkgs/development/compilers/ghc @basvandijk
/pkgs/development/haskell-modules @peti @ryantm @basvandijk /pkgs/development/haskell-modules @basvandijk
/pkgs/development/haskell-modules/default.nix @peti @ryantm @basvandijk /pkgs/development/haskell-modules/default.nix @basvandijk
/pkgs/development/haskell-modules/generic-builder.nix @peti @ryantm @basvandijk /pkgs/development/haskell-modules/generic-builder.nix @basvandijk
/pkgs/development/haskell-modules/hoogle.nix @peti @ryantm @basvandijk /pkgs/development/haskell-modules/hoogle.nix @basvandijk
# Perl
/pkgs/development/interpreters/perl @volth
/pkgs/top-level/perl-packages.nix @volth
/pkgs/development/perl-modules @volth
# R # R
/pkgs/applications/science/math/R @peti /pkgs/applications/science/math/R @peti
/pkgs/development/r-modules @peti /pkgs/development/r-modules @peti
# Ruby # Ruby
/pkgs/development/interpreters/ruby @zimbatm /pkgs/development/interpreters/ruby @alyssais @zimbatm
/pkgs/development/ruby-modules @zimbatm /pkgs/development/ruby-modules @alyssais @zimbatm
# Rust # Rust
/pkgs/development/compilers/rust @Mic92 @LnL7 /pkgs/development/compilers/rust @Mic92 @LnL7
@ -74,6 +84,14 @@
/pkgs/stdenv/darwin @NixOS/darwin-maintainers /pkgs/stdenv/darwin @NixOS/darwin-maintainers
/pkgs/os-specific/darwin @NixOS/darwin-maintainers /pkgs/os-specific/darwin @NixOS/darwin-maintainers
# C compilers
/pkgs/development/compilers/gcc @matthewbauer
/pkgs/development/compilers/llvm @matthewbauer
# Compatibility stuff
/pkgs/top-level/unix-tools.nix @matthewbauer
/pkgs/development/tools/xcbuild @matthewbauer
# Beam-related (Erlang, Elixir, LFE, etc) # Beam-related (Erlang, Elixir, LFE, etc)
/pkgs/development/beam-modules @gleber /pkgs/development/beam-modules @gleber
/pkgs/development/interpreters/erlang @gleber /pkgs/development/interpreters/erlang @gleber
@ -97,3 +115,27 @@
/pkgs/desktops/plasma-5 @ttuegel /pkgs/desktops/plasma-5 @ttuegel
/pkgs/development/libraries/kde-frameworks @ttuegel /pkgs/development/libraries/kde-frameworks @ttuegel
/pkgs/development/libraries/qt-5 @ttuegel /pkgs/development/libraries/qt-5 @ttuegel
# PostgreSQL and related stuff
/pkgs/servers/sql/postgresql @thoughtpolice
/nixos/modules/services/databases/postgresql.xml @thoughtpolice
/nixos/modules/services/databases/postgresql.nix @thoughtpolice
/nixos/tests/postgresql.nix @thoughtpolice
# Hardened profile & related modules
/nixos/modules/profiles/hardened.nix @joachifm
/nixos/modules/security/hidepid.nix @joachifm
/nixos/modules/security/lock-kernel-modules.nix @joachifm
/nixos/modules/security/misc.nix @joachifm
/nixos/tests/hardened.nix @joachifm
/pkgs/os-specific/linux/kernel/hardened-config.nix @joachifm
# Dhall
/pkgs/development/dhall-modules @Gabriel439 @Profpatsch
/pkgs/development/interpreters/dhall @Gabriel439 @Profpatsch
# Idris
/pkgs/development/idris-modules @Infinisil
# Bazel
/pkgs/development/tools/build-managers/bazel @mboes @Profpatsch

View File

@ -20,6 +20,8 @@ under the terms of [COPYING](../COPYING), which is an MIT-like license.
(Motivation for change. Additional information.) (Motivation for change. Additional information.)
``` ```
For consistency, there should not be a period at the end of the commit message's summary line (the first line of the commit message).
Examples: Examples:
* nginx: init at 2.0.1 * nginx: init at 2.0.1
@ -43,7 +45,7 @@ See the nixpkgs manual for more details on [standard meta-attributes](https://ni
## Writing good commit messages ## Writing good commit messages
In addition to writing properly formatted commit messages, it's important to include relevant information so other developers can later understand *why* a change was made. While this information usually can be found by digging code, mailing list archives, pull request discussions or upstream changes, it may require a lot of work. In addition to writing properly formatted commit messages, it's important to include relevant information so other developers can later understand *why* a change was made. While this information usually can be found by digging code, mailing list/Discourse archives, pull request discussions or upstream changes, it may require a lot of work.
For package version upgrades and such a one-line commit message is usually sufficient. For package version upgrades and such a one-line commit message is usually sufficient.

View File

@ -1,3 +1,4 @@
<!-- Nixpkgs has a lot of new incoming Pull Requests, but not enough people to review this constant stream. Even if you aren't a committer, we would appreciate reviews of other PRs, especially simple ones like package updates. Just testing the relevant package/service and leaving a comment saying what you tested, how you tested it and whether it worked would be great. List of open PRs: <https://github.com/NixOS/nixpkgs/pulls>, for more about reviewing contributions: <https://hydra.nixos.org/job/nixpkgs/trunk/manual/latest/download/1/nixpkgs/manual.html#sec-reviewing-contributions>. Reviewing isn't mandatory, but it would help out a lot and reduce the average time-to-merge for all of us. Thanks a lot if you do! -->
###### Motivation for this change ###### Motivation for this change
@ -11,10 +12,10 @@
- [ ] macOS - [ ] macOS
- [ ] other Linux distributions - [ ] other Linux distributions
- [ ] Tested via one or more NixOS test(s) if existing and applicable for the change (look inside [nixos/tests](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests)) - [ ] Tested via one or more NixOS test(s) if existing and applicable for the change (look inside [nixos/tests](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests))
- [ ] Tested compilation of all pkgs that depend on this change using `nix-shell -p nox --run "nox-review wip"` - [ ] Tested compilation of all pkgs that depend on this change using `nix-shell -p nix-review --run "nix-review wip"`
- [ ] Tested execution of all binary files (usually in `./result/bin/`) - [ ] Tested execution of all binary files (usually in `./result/bin/`)
- [ ] Determined the impact on package closure size (by running `nix path-info -S` before and after) - [ ] Determined the impact on package closure size (by running `nix path-info -S` before and after)
- [ ] Assured whether relevant documentation is up to date
- [ ] Fits [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/.github/CONTRIBUTING.md). - [ ] Fits [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/.github/CONTRIBUTING.md).
--- ---

3
.gitignore vendored
View File

@ -13,4 +13,5 @@ result-*
.DS_Store .DS_Store
/pkgs/development/libraries/qt-5/*/tmp/ /pkgs/development/libraries/qt-5/*/tmp/
/pkgs/desktops/kde-5/*/tmp/ /pkgs/desktops/kde-5/*/tmp/
/pkgs/development/mobile/androidenv/xml/*

View File

@ -1 +1 @@
18.09 19.09

11
COPYING
View File

@ -1,4 +1,4 @@
Copyright (c) 2003-2018 Eelco Dolstra and the Nixpkgs/NixOS contributors Copyright (c) 2003-2019 Eelco Dolstra and the Nixpkgs/NixOS contributors
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
@ -18,12 +18,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================================================================
Note: the license above does not apply to the packages built by the
Nix Packages collection, merely to the package descriptions (i.e., Nix
expressions, build scripts, etc.). It also might not apply to patches
included in Nixpkgs, which may be derivative works of the packages to
which they apply. The aforementioned artifacts are all covered by the
licenses of the respective packages.

View File

@ -12,15 +12,15 @@ build daemon as so-called channels. To get channel information via git, add
``` ```
For stability and maximum binary package support, it is recommended to maintain For stability and maximum binary package support, it is recommended to maintain
custom changes on top of one of the channels, e.g. `nixos-18.03` for the latest custom changes on top of one of the channels, e.g. `nixos-19.03` for the latest
release and `nixos-unstable` for the latest successful build of master: release and `nixos-unstable` for the latest successful build of master:
``` ```
% git remote update channels % git remote update channels
% git rebase channels/nixos-18.03 % git rebase channels/nixos-19.03
``` ```
For pull-requests, please rebase onto nixpkgs `master`. For pull requests, please rebase onto nixpkgs `master`.
[NixOS](https://nixos.org/nixos/) Linux distribution source code is located inside [NixOS](https://nixos.org/nixos/) Linux distribution source code is located inside
`nixos/` folder. `nixos/` folder.
@ -31,12 +31,17 @@ For pull-requests, please rebase onto nixpkgs `master`.
* [Manual (NixOS)](https://nixos.org/nixos/manual/) * [Manual (NixOS)](https://nixos.org/nixos/manual/)
* [Community maintained wiki](https://nixos.wiki/) * [Community maintained wiki](https://nixos.wiki/)
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined) * [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Continuous package builds for 18.03 release](https://hydra.nixos.org/jobset/nixos/release-18.03) * [Continuous package builds for 19.03 release](https://hydra.nixos.org/jobset/nixos/release-19.03)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents) * [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for 18.03 release](https://hydra.nixos.org/job/nixos/release-18.03/tested#tabs-constituents) * [Tests for 19.03 release](https://hydra.nixos.org/job/nixos/release-19.03/tested#tabs-constituents)
Communication: Communication:
* [Discourse Forum](https://discourse.nixos.org/) * [Discourse Forum](https://discourse.nixos.org/)
* [Mailing list](https://groups.google.com/forum/#!forum/nix-devel)
* [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos) * [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)
Note: MIT license does not apply to the packages built by Nixpkgs, merely to
the package descriptions (Nix expressions, build scripts, and so on). It also
might not apply to patches included in Nixpkgs, which may be derivative works
of the packages to which they apply. The aforementioned artifacts are all
covered by the licenses of the respective packages.

View File

@ -15,6 +15,12 @@ if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.
it is safe to upgrade by running it again: it is safe to upgrade by running it again:
curl https://nixos.org/nix/install | sh curl https://nixos.org/nix/install | sh
For more information, please see the NixOS release notes at
https://nixos.org/nixos/manual or locally at
${toString ./nixos/doc/manual/release-notes}.
If you need further help, see https://nixos.org/nixos/support.html
'' ''
else else

6
doc/.gitignore vendored
View File

@ -1,6 +1,8 @@
*.chapter.xml *.chapter.xml
*.section.xml *.section.xml
.version .version
out functions/library/generated
manual-full.xml functions/library/locations.xml
highlightjs highlightjs
manual-full.xml
out

View File

@ -9,8 +9,10 @@ debug:
.PHONY: format .PHONY: format
format: format:
find . -iname '*.xml' -type f -print0 | xargs -0 -I{} -n1 \ find . -iname '*.xml' -type f | while read f; do \
xmlformat --config-file "$$XMLFORMAT_CONFIG" -i {} echo $$f ;\
xmlformat --config-file "$$XMLFORMAT_CONFIG" -i $$f ;\
done
.PHONY: fix-misc-xml .PHONY: fix-misc-xml
fix-misc-xml: fix-misc-xml:
@ -19,7 +21,7 @@ fix-misc-xml:
.PHONY: clean .PHONY: clean
clean: clean:
rm -f ${MD_TARGETS} .version manual-full.xml rm -f ${MD_TARGETS} .version manual-full.xml functions/library/locations.xml functions/library/generated
rm -rf ./out/ ./highlightjs rm -rf ./out/ ./highlightjs
.PHONY: validate .PHONY: validate
@ -69,13 +71,22 @@ highlightjs:
cp -r "$$HIGHLIGHTJS/loader.js" highlightjs/ cp -r "$$HIGHLIGHTJS/loader.js" highlightjs/
manual-full.xml: ${MD_TARGETS} .version *.xml manual-full.xml: ${MD_TARGETS} .version functions/library/locations.xml functions/library/generated *.xml **/*.xml **/**/*.xml
xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml
.version: .version:
nix-instantiate --eval \ nix-instantiate --eval \
-E '(import ../lib).version' > .version -E '(import ../lib).version' > .version
functions/library/locations.xml:
nix-build ./lib-function-locations.nix \
--out-link $@
functions/library/generated: functions/library/locations.xml
nix-build ./lib-function-docs.nix \
--arg locationsXml $< \
--out-link $@
%.section.xml: %.section.md %.section.xml: %.section.md
pandoc $^ -w docbook+smart \ pandoc $^ -w docbook+smart \
-f markdown+smart \ -f markdown+smart \

View File

@ -56,25 +56,30 @@ foo { arg = ...; }
or list elements should be aligned: or list elements should be aligned:
<programlisting> <programlisting>
# A long list. # A long list.
list = list = [
[ elem1 elem1
elem2 elem2
elem3 elem3
]; ];
# A long attribute set. # A long attribute set.
attrs =
{ attr1 = short_expr;
attr2 =
if true then big_expr else big_expr;
};
# Alternatively:
attrs = { attrs = {
attr1 = short_expr; attr1 = short_expr;
attr2 = attr2 =
if true then big_expr else big_expr; if true then big_expr else big_expr;
}; };
# Combined
listOfAttrs = [
{
attr1 = 3;
attr2 = "fff";
}
{
attr1 = 5;
attr2 = "ggg";
}
];
</programlisting> </programlisting>
</para> </para>
</listitem> </listitem>
@ -191,6 +196,17 @@ args.stdenv.mkDerivation (args // {
<section xml:id="sec-package-naming"> <section xml:id="sec-package-naming">
<title>Package naming</title> <title>Package naming</title>
<para>
The key words <emphasis>must</emphasis>, <emphasis>must not</emphasis>,
<emphasis>required</emphasis>, <emphasis>shall</emphasis>, <emphasis>shall
not</emphasis>, <emphasis>should</emphasis>, <emphasis>should
not</emphasis>, <emphasis>recommended</emphasis>, <emphasis>may</emphasis>,
and <emphasis>optional</emphasis> in this section are to be interpreted as
described in <link xlink:href="https://tools.ietf.org/html/rfc2119">RFC
2119</link>. Only <emphasis>emphasized</emphasis> words are to be
interpreted in this way.
</para>
<para> <para>
In Nixpkgs, there are generally three different names associated with a In Nixpkgs, there are generally three different names associated with a
package: package:
@ -231,14 +247,15 @@ args.stdenv.mkDerivation (args // {
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Generally, try to stick to the upstream package name. The <literal>name</literal> attribute <emphasis>should</emphasis> be
identical to the upstream package name.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Dont use uppercase letters in the <literal>name</literal> attribute The <literal>name</literal> attribute <emphasis>must not</emphasis>
— e.g., <literal>"mplayer-1.0rc2"</literal> instead of contain uppercase letters — e.g., <literal>"mplayer-1.0rc2"</literal>
<literal>"MPlayer-1.0rc2"</literal>. instead of <literal>"MPlayer-1.0rc2"</literal>.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -252,28 +269,29 @@ args.stdenv.mkDerivation (args // {
<para> <para>
If a package is not a release but a commit from a repository, then the If a package is not a release but a commit from a repository, then the
version part of the name <emphasis>must</emphasis> be the date of that version part of the name <emphasis>must</emphasis> be the date of that
(fetched) commit. The date must be in <literal>"YYYY-MM-DD"</literal> (fetched) commit. The date <emphasis>must</emphasis> be in
format. Also append <literal>"unstable"</literal> to the name - e.g., <literal>"YYYY-MM-DD"</literal> format. Also append
<literal>"unstable"</literal> to the name - e.g.,
<literal>"pkgname-unstable-2014-09-23"</literal>. <literal>"pkgname-unstable-2014-09-23"</literal>.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Dashes in the package name should be preserved in new variable names, Dashes in the package name <emphasis>should</emphasis> be preserved in
rather than converted to underscores or camel cased — e.g., new variable names, rather than converted to underscores or camel cased
<varname>http-parser</varname> instead of <varname>http_parser</varname> — e.g., <varname>http-parser</varname> instead of
or <varname>httpParser</varname>. The hyphenated style is preferred in <varname>http_parser</varname> or <varname>httpParser</varname>. The
all three package names. hyphenated style is preferred in all three package names.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
If there are multiple versions of a package, this should be reflected in If there are multiple versions of a package, this
the variable names in <filename>all-packages.nix</filename>, e.g. <emphasis>should</emphasis> be reflected in the variable names in
<varname>json-c-0-9</varname> and <varname>json-c-0-11</varname>. If <filename>all-packages.nix</filename>, e.g. <varname>json-c-0-9</varname>
there is an obvious “default” version, make an attribute like and <varname>json-c-0-11</varname>. If there is an obvious “default”
<literal>json-c = json-c-0-9;</literal>. See also version, make an attribute like <literal>json-c = json-c-0-9;</literal>.
<xref linkend="sec-versioning" /> See also <xref linkend="sec-versioning" />
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -791,8 +809,8 @@ args.stdenv.mkDerivation (args // {
<para> <para>
There are multiple ways to fetch a package source in nixpkgs. The general There are multiple ways to fetch a package source in nixpkgs. The general
guideline is that you should package sources with a high degree of guideline is that you should package reproducible sources with a high degree
availability. Right now there is only one fetcher which has mirroring of availability. Right now there is only one fetcher which has mirroring
support and that is <literal>fetchurl</literal>. Note that you should also support and that is <literal>fetchurl</literal>. Note that you should also
prefer protocols which have a corresponding proxy environment variable. prefer protocols which have a corresponding proxy environment variable.
</para> </para>
@ -842,14 +860,143 @@ src = fetchFromGitHub {
owner = "NixOS"; owner = "NixOS";
repo = "nix"; repo = "nix";
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae"; rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
sha256 = "04yri911rj9j19qqqn6m82266fl05pz98inasni0vxr1cf1gdgv9"; sha256 = "1i2yxndxb6yc9l6c99pypbd92lfq5aac4klq7y2v93c9qvx2cgpc";
} }
</programlisting> </programlisting>
Find the value to put as <literal>sha256</literal> by running
<literal>nix run -f '&lt;nixpkgs&gt;' nix-prefetch-github -c
nix-prefetch-github --rev 1f795f9f44607cc5bec70d1300150bfefcef2aae NixOS
nix</literal> or <literal>nix-prefetch-url --unpack
https://github.com/NixOS/nix/archive/1f795f9f44607cc5bec70d1300150bfefcef2aae.tar.gz</literal>.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</para> </para>
</section> </section>
<section xml:id="sec-source-hashes">
<title>Obtaining source hash</title>
<para>
Preferred source hash type is sha256. There are several ways to get it.
</para>
<orderedlist>
<listitem>
<para>
Prefetch URL (with <literal>nix-prefetch-<replaceable>XXX</replaceable>
<replaceable>URL</replaceable></literal>, where
<replaceable>XXX</replaceable> is one of <literal>url</literal>,
<literal>git</literal>, <literal>hg</literal>, <literal>cvs</literal>,
<literal>bzr</literal>, <literal>svn</literal>). Hash is printed to
stdout.
</para>
</listitem>
<listitem>
<para>
Prefetch by package source (with <literal>nix-prefetch-url
'&lt;nixpkgs&gt;' -A <replaceable>PACKAGE</replaceable>.src</literal>,
where <replaceable>PACKAGE</replaceable> is package attribute name). Hash
is printed to stdout.
</para>
<para>
This works well when you've upgraded existing package version and want to
find out new hash, but is useless if package can't be accessed by
attribute or package has multiple sources (<literal>.srcs</literal>,
architecture-dependent sources, etc).
</para>
</listitem>
<listitem>
<para>
Upstream provided hash: use it when upstream provides
<literal>sha256</literal> or <literal>sha512</literal> (when upstream
provides <literal>md5</literal>, don't use it, compute
<literal>sha256</literal> instead).
</para>
<para>
A little nuance is that <literal>nix-prefetch-*</literal> tools produce
hash encoded with <literal>base32</literal>, but upstream usually provides
hexadecimal (<literal>base16</literal>) encoding. Fetchers understand both
formats. Nixpkgs does not standardize on any one format.
</para>
<para>
You can convert between formats with nix-hash, for example:
<screen>
$ nix-hash --type sha256 --to-base32 <replaceable>HASH</replaceable>
</screen>
</para>
</listitem>
<listitem>
<para>
Extracting hash from local source tarball can be done with
<literal>sha256sum</literal>. Use <literal>nix-prefetch-url
file:///path/to/tarball </literal> if you want base32 hash.
</para>
</listitem>
<listitem>
<para>
Fake hash: set fake hash in package expression, perform build and extract
correct hash from error Nix prints.
</para>
<para>
For package updates it is enough to change one symbol to make hash fake.
For new packages, you can use <literal>lib.fakeSha256</literal>,
<literal>lib.fakeSha512</literal> or any other fake hash.
</para>
<para>
This is last resort method when reconstructing source URL is non-trivial
and <literal>nix-prefetch-url -A</literal> isn't applicable (for example,
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/d2ab091dd308b99e4912b805a5eb088dd536adb9/pkgs/applications/video/kodi/default.nix#L73">
one of <literal>kodi</literal> dependencies</link>). The easiest way then
would be replace hash with a fake one and rebuild. Nix build will fail and
error message will contain desired hash.
</para>
<warning>
<para>
This method has security problems. Check below for details.
</para>
</warning>
</listitem>
</orderedlist>
<section xml:id="sec-source-hashes-security">
<title>Obtaining hashes securely</title>
<para>
Let's say Man-in-the-Middle (MITM) sits close to your network. Then instead
of fetching source you can fetch malware, and instead of source hash you
get hash of malware. Here are security considerations for this scenario:
</para>
<itemizedlist>
<listitem>
<para>
<literal>http://</literal> URLs are not secure to prefetch hash from;
</para>
</listitem>
<listitem>
<para>
hashes from upstream (in method 3) should be obtained via secure
protocol;
</para>
</listitem>
<listitem>
<para>
<literal>https://</literal> URLs are secure in methods 1, 2, 3;
</para>
</listitem>
<listitem>
<para>
<literal>https://</literal> URLs are not secure in method 5. When
obtaining hashes with fake hash method, TLS checks are disabled. So
refetch source hash from several different networks to exclude MITM
scenario. Alternatively, use fake hash method to make Nix error, but
instead of extracting hash from error, extract
<literal>https://</literal> URL and prefetch it with method 1.
</para>
</listitem>
</itemizedlist>
</section>
</section>
<section xml:id="sec-patches"> <section xml:id="sec-patches">
<title>Patches</title> <title>Patches</title>

View File

@ -132,13 +132,13 @@
</itemizedlist> </itemizedlist>
<para> <para>
The difference between an a package being unsupported on some system and The difference between a package being unsupported on some system and being
being broken is admittedly a bit fuzzy. If a program broken is admittedly a bit fuzzy. If a program <emphasis>ought</emphasis> to
<emphasis>ought</emphasis> to work on a certain platform, but doesn't, the work on a certain platform, but doesn't, the platform should be included in
platform should be included in <literal>meta.platforms</literal>, but marked <literal>meta.platforms</literal>, but marked as broken with e.g.
as broken with e.g. <literal>meta.broken = <literal>meta.broken = !hostPlatform.isWindows</literal>. Of course, this
!hostPlatform.isWindows</literal>. Of course, this begs the question of what begs the question of what "ought" means exactly. That is left to the package
"ought" means exactly. That is left to the package maintainer. maintainer.
</para> </para>
</section> </section>
<section xml:id="sec-allow-unfree"> <section xml:id="sec-allow-unfree">
@ -175,11 +175,15 @@
</programlisting> </programlisting>
</para> </para>
<para> <para>
A more useful example, the following configuration allows only allows For a more useful example, try the following. This configuration only
flash player and visual studio code: allows unfree packages named flash player and visual studio code:
<programlisting> <programlisting>
{ {
allowUnfreePredicate = (pkg: elem (builtins.parseDrvName pkg.name).name [ "flashplayer" "vscode" ]); allowUnfreePredicate = (pkg: builtins.elem
(builtins.parseDrvName pkg.name).name [
"flashplayer"
"vscode"
]);
} }
</programlisting> </programlisting>
</para> </para>
@ -286,8 +290,8 @@
<para> <para>
You can define a function called <varname>packageOverrides</varname> in your You can define a function called <varname>packageOverrides</varname> in your
local <filename>~/.config/nixpkgs/config.nix</filename> to override nix local <filename>~/.config/nixpkgs/config.nix</filename> to override Nix
packages. It must be a function that takes pkgs as an argument and return packages. It must be a function that takes pkgs as an argument and returns a
modified set of packages. modified set of packages.
<programlisting> <programlisting>
{ {
@ -321,11 +325,22 @@
packageOverrides = pkgs: with pkgs; { packageOverrides = pkgs: with pkgs; {
myPackages = pkgs.buildEnv { myPackages = pkgs.buildEnv {
name = "my-packages"; name = "my-packages";
paths = [ aspell bc coreutils gdb ffmpeg nixUnstable emscripten jq nox silver-searcher ]; paths = [
aspell
bc
coreutils
gdb
ffmpeg
nixUnstable
emscripten
jq
nox
silver-searcher
];
}; };
}; };
} }
</screen> </screen>
<para> <para>
To install it into our environment, you can just run <literal>nix-env -iA To install it into our environment, you can just run <literal>nix-env -iA
@ -342,12 +357,23 @@
packageOverrides = pkgs: with pkgs; { packageOverrides = pkgs: with pkgs; {
myPackages = pkgs.buildEnv { myPackages = pkgs.buildEnv {
name = "my-packages"; name = "my-packages";
paths = [ aspell bc coreutils gdb ffmpeg nixUnstable emscripten jq nox silver-searcher ]; paths = [
aspell
bc
coreutils
gdb
ffmpeg
nixUnstable
emscripten
jq
nox
silver-searcher
];
pathsToLink = [ "/share" "/bin" ]; pathsToLink = [ "/share" "/bin" ];
}; };
}; };
} }
</screen> </screen>
<para> <para>
<literal>pathsToLink</literal> tells Nixpkgs to only link the paths listed <literal>pathsToLink</literal> tells Nixpkgs to only link the paths listed
@ -377,13 +403,23 @@
packageOverrides = pkgs: with pkgs; { packageOverrides = pkgs: with pkgs; {
myPackages = pkgs.buildEnv { myPackages = pkgs.buildEnv {
name = "my-packages"; name = "my-packages";
paths = [ aspell bc coreutils ffmpeg nixUnstable emscripten jq nox silver-searcher ]; paths = [
aspell
bc
coreutils
ffmpeg
nixUnstable
emscripten
jq
nox
silver-searcher
];
pathsToLink = [ "/share/man" "/share/doc" "/bin" ]; pathsToLink = [ "/share/man" "/share/doc" "/bin" ];
extraOutputsToInstall = [ "man" "doc" ]; extraOutputsToInstall = [ "man" "doc" ];
}; };
}; };
} }
</screen> </screen>
<para> <para>
This provides us with some useful documentation for using our packages. This provides us with some useful documentation for using our packages.
@ -395,15 +431,15 @@
{ {
packageOverrides = pkgs: with pkgs; rec { packageOverrides = pkgs: with pkgs; rec {
myProfile = writeText "my-profile" '' myProfile = writeText "my-profile" ''
export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin
export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man
''; '';
myPackages = pkgs.buildEnv { myPackages = pkgs.buildEnv {
name = "my-packages"; name = "my-packages";
paths = [ paths = [
(runCommand "profile" {} '' (runCommand "profile" {} ''
mkdir -p $out/etc/profile.d mkdir -p $out/etc/profile.d
cp ${myProfile} $out/etc/profile.d/my-profile.sh cp ${myProfile} $out/etc/profile.d/my-profile.sh
'') '')
aspell aspell
bc bc
@ -421,7 +457,7 @@ cp ${myProfile} $out/etc/profile.d/my-profile.sh
}; };
}; };
} }
</screen> </screen>
<para> <para>
For this to work fully, you must also have this script sourced when you are For this to work fully, you must also have this script sourced when you are
@ -438,7 +474,7 @@ if [ -d $HOME/.nix-profile/etc/profile.d ]; then
fi fi
done done
fi fi
</screen> </screen>
<para> <para>
Now just run <literal>source $HOME/.profile</literal> and you can starting Now just run <literal>source $HOME/.profile</literal> and you can starting
@ -459,16 +495,16 @@ fi
{ {
packageOverrides = pkgs: with pkgs; rec { packageOverrides = pkgs: with pkgs; rec {
myProfile = writeText "my-profile" '' myProfile = writeText "my-profile" ''
export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin
export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man
export INFOPATH=$HOME/.nix-profile/share/info:/nix/var/nix/profiles/default/share/info:/usr/share/info export INFOPATH=$HOME/.nix-profile/share/info:/nix/var/nix/profiles/default/share/info:/usr/share/info
''; '';
myPackages = pkgs.buildEnv { myPackages = pkgs.buildEnv {
name = "my-packages"; name = "my-packages";
paths = [ paths = [
(runCommand "profile" {} '' (runCommand "profile" {} ''
mkdir -p $out/etc/profile.d mkdir -p $out/etc/profile.d
cp ${myProfile} $out/etc/profile.d/my-profile.sh cp ${myProfile} $out/etc/profile.d/my-profile.sh
'') '')
aspell aspell
bc bc
@ -485,17 +521,17 @@ cp ${myProfile} $out/etc/profile.d/my-profile.sh
pathsToLink = [ "/share/man" "/share/doc" "/share/info" "/bin" "/etc" ]; pathsToLink = [ "/share/man" "/share/doc" "/share/info" "/bin" "/etc" ];
extraOutputsToInstall = [ "man" "doc" "info" ]; extraOutputsToInstall = [ "man" "doc" "info" ];
postBuild = '' postBuild = ''
if [ -x $out/bin/install-info -a -w $out/share/info ]; then if [ -x $out/bin/install-info -a -w $out/share/info ]; then
shopt -s nullglob shopt -s nullglob
for i in $out/share/info/*.info $out/share/info/*.info.gz; do for i in $out/share/info/*.info $out/share/info/*.info.gz; do
$out/bin/install-info $i $out/share/info/dir $out/bin/install-info $i $out/share/info/dir
done done
fi fi
''; '';
}; };
}; };
} }
</screen> </screen>
<para> <para>
<literal>postBuild</literal> tells Nixpkgs to run a command after building <literal>postBuild</literal> tells Nixpkgs to run a command after building

View File

@ -7,15 +7,16 @@
<para> <para>
"Cross-compilation" means compiling a program on one machine for another "Cross-compilation" means compiling a program on one machine for another
type of machine. For example, a typical use of cross compilation is to type of machine. For example, a typical use of cross-compilation is to
compile programs for embedded devices. These devices often don't have the compile programs for embedded devices. These devices often don't have the
computing power and memory to compile their own programs. One might think computing power and memory to compile their own programs. One might think
that cross-compilation is a fairly niche concern, but there are advantages that cross-compilation is a fairly niche concern. However, there are
to being rigorous about distinguishing build-time vs run-time environments significant advantages to rigorously distinguishing between build-time and
even when one is developing and deploying on the same machine. Nixpkgs is run-time environments! Significant, because the benefits apply even when one
increasingly adopting the opinion that packages should be written with is developing and deploying on the same machine. Nixpkgs is increasingly
cross-compilation in mind, and nixpkgs should evaluate in a similar way (by adopting the opinion that packages should be written with cross-compilation
minimizing cross-compilation-specific special cases) whether or not one is in mind, and nixpkgs should evaluate in a similar way (by minimizing
cross-compilation-specific special cases) whether or not one is
cross-compiling. cross-compiling.
</para> </para>
@ -30,30 +31,28 @@
<section xml:id="sec-cross-packaging"> <section xml:id="sec-cross-packaging">
<title>Packaging in a cross-friendly manner</title> <title>Packaging in a cross-friendly manner</title>
<section> <section xml:id="ssec-cross-platform-parameters">
<title>Platform parameters</title> <title>Platform parameters</title>
<para> <para>
Nixpkgs follows the Nixpkgs follows the
<link xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html">common <link
historical convention of GNU autoconf</link> of distinguishing between 3 xlink:href="https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html">conventions
types of platform: <wordasword>build</wordasword>, of GNU autoconf</link>. We distinguish between 3 types of platforms when
building a derivation: <wordasword>build</wordasword>,
<wordasword>host</wordasword>, and <wordasword>target</wordasword>. In <wordasword>host</wordasword>, and <wordasword>target</wordasword>. In
summary, <wordasword>build</wordasword> is the platform on which a package summary, <wordasword>build</wordasword> is the platform on which a package
is being built, <wordasword>host</wordasword> is the platform on which it is being built, <wordasword>host</wordasword> is the platform on which it
is to run. The third attribute, <wordasword>target</wordasword>, is will run. The third attribute, <wordasword>target</wordasword>, is relevant
relevant only for certain specific compilers and build tools. only for certain specific compilers and build tools.
</para> </para>
<para> <para>
In Nixpkgs, these three platforms are defined as attribute sets under the In Nixpkgs, these three platforms are defined as attribute sets under the
names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>, names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>,
and <literal>targetPlatform</literal>. All three are always defined as and <literal>targetPlatform</literal>. They are always defined as
attributes in the standard environment, and at the top level. That means attributes in the standard environment. That means one can access them
one can get at them just like a dependency in a function that is imported like:
with <literal>callPackage</literal>:
<programlisting>{ stdenv, buildPlatform, hostPlatform, fooDep, barDep, .. }: ...buildPlatform...</programlisting>
, or just off <varname>stdenv</varname>:
<programlisting>{ stdenv, fooDep, barDep, .. }: ...stdenv.buildPlatform...</programlisting> <programlisting>{ stdenv, fooDep, barDep, .. }: ...stdenv.buildPlatform...</programlisting>
. .
</para> </para>
@ -67,7 +66,7 @@
<para> <para>
The "build platform" is the platform on which a package is built. Once The "build platform" is the platform on which a package is built. Once
someone has a built package, or pre-built binary package, the build someone has a built package, or pre-built binary package, the build
platform should not matter and be safe to ignore. platform should not matter and can be ignored.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -97,11 +96,11 @@
<para> <para>
The build process of certain compilers is written in such a way that the The build process of certain compilers is written in such a way that the
compiler resulting from a single build can itself only produce binaries compiler resulting from a single build can itself only produce binaries
for a single platform. The task specifying this single "target platform" for a single platform. The task of specifying this single "target
is thus pushed to build time of the compiler. The root cause of this platform" is thus pushed to build time of the compiler. The root cause
mistake is often that the compiler (which will be run on the host) and of this is that the compiler (which will be run on the host) and the
the the standard library/runtime (which will be run on the target) are standard library/runtime (which will be run on the target) are built by
built by a single build process. a single build process.
</para> </para>
<para> <para>
There is no fundamental need to think about a single target ahead of There is no fundamental need to think about a single target ahead of
@ -138,8 +137,10 @@
<para> <para>
This is a two-component shorthand for the platform. Examples of this This is a two-component shorthand for the platform. Examples of this
would be "x86_64-darwin" and "i686-linux"; see would be "x86_64-darwin" and "i686-linux"; see
<literal>lib.systems.doubles</literal> for more. This format isn't very <literal>lib.systems.doubles</literal> for more. The first component
standard, but has built-in support in Nix, such as the corresponds to the CPU architecture of the platform and the second to
the operating system of the platform (<literal>[cpu]-[os]</literal>).
This format has built-in support in Nix, such as the
<varname>builtins.currentSystem</varname> impure string. <varname>builtins.currentSystem</varname> impure string.
</para> </para>
</listitem> </listitem>
@ -151,12 +152,13 @@
<listitem> <listitem>
<para> <para>
This is a 3- or 4- component shorthand for the platform. Examples of This is a 3- or 4- component shorthand for the platform. Examples of
this would be "x86_64-unknown-linux-gnu" and "aarch64-apple-darwin14". this would be <literal>x86_64-unknown-linux-gnu</literal> and
This is a standard format called the "LLVM target triple", as they are <literal>aarch64-apple-darwin14</literal>. This is a standard format
pioneered by LLVM and traditionally just used for the called the "LLVM target triple", as they are pioneered by LLVM. In the
<varname>targetPlatform</varname>. This format is strictly more 4-part form, this corresponds to
informative than the "Nix host double", as the previous format could <literal>[cpu]-[vendor]-[os]-[abi]</literal>. This format is strictly
analogously be termed. This needs a better name than more informative than the "Nix host double", as the previous format
could analogously be termed. This needs a better name than
<varname>config</varname>! <varname>config</varname>!
</para> </para>
</listitem> </listitem>
@ -167,11 +169,9 @@
</term> </term>
<listitem> <listitem>
<para> <para>
This is a nix representation of a parsed LLVM target triple with This is a Nix representation of a parsed LLVM target triple with
white-listed components. This can be specified directly, or actually white-listed components. This can be specified directly, or actually
parsed from the <varname>config</varname>. [Technically, only one need parsed from the <varname>config</varname>. See
be specified and the others can be inferred, though the precision of
inference may not be very good.] See
<literal>lib.systems.parse</literal> for the exact representation. <literal>lib.systems.parse</literal> for the exact representation.
</para> </para>
</listitem> </listitem>
@ -196,7 +196,7 @@
<listitem> <listitem>
<para> <para>
These predicates are defined in <literal>lib.systems.inspect</literal>, These predicates are defined in <literal>lib.systems.inspect</literal>,
and slapped on every platform. They are superior to the ones in and slapped onto every platform. They are superior to the ones in
<varname>stdenv</varname> as they force the user to be explicit about <varname>stdenv</varname> as they force the user to be explicit about
which platform they are inspecting. Please use these instead of those. which platform they are inspecting. Please use these instead of those.
</para> </para>
@ -219,105 +219,132 @@
</variablelist> </variablelist>
</section> </section>
<section> <section xml:id="ssec-cross-dependency-categorization">
<title>Specifying Dependencies</title> <title>Theory of dependency categorization</title>
<note>
<para>
This is a rather philosophical description that isn't very
Nixpkgs-specific. For an overview of all the relevant attributes given to
<varname>mkDerivation</varname>, see
<xref
linkend="ssec-stdenv-dependencies"/>. For a description of how
everything is implemented, see
<xref linkend="ssec-cross-dependency-implementation" />.
</para>
</note>
<para> <para>
In this section we explore the relationship between both runtime and In this section we explore the relationship between both runtime and
buildtime dependencies and the 3 Autoconf platforms. build-time dependencies and the 3 Autoconf platforms.
</para> </para>
<para> <para>
A runtime dependency between 2 packages implies that between them both the A run time dependency between two packages requires that their host
host and target platforms match. This is directly implied by the meaning of platforms match. This is directly implied by the meaning of "host platform"
"host platform" and "runtime dependency": The package dependency exists and "runtime dependency": The package dependency exists while both packages
while both packages are running on a single host platform. are running on a single host platform.
</para> </para>
<para> <para>
A build time dependency, however, implies a shift in platforms between the A build time dependency, however, has a shift in platforms between the
depending package and the depended-on package. The meaning of a build time depending package and the depended-on package. "build time dependency"
dependency is that to build the depending package we need to be able to run means that to build the depending package we need to be able to run the
the depended-on's package. The depending package's build platform is depended-on's package. The depending package's build platform is therefore
therefore equal to the depended-on package's host platform. Analogously, equal to the depended-on package's host platform.
the depending package's host platform is equal to the depended-on package's
target platform.
</para> </para>
<para> <para>
In this manner, given the 3 platforms for one package, we can determine the If both the dependency and depending packages aren't compilers or other
three platforms for all its transitive dependencies. This is the most machine-code-producing tools, we're done. And indeed
important guiding principle behind cross-compilation with Nixpkgs, and will <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>
be called the <wordasword>sliding window principle</wordasword>. have covered these simpler build-time and run-time (respectively) changes
for many years. But if the dependency does produce machine code, we might
need to worry about its target platform too. In principle, that target
platform might be any of the depending package's build, host, or target
platforms, but we prohibit dependencies from a "later" platform to an
earlier platform to limit confusion because we've never seen a legitimate
use for them.
</para> </para>
<para> <para>
Some examples will probably make this clearer. If a package is being built Finally, if the depending package is a compiler or other
with a <literal>(build, host, target)</literal> platform triple of machine-code-producing tool, it might need dependencies that run at "emit
<literal>(foo, bar, bar)</literal>, then its build-time dependencies would time". This is for compilers that (regrettably) insist on being built
have a triple of <literal>(foo, foo, bar)</literal>, and <emphasis>those together with their source langauges' standard libraries. Assuming build !=
packages'</emphasis> build-time dependencies would have triple of host != target, a run-time dependency of the standard library cannot be run
<literal>(foo, foo, foo)</literal>. In other words, it should take two at the compiler's build time or run time, but only at the run time of code
"rounds" of following build-time dependency edges before one reaches a emitted by the compiler.
fixed point where, by the sliding window principle, the platform triple no
longer changes. Indeed, this happens with cross compilation, where only
rounds of native dependencies starting with the second necessarily coincide
with native packages.
</para> </para>
<note>
<para>
The depending package's target platform is unconstrained by the sliding
window principle, which makes sense in that one can in principle build
cross compilers targeting arbitrary platforms.
</para>
</note>
<para> <para>
How does this work in practice? Nixpkgs is now structured so that Putting this all together, that means we have dependencies in the form
build-time dependencies are taken from <varname>buildPackages</varname>, "host → target", in at most the following six combinations:
whereas run-time dependencies are taken from the top level attribute set. <table>
For example, <varname>buildPackages.gcc</varname> should be used at build <caption>Possible dependency types</caption>
time, while <varname>gcc</varname> should be used at run time. Now, for <thead>
most of Nixpkgs's history, there was no <varname>buildPackages</varname>, <tr>
and most packages have not been refactored to use it explicitly. Instead, <th>Dependency's host platform</th>
one can use the six (<emphasis>gasp</emphasis>) attributes used for <th>Dependency's target platform</th>
specifying dependencies as documented in </tr>
<xref linkend="ssec-stdenv-dependencies"/>. We "splice" together the </thead>
run-time and build-time package sets with <varname>callPackage</varname>, <tbody>
and then <varname>mkDerivation</varname> for each of four attributes pulls <tr>
the right derivation out. This splicing can be skipped when not cross <td>build</td>
compiling as the package sets are the same, but is a bit slow for cross <td>build</td>
compiling. Because of this, a best-of-both-worlds solution is in the works </tr>
with no splicing or explicit access of <varname>buildPackages</varname> <tr>
needed. For now, feel free to use either method. <td>build</td>
<td>host</td>
</tr>
<tr>
<td>build</td>
<td>target</td>
</tr>
<tr>
<td>host</td>
<td>host</td>
</tr>
<tr>
<td>host</td>
<td>target</td>
</tr>
<tr>
<td>target</td>
<td>target</td>
</tr>
</tbody>
</table>
</para> </para>
<note> <para>
<para> Some examples will make this table clearer. Suppose there's some package
There is also a "backlink" <varname>targetPackages</varname>, yielding a that is being built with a <literal>(build, host, target)</literal>
package set whose <varname>buildPackages</varname> is the current package platform triple of <literal>(foo, bar, baz)</literal>. If it has a
set. This is a hack, though, to accommodate compilers with lousy build build-time library dependency, that would be a "host → build" dependency
systems. Please do not use this unless you are absolutely sure you are with a triple of <literal>(foo, foo, *)</literal> (the target platform is
packaging such a compiler and there is no other way. irrelevant). If it needs a compiler to be built, that would be a "build →
</para> host" dependency with a triple of <literal>(foo, foo, *)</literal> (the
</note> target platform is irrelevant). That compiler, would be built with another
compiler, also "build → host" dependency, with a triple of <literal>(foo,
foo, foo)</literal>.
</para>
</section> </section>
<section> <section xml:id="ssec-cross-cookbook">
<title>Cross packaging cookbook</title> <title>Cross packaging cookbook</title>
<para> <para>
Some frequently problems when packaging for cross compilation are good to Some frequently encountered problems when packaging for cross-compilation
just spell and answer. Ideally the information above is exhaustive, so this should be answered here. Ideally, the information above is exhaustive, so
section cannot provide any new information, but its ludicrous and cruel to this section cannot provide any new information, but it is ludicrous and
expect everyone to spend effort working through the interaction of many cruel to expect everyone to spend effort working through the interaction of
features just to figure out the same answer to the same common problem. many features just to figure out the same answer to the same common
Feel free to add to this list! problem. Feel free to add to this list!
</para> </para>
<qandaset> <qandaset>
<qandaentry> <qandaentry xml:id="cross-qa-build-c-program-in-build-environment">
<question> <question>
<para> <para>
What if my package's build system needs to build a C program to be run What if my package's build system needs to build a C program to be run
@ -331,7 +358,7 @@
</para> </para>
</answer> </answer>
</qandaentry> </qandaentry>
<qandaentry> <qandaentry xml:id="cross-qa-fails-to-find-ar">
<question> <question>
<para> <para>
My package fails to find <command>ar</command>. My package fails to find <command>ar</command>.
@ -347,7 +374,7 @@
</para> </para>
</answer> </answer>
</qandaentry> </qandaentry>
<qandaentry> <qandaentry xml:id="cross-testsuite-runs-host-code">
<question> <question>
<para> <para>
My package's testsuite needs to run host platform code. My package's testsuite needs to run host platform code.
@ -367,17 +394,9 @@
<section xml:id="sec-cross-usage"> <section xml:id="sec-cross-usage">
<title>Cross-building packages</title> <title>Cross-building packages</title>
<note>
<para>
More information needs to moved from the old wiki, especially
<link xlink:href="https://nixos.org/wiki/CrossCompiling" />, for this
section.
</para>
</note>
<para> <para>
Nixpkgs can be instantiated with <varname>localSystem</varname> alone, in Nixpkgs can be instantiated with <varname>localSystem</varname> alone, in
which case there is no cross compiling and everything is built by and for which case there is no cross-compiling and everything is built by and for
that system, or also with <varname>crossSystem</varname>, in which case that system, or also with <varname>crossSystem</varname>, in which case
packages run on the latter, but all building happens on the former. Both packages run on the latter, but all building happens on the former. Both
parameters take the same schema as the 3 (build, host, and target) platforms parameters take the same schema as the 3 (build, host, and target) platforms
@ -394,7 +413,7 @@ nix-build &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).system
Eventually we would like to make these platform examples an unnecessary Eventually we would like to make these platform examples an unnecessary
convenience so that convenience so that
<programlisting> <programlisting>
nix-build &lt;nixpkgs&gt; --arg crossSystem.config '&lt;arch&gt;-&lt;os&gt;-&lt;vendor&gt;-&lt;abi&gt;' -A whatever</programlisting> nix-build &lt;nixpkgs&gt; --arg crossSystem '{ config = "&lt;arch&gt;-&lt;os&gt;-&lt;vendor&gt;-&lt;abi&gt;"; }' -A whatever</programlisting>
works in the vast majority of cases. The problem today is dependencies on works in the vast majority of cases. The problem today is dependencies on
other sorts of configuration which aren't given proper defaults. We rely on other sorts of configuration which aren't given proper defaults. We rely on
the examples to crudely to set those configuration parameters in some the examples to crudely to set those configuration parameters in some
@ -448,7 +467,7 @@ nix-build &lt;nixpkgs&gt; --arg crossSystem.config '&lt;arch&gt;-&lt;os&gt;-&lt;
dependencies or <varname>buildPackages</varname>, the three platforms will dependencies or <varname>buildPackages</varname>, the three platforms will
be defined as one of <varname>localSystem</varname> or be defined as one of <varname>localSystem</varname> or
<varname>crossSystem</varname>, with the former replacing the latter as one <varname>crossSystem</varname>, with the former replacing the latter as one
traverses build-time dependencies. A last simple difference then is traverses build-time dependencies. A last simple difference is that
<varname>crossSystem</varname> should be null when one doesn't want to <varname>crossSystem</varname> should be null when one doesn't want to
cross-compile, while the <varname>*Platform</varname>s are always non-null. cross-compile, while the <varname>*Platform</varname>s are always non-null.
<varname>localSystem</varname> is always non-null. <varname>localSystem</varname> is always non-null.
@ -458,21 +477,202 @@ nix-build &lt;nixpkgs&gt; --arg crossSystem.config '&lt;arch&gt;-&lt;os&gt;-&lt;
<section xml:id="sec-cross-infra"> <section xml:id="sec-cross-infra">
<title>Cross-compilation infrastructure</title> <title>Cross-compilation infrastructure</title>
<para> <section xml:id="ssec-cross-dependency-implementation">
To be written. <title>Implementation of dependencies</title>
</para>
<note>
<para> <para>
If one explores nixpkgs, they will see derivations with names like The categorizes of dependencies developed in
<literal>gccCross</literal>. Such <literal>*Cross</literal> derivations is <xref
a holdover from before we properly distinguished between the host and linkend="ssec-cross-dependency-categorization"/> are specified as
target platforms —the derivation with "Cross" in the name covered the lists of derivations given to <varname>mkDerivation</varname>, as
<literal>build = host != target</literal> case, while the other covered the documented in <xref linkend="ssec-stdenv-dependencies"/>. In short,
<literal>host = target</literal>, with build platform the same or not based each list of dependencies for "host → target" of "foo → bar" is called
on whether one was using its <literal>.nativeDrv</literal> or <varname>depsFooBar</varname>, with exceptions for backwards
<literal>.crossDrv</literal>. This ugliness will disappear soon. compatibility that <varname>depsBuildHost</varname> is instead called
<varname>nativeBuildInputs</varname> and <varname>depsHostTarget</varname>
is instead called <varname>buildInputs</varname>. Nixpkgs is now structured
so that each <varname>depsFooBar</varname> is automatically taken from
<varname>pkgsFooBar</varname>. (These <varname>pkgsFooBar</varname>s are
quite new, so there is no special case for
<varname>nativeBuildInputs</varname> and <varname>buildInputs</varname>.)
For example, <varname>pkgsBuildHost.gcc</varname> should be used at
build-time, while <varname>pkgsHostTarget.gcc</varname> should be used at
run-time.
</para> </para>
</note>
<para>
Now, for most of Nixpkgs's history, there were no
<varname>pkgsFooBar</varname> attributes, and most packages have not been
refactored to use it explicitly. Prior to those, there were just
<varname>buildPackages</varname>, <varname>pkgs</varname>, and
<varname>targetPackages</varname>. Those are now redefined as aliases to
<varname>pkgsBuildHost</varname>, <varname>pkgsHostTarget</varname>, and
<varname>pkgsTargetTarget</varname>. It is acceptable, even
recommended, to use them for libraries to show that the host platform is
irrelevant.
</para>
<para>
But before that, there was just <varname>pkgs</varname>, even though both
<varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>
existed. [Cross barely worked, and those were implemented with some hacks
on <varname>mkDerivation</varname> to override dependencies.] What this
means is the vast majority of packages do not use any explicit package set
to populate their dependencies, just using whatever
<varname>callPackage</varname> gives them even if they do correctly sort
their dependencies into the multiple lists described above. And indeed,
asking that users both sort their dependencies, <emphasis>and</emphasis>
take them from the right attribute set, is both too onerous and redundant,
so the recommended approach (for now) is to continue just categorizing by
list and not using an explicit package set.
</para>
<para>
To make this work, we "splice" together the six
<varname>pkgsFooBar</varname> package sets and have
<varname>callPackage</varname> actually take its arguments from that. This
is currently implemented in <filename>pkgs/top-level/splice.nix</filename>.
<varname>mkDerivation</varname> then, for each dependency attribute, pulls
the right derivation out from the splice. This splicing can be skipped when
not cross-compiling as the package sets are the same, but still is a bit
slow for cross-compiling. We'd like to do something better, but haven't
come up with anything yet.
</para>
</section>
<section xml:id="ssec-bootstrapping">
<title>Bootstrapping</title>
<para>
Each of the package sets described above come from a single bootstrapping
stage. While <filename>pkgs/top-level/default.nix</filename>, coordinates
the composition of stages at a high level,
<filename>pkgs/top-level/stage.nix</filename> "ties the knot" (creates the
fixed point) of each stage. The package sets are defined per-stage however,
so they can be thought of as edges between stages (the nodes) in a graph.
Compositions like <literal>pkgsBuildTarget.targetPackages</literal> can be
thought of as paths to this graph.
</para>
<para>
While there are many package sets, and thus many edges, the stages can also
be arranged in a linear chain. In other words, many of the edges are
redundant as far as connectivity is concerned. This hinges on the type of
bootstrapping we do. Currently for cross it is:
<orderedlist>
<listitem>
<para>
<literal>(native, native, native)</literal>
</para>
</listitem>
<listitem>
<para>
<literal>(native, native, foreign)</literal>
</para>
</listitem>
<listitem>
<para>
<literal>(native, foreign, foreign)</literal>
</para>
</listitem>
</orderedlist>
In each stage, <varname>pkgsBuildHost</varname> refers the the previous
stage, <varname>pkgsBuildBuild</varname> refers to the one before that, and
<varname>pkgsHostTarget</varname> refers to the current one, and
<varname>pkgsTargetTarget</varname> refers to the next one. When there is
no previous or next stage, they instead refer to the current stage. Note
how all the invariants regarding the mapping between dependency and depending
packages' build host and target platforms are preserved.
<varname>pkgsBuildTarget</varname> and <varname>pkgsHostHost</varname> are
more complex in that the stage fitting the requirements isn't always a
fixed chain of "prevs" and "nexts" away (modulo the "saturating"
self-references at the ends). We just special case each instead. All the primary
edges are implemented is in <filename>pkgs/stdenv/booter.nix</filename>,
and secondarily aliases in <filename>pkgs/top-level/stage.nix</filename>.
</para>
<note>
<para>
Note the native stages are bootstrapped in legacy ways that predate the
current cross implementation. This is why the the bootstrapping stages
leading up to the final stages are ignored inthe previous paragraph.
</para>
</note>
<para>
If one looks at the 3 platform triples, one can see that they overlap such
that one could put them together into a chain like:
<programlisting>
(native, native, native, foreign, foreign)
</programlisting>
If one imagines the saturating self references at the end being replaced
with infinite stages, and then overlays those platform triples, one ends up
with the infinite tuple:
<programlisting>
(native..., native, native, native, foreign, foreign, foreign...)
</programlisting>
On can then imagine any sequence of platforms such that there are bootstrap
stages with their 3 platforms determined by "sliding a window" that is the
3 tuple through the sequence. This was the original model for
bootstrapping. Without a target platform (assume a better world where all
compilers are multi-target and all standard libraries are built in their
own derivation), this is sufficient. Conversely if one wishes to cross
compile "faster", with a "Canadian Cross" bootstraping stage where
<literal>build != host != target</literal>, more bootstrapping stages are
needed since no sliding window providess the pesky
<varname>pkgsBuildTarget</varname> package set since it skips the Canadian
cross stage's "host".
</para>
<note>
<para>
It is much better to refer to <varname>buildPackages</varname> than
<varname>targetPackages</varname>, or more broadly package sets that do
not mention "target". There are three reasons for this.
</para>
<para>
First, it is because bootstrapping stages do not have a unique
<varname>targetPackages</varname>. For example a <literal>(x86-linux,
x86-linux, arm-linux)</literal> and <literal>(x86-linux, x86-linux,
x86-windows)</literal> package set both have a <literal>(x86-linux,
x86-linux, x86-linux)</literal> package set. Because there is no canonical
<varname>targetPackages</varname> for such a native (<literal>build ==
host == target</literal>) package set, we set their
<varname>targetPackages</varname>
</para>
<para>
Second, it is because this is a frequent source of hard-to-follow
"infinite recursions" / cycles. When only package sets that don't mention
target are used, the package set forms a directed acyclic graph. This
means that all cycles that exist are confined to one stage. This means
they are a lot smaller, and easier to follow in the code or a backtrace. It
also means they are present in native and cross builds alike, and so more
likely to be caught by CI and other users.
</para>
<para>
Thirdly, it is because everything target-mentioning only exists to
accommodate compilers with lousy build systems that insist on the compiler
itself and standard library being built together. Of course that is bad
because bigger derivations means longer rebuilds. It is also problematic because
it tends to make the standard libraries less like other libraries than
they could be, complicating code and build systems alike. Because of the
other problems, and because of these innate disadvantages, compilers ought
to be packaged another way where possible.
</para>
</note>
<note>
<para>
If one explores Nixpkgs, they will see derivations with names like
<literal>gccCross</literal>. Such <literal>*Cross</literal> derivations is
a holdover from before we properly distinguished between the host and
target platforms—the derivation with "Cross" in the name covered the
<literal>build = host != target</literal> case, while the other covered
the <literal>host = target</literal>, with build platform the same or not
based on whether one was using its <literal>.nativeDrv</literal> or
<literal>.crossDrv</literal>. This ugliness will disappear soon.
</para>
</note>
</section>
</section> </section>
</chapter> </chapter>

View File

@ -1,8 +1,9 @@
{ pkgs ? (import ./.. { }), nixpkgs ? { }}:
let let
pkgs = import ./.. { };
lib = pkgs.lib; lib = pkgs.lib;
in locationsXml = import ./lib-function-locations.nix { inherit pkgs nixpkgs; };
pkgs.stdenv.mkDerivation { functionDocs = import ./lib-function-docs.nix { inherit locationsXml pkgs; };
in pkgs.stdenv.mkDerivation {
name = "nixpkgs-manual"; name = "nixpkgs-manual";
buildInputs = with pkgs; [ pandoc libxml2 libxslt zip jing xmlformat ]; buildInputs = with pkgs; [ pandoc libxml2 libxslt zip jing xmlformat ];
@ -29,6 +30,9 @@ pkgs.stdenv.mkDerivation {
]; ];
postPatch = '' postPatch = ''
rm -rf ./functions/library/locations.xml
ln -s ${locationsXml} ./functions/library/locations.xml
ln -s ${functionDocs} ./functions/library/generated
echo ${lib.version} > .version echo ${lib.version} > .version
''; '';

View File

@ -1,796 +1,22 @@
<chapter xmlns="http://docbook.org/ns/docbook" <chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-functions"> xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="chap-functions">
<title>Functions reference</title> <title>Functions reference</title>
<para> <para>
The nixpkgs repository has several utility functions to manipulate Nix The nixpkgs repository has several utility functions to manipulate Nix
expressions. expressions.
</para> </para>
<section xml:id="sec-overrides"> <xi:include href="functions/library.xml" />
<title>Overriding</title> <xi:include href="functions/overrides.xml" />
<xi:include href="functions/generators.xml" />
<para> <xi:include href="functions/debug.xml" />
Sometimes one wants to override parts of <literal>nixpkgs</literal>, e.g. <xi:include href="functions/fetchers.xml" />
derivation attributes, the results of derivations or even the whole package <xi:include href="functions/trivial-builders.xml" />
set. <xi:include href="functions/fhs-environments.xml" />
</para> <xi:include href="functions/shell.xml" />
<xi:include href="functions/dockertools.xml" />
<section xml:id="sec-pkg-override"> <xi:include href="functions/appimagetools.xml" />
<title>&lt;pkg&gt;.override</title> <xi:include href="functions/prefer-remote-fetch.xml" />
<xi:include href="functions/nix-gitignore.xml" />
<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>import pkgs.path { overlays = [ (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-overrideAttrs">
<title>&lt;pkg&gt;.overrideAttrs</title>
<para>
The function <varname>overrideAttrs</varname> allows overriding the
attribute set passed to a <varname>stdenv.mkDerivation</varname> call,
producing a new derivation based on the original one. This function is
available on all derivations produced by the
<varname>stdenv.mkDerivation</varname> function, which is most packages in
the nixpkgs expression <varname>pkgs</varname>.
</para>
<para>
Example usage:
<programlisting>helloWithDebug = pkgs.hello.overrideAttrs (oldAttrs: rec {
separateDebugInfo = true;
});</programlisting>
</para>
<para>
In the above example, the <varname>separateDebugInfo</varname> attribute is
overridden to be true, thus building debug info for
<varname>helloWithDebug</varname>, while all other attributes will be
retained from the original <varname>hello</varname> package.
</para>
<para>
The argument <varname>oldAttrs</varname> is conventionally used to refer to
the attr set originally passed to <varname>stdenv.mkDerivation</varname>.
</para>
<note>
<para>
Note that <varname>separateDebugInfo</varname> is processed only by the
<varname>stdenv.mkDerivation</varname> function, not the generated, raw
Nix derivation. Thus, using <varname>overrideDerivation</varname> will not
work in this case, as it overrides only the attributes of the final
derivation. It is for this reason that <varname>overrideAttrs</varname>
should be preferred in (almost) all cases to
<varname>overrideDerivation</varname>, i.e. to allow using
<varname>sdenv.mkDerivation</varname> to process input arguments, as well
as the fact that it is easier to use (you can use the same attribute names
you see in your Nix code, instead of the ones generated (e.g.
<varname>buildInputs</varname> vs <varname>nativeBuildInputs</varname>,
and involves less typing.
</para>
</note>
</section>
<section xml:id="sec-pkg-overrideDerivation">
<title>&lt;pkg&gt;.overrideDerivation</title>
<warning>
<para>
You should prefer <varname>overrideAttrs</varname> in almost all cases,
see its documentation for the reasons why.
<varname>overrideDerivation</varname> is not deprecated and will continue
to work, but is less nice to use and does not have as many abilities as
<varname>overrideAttrs</varname>.
</para>
</warning>
<warning>
<para>
Do not use this function in Nixpkgs as it evaluates a Derivation before
modifying it, which breaks package abstraction and removes error-checking
of function arguments. In addition, this evaluation-per-function
application incurs a performance penalty, which can become a problem if
many overrides are used. It is only intended for ad-hoc customisation,
such as in <filename>~/.config/nixpkgs/config.nix</filename>.
</para>
</warning>
<para>
The function <varname>overrideDerivation</varname> creates a new derivation
based on an existing one by overriding the original's attributes with the
attribute set produced by the specified function. This function is
available on all derivations defined using the
<varname>makeOverridable</varname> function. Most standard
derivation-producing functions, such as
<varname>stdenv.mkDerivation</varname>, are defined using this function,
which means most packages in the nixpkgs expression,
<varname>pkgs</varname>, have this 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 <varname>name</varname>, <varname>src</varname>,
and <varname>patches</varname> 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>
<note>
<para>
A package's attributes are evaluated *before* being modified by the
<varname>overrideDerivation</varname> function. For example, the
<varname>name</varname> attribute reference in <varname>url =
"mirror://gnu/hello/${name}.tar.gz";</varname> is filled-in *before* the
<varname>overrideDerivation</varname> function modifies the attribute set.
This means that overriding the <varname>name</varname> attribute, in this
example, *will not* change the value of the <varname>url</varname>
attribute. Instead, we need to override both the <varname>name</varname>
*and* <varname>url</varname> attributes.
</para>
</note>
</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>
<section xml:id="sec-generators">
<title>Generators</title>
<para>
Generators are functions that create file formats from nix data structures,
e.g. for configuration files. There are generators available for:
<literal>INI</literal>, <literal>JSON</literal> and <literal>YAML</literal>
</para>
<para>
All generators follow a similar call interface: <code>generatorName
configFunctions data</code>, where <literal>configFunctions</literal> is an
attrset of user-defined functions that format nested parts of the content.
They each have common defaults, so often they do not need to be set
manually. An example is <code>mkSectionName ? (name: libStr.escape [ "[" "]"
] name)</code> from the <literal>INI</literal> generator. It receives the
name of a section and sanitizes it. The default
<literal>mkSectionName</literal> escapes <literal>[</literal> and
<literal>]</literal> with a backslash.
</para>
<para>
Generators can be fine-tuned to produce exactly the file format required by
your application/service. One example is an INI-file format which uses
<literal>: </literal> as separator, the strings
<literal>"yes"</literal>/<literal>"no"</literal> as boolean values and
requires all string values to be quoted:
</para>
<programlisting>
with lib;
let
customToINI = generators.toINI {
# specifies how to format a key/value pair
mkKeyValue = generators.mkKeyValueDefault {
# specifies the generated string for a subset of nix values
mkValueString = v:
if v == true then ''"yes"''
else if v == false then ''"no"''
else if isString v then ''"${v}"''
# and delegats all other values to the default generator
else generators.mkValueStringDefault {} v;
} ":";
};
# the INI file can now be given as plain old nix values
in customToINI {
main = {
pushinfo = true;
autopush = false;
host = "localhost";
port = 42;
};
mergetool = {
merge = "diff3";
};
}
</programlisting>
<para>
This will produce the following INI file as nix string:
</para>
<programlisting>
[main]
autopush:"no"
host:"localhost"
port:42
pushinfo:"yes"
str\:ange:"very::strange"
[mergetool]
merge:"diff3"
</programlisting>
<note>
<para>
Nix store paths can be converted to strings by enclosing a derivation
attribute like so: <code>"${drv}"</code>.
</para>
</note>
<para>
Detailed documentation for each generator can be found in
<literal>lib/generators.nix</literal>.
</para>
</section>
<section xml:id="sec-debug">
<title>Debugging Nix Expressions</title>
<para>
Nix is a unityped, dynamic language, this means every value can potentially
appear anywhere. Since it is also non-strict, evaluation order and what
ultimately is evaluated might surprise you. Therefore it is important to be
able to debug nix expressions.
</para>
<para>
In the <literal>lib/debug.nix</literal> file you will find a number of
functions that help (pretty-)printing values while evaluation is runnnig.
You can even specify how deep these values should be printed recursively,
and transform them on the fly. Please consult the docstrings in
<literal>lib/debug.nix</literal> for usage information.
</para>
</section>
<section xml:id="sec-fhs-environments">
<title>buildFHSUserEnv</title>
<para>
<function>buildFHSUserEnv</function> provides a way to build and run
FHS-compatible lightweight sandboxes. It creates an isolated root with bound
<filename>/nix/store</filename>, so its 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. It uses Linux namespaces feature to
create temporary lightweight environments which are destroyed after all
child processes exit, without root user rights requirement. Accepted
arguments are:
</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). Along with libraries binaries are also installed.
</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). Only libraries are installed by
default.
</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>extraBuildCommands</literal>, but executed only on multilib
architectures.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraOutputsToInstall</literal>
</term>
<listitem>
<para>
Additional derivation outputs to be linked for both target and
multi-architecture packages.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraInstallCommands</literal>
</term>
<listitem>
<para>
Additional commands to be executed for finalizing the derivation with
runner script.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>runScript</literal>
</term>
<listitem>
<para>
A command that would be executed inside the sandbox and passed all the
command line arguments. It defaults to <literal>bash</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
One can create a simple environment using a <literal>shell.nix</literal>
like that:
</para>
<programlisting><![CDATA[
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSUserEnv {
name = "simple-x11-env";
targetPkgs = pkgs: (with pkgs;
[ udev
alsaLib
]) ++ (with pkgs.xorg;
[ libX11
libXcursor
libXrandr
]);
multiPkgs = pkgs: (with pkgs;
[ udev
alsaLib
]);
runScript = "bash";
}).env
]]></programlisting>
<para>
Running <literal>nix-shell</literal> would then drop you into a shell with
these libraries and binaries available. You can use this to run
closed-source applications which expect FHS structure without hassles:
simply change <literal>runScript</literal> to the application path, e.g.
<filename>./bin/start.sh</filename> -- relative paths are supported.
</para>
</section>
<section xml:id="sec-pkgs-dockerTools">
<title>pkgs.dockerTools</title>
<para>
<varname>pkgs.dockerTools</varname> is a set of functions for creating and
manipulating Docker images according to the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#docker-image-specification-v120">
Docker Image Specification v1.2.0 </link>. Docker itself is not used to
perform any of the operations done by these functions.
</para>
<warning>
<para>
The <varname>dockerTools</varname> API is unstable and may be subject to
backwards-incompatible changes in the future.
</para>
</warning>
<section xml:id="ssec-pkgs-dockerTools-buildImage">
<title>buildImage</title>
<para>
This function is analogous to the <command>docker build</command> command,
in that can used to build a Docker-compatible repository tarball containing
a single image with one or multiple layers. As such, the result is suitable
for being loaded in Docker with <command>docker load</command>.
</para>
<para>
The parameters of <varname>buildImage</varname> with relative example
values are described below:
</para>
<example xml:id='ex-dockerTools-buildImage'>
<title>Docker build</title>
<programlisting>
buildImage {
name = "redis"; <co xml:id='ex-dockerTools-buildImage-1' />
tag = "latest"; <co xml:id='ex-dockerTools-buildImage-2' />
fromImage = someBaseImage; <co xml:id='ex-dockerTools-buildImage-3' />
fromImageName = null; <co xml:id='ex-dockerTools-buildImage-4' />
fromImageTag = "latest"; <co xml:id='ex-dockerTools-buildImage-5' />
contents = pkgs.redis; <co xml:id='ex-dockerTools-buildImage-6' />
runAsRoot = '' <co xml:id='ex-dockerTools-buildImage-runAsRoot' />
#!${stdenv.shell}
mkdir -p /data
'';
config = { <co xml:id='ex-dockerTools-buildImage-8' />
Cmd = [ "/bin/redis-server" ];
WorkingDir = "/data";
Volumes = {
"/data" = {};
};
};
}
</programlisting>
</example>
<para>
The above example will build a Docker image <literal>redis/latest</literal>
from the given base image. Loading and running this image in Docker results
in <literal>redis-server</literal> being started automatically.
</para>
<calloutlist>
<callout arearefs='ex-dockerTools-buildImage-1'>
<para>
<varname>name</varname> specifies the name of the resulting image. This
is the only required argument for <varname>buildImage</varname>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-2'>
<para>
<varname>tag</varname> specifies the tag of the resulting image. By
default it's <literal>null</literal>, which indicates that the nix output hash will be used as tag.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-3'>
<para>
<varname>fromImage</varname> is the repository tarball containing the
base image. It must be a valid Docker image, such as exported by
<command>docker save</command>. By default it's <literal>null</literal>,
which can be seen as equivalent to <literal>FROM scratch</literal> of a
<filename>Dockerfile</filename>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-4'>
<para>
<varname>fromImageName</varname> can be used to further specify the base
image within the repository, in case it contains multiple images. By
default it's <literal>null</literal>, in which case
<varname>buildImage</varname> will peek the first image available in the
repository.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-5'>
<para>
<varname>fromImageTag</varname> can be used to further specify the tag of
the base image within the repository, in case an image contains multiple
tags. By default it's <literal>null</literal>, in which case
<varname>buildImage</varname> will peek the first tag available for the
base image.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-6'>
<para>
<varname>contents</varname> is a derivation that will be copied in the
new layer of the resulting image. This can be similarly seen as
<command>ADD contents/ /</command> in a <filename>Dockerfile</filename>.
By default it's <literal>null</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-runAsRoot'>
<para>
<varname>runAsRoot</varname> is a bash script that will run as root in an
environment that overlays the existing layers of the base image with the
new resulting layer, including the previously copied
<varname>contents</varname> derivation. This can be similarly seen as
<command>RUN ...</command> in a <filename>Dockerfile</filename>.
<note>
<para>
Using this parameter requires the <literal>kvm</literal> device to be
available.
</para>
</note>
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-8'>
<para>
<varname>config</varname> is used to specify the configuration of the
containers that will be started off the built image in Docker. The
available options are listed in the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0 </link>.
</para>
</callout>
</calloutlist>
<para>
After the new layer has been created, its closure (to which
<varname>contents</varname>, <varname>config</varname> and
<varname>runAsRoot</varname> contribute) will be copied in the layer
itself. Only new dependencies that are not already in the existing layers
will be copied.
</para>
<para>
At the end of the process, only one new single layer will be produced and
added to the resulting image.
</para>
<para>
The resulting repository will only list the single image
<varname>image/tag</varname>. In the case of
<xref linkend='ex-dockerTools-buildImage'/> it would be
<varname>redis/latest</varname>.
</para>
<para>
It is possible to inspect the arguments with which an image was built using
its <varname>buildArgs</varname> attribute.
</para>
<note>
<para>
If you see errors similar to <literal>getProtocolByName: does not exist
(no such protocol name: tcp)</literal> you may need to add
<literal>pkgs.iana-etc</literal> to <varname>contents</varname>.
</para>
</note>
<note>
<para>
If you see errors similar to <literal>Error_Protocol ("certificate has
unknown CA",True,UnknownCa)</literal> you may need to add
<literal>pkgs.cacert</literal> to <varname>contents</varname>.
</para>
</note>
</section>
<section xml:id="ssec-pkgs-dockerTools-fetchFromRegistry">
<title>pullImage</title>
<para>
This function is analogous to the <command>docker pull</command> command,
in that can be used to pull a Docker image from a Docker registry. By
default <link xlink:href="https://hub.docker.com/">Docker Hub</link> is
used to pull images.
</para>
<para>
Its parameters are described in the example below:
</para>
<example xml:id='ex-dockerTools-pullImage'>
<title>Docker pull</title>
<programlisting>
pullImage {
imageName = "nixos/nix"; <co xml:id='ex-dockerTools-pullImage-1' />
imageDigest = "sha256:20d9485b25ecfd89204e843a962c1bd70e9cc6858d65d7f5fadc340246e2116b"; <co xml:id='ex-dockerTools-pullImage-2' />
finalImageTag = "1.11"; <co xml:id='ex-dockerTools-pullImage-3' />
sha256 = "0mqjy3zq2v6rrhizgb9nvhczl87lcfphq9601wcprdika2jz7qh8"; <co xml:id='ex-dockerTools-pullImage-4' />
os = "linux"; <co xml:id='ex-dockerTools-pullImage-5' />
arch = "x86_64"; <co xml:id='ex-dockerTools-pullImage-6' />
}
</programlisting>
</example>
<calloutlist>
<callout arearefs='ex-dockerTools-pullImage-1'>
<para>
<varname>imageName</varname> specifies the name of the image to be
downloaded, which can also include the registry namespace (e.g.
<literal>nixos</literal>). This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-2'>
<para>
<varname>imageDigest</varname> specifies the digest of the image to be
downloaded. Skopeo can be used to get the digest of an image, with its
<varname>inspect</varname> subcommand. Since a given <varname>imageName</varname>
may transparently refer to a manifest list of images which support
multiple architectures and/or operating systems, supply the `--override-os`
and `--override-arch` arguments to specify exactly which image you
want. By default it will match the OS and architecture of the host the
command is run on.
<programlisting>
$ nix-shell --packages skopeo jq --command "skopeo --override-os linux --override-arch x86_64 inspect docker://docker.io/nixos/nix:1.11 | jq -r '.Digest'"
sha256:20d9485b25ecfd89204e843a962c1bd70e9cc6858d65d7f5fadc340246e2116b
</programlisting>
This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-3'>
<para>
<varname>finalImageTag</varname>, if specified, this is the tag of the
image to be created. Note it is never used to fetch the image since we
prefer to rely on the immutable digest ID. By default it's
<literal>latest</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-4'>
<para>
<varname>sha256</varname> is the checksum of the whole fetched image.
This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-5'>
<para>
<varname>os</varname>, if specified, is the operating system of the fetched image.
By default it's <literal>linux</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-6'>
<para>
<varname>arch</varname>, if specified, is the cpu architecture of the fetched image.
By default it's <literal>x86_64</literal>.
</para>
</callout>
</calloutlist>
</section>
<section xml:id="ssec-pkgs-dockerTools-exportImage">
<title>exportImage</title>
<para>
This function is analogous to the <command>docker export</command> command,
in that can used to flatten a Docker image that contains multiple layers.
It is in fact the result of the merge of all the layers of the image. As
such, the result is suitable for being imported in Docker with
<command>docker import</command>.
</para>
<note>
<para>
Using this function requires the <literal>kvm</literal> device to be
available.
</para>
</note>
<para>
The parameters of <varname>exportImage</varname> are the following:
</para>
<example xml:id='ex-dockerTools-exportImage'>
<title>Docker export</title>
<programlisting>
exportImage {
fromImage = someLayeredImage;
fromImageName = null;
fromImageTag = null;
name = someLayeredImage.name;
}
</programlisting>
</example>
<para>
The parameters relative to the base image have the same synopsis as
described in <xref linkend='ssec-pkgs-dockerTools-buildImage'/>, except
that <varname>fromImage</varname> is the only required argument in this
case.
</para>
<para>
The <varname>name</varname> argument is the name of the derivation output,
which defaults to <varname>fromImage.name</varname>.
</para>
</section>
<section xml:id="ssec-pkgs-dockerTools-shadowSetup">
<title>shadowSetup</title>
<para>
This constant string is a helper for setting up the base files for managing
users and groups, only if such files don't exist already. It is suitable
for being used in a <varname>runAsRoot</varname>
<xref linkend='ex-dockerTools-buildImage-runAsRoot'/> script for cases like
in the example below:
</para>
<example xml:id='ex-dockerTools-shadowSetup'>
<title>Shadow base files</title>
<programlisting>
buildImage {
name = "shadow-basic";
runAsRoot = ''
#!${stdenv.shell}
${shadowSetup}
groupadd -r redis
useradd -r -g redis redis
mkdir /data
chown redis:redis /data
'';
}
</programlisting>
</example>
<para>
Creating base files like <literal>/etc/passwd</literal> or
<literal>/etc/login.defs</literal> are necessary for shadow-utils to
manipulate users and groups.
</para>
</section>
</section>
</chapter> </chapter>

View File

@ -0,0 +1,118 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-appimageTools">
<title>pkgs.appimageTools</title>
<para>
<varname>pkgs.appimageTools</varname> is a set of functions for extracting
and wrapping <link xlink:href="https://appimage.org/">AppImage</link> files.
They are meant to be used if traditional packaging from source is infeasible,
or it would take too long. To quickly run an AppImage file,
<literal>pkgs.appimage-run</literal> can be used as well.
</para>
<warning>
<para>
The <varname>appimageTools</varname> API is unstable and may be subject to
backwards-incompatible changes in the future.
</para>
</warning>
<section xml:id="ssec-pkgs-appimageTools-formats">
<title>AppImage formats</title>
<para>
There are different formats for AppImages, see
<link xlink:href="https://github.com/AppImage/AppImageSpec/blob/74ad9ca2f94bf864a4a0dac1f369dd4f00bd1c28/draft.md#image-format">the
specification</link> for details.
</para>
<itemizedlist>
<listitem>
<para>
Type 1 images are ISO 9660 files that are also ELF executables.
</para>
</listitem>
<listitem>
<para>
Type 2 images are ELF executables with an appended filesystem.
</para>
</listitem>
</itemizedlist>
<para>
They can be told apart with <command>file -k</command>:
</para>
<screen>
<prompt>$ </prompt>file -k type1.AppImage
type1.AppImage: ELF 64-bit LSB executable, x86-64, version 1 (SYSV) ISO 9660 CD-ROM filesystem data 'AppImage' (Lepton 3.x), scale 0-0,
spot sensor temperature 0.000000, unit celsius, color scheme 0, calibration: offset 0.000000, slope 0.000000, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=d629f6099d2344ad82818172add1d38c5e11bc6d, stripped\012- data
<prompt>$ </prompt>file -k type2.AppImage
type2.AppImage: ELF 64-bit LSB executable, x86-64, version 1 (SYSV) (Lepton 3.x), scale 232-60668, spot sensor temperature -4.187500, color scheme 15, show scale bar, calibration: offset -0.000000, slope 0.000000 (Lepton 2.x), scale 4111-45000, spot sensor temperature 412442.250000, color scheme 3, minimum point enabled, calibration: offset -75402534979642766821519867692934234112.000000, slope 5815371847733706829839455140374904832.000000, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=79dcc4e55a61c293c5e19edbd8d65b202842579f, stripped\012- data
</screen>
<para>
Note how the type 1 AppImage is described as an <literal>ISO 9660 CD-ROM
filesystem</literal>, and the type 2 AppImage is not.
</para>
</section>
<section xml:id="ssec-pkgs-appimageTools-wrapping">
<title>Wrapping</title>
<para>
Depending on the type of AppImage you're wrapping, you'll have to use
<varname>wrapType1</varname> or <varname>wrapType2</varname>.
</para>
<programlisting>
appimageTools.wrapType2 { # or wrapType1
name = "patchwork"; <co xml:id='ex-appimageTools-wrapping-1' />
src = fetchurl { <co xml:id='ex-appimageTools-wrapping-2' />
url = https://github.com/ssbc/patchwork/releases/download/v3.11.4/Patchwork-3.11.4-linux-x86_64.AppImage;
sha256 = "1blsprpkvm0ws9b96gb36f0rbf8f5jgmw4x6dsb1kswr4ysf591s";
};
extraPkgs = pkgs: with pkgs; [ ]; <co xml:id='ex-appimageTools-wrapping-3' />
}</programlisting>
<calloutlist>
<callout arearefs='ex-appimageTools-wrapping-1'>
<para>
<varname>name</varname> specifies the name of the resulting image.
</para>
</callout>
<callout arearefs='ex-appimageTools-wrapping-2'>
<para>
<varname>src</varname> specifies the AppImage file to extract.
</para>
</callout>
<callout arearefs='ex-appimageTools-wrapping-2'>
<para>
<varname>extraPkgs</varname> allows you to pass a function to include
additional packages inside the FHS environment your AppImage is going to
run in. There are a few ways to learn which dependencies an application
needs:
<itemizedlist>
<listitem>
<para>
Looking through the extracted AppImage files, reading its scripts and
running <command>patchelf</command> and <command>ldd</command> on its
executables. This can also be done in <command>appimage-run</command>,
by setting <command>APPIMAGE_DEBUG_EXEC=bash</command>.
</para>
</listitem>
<listitem>
<para>
Running <command>strace -vfefile</command> on the wrapped executable,
looking for libraries that can't be found.
</para>
</listitem>
</itemizedlist>
</para>
</callout>
</calloutlist>
</section>
</section>

21
doc/functions/debug.xml Normal file
View File

@ -0,0 +1,21 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-debug">
<title>Debugging Nix Expressions</title>
<para>
Nix is a unityped, dynamic language, this means every value can potentially
appear anywhere. Since it is also non-strict, evaluation order and what
ultimately is evaluated might surprise you. Therefore it is important to be
able to debug nix expressions.
</para>
<para>
In the <literal>lib/debug.nix</literal> file you will find a number of
functions that help (pretty-)printing values while evaluation is runnnig. You
can even specify how deep these values should be printed recursively, and
transform them on the fly. Please consult the docstrings in
<literal>lib/debug.nix</literal> for usage information.
</para>
</section>

View File

@ -0,0 +1,590 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-dockerTools">
<title>pkgs.dockerTools</title>
<para>
<varname>pkgs.dockerTools</varname> is a set of functions for creating and
manipulating Docker images according to the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#docker-image-specification-v120">
Docker Image Specification v1.2.0 </link>. Docker itself is not used to
perform any of the operations done by these functions.
</para>
<warning>
<para>
The <varname>dockerTools</varname> API is unstable and may be subject to
backwards-incompatible changes in the future.
</para>
</warning>
<section xml:id="ssec-pkgs-dockerTools-buildImage">
<title>buildImage</title>
<para>
This function is analogous to the <command>docker build</command> command,
in that it can be used to build a Docker-compatible repository tarball
containing a single image with one or multiple layers. As such, the result
is suitable for being loaded in Docker with <command>docker load</command>.
</para>
<para>
The parameters of <varname>buildImage</varname> with relative example values
are described below:
</para>
<example xml:id='ex-dockerTools-buildImage'>
<title>Docker build</title>
<programlisting>
buildImage {
name = "redis"; <co xml:id='ex-dockerTools-buildImage-1' />
tag = "latest"; <co xml:id='ex-dockerTools-buildImage-2' />
fromImage = someBaseImage; <co xml:id='ex-dockerTools-buildImage-3' />
fromImageName = null; <co xml:id='ex-dockerTools-buildImage-4' />
fromImageTag = "latest"; <co xml:id='ex-dockerTools-buildImage-5' />
contents = pkgs.redis; <co xml:id='ex-dockerTools-buildImage-6' />
runAsRoot = '' <co xml:id='ex-dockerTools-buildImage-runAsRoot' />
#!${pkgs.runtimeShell}
mkdir -p /data
'';
config = { <co xml:id='ex-dockerTools-buildImage-8' />
Cmd = [ "/bin/redis-server" ];
WorkingDir = "/data";
Volumes = {
"/data" = {};
};
};
}
</programlisting>
</example>
<para>
The above example will build a Docker image <literal>redis/latest</literal>
from the given base image. Loading and running this image in Docker results
in <literal>redis-server</literal> being started automatically.
</para>
<calloutlist>
<callout arearefs='ex-dockerTools-buildImage-1'>
<para>
<varname>name</varname> specifies the name of the resulting image. This is
the only required argument for <varname>buildImage</varname>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-2'>
<para>
<varname>tag</varname> specifies the tag of the resulting image. By
default it's <literal>null</literal>, which indicates that the nix output
hash will be used as tag.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-3'>
<para>
<varname>fromImage</varname> is the repository tarball containing the base
image. It must be a valid Docker image, such as exported by
<command>docker save</command>. By default it's <literal>null</literal>,
which can be seen as equivalent to <literal>FROM scratch</literal> of a
<filename>Dockerfile</filename>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-4'>
<para>
<varname>fromImageName</varname> can be used to further specify the base
image within the repository, in case it contains multiple images. By
default it's <literal>null</literal>, in which case
<varname>buildImage</varname> will peek the first image available in the
repository.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-5'>
<para>
<varname>fromImageTag</varname> can be used to further specify the tag of
the base image within the repository, in case an image contains multiple
tags. By default it's <literal>null</literal>, in which case
<varname>buildImage</varname> will peek the first tag available for the
base image.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-6'>
<para>
<varname>contents</varname> is a derivation that will be copied in the new
layer of the resulting image. This can be similarly seen as <command>ADD
contents/ /</command> in a <filename>Dockerfile</filename>. By default
it's <literal>null</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-runAsRoot'>
<para>
<varname>runAsRoot</varname> is a bash script that will run as root in an
environment that overlays the existing layers of the base image with the
new resulting layer, including the previously copied
<varname>contents</varname> derivation. This can be similarly seen as
<command>RUN ...</command> in a <filename>Dockerfile</filename>.
<note>
<para>
Using this parameter requires the <literal>kvm</literal> device to be
available.
</para>
</note>
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-8'>
<para>
<varname>config</varname> is used to specify the configuration of the
containers that will be started off the built image in Docker. The
available options are listed in the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0 </link>.
</para>
</callout>
</calloutlist>
<para>
After the new layer has been created, its closure (to which
<varname>contents</varname>, <varname>config</varname> and
<varname>runAsRoot</varname> contribute) will be copied in the layer itself.
Only new dependencies that are not already in the existing layers will be
copied.
</para>
<para>
At the end of the process, only one new single layer will be produced and
added to the resulting image.
</para>
<para>
The resulting repository will only list the single image
<varname>image/tag</varname>. In the case of
<xref linkend='ex-dockerTools-buildImage'/> it would be
<varname>redis/latest</varname>.
</para>
<para>
It is possible to inspect the arguments with which an image was built using
its <varname>buildArgs</varname> attribute.
</para>
<note>
<para>
If you see errors similar to <literal>getProtocolByName: does not exist (no
such protocol name: tcp)</literal> you may need to add
<literal>pkgs.iana-etc</literal> to <varname>contents</varname>.
</para>
</note>
<note>
<para>
If you see errors similar to <literal>Error_Protocol ("certificate has
unknown CA",True,UnknownCa)</literal> you may need to add
<literal>pkgs.cacert</literal> to <varname>contents</varname>.
</para>
</note>
<example xml:id="example-pkgs-dockerTools-buildImage-creation-date">
<title>Impurely Defining a Docker Layer's Creation Date</title>
<para>
By default <function>buildImage</function> will use a static date of one
second past the UNIX Epoch. This allows <function>buildImage</function> to
produce binary reproducible images. When listing images with
<command>docker images</command>, the newly created images will be listed
like this:
</para>
<screen><![CDATA[
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest 08c791c7846e 48 years ago 25.2MB
]]></screen>
<para>
You can break binary reproducibility but have a sorted, meaningful
<literal>CREATED</literal> column by setting <literal>created</literal> to
<literal>now</literal>.
</para>
<programlisting><![CDATA[
pkgs.dockerTools.buildImage {
name = "hello";
tag = "latest";
created = "now";
contents = pkgs.hello;
config.Cmd = [ "/bin/hello" ];
}
]]></programlisting>
<para>
and now the Docker CLI will display a reasonable date and sort the images
as expected:
<screen><![CDATA[
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest de2bf4786de6 About a minute ago 25.2MB
]]></screen>
however, the produced images will not be binary reproducible.
</para>
</example>
</section>
<section xml:id="ssec-pkgs-dockerTools-buildLayeredImage">
<title>buildLayeredImage</title>
<para>
Create a Docker image with many of the store paths being on their own layer
to improve sharing between images.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the resulting image.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>tag</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Tag of the generated image.
</para>
<para>
<emphasis>Default:</emphasis> the output path's hash
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>contents</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Top level paths in the container. Either a single derivation, or a list
of derivations.
</para>
<para>
<emphasis>Default:</emphasis> <literal>[]</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>config</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Run-time configuration of the container. A full list of the options are
available at in the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0 </link>.
</para>
<para>
<emphasis>Default:</emphasis> <literal>{}</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>created</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Date and time the layers were created. Follows the same
<literal>now</literal> exception supported by
<literal>buildImage</literal>.
</para>
<para>
<emphasis>Default:</emphasis> <literal>1970-01-01T00:00:01Z</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>maxLayers</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Maximum number of layers to create.
</para>
<para>
<emphasis>Default:</emphasis> <literal>24</literal>
</para>
</listitem>
</varlistentry>
</variablelist>
<section xml:id="dockerTools-buildLayeredImage-arg-contents">
<title>Behavior of <varname>contents</varname> in the final image</title>
<para>
Each path directly listed in <varname>contents</varname> will have a
symlink in the root of the image.
</para>
<para>
For example:
<programlisting><![CDATA[
pkgs.dockerTools.buildLayeredImage {
name = "hello";
contents = [ pkgs.hello ];
}
]]></programlisting>
will create symlinks for all the paths in the <literal>hello</literal>
package:
<screen><![CDATA[
/bin/hello -> /nix/store/h1zb1padqbbb7jicsvkmrym3r6snphxg-hello-2.10/bin/hello
/share/info/hello.info -> /nix/store/h1zb1padqbbb7jicsvkmrym3r6snphxg-hello-2.10/share/info/hello.info
/share/locale/bg/LC_MESSAGES/hello.mo -> /nix/store/h1zb1padqbbb7jicsvkmrym3r6snphxg-hello-2.10/share/locale/bg/LC_MESSAGES/hello.mo
]]></screen>
</para>
</section>
<section xml:id="dockerTools-buildLayeredImage-arg-config">
<title>Automatic inclusion of <varname>config</varname> references</title>
<para>
The closure of <varname>config</varname> is automatically included in the
closure of the final image.
</para>
<para>
This allows you to make very simple Docker images with very little code.
This container will start up and run <command>hello</command>:
<programlisting><![CDATA[
pkgs.dockerTools.buildLayeredImage {
name = "hello";
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
}
]]></programlisting>
</para>
</section>
<section xml:id="dockerTools-buildLayeredImage-arg-maxLayers">
<title>Adjusting <varname>maxLayers</varname></title>
<para>
Increasing the <varname>maxLayers</varname> increases the number of layers
which have a chance to be shared between different images.
</para>
<para>
Modern Docker installations support up to 128 layers, however older
versions support as few as 42.
</para>
<para>
If the produced image will not be extended by other Docker builds, it is
safe to set <varname>maxLayers</varname> to <literal>128</literal>. However
it will be impossible to extend the image further.
</para>
<para>
The first (<literal>maxLayers-2</literal>) most "popular" paths will have
their own individual layers, then layer #<literal>maxLayers-1</literal>
will contain all the remaining "unpopular" paths, and finally layer
#<literal>maxLayers</literal> will contain the Image configuration.
</para>
<para>
Docker's Layers are not inherently ordered, they are content-addressable
and are not explicitly layered until they are composed in to an Image.
</para>
</section>
</section>
<section xml:id="ssec-pkgs-dockerTools-fetchFromRegistry">
<title>pullImage</title>
<para>
This function is analogous to the <command>docker pull</command> command, in
that it can be used to pull a Docker image from a Docker registry. By
default <link xlink:href="https://hub.docker.com/">Docker Hub</link> is used
to pull images.
</para>
<para>
Its parameters are described in the example below:
</para>
<example xml:id='ex-dockerTools-pullImage'>
<title>Docker pull</title>
<programlisting>
pullImage {
imageName = "nixos/nix"; <co xml:id='ex-dockerTools-pullImage-1' />
imageDigest = "sha256:20d9485b25ecfd89204e843a962c1bd70e9cc6858d65d7f5fadc340246e2116b"; <co xml:id='ex-dockerTools-pullImage-2' />
finalImageName = "nix"; <co xml:id='ex-dockerTools-pullImage-3' />
finalImageTag = "1.11"; <co xml:id='ex-dockerTools-pullImage-4' />
sha256 = "0mqjy3zq2v6rrhizgb9nvhczl87lcfphq9601wcprdika2jz7qh8"; <co xml:id='ex-dockerTools-pullImage-5' />
os = "linux"; <co xml:id='ex-dockerTools-pullImage-6' />
arch = "x86_64"; <co xml:id='ex-dockerTools-pullImage-7' />
}
</programlisting>
</example>
<calloutlist>
<callout arearefs='ex-dockerTools-pullImage-1'>
<para>
<varname>imageName</varname> specifies the name of the image to be
downloaded, which can also include the registry namespace (e.g.
<literal>nixos</literal>). This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-2'>
<para>
<varname>imageDigest</varname> specifies the digest of the image to be
downloaded. This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-3'>
<para>
<varname>finalImageName</varname>, if specified, this is the name of the
image to be created. Note it is never used to fetch the image since we
prefer to rely on the immutable digest ID. By default it's equal to
<varname>imageName</varname>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-4'>
<para>
<varname>finalImageTag</varname>, if specified, this is the tag of the
image to be created. Note it is never used to fetch the image since we
prefer to rely on the immutable digest ID. By default it's
<literal>latest</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-5'>
<para>
<varname>sha256</varname> is the checksum of the whole fetched image. This
argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-6'>
<para>
<varname>os</varname>, if specified, is the operating system of the
fetched image. By default it's <literal>linux</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-7'>
<para>
<varname>arch</varname>, if specified, is the cpu architecture of the
fetched image. By default it's <literal>x86_64</literal>.
</para>
</callout>
</calloutlist>
<para>
<literal>nix-prefetch-docker</literal> command can be used to get required
image parameters:
<programlisting>
$ nix run nixpkgs.nix-prefetch-docker -c nix-prefetch-docker --image-name mysql --image-tag 5
</programlisting>
Since a given <varname>imageName</varname> may transparently refer to a
manifest list of images which support multiple architectures and/or
operating systems, you can supply the <option>--os</option> and
<option>--arch</option> arguments to specify exactly which image you want.
By default it will match the OS and architecture of the host the command is
run on.
<programlisting>
$ nix-prefetch-docker --image-name mysql --image-tag 5 --arch x86_64 --os linux
</programlisting>
Desired image name and tag can be set using
<option>--final-image-name</option> and <option>--final-image-tag</option>
arguments:
<programlisting>
$ nix-prefetch-docker --image-name mysql --image-tag 5 --final-image-name eu.gcr.io/my-project/mysql --final-image-tag prod
</programlisting>
</para>
</section>
<section xml:id="ssec-pkgs-dockerTools-exportImage">
<title>exportImage</title>
<para>
This function is analogous to the <command>docker export</command> command,
in that it can be used to flatten a Docker image that contains multiple
layers. It is in fact the result of the merge of all the layers of the
image. As such, the result is suitable for being imported in Docker with
<command>docker import</command>.
</para>
<note>
<para>
Using this function requires the <literal>kvm</literal> device to be
available.
</para>
</note>
<para>
The parameters of <varname>exportImage</varname> are the following:
</para>
<example xml:id='ex-dockerTools-exportImage'>
<title>Docker export</title>
<programlisting>
exportImage {
fromImage = someLayeredImage;
fromImageName = null;
fromImageTag = null;
name = someLayeredImage.name;
}
</programlisting>
</example>
<para>
The parameters relative to the base image have the same synopsis as
described in <xref linkend='ssec-pkgs-dockerTools-buildImage'/>, except that
<varname>fromImage</varname> is the only required argument in this case.
</para>
<para>
The <varname>name</varname> argument is the name of the derivation output,
which defaults to <varname>fromImage.name</varname>.
</para>
</section>
<section xml:id="ssec-pkgs-dockerTools-shadowSetup">
<title>shadowSetup</title>
<para>
This constant string is a helper for setting up the base files for managing
users and groups, only if such files don't exist already. It is suitable for
being used in a <varname>runAsRoot</varname>
<xref linkend='ex-dockerTools-buildImage-runAsRoot'/> script for cases like
in the example below:
</para>
<example xml:id='ex-dockerTools-shadowSetup'>
<title>Shadow base files</title>
<programlisting>
buildImage {
name = "shadow-basic";
runAsRoot = ''
#!${pkgs.runtimeShell}
${shadowSetup}
groupadd -r redis
useradd -r -g redis redis
mkdir /data
chown redis:redis /data
'';
}
</programlisting>
</example>
<para>
Creating base files like <literal>/etc/passwd</literal> or
<literal>/etc/login.defs</literal> is necessary for shadow-utils to
manipulate users and groups.
</para>
</section>
</section>

194
doc/functions/fetchers.xml Normal file
View File

@ -0,0 +1,194 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-fetchers">
<title>Fetcher functions</title>
<para>
When using Nix, you will frequently need to download source code and other
files from the internet. Nixpkgs comes with a few helper functions that allow
you to fetch fixed-output derivations in a structured way.
</para>
<para>
The two fetcher primitives are <function>fetchurl</function> and
<function>fetchzip</function>. Both of these have two required arguments, a
URL and a hash. The hash is typically <literal>sha256</literal>, although
many more hash algorithms are supported. Nixpkgs contributors are currently
recommended to use <literal>sha256</literal>. This hash will be used by Nix
to identify your source. A typical usage of fetchurl is provided below.
</para>
<programlisting><![CDATA[
{ stdenv, fetchurl }:
stdenv.mkDerivation {
name = "hello";
src = fetchurl {
url = "http://www.example.org/hello.tar.gz";
sha256 = "1111111111111111111111111111111111111111111111111111";
};
}
]]></programlisting>
<para>
The main difference between <function>fetchurl</function> and
<function>fetchzip</function> is in how they store the contents.
<function>fetchurl</function> will store the unaltered contents of the URL
within the Nix store. <function>fetchzip</function> on the other hand will
decompress the archive for you, making files and directories directly
accessible in the future. <function>fetchzip</function> can only be used with
archives. Despite the name, <function>fetchzip</function> is not limited to
.zip files and can also be used with any tarball.
</para>
<para>
<function>fetchpatch</function> works very similarly to
<function>fetchurl</function> with the same arguments expected. It expects
patch files as a source and and performs normalization on them before
computing the checksum. For example it will remove comments or other unstable
parts that are sometimes added by version control systems and can change over
time.
</para>
<para>
Other fetcher functions allow you to add source code directly from a VCS such
as subversion or git. These are mostly straightforward names based on the
name of the command used with the VCS system. Because they give you a working
repository, they act most like <function>fetchzip</function>.
</para>
<variablelist>
<varlistentry>
<term>
<literal>fetchsvn</literal>
</term>
<listitem>
<para>
Used with Subversion. Expects <literal>url</literal> to a Subversion
directory, <literal>rev</literal>, and <literal>sha256</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchgit</literal>
</term>
<listitem>
<para>
Used with Git. Expects <literal>url</literal> to a Git repo,
<literal>rev</literal>, and <literal>sha256</literal>.
<literal>rev</literal> in this case can be full the git commit id (SHA1
hash) or a tag name like <literal>refs/tags/v1.0</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchfossil</literal>
</term>
<listitem>
<para>
Used with Fossil. Expects <literal>url</literal> to a Fossil archive,
<literal>rev</literal>, and <literal>sha256</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchcvs</literal>
</term>
<listitem>
<para>
Used with CVS. Expects <literal>cvsRoot</literal>, <literal>tag</literal>,
and <literal>sha256</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchhg</literal>
</term>
<listitem>
<para>
Used with Mercurial. Expects <literal>url</literal>,
<literal>rev</literal>, and <literal>sha256</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
A number of fetcher functions wrap part of <function>fetchurl</function> and
<function>fetchzip</function>. They are mainly convenience functions intended
for commonly used destinations of source code in Nixpkgs. These wrapper
fetchers are listed below.
</para>
<variablelist>
<varlistentry>
<term>
<literal>fetchFromGitHub</literal>
</term>
<listitem>
<para>
<function>fetchFromGitHub</function> expects four arguments.
<literal>owner</literal> is a string corresponding to the GitHub user or
organization that controls this repository. <literal>repo</literal>
corresponds to the name of the software repository. These are located at
the top of every GitHub HTML page as
<literal>owner</literal>/<literal>repo</literal>. <literal>rev</literal>
corresponds to the Git commit hash or tag (e.g <literal>v1.0</literal>)
that will be downloaded from Git. Finally, <literal>sha256</literal>
corresponds to the hash of the extracted directory. Again, other hash
algorithms are also available but <literal>sha256</literal> is currently
preferred.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchFromGitLab</literal>
</term>
<listitem>
<para>
This is used with GitLab repositories. The arguments expected are very
similar to fetchFromGitHub above.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchFromBitbucket</literal>
</term>
<listitem>
<para>
This is used with BitBucket repositories. The arguments expected are very
similar to fetchFromGitHub above.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchFromSavannah</literal>
</term>
<listitem>
<para>
This is used with Savannah repositories. The arguments expected are very
similar to fetchFromGitHub above.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>fetchFromRepoOrCz</literal>
</term>
<listitem>
<para>
This is used with repo.or.cz repositories. The arguments expected are very
similar to fetchFromGitHub above.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>

View File

@ -0,0 +1,142 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-fhs-environments">
<title>buildFHSUserEnv</title>
<para>
<function>buildFHSUserEnv</function> provides a way to build and run
FHS-compatible lightweight sandboxes. It creates an isolated root with bound
<filename>/nix/store</filename>, so its 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. It uses Linux namespaces feature to create
temporary lightweight environments which are destroyed after all child
processes exit, without root user rights requirement. Accepted arguments are:
</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). Along with libraries binaries are also installed.
</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). Only libraries are installed by
default.
</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>extraBuildCommands</literal>, but executed only on multilib
architectures.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraOutputsToInstall</literal>
</term>
<listitem>
<para>
Additional derivation outputs to be linked for both target and
multi-architecture packages.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraInstallCommands</literal>
</term>
<listitem>
<para>
Additional commands to be executed for finalizing the derivation with
runner script.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>runScript</literal>
</term>
<listitem>
<para>
A command that would be executed inside the sandbox and passed all the
command line arguments. It defaults to <literal>bash</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
One can create a simple environment using a <literal>shell.nix</literal> like
that:
</para>
<programlisting><![CDATA[
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSUserEnv {
name = "simple-x11-env";
targetPkgs = pkgs: (with pkgs;
[ udev
alsaLib
]) ++ (with pkgs.xorg;
[ libX11
libXcursor
libXrandr
]);
multiPkgs = pkgs: (with pkgs;
[ udev
alsaLib
]);
runScript = "bash";
}).env
]]></programlisting>
<para>
Running <literal>nix-shell</literal> would then drop you into a shell with
these libraries and binaries available. You can use this to run closed-source
applications which expect FHS structure without hassles: simply change
<literal>runScript</literal> to the application path, e.g.
<filename>./bin/start.sh</filename> -- relative paths are supported.
</para>
</section>

View File

@ -0,0 +1,89 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-generators">
<title>Generators</title>
<para>
Generators are functions that create file formats from nix data structures,
e.g. for configuration files. There are generators available for:
<literal>INI</literal>, <literal>JSON</literal> and <literal>YAML</literal>
</para>
<para>
All generators follow a similar call interface: <code>generatorName
configFunctions data</code>, where <literal>configFunctions</literal> is an
attrset of user-defined functions that format nested parts of the content.
They each have common defaults, so often they do not need to be set manually.
An example is <code>mkSectionName ? (name: libStr.escape [ "[" "]" ]
name)</code> from the <literal>INI</literal> generator. It receives the name
of a section and sanitizes it. The default <literal>mkSectionName</literal>
escapes <literal>[</literal> and <literal>]</literal> with a backslash.
</para>
<para>
Generators can be fine-tuned to produce exactly the file format required by
your application/service. One example is an INI-file format which uses
<literal>: </literal> as separator, the strings
<literal>"yes"</literal>/<literal>"no"</literal> as boolean values and
requires all string values to be quoted:
</para>
<programlisting>
with lib;
let
customToINI = generators.toINI {
# specifies how to format a key/value pair
mkKeyValue = generators.mkKeyValueDefault {
# specifies the generated string for a subset of nix values
mkValueString = v:
if v == true then ''"yes"''
else if v == false then ''"no"''
else if isString v then ''"${v}"''
# and delegats all other values to the default generator
else generators.mkValueStringDefault {} v;
} ":";
};
# the INI file can now be given as plain old nix values
in customToINI {
main = {
pushinfo = true;
autopush = false;
host = "localhost";
port = 42;
};
mergetool = {
merge = "diff3";
};
}
</programlisting>
<para>
This will produce the following INI file as nix string:
</para>
<programlisting>
[main]
autopush:"no"
host:"localhost"
port:42
pushinfo:"yes"
str\:ange:"very::strange"
[mergetool]
merge:"diff3"
</programlisting>
<note>
<para>
Nix store paths can be converted to strings by enclosing a derivation
attribute like so: <code>"${drv}"</code>.
</para>
</note>
<para>
Detailed documentation for each generator can be found in
<literal>lib/generators.nix</literal>.
</para>
</section>

29
doc/functions/library.xml Normal file
View File

@ -0,0 +1,29 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-functions-library">
<title>Nixpkgs Library Functions</title>
<para>
Nixpkgs provides a standard library at <varname>pkgs.lib</varname>, or
through <code>import &lt;nixpkgs/lib&gt;</code>.
</para>
<xi:include href="./library/asserts.xml" />
<xi:include href="./library/attrsets.xml" />
<!-- These docs are generated via nixdoc. To add another generated
library function file to this list, the file
`lib-function-docs.nix` must also be updated. -->
<xi:include href="./library/generated/strings.xml" />
<xi:include href="./library/generated/trivial.xml" />
<xi:include href="./library/generated/lists.xml" />
<xi:include href="./library/generated/debug.xml" />
<xi:include href="./library/generated/options.xml" />
</section>

View File

@ -0,0 +1,117 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-functions-library-asserts">
<title>Assert functions</title>
<section xml:id="function-library-lib.asserts.assertMsg">
<title><function>lib.asserts.assertMsg</function></title>
<subtitle><literal>assertMsg :: Bool -> String -> Bool</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.asserts.assertMsg" />
<para>
Print a trace message if <literal>pred</literal> is false.
</para>
<para>
Intended to be used to augment asserts with helpful error messages.
</para>
<variablelist>
<varlistentry>
<term>
<varname>pred</varname>
</term>
<listitem>
<para>
Condition under which the <varname>msg</varname> should
<emphasis>not</emphasis> be printed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>msg</varname>
</term>
<listitem>
<para>
Message to print.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.asserts.assertMsg-example-false">
<title>Printing when the predicate is false</title>
<programlisting><![CDATA[
assert lib.asserts.assertMsg ("foo" == "bar") "foo is not bar, silly"
stderr> trace: foo is not bar, silly
stderr> assert failed
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.asserts.assertOneOf">
<title><function>lib.asserts.assertOneOf</function></title>
<subtitle><literal>assertOneOf :: String -> String ->
StringList -> Bool</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.asserts.assertOneOf" />
<para>
Specialized <function>asserts.assertMsg</function> for checking if
<varname>val</varname> is one of the elements of <varname>xs</varname>.
Useful for checking enums.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the variable the user entered <varname>val</varname> into,
for inclusion in the error message.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>val</varname>
</term>
<listitem>
<para>
The value of what the user provided, to be compared against the values in
<varname>xs</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>xs</varname>
</term>
<listitem>
<para>
The list of valid values.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.asserts.assertOneOf-example">
<title>Ensuring a user provided a possible value</title>
<programlisting><![CDATA[
let sslLibrary = "bearssl";
in lib.asserts.assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ];
=> false
stderr> trace: sslLibrary must be one of "openssl", "libressl", but is: "bearssl"
]]></programlisting>
</example>
</section>
</section>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-nix-gitignore">
<title>pkgs.nix-gitignore</title>
<para>
<function>pkgs.nix-gitignore</function> is a function that acts similarly to
<literal>builtins.filterSource</literal> but also allows filtering with the
help of the gitignore format.
</para>
<section xml:id="sec-pkgs-nix-gitignore-usage">
<title>Usage</title>
<para>
<literal>pkgs.nix-gitignore</literal> exports a number of functions, but
you'll most likely need either <literal>gitignoreSource</literal> or
<literal>gitignoreSourcePure</literal>. As their first argument, they both
accept either 1. a file with gitignore lines or 2. a string with gitignore
lines, or 3. a list of either of the two. They will be concatenated into a
single big string.
</para>
<programlisting><![CDATA[
{ pkgs ? import <nixpkgs> {} }:
nix-gitignore.gitignoreSource [] ./source
# Simplest version
nix-gitignore.gitignoreSource "supplemental-ignores\n" ./source
# This one reads the ./source/.gitignore and concats the auxiliary ignores
nix-gitignore.gitignoreSourcePure "ignore-this\nignore-that\n" ./source
# Use this string as gitignore, don't read ./source/.gitignore.
nix-gitignore.gitignoreSourcePure ["ignore-this\nignore-that\n", ~/.gitignore] ./source
# It also accepts a list (of strings and paths) that will be concatenated
# once the paths are turned to strings via readFile.
]]></programlisting>
<para>
These functions are derived from the <literal>Filter</literal> functions by
setting the first filter argument to <literal>(_: _: true)</literal>:
</para>
<programlisting><![CDATA[
gitignoreSourcePure = gitignoreFilterSourcePure (_: _: true);
gitignoreSource = gitignoreFilterSource (_: _: true);
]]></programlisting>
<para>
Those filter functions accept the same arguments the
<literal>builtins.filterSource</literal> function would pass to its filters,
thus <literal>fn: gitignoreFilterSourcePure fn ""</literal> should be
extensionally equivalent to <literal>filterSource</literal>. The file is
blacklisted iff it's blacklisted by either your filter or the
gitignoreFilter.
</para>
<para>
If you want to make your own filter from scratch, you may use
</para>
<programlisting><![CDATA[
gitignoreFilter = ign: root: filterPattern (gitignoreToPatterns ign) root;
]]></programlisting>
</section>
<section xml:id="sec-pkgs-nix-gitignore-usage-recursive">
<title>gitignore files in subdirectories</title>
<para>
If you wish to use a filter that would search for .gitignore files in
subdirectories, just like git does by default, use this function:
</para>
<programlisting><![CDATA[
gitignoreFilterRecursiveSource = filter: patterns: root:
# OR
gitignoreRecursiveSource = gitignoreFilterSourcePure (_: _: true);
]]></programlisting>
</section>
</section>

212
doc/functions/overrides.xml Normal file
View File

@ -0,0 +1,212 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-overrides">
<title>Overriding</title>
<para>
Sometimes one wants to override parts of <literal>nixpkgs</literal>, e.g.
derivation attributes, the results of derivations.
</para>
<para>
These functions are used to make changes to packages, returning only single
packages. <link xlink:href="#chap-overlays">Overlays</link>, on the other
hand, can be used to combine the overridden packages across the entire
package set of Nixpkgs.
</para>
<section xml:id="sec-pkg-override">
<title>&lt;pkg&gt;.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>
<!-- TODO: move below programlisting to a new section about extending and overlays
and reference it
-->
<programlisting>
import pkgs.path { overlays = [ (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-overrideAttrs">
<title>&lt;pkg&gt;.overrideAttrs</title>
<para>
The function <varname>overrideAttrs</varname> allows overriding the
attribute set passed to a <varname>stdenv.mkDerivation</varname> call,
producing a new derivation based on the original one. This function is
available on all derivations produced by the
<varname>stdenv.mkDerivation</varname> function, which is most packages in
the nixpkgs expression <varname>pkgs</varname>.
</para>
<para>
Example usage:
<programlisting>
helloWithDebug = pkgs.hello.overrideAttrs (oldAttrs: rec {
separateDebugInfo = true;
});
</programlisting>
</para>
<para>
In the above example, the <varname>separateDebugInfo</varname> attribute is
overridden to be true, thus building debug info for
<varname>helloWithDebug</varname>, while all other attributes will be
retained from the original <varname>hello</varname> package.
</para>
<para>
The argument <varname>oldAttrs</varname> is conventionally used to refer to
the attr set originally passed to <varname>stdenv.mkDerivation</varname>.
</para>
<note>
<para>
Note that <varname>separateDebugInfo</varname> is processed only by the
<varname>stdenv.mkDerivation</varname> function, not the generated, raw Nix
derivation. Thus, using <varname>overrideDerivation</varname> will not work
in this case, as it overrides only the attributes of the final derivation.
It is for this reason that <varname>overrideAttrs</varname> should be
preferred in (almost) all cases to <varname>overrideDerivation</varname>,
i.e. to allow using <varname>stdenv.mkDerivation</varname> to process input
arguments, as well as the fact that it is easier to use (you can use the
same attribute names you see in your Nix code, instead of the ones
generated (e.g. <varname>buildInputs</varname> vs
<varname>nativeBuildInputs</varname>), and it involves less typing).
</para>
</note>
</section>
<section xml:id="sec-pkg-overrideDerivation">
<title>&lt;pkg&gt;.overrideDerivation</title>
<warning>
<para>
You should prefer <varname>overrideAttrs</varname> in almost all cases, see
its documentation for the reasons why.
<varname>overrideDerivation</varname> is not deprecated and will continue
to work, but is less nice to use and does not have as many abilities as
<varname>overrideAttrs</varname>.
</para>
</warning>
<warning>
<para>
Do not use this function in Nixpkgs as it evaluates a Derivation before
modifying it, which breaks package abstraction and removes error-checking
of function arguments. In addition, this evaluation-per-function
application incurs a performance penalty, which can become a problem if
many overrides are used. It is only intended for ad-hoc customisation, such
as in <filename>~/.config/nixpkgs/config.nix</filename>.
</para>
</warning>
<para>
The function <varname>overrideDerivation</varname> creates a new derivation
based on an existing one by overriding the original's attributes with the
attribute set produced by the specified function. This function is available
on all derivations defined using the <varname>makeOverridable</varname>
function. Most standard derivation-producing functions, such as
<varname>stdenv.mkDerivation</varname>, are defined using this function,
which means most packages in the nixpkgs expression,
<varname>pkgs</varname>, have this 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 <varname>name</varname>, <varname>src</varname>,
and <varname>patches</varname> 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>
<note>
<para>
A package's attributes are evaluated *before* being modified by the
<varname>overrideDerivation</varname> function. For example, the
<varname>name</varname> attribute reference in <varname>url =
"mirror://gnu/hello/${name}.tar.gz";</varname> is filled-in *before* the
<varname>overrideDerivation</varname> function modifies the attribute set.
This means that overriding the <varname>name</varname> attribute, in this
example, *will not* change the value of the <varname>url</varname>
attribute. Instead, we need to override both the <varname>name</varname>
*and* <varname>url</varname> attributes.
</para>
</note>
</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>

View File

@ -0,0 +1,25 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/xinclude"
xml:id="sec-prefer-remote-fetch">
<title>prefer-remote-fetch overlay</title>
<para>
<function>prefer-remote-fetch</function> is an overlay that download sources
on remote builder. This is useful when the evaluating machine has a slow
upload while the builder can fetch faster directly from the source. To use
it, put the following snippet as a new overlay:
<programlisting>
self: super:
(super.prefer-remote-fetch self super)
</programlisting>
A full configuration example for that sets the overlay up for your own
account, could look like this
<programlisting>
$ mkdir ~/.config/nixpkgs/overlays/
$ cat &gt; ~/.config/nixpkgs/overlays/prefer-remote-fetch.nix &lt;&lt;EOF
self: super: super.prefer-remote-fetch self super
EOF
</programlisting>
</para>
</section>

26
doc/functions/shell.xml Normal file
View File

@ -0,0 +1,26 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-mkShell">
<title>pkgs.mkShell</title>
<para>
<function>pkgs.mkShell</function> is a special kind of derivation that is
only useful when using it combined with <command>nix-shell</command>. It will
in fact fail to instantiate when invoked with <command>nix-build</command>.
</para>
<section xml:id="sec-pkgs-mkShell-usage">
<title>Usage</title>
<programlisting><![CDATA[
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar
# available to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
]]></programlisting>
</section>
</section>

View File

@ -0,0 +1,113 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-trivial-builders">
<title>Trivial builders</title>
<para>
Nixpkgs provides a couple of functions that help with building derivations.
The most important one, <function>stdenv.mkDerivation</function>, has already
been documented above. The following functions wrap
<function>stdenv.mkDerivation</function>, making it easier to use in certain
cases.
</para>
<variablelist>
<varlistentry>
<term>
<literal>runCommand</literal>
</term>
<listitem>
<para>
This takes three arguments, <literal>name</literal>,
<literal>env</literal>, and <literal>buildCommand</literal>.
<literal>name</literal> is just the name that Nix will append to the store
path in the same way that <literal>stdenv.mkDerivation</literal> uses its
<literal>name</literal> attribute. <literal>env</literal> is an attribute
set specifying environment variables that will be set for this derivation.
These attributes are then passed to the wrapped
<literal>stdenv.mkDerivation</literal>. <literal>buildCommand</literal>
specifies the commands that will be run to create this derivation. Note
that you will need to create <literal>$out</literal> for Nix to register
the command as successful.
</para>
<para>
An example of using <literal>runCommand</literal> is provided below.
</para>
<programlisting>
(import &lt;nixpkgs&gt; {}).runCommand "my-example" {} ''
echo My example command is running
mkdir $out
echo I can write data to the Nix store > $out/message
echo I can also run basic commands like:
echo ls
ls
echo whoami
whoami
echo date
date
''
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>runCommandCC</literal>
</term>
<listitem>
<para>
This works just like <literal>runCommand</literal>. The only difference is
that it also provides a C compiler in <literal>buildCommand</literal>s
environment. To minimize your dependencies, you should only use this if
you are sure you will need a C compiler as part of running your command.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>writeTextFile</literal>, <literal>writeText</literal>, <literal>writeTextDir</literal>, <literal>writeScript</literal>, <literal>writeScriptBin</literal>
</term>
<listitem>
<para>
These functions write <literal>text</literal> to the Nix store. This is
useful for creating scripts from Nix expressions.
<literal>writeTextFile</literal> takes an attribute set and expects two
arguments, <literal>name</literal> and <literal>text</literal>.
<literal>name</literal> corresponds to the name used in the Nix store
path. <literal>text</literal> will be the contents of the file. You can
also set <literal>executable</literal> to true to make this file have the
executable bit set.
</para>
<para>
Many more commands wrap <literal>writeTextFile</literal> including
<literal>writeText</literal>, <literal>writeTextDir</literal>,
<literal>writeScript</literal>, and <literal>writeScriptBin</literal>.
These are convenience functions over <literal>writeTextFile</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>symlinkJoin</literal>
</term>
<listitem>
<para>
This can be used to put many derivations into the same directory
structure. It works by creating a new derivation and adding symlinks to
each of the paths listed. It expects two arguments,
<literal>name</literal>, and <literal>paths</literal>.
<literal>name</literal> is the name used in the Nix store path for the
created derivation. <literal>paths</literal> is a list of paths that will
be symlinked. These paths can be to Nix store derivations or any other
subdirectory contained within.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>

View File

@ -0,0 +1,240 @@
---
title: Android
author: Sander van der Burg
date: 2018-11-18
---
# Android
The Android build environment provides three major features and a number of
supporting features.
Deploying an Android SDK installation with plugins
--------------------------------------------------
The first use case is deploying the SDK with a desired set of plugins or subsets
of an SDK.
```nix
with import <nixpkgs> {};
let
androidComposition = androidenv.composeAndroidPackages {
toolsVersion = "25.2.5";
platformToolsVersion = "27.0.1";
buildToolsVersions = [ "27.0.3" ];
includeEmulator = false;
emulatorVersion = "27.2.0";
platformVersions = [ "24" ];
includeSources = false;
includeDocs = false;
includeSystemImages = false;
systemImageTypes = [ "default" ];
abiVersions = [ "armeabi-v7a" ];
lldbVersions = [ "2.0.2558144" ];
cmakeVersions = [ "3.6.4111459" ];
includeNDK = false;
ndkVersion = "16.1.4479499";
useGoogleAPIs = false;
useGoogleTVAddOns = false;
includeExtras = [
"extras;google;gcm"
];
};
in
androidComposition.androidsdk
```
The above function invocation states that we want an Android SDK with the above
specified plugin versions. By default, most plugins are disabled. Notable
exceptions are the tools, platform-tools and build-tools sub packages.
The following parameters are supported:
* `toolsVersion`, specifies the version of the tools package to use
* `platformsToolsVersion` specifies the version of the `platform-tools` plugin
* `buildToolsVersion` specifies the versions of the `build-tools` plugins to
use.
* `includeEmulator` specifies whether to deploy the emulator package (`false`
by default). When enabled, the version of the emulator to deploy can be
specified by setting the `emulatorVersion` parameter.
* `includeDocs` specifies whether the documentation catalog should be included.
* `lldbVersions` specifies what LLDB versions should be deployed.
* `cmakeVersions` specifies which CMake versions should be deployed.
* `includeNDK` specifies that the Android NDK bundle should be included.
Defaults to: `false`.
* `ndkVersion` specifies the NDK version that we want to use.
* `includeExtras` is an array of identifier strings referring to arbitrary
add-on packages that should be installed.
* `platformVersions` specifies which platform SDK versions should be included.
For each platform version that has been specified, we can apply the following
options:
* `includeSystemImages` specifies whether a system image for each platform SDK
should be included.
* `includeSources` specifies whether the sources for each SDK version should be
included.
* `useGoogleAPIs` specifies that for each selected platform version the
Google API should be included.
* `useGoogleTVAddOns` specifies that for each selected platform version the
Google TV add-on should be included.
For each requested system image we can specify the following options:
* `systemImageTypes` specifies what kind of system images should be included.
Defaults to: `default`.
* `abiVersions` specifies what kind of ABI version of each system image should
be included. Defaults to: `armeabi-v7a`.
Most of the function arguments have reasonable default settings.
When building the above expression with:
```bash
$ nix-build
```
The Android SDK gets deployed with all desired plugin versions.
We can also deploy subsets of the Android SDK. For example, to only the the
`platform-tools` package, you can evaluate the following expression:
```nix
with import <nixpkgs> {};
let
androidComposition = androidenv.composeAndroidPackages {
# ...
};
in
androidComposition.platform-tools
```
Using predefine Android package compositions
--------------------------------------------
In addition to composing an Android package set manually, it is also possible
to use a predefined composition that contains all basic packages for a specific
Android version, such as version 9.0 (API-level 28).
The following Nix expression can be used to deploy the entire SDK with all basic
plugins:
```nix
with import <nixpkgs> {};
androidenv.androidPkgs_9_0.androidsdk
```
It is also possible to use one plugin only:
```nix
with import <nixpkgs> {};
androidenv.androidPkgs_9_0.platform-tools
```
Building an Android application
-------------------------------
In addition to the SDK, it is also possible to build an Ant-based Android
project and automatically deploy all the Android plugins that a project
requires.
```nix
with import <nixpkgs> {};
androidenv.buildApp {
name = "MyAndroidApp";
src = ./myappsources;
release = true;
# If release is set to true, you need to specify the following parameters
keyStore = ./keystore;
keyAlias = "myfirstapp";
keyStorePassword = "mykeystore";
keyAliasPassword = "myfirstapp";
# Any Android SDK parameters that install all the relevant plugins that a
# build requires
platformVersions = [ "24" ];
# When we include the NDK, then ndk-build is invoked before Ant gets invoked
includeNDK = true;
}
```
Aside from the app-specific build parameters (`name`, `src`, `release` and
keystore parameters), the `buildApp {}` function supports all the function
parameters that the SDK composition function (the function shown in the
previous section) supports.
This build function is particularly useful when it is desired to use
[Hydra](http://nixos.org/hydra): the Nix-based continuous integration solution
to build Android apps. An Android APK gets exposed as a build product and can be
installed on any Android device with a web browser by navigating to the build
result page.
Spawning emulator instances
---------------------------
For testing purposes, it can also be quite convenient to automatically generate
scripts that spawn emulator instances with all desired configuration settings.
An emulator spawn script can be configured by invoking the `emulateApp {}`
function:
```nix
with import <nixpkgs> {};
androidenv.emulateApp {
name = "emulate-MyAndroidApp";
platformVersion = "24";
abiVersion = "armeabi-v7a"; # mips, x86 or x86_64
systemImageType = "default";
useGoogleAPIs = false;
}
```
It is also possible to specify an APK to deploy inside the emulator
and the package and activity names to launch it:
```nix
with import <nixpkgs> {};
androidenv.emulateApp {
name = "emulate-MyAndroidApp";
platformVersion = "24";
abiVersion = "armeabi-v7a"; # mips, x86 or x86_64
systemImageType = "default";
useGoogleAPIs = false;
app = ./MyApp.apk;
package = "MyApp";
activity = "MainActivity";
}
```
In addition to prebuilt APKs, you can also bind the APK parameter to a
`buildApp {}` function invocation shown in the previous example.
Querying the available versions of each plugin
----------------------------------------------
When using any of the previously shown functions, it may be a bit inconvenient
to find out what options are supported, since the Android SDK provides many
plugins.
A shell script in the `pkgs/development/mobile/androidenv/` sub directory can be used to retrieve all
possible options:
```bash
sh ./querypackages.sh packages build-tools
```
The above command-line instruction queries all build-tools versions in the
generated `packages.nix` expression.
Updating the generated expressions
----------------------------------
Most of the Nix expressions are generated from XML files that the Android
package manager uses. To update the expressions run the `generate.sh` script
that is stored in the `pkgs/development/mobile/androidenv/` sub directory:
```bash
sh ./generate.sh
```

View File

@ -11,10 +11,9 @@
</para> </para>
<para> <para>
Some libraries require OCaml and sometimes also Camlp5 or findlib. The exact Some extensions (plugins) might require OCaml and sometimes other OCaml
versions that were used to build Coq are saved in the packages. The <literal>coq.ocamlPackages</literal> attribute can be used to
<literal>coq.ocaml</literal> and <literal>coq.camlp5</literal> and depend on the same package set Coq was built against.
<literal>coq.findlib</literal> attributes.
</para> </para>
<para> <para>

View File

@ -3,12 +3,91 @@
xml:id="sec-language-go"> xml:id="sec-language-go">
<title>Go</title> <title>Go</title>
<para> <section xml:id="ssec-go-modules">
The function <varname>buildGoPackage</varname> builds standard Go programs. <title>Go modules</title>
</para>
<example xml:id='ex-buildGoPackage'> <para>
<title>buildGoPackage</title> The function <varname> buildGoModule </varname> builds Go programs managed
with Go modules. It builds a
<link xlink:href="https://github.com/golang/go/wiki/Modules">Go
modules</link> through a two phase build:
<itemizedlist>
<listitem>
<para>
An intermediate fetcher derivation. This derivation will be used to fetch
all of the dependencies of the Go module.
</para>
</listitem>
<listitem>
<para>
A final derivation will use the output of the intermediate derivation to
build the binaries and produce the final output.
</para>
</listitem>
</itemizedlist>
</para>
<example xml:id='ex-buildGoModule'>
<title>buildGoModule</title>
<programlisting>
pet = buildGoModule rec {
name = "pet-${version}";
version = "0.3.4";
src = fetchFromGitHub {
owner = "knqyf263";
repo = "pet";
rev = "v${version}";
sha256 = "0m2fzpqxk7hrbxsgqplkg7h2p7gv6s1miymv3gvw0cz039skag0s";
};
modSha256 = "1879j77k96684wi554rkjxydrj8g3hpp0kvxz03sd8dmwr3lh83j"; <co xml:id='ex-buildGoModule-1' />
subPackages = [ "." ]; <co xml:id='ex-buildGoModule-2' />
meta = with lib; {
description = "Simple command-line snippet manager, written in Go";
homepage = https://github.com/knqyf263/pet;
license = licenses.mit;
maintainers = with maintainers; [ kalbasit ];
platforms = platforms.linux ++ platforms.darwin;
};
}
</programlisting>
</example>
<para>
<xref linkend='ex-buildGoModule'/> is an example expression using
buildGoModule, the following arguments are of special significance to the
function:
<calloutlist>
<callout arearefs='ex-buildGoModule-1'>
<para>
<varname>modSha256</varname> is the hash of the output of the
intermediate fetcher derivation.
</para>
</callout>
<callout arearefs='ex-buildGoModule-2'>
<para>
<varname>subPackages</varname> limits the builder from building child
packages that have not been listed. If <varname>subPackages</varname> is
not specified, all child packages will be built.
</para>
</callout>
</calloutlist>
</para>
</section>
<section xml:id="ssec-go-legacy">
<title>Go legacy</title>
<para>
The function <varname> buildGoPackage </varname> builds legacy Go programs,
not supporting Go modules.
</para>
<example xml:id='ex-buildGoPackage'>
<title>buildGoPackage</title>
<programlisting> <programlisting>
deis = buildGoPackage rec { deis = buildGoPackage rec {
name = "deis-${version}"; name = "deis-${version}";
@ -29,56 +108,56 @@ deis = buildGoPackage rec {
buildFlags = "--tags release"; <co xml:id='ex-buildGoPackage-4' /> buildFlags = "--tags release"; <co xml:id='ex-buildGoPackage-4' />
} }
</programlisting> </programlisting>
</example> </example>
<para> <para>
<xref linkend='ex-buildGoPackage'/> is an example expression using <xref linkend='ex-buildGoPackage'/> is an example expression using
buildGoPackage, the following arguments are of special significance to the buildGoPackage, the following arguments are of special significance to the
function: function:
<calloutlist> <calloutlist>
<callout arearefs='ex-buildGoPackage-1'> <callout arearefs='ex-buildGoPackage-1'>
<para> <para>
<varname>goPackagePath</varname> specifies the package's canonical Go <varname>goPackagePath</varname> specifies the package's canonical Go
import path. import path.
</para> </para>
</callout> </callout>
<callout arearefs='ex-buildGoPackage-2'> <callout arearefs='ex-buildGoPackage-2'>
<para> <para>
<varname>subPackages</varname> limits the builder from building child <varname>subPackages</varname> limits the builder from building child
packages that have not been listed. If <varname>subPackages</varname> is packages that have not been listed. If <varname>subPackages</varname> is
not specified, all child packages will be built. not specified, all child packages will be built.
</para> </para>
<para> <para>
In this example only <literal>github.com/deis/deis/client</literal> will In this example only <literal>github.com/deis/deis/client</literal> will
be built. be built.
</para> </para>
</callout> </callout>
<callout arearefs='ex-buildGoPackage-3'> <callout arearefs='ex-buildGoPackage-3'>
<para> <para>
<varname>goDeps</varname> is where the Go dependencies of a Go program are <varname>goDeps</varname> is where the Go dependencies of a Go program
listed as a list of package source identified by Go import path. It could are listed as a list of package source identified by Go import path. It
be imported as a separate <varname>deps.nix</varname> file for could be imported as a separate <varname>deps.nix</varname> file for
readability. The dependency data structure is described below. readability. The dependency data structure is described below.
</para> </para>
</callout> </callout>
<callout arearefs='ex-buildGoPackage-4'> <callout arearefs='ex-buildGoPackage-4'>
<para> <para>
<varname>buildFlags</varname> is a list of flags passed to the go build <varname>buildFlags</varname> is a list of flags passed to the go build
command. command.
</para> </para>
</callout> </callout>
</calloutlist> </calloutlist>
</para> </para>
<para> <para>
The <varname>goDeps</varname> attribute can be imported from a separate The <varname>goDeps</varname> attribute can be imported from a separate
<varname>nix</varname> file that defines which Go libraries are needed and <varname>nix</varname> file that defines which Go libraries are needed and
should be included in <varname>GOPATH</varname> for should be included in <varname>GOPATH</varname> for
<varname>buildPhase</varname>. <varname>buildPhase</varname>.
</para> </para>
<example xml:id='ex-goDeps'> <example xml:id='ex-goDeps'>
<title>deps.nix</title> <title>deps.nix</title>
<programlisting> <programlisting>
[ <co xml:id='ex-goDeps-1' /> [ <co xml:id='ex-goDeps-1' />
{ {
@ -101,60 +180,62 @@ deis = buildGoPackage rec {
} }
] ]
</programlisting> </programlisting>
</example> </example>
<para> <para>
<calloutlist> <calloutlist>
<callout arearefs='ex-goDeps-1'> <callout arearefs='ex-goDeps-1'>
<para> <para>
<varname>goDeps</varname> is a list of Go dependencies. <varname>goDeps</varname> is a list of Go dependencies.
</para> </para>
</callout> </callout>
<callout arearefs='ex-goDeps-2'> <callout arearefs='ex-goDeps-2'>
<para> <para>
<varname>goPackagePath</varname> specifies Go package import path. <varname>goPackagePath</varname> specifies Go package import path.
</para> </para>
</callout> </callout>
<callout arearefs='ex-goDeps-3'> <callout arearefs='ex-goDeps-3'>
<para> <para>
<varname>fetch type</varname> that needs to be used to get package source. <varname>fetch type</varname> that needs to be used to get package
If <varname>git</varname> is used there should be <varname>url</varname>, source. If <varname>git</varname> is used there should be
<varname>rev</varname> and <varname>sha256</varname> defined next to it. <varname>url</varname>, <varname>rev</varname> and
</para> <varname>sha256</varname> defined next to it.
</callout> </para>
</calloutlist> </callout>
</para> </calloutlist>
</para>
<para> <para>
To extract dependency information from a Go package in automated way use To extract dependency information from a Go package in automated way use
<link xlink:href="https://github.com/kamilchm/go2nix">go2nix</link>. It can <link xlink:href="https://github.com/kamilchm/go2nix">go2nix</link>. It can
produce complete derivation and <varname>goDeps</varname> file for Go produce complete derivation and <varname>goDeps</varname> file for Go
programs. programs.
</para> </para>
<para> <para>
<varname>buildGoPackage</varname> produces <varname>buildGoPackage</varname> produces
<xref linkend='chap-multiple-output' xrefstyle="select: title" /> where <xref linkend='chap-multiple-output' xrefstyle="select: title" /> where
<varname>bin</varname> includes program binaries. You can test build a Go <varname>bin</varname> includes program binaries. You can test build a Go
binary as follows: binary as follows:
<screen> <screen>
$ nix-build -A deis.bin $ nix-build -A deis.bin
</screen> </screen>
or build all outputs with: or build all outputs with:
<screen> <screen>
$ nix-build -A deis.all $ nix-build -A deis.all
</screen> </screen>
<varname>bin</varname> output will be installed by default with <varname>bin</varname> output will be installed by default with
<varname>nix-env -i</varname> or <varname>systemPackages</varname>. <varname>nix-env -i</varname> or <varname>systemPackages</varname>.
</para> </para>
<para> <para>
You may use Go packages installed into the active Nix profiles by adding the You may use Go packages installed into the active Nix profiles by adding the
following to your ~/.bashrc: following to your ~/.bashrc:
<screen> <screen>
for p in $NIX_PROFILES; do for p in $NIX_PROFILES; do
GOPATH="$p/share/go:$GOPATH" GOPATH="$p/share/go:$GOPATH"
done done
</screen> </screen>
</para> </para>
</section>
</section> </section>

View File

@ -55,7 +55,7 @@ package `haskell-pandoc`, for example, installs both a library and an
application. You can install and use Haskell executables just like any other application. You can install and use Haskell executables just like any other
program in Nixpkgs, but using Haskell libraries for development is a bit program in Nixpkgs, but using Haskell libraries for development is a bit
trickier and we'll address that subject in great detail in section [How to trickier and we'll address that subject in great detail in section [How to
create a development environment]. create a development environment](#how-to-create-a-development-environment).
Attribute paths are deterministic inside of Nixpkgs, but the path necessary to Attribute paths are deterministic inside of Nixpkgs, but the path necessary to
reach Nixpkgs varies from system to system. We dodged that problem by giving reach Nixpkgs varies from system to system. We dodged that problem by giving
@ -127,7 +127,7 @@ Also, the attributes `haskell.compiler.ghcXYC` and
A simple development environment consists of a Haskell compiler and one or both A simple development environment consists of a Haskell compiler and one or both
of the tools `cabal-install` and `stack`. We saw in section of the tools `cabal-install` and `stack`. We saw in section
[How to install Haskell packages] how you can install those programs into your [How to install Haskell packages](#how-to-install-haskell-packages) how you can install those programs into your
user profile: user profile:
```shell ```shell
nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install nix-env -f "<nixpkgs>" -iA haskellPackages.ghc haskellPackages.cabal-install
@ -162,7 +162,7 @@ nix-shell -p haskell.compiler.ghc784
to bring GHC 7.8.4 into `$PATH`. Alternatively, you can use Stack instead of to bring GHC 7.8.4 into `$PATH`. Alternatively, you can use Stack instead of
`nix-shell` directly to select compiler versions and other build tools `nix-shell` directly to select compiler versions and other build tools
per-project. It uses `nix-shell` under the hood when Nix support is turned on. per-project. It uses `nix-shell` under the hood when Nix support is turned on.
See [How to build a Haskell project using Stack]. See [How to build a Haskell project using Stack](#how-to-build-a-haskell-project-using-stack).
If you're using `cabal-install`, re-running `cabal configure` inside the spawned If you're using `cabal-install`, re-running `cabal configure` inside the spawned
shell switches your build to use that compiler instead. If you're working on shell switches your build to use that compiler instead. If you're working on
@ -352,9 +352,9 @@ you want them to come from. Add the following to `configuration.nix`.
```nix ```nix
services.hoogle = { services.hoogle = {
enable = true; enable = true;
packages = (hpkgs: with hpkgs; [text cryptonite]); packages = (hpkgs: with hpkgs; [text cryptonite]);
haskellPackages = pkgs.haskellPackages; haskellPackages = pkgs.haskellPackages;
}; };
``` ```
@ -366,7 +366,7 @@ automatically select the right version of GHC and other build tools to build,
test and execute apps in an existing project downloaded from somewhere on the test and execute apps in an existing project downloaded from somewhere on the
Internet. Pass the `--nix` flag to any `stack` command to do so, e.g. Internet. Pass the `--nix` flag to any `stack` command to do so, e.g.
```shell ```shell
git clone --recursive http://github.com/yesodweb/wai git clone --recursive https://github.com/yesodweb/wai
cd wai cd wai
stack --nix build stack --nix build
``` ```
@ -935,7 +935,7 @@ The implementation can be found in the
[integer-gmp](http://hackage.haskell.org/package/integer-gmp) package. [integer-gmp](http://hackage.haskell.org/package/integer-gmp) package.
A potential problem with this is that GMP is licensed under the A potential problem with this is that GMP is licensed under the
[GNU Lesser General Public License (LGPL)](http://www.gnu.org/copyleft/lesser.html), [GNU Lesser General Public License (LGPL)](https://www.gnu.org/copyleft/lesser.html),
a kind of "copyleft" license. According to the terms of the LGPL, paragraph 5, a kind of "copyleft" license. According to the terms of the LGPL, paragraph 5,
you may distribute a program that is designed to be compiled and dynamically you may distribute a program that is designed to be compiled and dynamically
linked with the library under the terms of your choice (i.e., commercially) but linked with the library under the terms of your choice (i.e., commercially) but

View File

@ -1,39 +1,115 @@
Idris packages # Idris packages
==============
This directory contains build rules for idris packages. In addition, ## Installing Idris
it contains several functions to build and compose those packages.
Everything is exposed to the user via the `idrisPackages` attribute.
callPackage The easiest way to get a working idris version is to install the `idris` attribute:
------------
This is like the normal nixpkgs callPackage function, specialized to ```
idris packages. $ # On NixOS
$ nix-env -i nixos.idris
$ # On non-NixOS
$ nix-env -i nixpkgs.idris
```
builtins This however only provides the `prelude` and `base` libraries. To install additional libraries:
---------
This is a list of all of the libraries that come packaged with Idris ```
itself. $ nix-env -iE 'pkgs: pkgs.idrisPackages.with-packages (with pkgs.idrisPackages; [ contrib pruviloj ])'
```
build-idris-package To see all available Idris packages:
-------------------- ```
$ # On NixOS
$ nix-env -qaPA nixos.idrisPackages
$ # On non-NixOS
$ nix-env -qaPA nixpkgs.idrisPackages
```
A function to build an idris package. Its sole argument is a set like Similarly, entering a `nix-shell`:
you might pass to `stdenv.mkDerivation`, except `build-idris-package` ```
sets several attributes for you. See `build-idris-package.nix` for $ nix-shell -p 'idrisPackages.with-packages (with idrisPackages; [ contrib pruviloj ])'
details. ```
build-builtin-package ## Starting Idris with library support
----------------------
A version of `build-idris-package` specialized to builtin libraries. To have access to these libraries in idris, call it with an argument `-p <library name>` for each library:
Mostly for internal use.
with-packages ```
------------- $ nix-shell -p 'idrisPackages.with-packages (with idrisPackages; [ contrib pruviloj ])'
[nix-shell:~]$ idris -p contrib -p pruviloj
```
Bundle idris together with a list of packages. Because idris currently A listing of all available packages the Idris binary has access to is available via `--listlibs`:
only supports a single directory in its library path, you must include
all desired libraries here, including `prelude` and `base`. ```
$ idris --listlibs
00prelude-idx.ibc
pruviloj
base
contrib
prelude
00pruviloj-idx.ibc
00base-idx.ibc
00contrib-idx.ibc
```
## Building an Idris project with Nix
As an example of how a Nix expression for an Idris package can be created, here is the one for `idrisPackages.yaml`:
```nix
{ build-idris-package
, fetchFromGitHub
, contrib
, lightyear
, lib
}:
build-idris-package {
name = "yaml";
version = "2018-01-25";
# This is the .ipkg file that should be built, defaults to the package name
# In this case it should build `Yaml.ipkg` instead of `yaml.ipkg`
# This is only necessary because the yaml packages ipkg file is
# different from its package name here.
ipkgName = "Yaml";
# Idris dependencies to provide for the build
idrisDeps = [ contrib lightyear ];
src = fetchFromGitHub {
owner = "Heather";
repo = "Idris.Yaml";
rev = "5afa51ffc839844862b8316faba3bafa15656db4";
sha256 = "1g4pi0swmg214kndj85hj50ccmckni7piprsxfdzdfhg87s0avw7";
};
meta = {
description = "Idris YAML lib";
homepage = https://github.com/Heather/Idris.Yaml;
license = lib.licenses.mit;
maintainers = [ lib.maintainers.brainrape ];
};
}
```
Assuming this file is saved as `yaml.nix`, it's buildable using
```
$ nix-build -E '(import <nixpkgs> {}).idrisPackages.callPackage ./yaml.nix {}'
```
Or it's possible to use
```nix
with import <nixpkgs> {};
{
yaml = idrisPackages.callPackage ./yaml.nix {};
}
```
in another file (say `default.nix`) to be able to build it with
```
$ nix-build -A yaml
```

View File

@ -10,15 +10,18 @@
Nixpkgs to easily build packages for other programming languages, such as Nixpkgs to easily build packages for other programming languages, such as
Perl or Haskell. These are described in this chapter. Perl or Haskell. These are described in this chapter.
</para> </para>
<xi:include href="android.section.xml" />
<xi:include href="beam.xml" /> <xi:include href="beam.xml" />
<xi:include href="bower.xml" /> <xi:include href="bower.xml" />
<xi:include href="coq.xml" /> <xi:include href="coq.xml" />
<xi:include href="go.xml" /> <xi:include href="go.xml" />
<xi:include href="haskell.section.xml" /> <xi:include href="haskell.section.xml" />
<xi:include href="idris.section.xml" /> <xi:include href="idris.section.xml" />
<xi:include href="ios.section.xml" />
<xi:include href="java.xml" /> <xi:include href="java.xml" />
<xi:include href="lua.xml" /> <xi:include href="lua.xml" />
<xi:include href="node.section.xml" /> <xi:include href="node.section.xml" />
<xi:include href="ocaml.xml" />
<xi:include href="perl.xml" /> <xi:include href="perl.xml" />
<xi:include href="python.section.xml" /> <xi:include href="python.section.xml" />
<xi:include href="qt.xml" /> <xi:include href="qt.xml" />
@ -26,6 +29,7 @@
<xi:include href="ruby.xml" /> <xi:include href="ruby.xml" />
<xi:include href="rust.section.xml" /> <xi:include href="rust.section.xml" />
<xi:include href="texlive.xml" /> <xi:include href="texlive.xml" />
<xi:include href="titanium.section.xml" />
<xi:include href="vim.section.xml" /> <xi:include href="vim.section.xml" />
<xi:include href="emscripten.section.xml" /> <xi:include href="emscripten.section.xml" />
</chapter> </chapter>

View File

@ -0,0 +1,219 @@
---
title: iOS
author: Sander van der Burg
date: 2018-11-18
---
# iOS
This component is basically a wrapper/workaround that makes it possible to
expose an Xcode installation as a Nix package by means of symlinking to the
relevant executables on the host system.
Since Xcode can't be packaged with Nix, nor we can publish it as a Nix package
(because of its license) this is basically the only integration strategy
making it possible to do iOS application builds that integrate with other
components of the Nix ecosystem
The primary objective of this project is to use the Nix expression language to
specify how iOS apps can be built from source code, and to automatically spawn
iOS simulator instances for testing.
This component also makes it possible to use [Hydra](http://nixos.org/hydra),
the Nix-based continuous integration server to regularly build iOS apps and to
do wireless ad-hoc installations of enterprise IPAs on iOS devices through
Hydra.
The Xcode build environment implements a number of features.
Deploying a proxy component wrapper exposing Xcode
--------------------------------------------------
The first use case is deploying a Nix package that provides symlinks to the Xcode
installation on the host system. This package can be used as a build input to
any build function implemented in the Nix expression language that requires
Xcode.
```nix
let
pkgs = import <nixpkgs> {};
xcodeenv = import ./xcodeenv {
inherit (pkgs) stdenv;
};
in
xcodeenv.composeXcodeWrapper {
version = "9.2";
xcodeBaseDir = "/Applications/Xcode.app";
}
```
By deploying the above expression with `nix-build` and inspecting its content
you will notice that several Xcode-related executables are exposed as a Nix
package:
```bash
$ ls result/bin
lrwxr-xr-x 1 sander staff 94 1 jan 1970 Simulator -> /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator
lrwxr-xr-x 1 sander staff 17 1 jan 1970 codesign -> /usr/bin/codesign
lrwxr-xr-x 1 sander staff 17 1 jan 1970 security -> /usr/bin/security
lrwxr-xr-x 1 sander staff 21 1 jan 1970 xcode-select -> /usr/bin/xcode-select
lrwxr-xr-x 1 sander staff 61 1 jan 1970 xcodebuild -> /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
lrwxr-xr-x 1 sander staff 14 1 jan 1970 xcrun -> /usr/bin/xcrun
```
Building an iOS application
---------------------------
We can build an iOS app executable for the simulator, or an IPA/xcarchive file
for release purposes, e.g. ad-hoc, enterprise or store installations, by
executing the `xcodeenv.buildApp {}` function:
```nix
let
pkgs = import <nixpkgs> {};
xcodeenv = import ./xcodeenv {
inherit (pkgs) stdenv;
};
in
xcodeenv.buildApp {
name = "MyApp";
src = ./myappsources;
sdkVersion = "11.2";
target = null; # Corresponds to the name of the app by default
configuration = null; # Release for release builds, Debug for debug builds
scheme = null; # -scheme will correspond to the app name by default
sdk = null; # null will set it to 'iphonesimulator` for simulator builds or `iphoneos` to real builds
xcodeFlags = "";
release = true;
certificateFile = ./mycertificate.p12;
certificatePassword = "secret";
provisioningProfile = ./myprovisioning.profile;
signMethod = "ad-hoc"; # 'enterprise' or 'store'
generateIPA = true;
generateXCArchive = false;
enableWirelessDistribution = true;
installURL = "/installipa.php";
bundleId = "mycompany.myapp";
appVersion = "1.0";
# Supports all xcodewrapper parameters as well
xcodeBaseDir = "/Applications/Xcode.app";
}
```
The above function takes a variety of parameters:
* The `name` and `src` parameters are mandatory and specify the name of the app
and the location where the source code resides
* `sdkVersion` specifies which version of the iOS SDK to use.
It also possile to adjust the `xcodebuild` parameters. This is only needed in
rare circumstances. In most cases the default values should suffice:
* Specifies which `xcodebuild` target to build. By default it takes the target
that has the same name as the app.
* The `configuration` parameter can be overridden if desired. By default, it
will do a debug build for the simulator and a release build for real devices.
* The `scheme` parameter specifies which `-scheme` parameter to propagate to
`xcodebuild`. By default, it corresponds to the app name.
* The `sdk` parameter specifies which SDK to use. By default, it picks
`iphonesimulator` for simulator builds and `iphoneos` for release builds.
* The `xcodeFlags` parameter specifies arbitrary command line parameters that
should be propagated to `xcodebuild`.
By default, builds are carried out for the iOS simulator. To do release builds
(builds for real iOS devices), you must set the `release` parameter to `true`.
In addition, you need to set the following parameters:
* `certificateFile` refers to a P12 certificate file.
* `certificatePassword` specifies the password of the P12 certificate.
* `provisioningProfile` refers to the provision profile needed to sign the app
* `signMethod` should refer to `ad-hoc` for signing the app with an ad-hoc
certificate, `enterprise` for enterprise certificates and `app-store` for App
store certificates.
* `generateIPA` specifies that we want to produce an IPA file (this is probably
what you want)
* `generateXCArchive` specifies thet we want to produce an xcarchive file.
When building IPA files on Hydra and when it is desired to allow iOS devices to
install IPAs by browsing to the Hydra build products page, you can enable the
`enableWirelessDistribution` parameter.
When enabled, you need to configure the following options:
* The `installURL` parameter refers to the URL of a PHP script that composes the
`itms-services://` URL allowing iOS devices to install the IPA file.
* `bundleId` refers to the bundle ID value of the app
* `appVersion` refers to the app's version number
To use wireless adhoc distributions, you must also install the corresponding
PHP script on a web server (see section: 'Installing the PHP script for wireless
ad hoc installations from Hydra' for more information).
In addition to the build parameters, you can also specify any parameters that
the `xcodeenv.composeXcodeWrapper {}` function takes. For example, the
`xcodeBaseDir` parameter can be overridden to refer to a different Xcode
version.
Spawning simulator instances
----------------------------
In addition to building iOS apps, we can also automatically spawn simulator
instances:
```nix
let
pkgs = import <nixpkgs> {};
xcodeenv = import ./xcodeenv {
inherit (pkgs) stdenv;
};
in
xcode.simulateApp {
name = "simulate";
# Supports all xcodewrapper parameters as well
xcodeBaseDir = "/Applications/Xcode.app";
}
```
The above expression produces a script that starts the simulator from the
provided Xcode installation. The script can be started as follows:
```bash
./result/bin/run-test-simulator
```
By default, the script will show an overview of UDID for all available simulator
instances and asks you to pick one. You can also provide a UDID as a
command-line parameter to launch an instance automatically:
```bash
./result/bin/run-test-simulator 5C93129D-CF39-4B1A-955F-15180C3BD4B8
```
You can also extend the simulator script to automatically deploy and launch an
app in the requested simulator instance:
```nix
let
pkgs = import <nixpkgs> {};
xcodeenv = import ./xcodeenv {
inherit (pkgs) stdenv;
};
in
xcode.simulateApp {
name = "simulate";
bundleId = "mycompany.myapp";
app = xcode.buildApp {
# ...
};
# Supports all xcodewrapper parameters as well
xcodeBaseDir = "/Applications/Xcode.app";
}
```
By providing the result of an `xcode.buildApp {}` function and configuring the
app bundle id, the app gets deployed automatically and started.

View File

@ -16,18 +16,17 @@ stdenv.mkDerivation {
} }
</programlisting> </programlisting>
Note that <varname>jdk</varname> is an alias for the OpenJDK (self-built Note that <varname>jdk</varname> is an alias for the OpenJDK (self-built
where available, or pre-built via Zulu). where available, or pre-built via Zulu). Platforms with OpenJDK not (yet) in
Platforms with OpenJDK not (yet) in Nixpkgs (<literal>Aarch32</literal>, Nixpkgs (<literal>Aarch32</literal>, <literal>Aarch64</literal>) point to the
<literal>Aarch64</literal>) point to the (unfree) (unfree) <literal>oraclejdk</literal>.
<literal>oraclejdk</literal>. </para>
</para>
<para> <para>
JAR files that are intended to be used by other packages should be installed JAR files that are intended to be used by other packages should be installed
in <filename>$out/share/java</filename>. JDKs have a stdenv setup hook in <filename>$out/share/java</filename>. JDKs have a stdenv setup hook that
that add any JARs in the <filename>share/java</filename> directories of the add any JARs in the <filename>share/java</filename> directories of the build
build inputs to the <envar>CLASSPATH</envar> environment variable. For inputs to the <envar>CLASSPATH</envar> environment variable. For instance, if
instance, if the package <literal>libfoo</literal> installs a JAR named the package <literal>libfoo</literal> installs a JAR named
<filename>foo.jar</filename> in its <filename>share/java</filename> <filename>foo.jar</filename> in its <filename>share/java</filename>
directory, and another package declares the attribute directory, and another package declares the attribute
<programlisting> <programlisting>
@ -61,18 +60,17 @@ installPhase =
<literal>${jre}/bin/java</literal> instead of <literal>${jre}/bin/java</literal> instead of
<literal>${jdk}/bin/java</literal>, you prevent your package from depending <literal>${jdk}/bin/java</literal>, you prevent your package from depending
on the JDK at runtime. on the JDK at runtime.
</para> </para>
<para> <para>
Note all JDKs passthru <literal>home</literal>, so if your application Note all JDKs passthru <literal>home</literal>, so if your application
requires environment variables like <envar>JAVA_HOME</envar> being set, that requires environment variables like <envar>JAVA_HOME</envar> being set, that
can be done in a generic fashion with the <literal>--set</literal> argument can be done in a generic fashion with the <literal>--set</literal> argument
of <literal>makeWrapper</literal>: of <literal>makeWrapper</literal>:
<programlisting> <programlisting>
--set JAVA_HOME ${jdk.home} --set JAVA_HOME ${jdk.home}
</programlisting> </programlisting>
</para> </para>
<para> <para>
It is possible to use a different Java compiler than <command>javac</command> It is possible to use a different Java compiler than <command>javac</command>

View File

@ -14,7 +14,7 @@ project.
The package set also provides support for multiple Node.js versions. The policy The package set also provides support for multiple Node.js versions. The policy
is that a new package should be added to the collection for the latest stable LTS is that a new package should be added to the collection for the latest stable LTS
release (which is currently 6.x), unless there is an explicit reason to support release (which is currently 10.x), unless there is an explicit reason to support
a different release. a different release.
If your package uses native addons, you need to examine what kind of native If your package uses native addons, you need to examine what kind of native
@ -26,7 +26,7 @@ build system it uses. Here are some examples:
After you have identified the correct system, you need to override your package After you have identified the correct system, you need to override your package
expression while adding in build system as a build input. For example, `dat` expression while adding in build system as a build input. For example, `dat`
requires `node-gyp-build`, so we override its expression in `default-v6.nix`: requires `node-gyp-build`, so we override its expression in `default-v10.nix`:
```nix ```nix
dat = nodePackages.dat.override (oldAttrs: { dat = nodePackages.dat.override (oldAttrs: {
@ -36,14 +36,14 @@ dat = nodePackages.dat.override (oldAttrs: {
To add a package from NPM to nixpkgs: To add a package from NPM to nixpkgs:
1. Modify `pkgs/development/node-packages/node-packages-v6.json` to add, update 1. Modify `pkgs/development/node-packages/node-packages-v10.json` to add, update
or remove package entries. (Or `pkgs/development/node-packages/node-packages-v4.json` or remove package entries. (Or `pkgs/development/node-packages/node-packages-v8.json`
for packages depending on Node.js 4.x) for packages depending on Node.js 8.x)
2. Run the script: `(cd pkgs/development/node-packages && ./generate.sh)`. 2. Run the script: `(cd pkgs/development/node-packages && ./generate.sh)`.
3. Build your new package to test your changes: 3. Build your new package to test your changes:
`cd /path/to/nixpkgs && nix-build -A nodePackages.<new-or-updated-package>`. `cd /path/to/nixpkgs && nix-build -A nodePackages.<new-or-updated-package>`.
To build against a specific Node.js version (e.g. 4.x): To build against a specific Node.js version (e.g. 10.x):
`nix-build -A nodePackages_4_x.<new-or-updated-package>` `nix-build -A nodePackages_10_x.<new-or-updated-package>`
4. Add and commit all modified and generated files. 4. Add and commit all modified and generated files.
For more information about the generation process, consult the For more information about the generation process, consult the

View File

@ -0,0 +1,97 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="sec-language-ocaml">
<title>OCaml</title>
<para>
OCaml libraries should be installed in
<literal>$(out)/lib/ocaml/${ocaml.version}/site-lib/</literal>. Such
directories are automatically added to the <literal>$OCAMLPATH</literal>
environment variable when building another package that depends on them or
when opening a <literal>nix-shell</literal>.
</para>
<para>
Given that most of the OCaml ecosystem is now built with dune, nixpkgs
includes a convenience build support function called
<literal>buildDunePackage</literal> that will build an OCaml package using
dune, OCaml and findlib and any additional dependencies provided as
<literal>buildInputs</literal> or <literal>propagatedBuildInputs</literal>.
</para>
<para>
Here is a simple package example. It defines an (optional) attribute
<literal>minimumOCamlVersion</literal> that will be used to throw a
descriptive evaluation error if building with an older OCaml is attempted. It
uses the <literal>fetchFromGitHub</literal> fetcher to get its source. It
sets the <literal>doCheck</literal> (optional) attribute to
<literal>true</literal> which means that tests will be run with <literal>dune
runtest -p angstrom</literal> after the build (<literal>dune build -p
angstrom</literal>) is complete. It uses <literal>alcotest</literal> as a
build input (because it is needed to run the tests) and
<literal>bigstringaf</literal> and <literal>result</literal> as propagated
build inputs (thus they will also be available to libraries depending on this
library). The library will be installed using the
<literal>angstrom.install</literal> file that dune generates.
</para>
<programlisting>
{ stdenv, fetchFromGitHub, buildDunePackage, alcotest, result, bigstringaf }:
buildDunePackage rec {
pname = "angstrom";
version = "0.10.0";
minimumOCamlVersion = "4.03";
src = fetchFromGitHub {
owner = "inhabitedtype";
repo = pname;
rev = version;
sha256 = "0lh6024yf9ds0nh9i93r9m6p5psi8nvrqxl5x7jwl13zb0r9xfpw";
};
buildInputs = [ alcotest ];
propagatedBuildInputs = [ bigstringaf result ];
doCheck = true;
meta = {
homepage = https://github.com/inhabitedtype/angstrom;
description = "OCaml parser combinators built for speed and memory efficiency";
license = stdenv.lib.licenses.bsd3;
maintainers = with stdenv.lib.maintainers; [ sternenseemann ];
};
}
</programlisting>
<para>
Here is a second example, this time using a source archive generated with
<literal>dune-release</literal>. It is a good idea to use this archive when
it is available as it will usually contain substituted variables such as a
<literal>%%VERSION%%</literal> field. This library does not depend on any
other OCaml library and no tests are run after building it.
</para>
<programlisting>
{ stdenv, fetchurl, buildDunePackage }:
buildDunePackage rec {
pname = "wtf8";
version = "1.0.1";
minimumOCamlVersion = "4.01";
src = fetchurl {
url = "https://github.com/flowtype/ocaml-${pname}/releases/download/v${version}/${pname}-${version}.tbz";
sha256 = "1msg3vycd3k8qqj61sc23qks541cxpb97vrnrvrhjnqxsqnh6ygq";
};
meta = with stdenv.lib; {
homepage = https://github.com/flowtype/ocaml-wtf8;
description = "WTF-8 is a superset of UTF-8 that allows unpaired surrogates.";
license = licenses.mit;
maintainers = [ maintainers.eqyiel ];
};
}
</programlisting>
</section>

View File

@ -186,25 +186,24 @@ building Python libraries is `buildPythonPackage`. Let's see how we can build th
`toolz` package. `toolz` package.
```nix ```nix
{ # ... { lib, buildPythonPackage, fetchPypi }:
toolz = buildPythonPackage rec { buildPythonPackage rec {
pname = "toolz"; pname = "toolz";
version = "0.7.4"; version = "0.7.4";
src = fetchPypi { src = fetchPypi {
inherit pname version; inherit pname version;
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd"; sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
}; };
doCheck = false; doCheck = false;
meta = { meta = with lib; {
homepage = "https://github.com/pytoolz/toolz/"; homepage = https://github.com/pytoolz/toolz;
description = "List processing tools and functional utilities"; description = "List processing tools and functional utilities";
license = licenses.bsd3; license = licenses.bsd3;
maintainers = with maintainers; [ fridh ]; maintainers = with maintainers; [ fridh ];
};
}; };
} }
``` ```
@ -267,43 +266,43 @@ that we introduced with the `let` expression.
#### Handling dependencies #### Handling dependencies
Our example, `toolz`, does not have any dependencies on other Python Our example, `toolz`, does not have any dependencies on other Python packages or
packages or system libraries. According to the manual, `buildPythonPackage` system libraries. According to the manual, `buildPythonPackage` uses the
uses the arguments `buildInputs` and `propagatedBuildInputs` to specify dependencies. If something is arguments `buildInputs` and `propagatedBuildInputs` to specify dependencies. If
exclusively a build-time dependency, then the dependency should be included as a something is exclusively a build-time dependency, then the dependency should be
`buildInput`, but if it is (also) a runtime dependency, then it should be added included as a `buildInput`, but if it is (also) a runtime dependency, then it
to `propagatedBuildInputs`. Test dependencies are considered build-time dependencies. should be added to `propagatedBuildInputs`. Test dependencies are considered
build-time dependencies and passed to `checkInputs`.
The following example shows which arguments are given to `buildPythonPackage` in The following example shows which arguments are given to `buildPythonPackage` in
order to build [`datashape`](https://github.com/blaze/datashape). order to build [`datashape`](https://github.com/blaze/datashape).
```nix ```nix
{ # ... { lib, buildPythonPackage, fetchPypi, numpy, multipledispatch, dateutil, pytest }:
datashape = buildPythonPackage rec { buildPythonPackage rec {
pname = "datashape"; pname = "datashape";
version = "0.4.7"; version = "0.4.7";
src = fetchPypi { src = fetchPypi {
inherit pname version; inherit pname version;
sha256 = "14b2ef766d4c9652ab813182e866f493475e65e558bed0822e38bf07bba1a278"; sha256 = "14b2ef766d4c9652ab813182e866f493475e65e558bed0822e38bf07bba1a278";
}; };
checkInputs = with self; [ pytest ]; checkInputs = [ pytest ];
propagatedBuildInputs = with self; [ numpy multipledispatch dateutil ]; propagatedBuildInputs = [ numpy multipledispatch dateutil ];
meta = { meta = with lib; {
homepage = https://github.com/ContinuumIO/datashape; homepage = https://github.com/ContinuumIO/datashape;
description = "A data description language"; description = "A data description language";
license = licenses.bsd2; license = licenses.bsd2;
maintainers = with maintainers; [ fridh ]; maintainers = with maintainers; [ fridh ];
};
}; };
} }
``` ```
We can see several runtime dependencies, `numpy`, `multipledispatch`, and We can see several runtime dependencies, `numpy`, `multipledispatch`, and
`dateutil`. Furthermore, we have one `buildInput`, i.e. `pytest`. `pytest` is a `dateutil`. Furthermore, we have one `checkInputs`, i.e. `pytest`. `pytest` is a
test runner and is only used during the `checkPhase` and is therefore not added test runner and is only used during the `checkPhase` and is therefore not added
to `propagatedBuildInputs`. to `propagatedBuildInputs`.
@ -313,25 +312,24 @@ Python bindings to `libxml2` and `libxslt`. These libraries are only required
when building the bindings and are therefore added as `buildInputs`. when building the bindings and are therefore added as `buildInputs`.
```nix ```nix
{ # ... { lib, pkgs, buildPythonPackage, fetchPypi }:
lxml = buildPythonPackage rec { buildPythonPackage rec {
pname = "lxml"; pname = "lxml";
version = "3.4.4"; version = "3.4.4";
src = fetchPypi { src = fetchPypi {
inherit pname version; inherit pname version;
sha256 = "16a0fa97hym9ysdk3rmqz32xdjqmy4w34ld3rm3jf5viqjx65lxk"; sha256 = "16a0fa97hym9ysdk3rmqz32xdjqmy4w34ld3rm3jf5viqjx65lxk";
}; };
buildInputs = with self; [ pkgs.libxml2 pkgs.libxslt ]; buildInputs = [ pkgs.libxml2 pkgs.libxslt ];
meta = { meta = with lib; {
description = "Pythonic binding for the libxml2 and libxslt libraries"; description = "Pythonic binding for the libxml2 and libxslt libraries";
homepage = https://lxml.de; homepage = https://lxml.de;
license = licenses.bsd3; license = licenses.bsd3;
maintainers = with maintainers; [ sjourdois ]; maintainers = with maintainers; [ sjourdois ];
};
}; };
} }
``` ```
@ -347,35 +345,34 @@ find each of them in a different folder, and therefore we have to set `LDFLAGS`
and `CFLAGS`. and `CFLAGS`.
```nix ```nix
{ # ... { lib, pkgs, buildPythonPackage, fetchPypi, numpy, scipy }:
pyfftw = buildPythonPackage rec { buildPythonPackage rec {
pname = "pyFFTW"; pname = "pyFFTW";
version = "0.9.2"; version = "0.9.2";
src = fetchPypi { src = fetchPypi {
inherit pname version; inherit pname version;
sha256 = "f6bbb6afa93085409ab24885a1a3cdb8909f095a142f4d49e346f2bd1b789074"; sha256 = "f6bbb6afa93085409ab24885a1a3cdb8909f095a142f4d49e346f2bd1b789074";
}; };
buildInputs = [ pkgs.fftw pkgs.fftwFloat pkgs.fftwLongDouble]; buildInputs = [ pkgs.fftw pkgs.fftwFloat pkgs.fftwLongDouble];
propagatedBuildInputs = with self; [ numpy scipy ]; propagatedBuildInputs = [ numpy scipy ];
# Tests cannot import pyfftw. pyfftw works fine though. # Tests cannot import pyfftw. pyfftw works fine though.
doCheck = false; doCheck = false;
preConfigure = '' preConfigure = ''
export LDFLAGS="-L${pkgs.fftw.dev}/lib -L${pkgs.fftwFloat.out}/lib -L${pkgs.fftwLongDouble.out}/lib" export LDFLAGS="-L${pkgs.fftw.dev}/lib -L${pkgs.fftwFloat.out}/lib -L${pkgs.fftwLongDouble.out}/lib"
export CFLAGS="-I${pkgs.fftw.dev}/include -I${pkgs.fftwFloat.dev}/include -I${pkgs.fftwLongDouble.dev}/include" export CFLAGS="-I${pkgs.fftw.dev}/include -I${pkgs.fftwFloat.dev}/include -I${pkgs.fftwLongDouble.dev}/include"
''; '';
meta = { meta = with lib; {
description = "A pythonic wrapper around FFTW, the FFT library, presenting a unified interface for all the supported transforms"; description = "A pythonic wrapper around FFTW, the FFT library, presenting a unified interface for all the supported transforms";
homepage = http://hgomersall.github.com/pyFFTW/; homepage = http://hgomersall.github.com/pyFFTW;
license = with licenses; [ bsd2 bsd3 ]; license = with licenses; [ bsd2 bsd3 ];
maintainers = with maintainers; [ fridh ]; maintainers = with maintainers; [ fridh ];
};
}; };
} }
``` ```
@ -403,7 +400,7 @@ Indeed, we can just add any package we like to have in our environment to `propa
```nix ```nix
with import <nixpkgs> {}; with import <nixpkgs> {};
with pkgs.python35Packages; with python35Packages;
buildPythonPackage rec { buildPythonPackage rec {
name = "mypackage"; name = "mypackage";
@ -436,7 +433,7 @@ Let's split the package definition from the environment definition.
We first create a function that builds `toolz` in `~/path/to/toolz/release.nix` We first create a function that builds `toolz` in `~/path/to/toolz/release.nix`
```nix ```nix
{ lib, pkgs, buildPythonPackage }: { lib, buildPythonPackage }:
buildPythonPackage rec { buildPythonPackage rec {
pname = "toolz"; pname = "toolz";
@ -448,7 +445,7 @@ buildPythonPackage rec {
}; };
meta = with lib; { meta = with lib; {
homepage = "http://github.com/pytoolz/toolz/"; homepage = "https://github.com/pytoolz/toolz/";
description = "List processing tools and functional utilities"; description = "List processing tools and functional utilities";
license = licenses.bsd3; license = licenses.bsd3;
maintainers = with maintainers; [ fridh ]; maintainers = with maintainers; [ fridh ];
@ -456,18 +453,17 @@ buildPythonPackage rec {
} }
``` ```
It takes two arguments, `pkgs` and `buildPythonPackage`. It takes an argument `buildPythonPackage`.
We now call this function using `callPackage` in the definition of our environment We now call this function using `callPackage` in the definition of our environment
```nix ```nix
with import <nixpkgs> {}; with import <nixpkgs> {};
( let ( let
toolz = pkgs.callPackage /path/to/toolz/release.nix { toolz = callPackage /path/to/toolz/release.nix {
pkgs = pkgs; buildPythonPackage = python35Packages.buildPythonPackage;
buildPythonPackage = pkgs.python35Packages.buildPythonPackage;
}; };
in pkgs.python35.withPackages (ps: [ ps.numpy toolz ]) in python35.withPackages (ps: [ ps.numpy toolz ])
).env ).env
``` ```
@ -478,18 +474,18 @@ don't explicitly define which `python` derivation should be used. In the above
example we use `buildPythonPackage` that is part of the set `python35Packages`, example we use `buildPythonPackage` that is part of the set `python35Packages`,
and in this case the `python35` interpreter is automatically used. and in this case the `python35` interpreter is automatically used.
## Reference ## Reference
### Interpreters ### Interpreters
Versions 2.7, 3.4, 3.5, 3.6 and 3.7 of the CPython interpreter are available as Versions 2.7, 3.5, 3.6 and 3.7 of the CPython interpreter are available as
respectively `python27`, `python34`, `python35` and `python36`. The PyPy interpreter respectively `python27`, `python35`, `python36` and `python37`. The aliases
is available as `pypy`. The aliases `python2` and `python3` correspond to respectively `python27` and `python2` and `python3` correspond to respectively `python27` and
`python35`. The default interpreter, `python`, maps to `python2`. `python37`. The default interpreter, `python`, maps to `python2`. The PyPy
The Nix expressions for the interpreters can be found in interpreters compatible with Python 2.7 and 3 are available as `pypy27` and
`pkgs/development/interpreters/python`. `pypy3`, with aliases `pypy2` mapping to `pypy27` and `pypy` mapping to
`pypy2`. The Nix expressions for the interpreters can be
found in `pkgs/development/interpreters/python`.
All packages depending on any Python interpreter get appended All packages depending on any Python interpreter get appended
`out/{python.sitePackages}` to `$PYTHONPATH` if such directory `out/{python.sitePackages}` to `$PYTHONPATH` if such directory
@ -508,13 +504,13 @@ Each interpreter has the following attributes:
- `buildEnv`. Function to build python interpreter environments with extra packages bundled together. See section *python.buildEnv function* for usage and documentation. - `buildEnv`. Function to build python interpreter environments with extra packages bundled together. See section *python.buildEnv function* for usage and documentation.
- `withPackages`. Simpler interface to `buildEnv`. See section *python.withPackages function* for usage and documentation. - `withPackages`. Simpler interface to `buildEnv`. See section *python.withPackages function* for usage and documentation.
- `sitePackages`. Alias for `lib/${libPrefix}/site-packages`. - `sitePackages`. Alias for `lib/${libPrefix}/site-packages`.
- `executable`. Name of the interpreter executable, e.g. `python3.4`. - `executable`. Name of the interpreter executable, e.g. `python3.7`.
- `pkgs`. Set of Python packages for that specific interpreter. The package set can be modified by overriding the interpreter and passing `packageOverrides`. - `pkgs`. Set of Python packages for that specific interpreter. The package set can be modified by overriding the interpreter and passing `packageOverrides`.
### Building packages and applications ### Building packages and applications
Python libraries and applications that use `setuptools` or Python libraries and applications that use `setuptools` or
`distutils` are typically build with respectively the `buildPythonPackage` and `distutils` are typically built with respectively the `buildPythonPackage` and
`buildPythonApplication` functions. These two functions also support installing a `wheel`. `buildPythonApplication` functions. These two functions also support installing a `wheel`.
All Python packages reside in `pkgs/top-level/python-packages.nix` and all All Python packages reside in `pkgs/top-level/python-packages.nix` and all
@ -530,7 +526,6 @@ attribute set is created for each available Python interpreter. The available
sets are sets are
* `pkgs.python27Packages` * `pkgs.python27Packages`
* `pkgs.python34Packages`
* `pkgs.python35Packages` * `pkgs.python35Packages`
* `pkgs.python36Packages` * `pkgs.python36Packages`
* `pkgs.python37Packages` * `pkgs.python37Packages`
@ -539,7 +534,7 @@ sets are
and the aliases and the aliases
* `pkgs.python2Packages` pointing to `pkgs.python27Packages` * `pkgs.python2Packages` pointing to `pkgs.python27Packages`
* `pkgs.python3Packages` pointing to `pkgs.python36Packages` * `pkgs.python3Packages` pointing to `pkgs.python37Packages`
* `pkgs.pythonPackages` pointing to `pkgs.python2Packages` * `pkgs.pythonPackages` pointing to `pkgs.python2Packages`
#### `buildPythonPackage` function #### `buildPythonPackage` function
@ -549,31 +544,31 @@ The `buildPythonPackage` function is implemented in
The following is an example: The following is an example:
```nix ```nix
{ lib, buildPythonPackage, fetchPypi, hypothesis, setuptools_scm, attrs, py, setuptools, six, pluggy }:
buildPythonPackage rec { buildPythonPackage rec {
version = "3.3.1";
pname = "pytest"; pname = "pytest";
version = "3.3.1";
preCheck = ''
# don't test bash builtins
rm testing/test_argcomplete.py
'';
src = fetchPypi { src = fetchPypi {
inherit pname version; inherit pname version;
sha256 = "cf8436dc59d8695346fcd3ab296de46425ecab00d64096cebe79fb51ecb2eb93"; sha256 = "cf8436dc59d8695346fcd3ab296de46425ecab00d64096cebe79fb51ecb2eb93";
}; };
postPatch = ''
# don't test bash builtins
rm testing/test_argcomplete.py
'';
checkInputs = [ hypothesis ]; checkInputs = [ hypothesis ];
buildInputs = [ setuptools_scm ]; nativeBuildInputs = [ setuptools_scm ];
propagatedBuildInputs = [ attrs py setuptools six pluggy ]; propagatedBuildInputs = [ attrs py setuptools six pluggy ];
meta = with stdenv.lib; { meta = with lib; {
maintainers = with maintainers; [ domenkozar lovek323 madjar lsix ]; maintainers = with maintainers; [ domenkozar lovek323 madjar lsix ];
description = "Framework for writing tests"; description = "Framework for writing tests";
}; };
} }
``` ```
The `buildPythonPackage` mainly does four things: The `buildPythonPackage` mainly does four things:
@ -586,11 +581,6 @@ The `buildPythonPackage` mainly does four things:
environment variable and add dependent libraries to script's `sys.path`. environment variable and add dependent libraries to script's `sys.path`.
* In the `installCheck` phase, `${python.interpreter} setup.py test` is ran. * In the `installCheck` phase, `${python.interpreter} setup.py test` is ran.
As in Perl, dependencies on other Python packages can be specified in the
`buildInputs` and `propagatedBuildInputs` attributes. If something is
exclusively a build-time dependency, use `buildInputs`; if it is (also) a runtime
dependency, use `propagatedBuildInputs`.
By default tests are run because `doCheck = true`. Test dependencies, like By default tests are run because `doCheck = true`. Test dependencies, like
e.g. the test runner, should be added to `checkInputs`. e.g. the test runner, should be added to `checkInputs`.
@ -602,11 +592,10 @@ as the interpreter unless overridden otherwise.
All parameters from `stdenv.mkDerivation` function are still supported. The following are specific to `buildPythonPackage`: All parameters from `stdenv.mkDerivation` function are still supported. The following are specific to `buildPythonPackage`:
* `catchConflicts ? true`: If `true`, abort package build if a package name appears more than once in dependency tree. Default is `true`. * `catchConflicts ? true`: If `true`, abort package build if a package name appears more than once in dependency tree. Default is `true`.
* `checkInputs ? []`: Dependencies needed for running the `checkPhase`. These are added to `buildInputs` when `doCheck = true`.
* `disabled` ? false: If `true`, package is not build for the particular Python interpreter version. * `disabled` ? false: If `true`, package is not build for the particular Python interpreter version.
* `dontWrapPythonPrograms ? false`: Skip wrapping of python programs. * `dontWrapPythonPrograms ? false`: Skip wrapping of python programs.
* `installFlags ? []`: A list of strings. Arguments to be passed to `pip install`. To pass options to `python setup.py install`, use `--install-option`. E.g., `installFlags=["--install-option='--cpp_implementation'"]. * `installFlags ? []`: A list of strings. Arguments to be passed to `pip install`. To pass options to `python setup.py install`, use `--install-option`. E.g., `installFlags=["--install-option='--cpp_implementation'"]`.
* `format ? "setuptools"`: Format of the source. Valid options are `"setuptools"`, `"flit"`, `"wheel"`, and `"other"`. `"setuptools"` is for when the source has a `setup.py` and `setuptools` is used to build a wheel, `flit`, in case `flit` should be used to build a wheel, and `wheel` in case a wheel is provided. Use `other` when a custom `buildPhase` and/or `installPhase` is needed. * `format ? "setuptools"`: Format of the source. Valid options are `"setuptools"`, `"pyproject"`, `"flit"`, `"wheel"`, and `"other"`. `"setuptools"` is for when the source has a `setup.py` and `setuptools` is used to build a wheel, `flit`, in case `flit` should be used to build a wheel, and `wheel` in case a wheel is provided. Use `other` when a custom `buildPhase` and/or `installPhase` is needed.
* `makeWrapperArgs ? []`: A list of strings. Arguments to be passed to `makeWrapper`, which wraps generated binaries. By default, the arguments to `makeWrapper` set `PATH` and `PYTHONPATH` environment variables before calling the binary. Additional arguments here can allow a developer to set environment variables which will be available when the binary is run. For example, `makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]`. * `makeWrapperArgs ? []`: A list of strings. Arguments to be passed to `makeWrapper`, which wraps generated binaries. By default, the arguments to `makeWrapper` set `PATH` and `PYTHONPATH` environment variables before calling the binary. Additional arguments here can allow a developer to set environment variables which will be available when the binary is run. For example, `makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]`.
* `namePrefix`: Prepends text to `${name}` parameter. In case of libraries, this defaults to `"python3.5-"` for Python 3.5, etc., and in case of applications to `""`. * `namePrefix`: Prepends text to `${name}` parameter. In case of libraries, this defaults to `"python3.5-"` for Python 3.5, etc., and in case of applications to `""`.
* `pythonPath ? []`: List of packages to be added into `$PYTHONPATH`. Packages in `pythonPath` are not propagated (contrary to `propagatedBuildInputs`). * `pythonPath ? []`: List of packages to be added into `$PYTHONPATH`. Packages in `pythonPath` are not propagated (contrary to `propagatedBuildInputs`).
@ -615,6 +604,14 @@ All parameters from `stdenv.mkDerivation` function are still supported. The foll
* `removeBinByteCode ? true`: Remove bytecode from `/bin`. Bytecode is only created when the filenames end with `.py`. * `removeBinByteCode ? true`: Remove bytecode from `/bin`. Bytecode is only created when the filenames end with `.py`.
* `setupPyBuildFlags ? []`: List of flags passed to `setup.py build_ext` command. * `setupPyBuildFlags ? []`: List of flags passed to `setup.py build_ext` command.
The `stdenv.mkDerivation` function accepts various parameters for describing build inputs (see "Specifying dependencies"). The following are of special
interest for Python packages, either because these are primarily used, or because their behaviour is different:
* `nativeBuildInputs ? []`: Build-time only dependencies. Typically executables as well as the items listed in `setup_requires`.
* `buildInputs ? []`: Build and/or run-time dependencies that need to be be compiled for the host machine. Typically non-Python libraries which are being linked.
* `checkInputs ? []`: Dependencies needed for running the `checkPhase`. These are added to `nativeBuildInputs` when `doCheck = true`. Items listed in `tests_require` go here.
* `propagatedBuildInputs ? []`: Aside from propagating dependencies, `buildPythonPackage` also injects code into and wraps executables with the paths included in this list. Items listed in `install_requires` go here.
##### Overriding Python packages ##### Overriding Python packages
The `buildPythonPackage` function has a `overridePythonAttrs` method that The `buildPythonPackage` function has a `overridePythonAttrs` method that
@ -645,9 +642,48 @@ in python.withPackages(ps: [ps.blaze])).env
#### `buildPythonApplication` function #### `buildPythonApplication` function
The `buildPythonApplication` function is practically the same as `buildPythonPackage`. The `buildPythonApplication` function is practically the same as
The difference is that `buildPythonPackage` by default prefixes the names of the packages with the version of the interpreter. `buildPythonPackage`. The main purpose of this function is to build a Python
Because this is irrelevant for applications, the prefix is omitted. package where one is interested only in the executables, and not importable
modules. For that reason, when adding this package to a `python.buildEnv`, the
modules won't be made available.
Another difference is that `buildPythonPackage` by default prefixes the names of
the packages with the version of the interpreter. Because this is irrelevant for
applications, the prefix is omitted.
When packaging a python application with `buildPythonApplication`, it should be
called with `callPackage` and passed `python` or `pythonPackages` (possibly
specifying an interpreter version), like this:
```nix
{ lib, python3Packages }:
python3Packages.buildPythonApplication rec {
pname = "luigi";
version = "2.7.9";
src = python3Packages.fetchPypi {
inherit pname version;
sha256 = "035w8gqql36zlan0xjrzz9j4lh9hs0qrsgnbyw07qs7lnkvbdv9x";
};
propagatedBuildInputs = with python3Packages; [ tornado_4 python-daemon ];
meta = with lib; {
...
};
}
```
This is then added to `all-packages.nix` just as any other application would be.
```nix
luigi = callPackage ../applications/networking/cluster/luigi { };
```
Since the package is an application, a consumer doesn't need to care about
python versions or modules, which is why they don't go in `pythonPackages`.
#### `toPythonApplication` function #### `toPythonApplication` function
@ -688,7 +724,7 @@ Saving the following as `default.nix`
with import <nixpkgs> {}; with import <nixpkgs> {};
python.buildEnv.override { python.buildEnv.override {
extraLibs = [ pkgs.pythonPackages.pyramid ]; extraLibs = [ pythonPackages.pyramid ];
ignoreCollisions = true; ignoreCollisions = true;
} }
``` ```
@ -770,11 +806,12 @@ Given a `default.nix`:
```nix ```nix
with import <nixpkgs> {}; with import <nixpkgs> {};
buildPythonPackage { name = "myproject"; pythonPackages.buildPythonPackage {
name = "myproject";
buildInputs = with pythonPackages; [ pyramid ];
buildInputs = with pkgs.pythonPackages; [ pyramid ]; src = ./.;
}
src = ./.; }
``` ```
Running `nix-shell` with no arguments should give you Running `nix-shell` with no arguments should give you
@ -799,7 +836,7 @@ community to help save time. No tool is preferred at the moment.
### Deterministic builds ### Deterministic builds
Python 2.7, 3.5 and 3.6 are now built deterministically and 3.4 mostly. The Python interpreters are now built deterministically.
Minor modifications had to be made to the interpreters in order to generate Minor modifications had to be made to the interpreters in order to generate
deterministic bytecode. This has security implications and is relevant for deterministic bytecode. This has security implications and is relevant for
those using Python in a `nix-shell`. those using Python in a `nix-shell`.
@ -835,7 +872,6 @@ example of such a situation is when `py.test` is used.
''; '';
} }
``` ```
- Unicode issues can typically be fixed by including `glibcLocales` in `buildInputs` and exporting `LC_ALL=en_US.utf-8`.
- Tests that attempt to access `$HOME` can be fixed by using the following work-around before running tests (e.g. `preCheck`): `export HOME=$(mktemp -d)` - Tests that attempt to access `$HOME` can be fixed by using the following work-around before running tests (e.g. `preCheck`): `export HOME=$(mktemp -d)`
## FAQ ## FAQ
@ -961,10 +997,13 @@ Create this `default.nix` file, together with a `requirements.txt` and simply ex
```nix ```nix
with import <nixpkgs> {}; with import <nixpkgs> {};
with pkgs.python27Packages; with python27Packages;
stdenv.mkDerivation { stdenv.mkDerivation {
name = "impurePythonEnv"; name = "impurePythonEnv";
src = null;
buildInputs = [ buildInputs = [
# these packages are required for virtualenv and pip to work: # these packages are required for virtualenv and pip to work:
# #
@ -984,14 +1023,15 @@ stdenv.mkDerivation {
libxslt libxslt
libzip libzip
stdenv stdenv
zlib ]; zlib
src = null; ];
shellHook = '' shellHook = ''
# set SOURCE_DATE_EPOCH so that we can use python wheels # set SOURCE_DATE_EPOCH so that we can use python wheels
SOURCE_DATE_EPOCH=$(date +%s) SOURCE_DATE_EPOCH=$(date +%s)
virtualenv --no-setuptools venv virtualenv --no-setuptools venv
export PATH=$PWD/venv/bin:$PATH export PATH=$PWD/venv/bin:$PATH
pip install -r requirements.txt pip install -r requirements.txt
''; '';
} }
``` ```
@ -1041,8 +1081,7 @@ To modify only a Python package set instead of a whole Python derivation, use th
Use the following overlay template: Use the following overlay template:
```nix ```nix
self: super: self: super: {
{
python = super.python.override { python = super.python.override {
packageOverrides = python-self: python-super: { packageOverrides = python-self: python-super: {
zerobin = python-super.zerobin.overrideAttrs (oldAttrs: { zerobin = python-super.zerobin.overrideAttrs (oldAttrs: {
@ -1057,6 +1096,42 @@ self: super:
} }
``` ```
### How to use Intel's MKL with numpy and scipy?
A `site.cfg` is created that configures BLAS based on the `blas` parameter
of the `numpy` derivation. By passing in `mkl`, `numpy` and packages depending
on `numpy` will be built with `mkl`.
The following is an overlay that configures `numpy` to use `mkl`:
```nix
self: super: {
python37 = super.python37.override {
packageOverrides = python-self: python-super: {
numpy = python-super.numpy.override {
blas = super.pkgs.mkl;
};
};
};
}
```
`mkl` requires an `openmp` implementation when running with multiple processors.
By default, `mkl` will use Intel's `iomp` implementation if no other is
specified, but this is a runtime-only dependency and binary compatible with the
LLVM implementation. To use that one instead, Intel recommends users set it with
`LD_PRELOAD`.
Note that `mkl` is only available on `x86_64-{linux,darwin}` platforms;
moreover, Hydra is not building and distributing pre-compiled binaries using it.
### What inputs do `setup_requires`, `install_requires` and `tests_require` map to?
In a `setup.py` or `setup.cfg` it is common to declare dependencies:
* `setup_requires` corresponds to `nativeBuildInputs`
* `install_requires` corresponds to `propagatedBuildInputs`
* `tests_require` corresponds to `checkInputs`
## Contributing ## Contributing
### Contributing guidelines ### Contributing guidelines
@ -1068,4 +1143,5 @@ Following rules are desired to be respected:
* Make sure libraries build for all Python interpreters. * Make sure libraries build for all Python interpreters.
* By default we enable tests. Make sure the tests are found and, in the case of libraries, are passing for all interpreters. If certain tests fail they can be disabled individually. Try to avoid disabling the tests altogether. In any case, when you disable tests, leave a comment explaining why. * By default we enable tests. Make sure the tests are found and, in the case of libraries, are passing for all interpreters. If certain tests fail they can be disabled individually. Try to avoid disabling the tests altogether. In any case, when you disable tests, leave a comment explaining why.
* Commit names of Python libraries should reflect that they are Python libraries, so write for example `pythonPackages.numpy: 1.11 -> 1.12`. * Commit names of Python libraries should reflect that they are Python libraries, so write for example `pythonPackages.numpy: 1.11 -> 1.12`.
* Attribute names in `python-packages.nix` should be normalized according to [PEP 0503](https://www.python.org/dev/peps/pep-0503/#normalized-names).
This means that characters should be converted to lowercase and `.` and `_` should be replaced by a single `-` (foo-bar-baz instead of Foo__Bar.baz )

View File

@ -50,6 +50,17 @@ bundlerEnv rec {
future updates can be run easily. future updates can be run easily.
</para> </para>
<para>
Updating Ruby packages can then be done like this:
</para>
<screen>
<![CDATA[$ cd pkgs/servers/monitoring/sensu
$ nix-shell -p bundler --run 'bundle lock --update'
$ nix-shell -p bundix --run 'bundix'
]]>
</screen>
<para> <para>
For tools written in Ruby - i.e. where the desire is to install a package and For tools written in Ruby - i.e. where the desire is to install a package and
then execute e.g. <command>rake</command> at the command line, there is an then execute e.g. <command>rake</command> at the command line, there is an

View File

@ -64,9 +64,6 @@ When the `Cargo.lock`, provided by upstream, is not in sync with the
added in `cargoPatches` will also be prepended to the patches in `patches` at added in `cargoPatches` will also be prepended to the patches in `patches` at
build-time. build-time.
To install crates with nix there is also an experimental project called
[nixcrates](https://github.com/fractalide/nixcrates).
## Compiling Rust crates using Nix instead of Cargo ## Compiling Rust crates using Nix instead of Cargo
### Simple operation ### Simple operation
@ -93,8 +90,8 @@ Now, the file produced by the call to `carnix`, called `hello.nix`, looks like:
``` ```
# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone # Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone
{ lib, buildPlatform, buildRustCrate, fetchgit }: { lib, stdenv, buildRustCrate, fetchgit }:
let kernel = buildPlatform.parsed.kernel.name; let kernel = stdenv.buildPlatform.parsed.kernel.name;
# ... (content skipped) # ... (content skipped)
in in
rec { rec {
@ -122,8 +119,8 @@ following nix file:
``` ```
# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone # Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone
{ lib, buildPlatform, buildRustCrate, fetchgit }: { lib, stdenv, buildRustCrate, fetchgit }:
let kernel = buildPlatform.parsed.kernel.name; let kernel = stdenv.buildPlatform.parsed.kernel.name;
# ... (content skipped) # ... (content skipped)
in in
rec { rec {
@ -306,11 +303,15 @@ with import <nixpkgs> {};
stdenv.mkDerivation { stdenv.mkDerivation {
name = "rust-env"; name = "rust-env";
buildInputs = [ nativeBuildInputs = [
rustc cargo rustc cargo
# Example Additional Dependencies # Example Build-time Additional Dependencies
pkgconfig openssl pkgconfig
];
buildInputs = [
# Example Run-time Additional Dependencies
openssl
]; ];
# Set Environment Variables # Set Environment Variables

View File

@ -8,7 +8,7 @@
under attribute <varname>texlive</varname>. under attribute <varname>texlive</varname>.
</para> </para>
<section> <section xml:id="sec-language-texlive-users-guide">
<title>User's guide</title> <title>User's guide</title>
<itemizedlist> <itemizedlist>
@ -49,12 +49,12 @@ texlive.combine {
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
You can list packages e.g. by <command>nix-repl</command>. You can list packages e.g. by <command>nix repl</command>.
<programlisting> <programlisting><![CDATA[
$ nix-repl $ nix repl
nix-repl> :l &lt;nixpkgs> nix-repl> :l <nixpkgs>
nix-repl> texlive.collection-&lt;TAB> nix-repl> texlive.collection-<TAB>
</programlisting> ]]></programlisting>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -68,7 +68,7 @@ nix-repl> texlive.collection-&lt;TAB>
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="sec-language-texlive-known-problems">
<title>Known problems</title> <title>Known problems</title>
<itemizedlist> <itemizedlist>

View File

@ -0,0 +1,115 @@
---
title: Titanium
author: Sander van der Burg
date: 2018-11-18
---
# Titanium
The Nixpkgs repository contains facilities to deploy a variety of versions of
the [Titanium SDK](https://www.appcelerator.com) versions, a cross-platform
mobile app development framework using JavaScript as an implementation language,
and includes a function abstraction making it possible to build Titanium
applications for Android and iOS devices from source code.
Not all Titanium features supported -- currently, it can only be used to build
Android and iOS apps.
Building a Titanium app
-----------------------
We can build a Titanium app from source for Android or iOS and for debugging or
release purposes by invoking the `titaniumenv.buildApp {}` function:
```nix
titaniumenv.buildApp {
name = "myapp";
src = ./myappsource;
preBuild = "";
target = "android"; # or 'iphone'
tiVersion = "7.1.0.GA";
release = true;
androidsdkArgs = {
platformVersions = [ "25" "26" ];
};
androidKeyStore = ./keystore;
androidKeyAlias = "myfirstapp";
androidKeyStorePassword = "secret";
xcodeBaseDir = "/Applications/Xcode.app";
xcodewrapperArgs = {
version = "9.3";
};
iosMobileProvisioningProfile = ./myprovisioning.profile;
iosCertificateName = "My Company";
iosCertificate = ./mycertificate.p12;
iosCertificatePassword = "secret";
iosVersion = "11.3";
iosBuildStore = false;
enableWirelessDistribution = true;
installURL = "/installipa.php";
}
```
The `titaniumenv.buildApp {}` function takes the following parameters:
* The `name` parameter refers to the name in the Nix store.
* The `src` parameter refers to the source code location of the app that needs
to be built.
* `preRebuild` contains optional build instructions that are carried out before
the build starts.
* `target` indicates for which device the app must be built. Currently only
'android' and 'iphone' (for iOS) are supported.
* `tiVersion` can be used to optionally override the requested Titanium version
in `tiapp.xml`. If not specified, it will use the version in `tiapp.xml`.
* `release` should be set to true when building an app for submission to the
Google Playstore or Apple Appstore. Otherwise, it should be false.
When the `target` has been set to `android`, we can configure the following
parameters:
* The `androidSdkArgs` parameter refers to an attribute set that propagates all
parameters to the `androidenv.composeAndroidPackages {}` function. This can
be used to install all relevant Android plugins that may be needed to perform
the Android build. If no parameters are given, it will deploy the platform
SDKs for API-levels 25 and 26 by default.
When the `release` parameter has been set to true, you need to provide
parameters to sign the app:
* `androidKeyStore` is the path to the keystore file
* `androidKeyAlias` is the key alias
* `androidKeyStorePassword` refers to the password to open the keystore file.
When the `target` has been set to `iphone`, we can configure the following
parameters:
* The `xcodeBaseDir` parameter refers to the location where Xcode has been
installed. When none value is given, the above value is the default.
* The `xcodewrapperArgs` parameter passes arbitrary parameters to the
`xcodeenv.composeXcodeWrapper {}` function. This can, for example, be used
to adjust the default version of Xcode.
When `release` has been set to true, you also need to provide the following
parameters:
* `iosMobileProvisioningProfile` refers to a mobile provisioning profile needed
for signing.
* `iosCertificateName` refers to the company name in the P12 certificate.
* `iosCertificate` refers to the path to the P12 file.
* `iosCertificatePassword` contains the password to open the P12 file.
* `iosVersion` refers to the iOS SDK version to use. It defaults to the latest
version.
* `iosBuildStore` should be set to `true` when building for the Apple Appstore
submission. For enterprise or ad-hoc builds it should be set to `false`.
When `enableWirelessDistribution` has been enabled, you must also provide the
path of the PHP script (`installURL`) (that is included with the iOS build
environment) to enable wireless ad-hoc installations.
Emulating or simulating the app
-------------------------------
It is also possible to simulate the correspond iOS simulator build by using
`xcodeenv.simulateApp {}` and emulate an Android APK by using
`androidenv.emulateApp {}`.

View File

@ -5,11 +5,17 @@ date: 2016-06-25
--- ---
# User's Guide to Vim Plugins/Addons/Bundles/Scripts in Nixpkgs # User's Guide to Vim Plugins/Addons/Bundles/Scripts in Nixpkgs
You'll get a vim(-your-suffix) in PATH also loading the plugins you want. Both Neovim and Vim can be configured to include your favorite plugins
and additional libraries.
Loading can be deferred; see examples. Loading can be deferred; see examples.
Vim packages, VAM (=vim-addon-manager) and Pathogen are supported to load At the moment we support three different methods for managing plugins:
packages.
- Vim packages (*recommend*)
- VAM (=vim-addon-manager)
- Pathogen
- vim-plug
## Custom configuration ## Custom configuration
@ -17,6 +23,7 @@ Adding custom .vimrc lines can be done using the following code:
``` ```
vim_configurable.customize { vim_configurable.customize {
# `name` specifies the name of the executable and package
name = "vim-with-plugins"; name = "vim-with-plugins";
vimrcConfig.customRC = '' vimrcConfig.customRC = ''
@ -25,9 +32,38 @@ vim_configurable.customize {
} }
``` ```
## Vim packages This configuration is used when vim is invoked with the command specified as name, in this case `vim-with-plugins`.
To store you plugins in Vim packages the following example can be used: For Neovim the `configure` argument can be overridden to achieve the same:
```
neovim.override {
configure = {
customRC = ''
# here your custom configuration goes!
'';
};
}
```
If you want to use `neovim-qt` as a graphical editor, you can configure it by overriding neovim in an overlay
or passing it an overridden neovimn:
```
neovim-qt.override {
neovim = neovim.override {
configure = {
customRC = ''
# your custom configuration
'';
};
};
}
```
## Managing plugins with Vim packages
To store you plugins in Vim packages (the native vim plugin manager, see `:help packages`) the following example can be used:
``` ```
vim_configurable.customize { vim_configurable.customize {
@ -35,16 +71,88 @@ vim_configurable.customize {
# loaded on launch # loaded on launch
start = [ youcompleteme fugitive ]; start = [ youcompleteme fugitive ];
# manually loadable by calling `:packadd $plugin-name` # manually loadable by calling `:packadd $plugin-name`
# however, if a vim plugin has a dependency that is not explicitly listed in
# opt that dependency will always be added to start to avoid confusion.
opt = [ phpCompletion elm-vim ]; opt = [ phpCompletion elm-vim ];
# To automatically load a plugin when opening a filetype, add vimrc lines like: # To automatically load a plugin when opening a filetype, add vimrc lines like:
# autocmd FileType php :packadd phpCompletion # autocmd FileType php :packadd phpCompletion
} };
}; }
``` ```
## VAM `myVimPackage` is an arbitrary name for the generated package. You can choose any name you like.
For Neovim the syntax is:
### dependencies by Vim plugins ```
neovim.override {
configure = {
customRC = ''
# here your custom configuration goes!
'';
packages.myVimPackage = with pkgs.vimPlugins; {
# see examples below how to use custom packages
start = [ ];
# If a vim plugin has a dependency that is not explicitly listed in
# opt that dependency will always be added to start to avoid confusion.
opt = [ ];
};
};
}
```
The resulting package can be added to `packageOverrides` in `~/.nixpkgs/config.nix` to make it installable:
```
{
packageOverrides = pkgs: with pkgs; {
myVim = vim_configurable.customize {
# `name` specifies the name of the executable and package
name = "vim-with-plugins";
# add here code from the example section
};
myNeovim = neovim.override {
configure = {
# add here code from the example section
};
};
};
}
```
After that you can install your special grafted `myVim` or `myNeovim` packages.
## Managing plugins with vim-plug
To use [vim-plug](https://github.com/junegunn/vim-plug) to manage your Vim
plugins the following example can be used:
```
vim_configurable.customize {
vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
# loaded on launch
plug.plugins = [ youcompleteme fugitive phpCompletion elm-vim ];
};
}
```
For Neovim the syntax is:
```
neovim.override {
configure = {
customRC = ''
# here your custom configuration goes!
'';
plug.plugins = with pkgs.vimPlugins; [
vim-go
];
};
}
```
## Managing plugins with VAM
### Handling dependencies of Vim plugins
VAM introduced .json files supporting dependencies without versioning VAM introduced .json files supporting dependencies without versioning
assuming that "using latest version" is ok most of the time. assuming that "using latest version" is ok most of the time.
@ -125,11 +233,23 @@ Sample output2:
] ]
## Adding new plugins to nixpkgs
In `pkgs/misc/vim-plugins/vim-plugin-names` we store the plugin names
for all vim plugins we automatically generate plugins for.
The format of this file `github username/github repository`:
For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
After adding your plugin to this file run the `./update.py` in the same folder.
This will updated a file called `generated.nix` and make your plugin accessible in the
`vimPlugins` attribute set (`vimPlugins.nerdtree` in our example).
If additional steps to the build process of the plugin are required, add an
override to the `pkgs/misc/vim-plugins/default.nix` in the same directory.
## Important repositories ## Important repositories
- [vim-pi](https://bitbucket.org/vimcommunity/vim-pi) is a plugin repository - [vim-pi](https://bitbucket.org/vimcommunity/vim-pi) is a plugin repository
from VAM plugin manager meant to be used by others as well used by from VAM plugin manager meant to be used by others as well used by
- [vim2nix](http://github.com/MarcWeber/vim-addon-vim2nix) which generates the - [vim2nix](https://github.com/MarcWeber/vim-addon-vim2nix) which generates the
.nix code .nix code

26
doc/lib-function-docs.nix Normal file
View File

@ -0,0 +1,26 @@
# Generates the documentation for library functons via nixdoc. To add
# another library function file to this list, the include list in the
# file `doc/functions/library.xml` must also be updated.
{ pkgs ? import ./.. {}, locationsXml }:
with pkgs; stdenv.mkDerivation {
name = "nixpkgs-lib-docs";
src = ./../lib;
buildInputs = [ nixdoc ];
installPhase = ''
function docgen {
nixdoc -c "$1" -d "$2" -f "../lib/$1.nix" > "$out/$1.xml"
}
mkdir -p $out
ln -s ${locationsXml} $out/locations.xml
docgen strings 'String manipulation functions'
docgen trivial 'Miscellaneous functions'
docgen lists 'List manipulation functions'
docgen debug 'Debugging functions'
docgen options 'NixOS / nixpkgs option handling'
'';
}

View File

@ -0,0 +1,85 @@
{ pkgs ? (import ./.. { }), nixpkgs ? { }}:
let
revision = pkgs.lib.trivial.revisionWithDefault (nixpkgs.revision or "master");
libDefPos = set:
builtins.map
(name: {
name = name;
location = builtins.unsafeGetAttrPos name set;
})
(builtins.attrNames set);
libset = toplib:
builtins.map
(subsetname: {
subsetname = subsetname;
functions = libDefPos toplib."${subsetname}";
})
(builtins.filter
(name: builtins.isAttrs toplib."${name}")
(builtins.attrNames toplib));
nixpkgsLib = pkgs.lib;
flattenedLibSubset = { subsetname, functions }:
builtins.map
(fn: {
name = "lib.${subsetname}.${fn.name}";
value = fn.location;
})
functions;
locatedlibsets = libs: builtins.map flattenedLibSubset (libset libs);
removeFilenamePrefix = prefix: filename:
let
prefixLen = (builtins.stringLength prefix) + 1; # +1 to remove the leading /
filenameLen = builtins.stringLength filename;
substr = builtins.substring prefixLen filenameLen filename;
in substr;
removeNixpkgs = removeFilenamePrefix (builtins.toString pkgs.path);
liblocations =
builtins.filter
(elem: elem.value != null)
(nixpkgsLib.lists.flatten
(locatedlibsets nixpkgsLib));
fnLocationRelative = { name, value }:
{
inherit name;
value = value // { file = removeNixpkgs value.file; };
};
relativeLocs = (builtins.map fnLocationRelative liblocations);
sanitizeId = builtins.replaceStrings
[ "'" ]
[ "-prime" ];
urlPrefix = "https://github.com/NixOS/nixpkgs/blob/${revision}";
xmlstrings = (nixpkgsLib.strings.concatMapStrings
({ name, value }:
''
<section><title>${name}</title>
<para xml:id="${sanitizeId name}">
Located at
<link
xlink:href="${urlPrefix}/${value.file}#L${builtins.toString value.line}">${value.file}:${builtins.toString value.line}</link>
in <literal>&lt;nixpkgs&gt;</literal>.
</para>
</section>
'')
relativeLocs);
in pkgs.writeText
"locations.xml"
''
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="5">
<title>All the locations for every lib function</title>
<para>This file is only for inclusion by other files.</para>
${xmlstrings}
</section>
''

View File

@ -14,7 +14,7 @@ meta = with stdenv.lib; {
GNU Hello is a program that prints "Hello, world!" when you run it. GNU Hello is a program that prints "Hello, world!" when you run it.
It is fully customizable. It is fully customizable.
''; '';
homepage = http://www.gnu.org/software/hello/manual/; homepage = https://www.gnu.org/software/hello/manual/;
license = licenses.gpl3Plus; license = licenses.gpl3Plus;
maintainers = [ maintainers.eelco ]; maintainers = [ maintainers.eelco ];
platforms = platforms.all; platforms = platforms.all;
@ -35,7 +35,7 @@ $ nix-env -qa hello --json
"hello": { "hello": {
"meta": { "meta": {
"description": "A program that produces a familiar, friendly greeting", "description": "A program that produces a familiar, friendly greeting",
"homepage": "http://www.gnu.org/software/hello/manual/", "homepage": "https://www.gnu.org/software/hello/manual/",
"license": { "license": {
"fullName": "GNU General Public License version 3 or later", "fullName": "GNU General Public License version 3 or later",
"shortName": "GPLv3+", "shortName": "GPLv3+",
@ -135,7 +135,7 @@ hello-2.3 A program that produces a familiar, friendly greeting
<listitem> <listitem>
<para> <para>
The packages homepage. Example: The packages homepage. Example:
<literal>http://www.gnu.org/software/hello/manual/</literal> <literal>https://www.gnu.org/software/hello/manual/</literal>
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -146,7 +146,7 @@ hello-2.3 A program that produces a familiar, friendly greeting
<listitem> <listitem>
<para> <para>
The page where a link to the current version can be found. Example: The page where a link to the current version can be found. Example:
<literal>http://ftp.gnu.org/gnu/hello/</literal> <literal>https://ftp.gnu.org/gnu/hello/</literal>
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -250,6 +250,60 @@ meta.platforms = stdenv.lib.platforms.linux;
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<varname>tests</varname>
</term>
<listitem>
<warning>
<para>
This attribute is special in that it is not actually under the
<literal>meta</literal> attribute set but rather under the
<literal>passthru</literal> attribute set. This is due to a current
limitation of Nix, and will change as soon as Nixpkgs will be able to
depend on a new enough version of Nix. See
<link xlink:href="https://github.com/NixOS/nix/issues/2532">the relevant
issue</link> for more details.
</para>
</warning>
<para>
An attribute set with as values tests. A test is a derivation, which
builds successfully when the test passes, and fails to build otherwise. A
derivation that is a test needs to have <literal>meta.timeout</literal>
defined.
</para>
<para>
The NixOS tests are available as <literal>nixosTests</literal> in
parameters of derivations. For instance, the OpenSMTPD derivation
includes lines similar to:
<programlisting>
{ /* ... */, nixosTests }:
{
# ...
passthru.tests = {
basic-functionality-and-dovecot-integration = nixosTests.opensmtpd;
};
}
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>timeout</varname>
</term>
<listitem>
<para>
A timeout (in seconds) for building the derivation. If the derivation
takes longer than this time to build, it can fail due to breaking the
timeout. However, all computers do not have the same computing power,
hence some builders may decide to apply a multiplicative factor to this
value. When filling this value in, try to keep it approximately
consistent with other values already present in
<literal>nixpkgs</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<varname>hydraPlatforms</varname> <varname>hydraPlatforms</varname>

View File

@ -6,13 +6,13 @@
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-multiple-output"> xml:id="chap-multiple-output">
<title>Multiple-output packages</title> <title>Multiple-output packages</title>
<section> <section xml:id="sec-multiple-outputs-introduction">
<title>Introduction</title> <title>Introduction</title>
<para> <para>
The Nix language allows a derivation to produce multiple outputs, which is The Nix language allows a derivation to produce multiple outputs, which is
similar to what is utilized by other Linux distribution packaging systems. similar to what is utilized by other Linux distribution packaging systems.
The outputs reside in separate nix store paths, so they can be mostly The outputs reside in separate Nix store paths, so they can be mostly
handled independently of each other, including passing to build inputs, handled independently of each other, including passing to build inputs,
garbage collection or binary substitution. The exception is that building garbage collection or binary substitution. The exception is that building
from source always produces all the outputs. from source always produces all the outputs.
@ -38,7 +38,7 @@
</para> </para>
</note> </note>
</section> </section>
<section> <section xml:id="sec-multiple-outputs-installing">
<title>Installing a split package</title> <title>Installing a split package</title>
<para> <para>
@ -84,7 +84,7 @@
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="sec-multiple-outputs-using-split-packages">
<title>Using a split package</title> <title>Using a split package</title>
<para> <para>
@ -101,8 +101,15 @@
contain <varname>$outputBin</varname> and <varname>$outputLib</varname> are contain <varname>$outputBin</varname> and <varname>$outputLib</varname> are
also added. (See <xref linkend="multiple-output-file-type-groups" />.) also added. (See <xref linkend="multiple-output-file-type-groups" />.)
</para> </para>
<para>
In some cases it may be desirable to combine different outputs under a
single store path. A function <literal>symlinkJoin</literal> can be used to
do this. (Note that it may negate some closure size benefits of using a
multiple-output package.)
</para>
</section> </section>
<section> <section xml:id="sec-multiple-outputs-">
<title>Writing a split derivation</title> <title>Writing a split derivation</title>
<para> <para>
@ -283,7 +290,7 @@
</variablelist> </variablelist>
</section> </section>
<section> <section xml:id="sec-multiple-outputs-caveats">
<title>Common caveats</title> <title>Common caveats</title>
<itemizedlist> <itemizedlist>

View File

@ -78,7 +78,7 @@ Step 2: build kernel headers for the target architecture
--- ---
{stdenv, fetchurl}: {stdenv, fetchurl}:
assert stdenv.system == "i686-linux"; assert stdenv.buildPlatform.system == "i686-linux";
stdenv.mkDerivation { stdenv.mkDerivation {
name = "linux-headers-2.6.13.1-arm"; name = "linux-headers-2.6.13.1-arm";

View File

@ -3,9 +3,9 @@
xml:id="chap-overlays"> xml:id="chap-overlays">
<title>Overlays</title> <title>Overlays</title>
<para> <para>
This chapter describes how to extend and change Nixpkgs packages using This chapter describes how to extend and change Nixpkgs using overlays.
overlays. Overlays are used to add layers in the fix-point used by Nixpkgs to Overlays are used to add layers in the fixed-point used by Nixpkgs to compose
compose the set of all packages. the set of all packages.
</para> </para>
<para> <para>
Nixpkgs can be configured with a list of overlays, which are applied in Nixpkgs can be configured with a list of overlays, which are applied in
@ -17,91 +17,122 @@
<title>Installing overlays</title> <title>Installing overlays</title>
<para> <para>
The list of overlays is determined as follows. The list of overlays can be set either explicitly in a Nix expression, or
through <literal>&lt;nixpkgs-overlays></literal> or user configuration
files.
</para> </para>
<para> <section xml:id="sec-overlays-argument">
If the <varname>overlays</varname> argument is not provided explicitly, we <title>Set overlays in NixOS or Nix expressions</title>
look for overlays in a path. The path is determined as follows:
<orderedlist>
<listitem>
<para>
First, if an <varname>overlays</varname> argument to the nixpkgs function
itself is given, then that is used.
</para>
<para>
This can be passed explicitly when importing nipxkgs, for example
<literal>import &lt;nixpkgs> { overlays = [ overlay1 overlay2 ];
}</literal>.
</para>
</listitem>
<listitem>
<para>
Otherwise, if the Nix path entry <literal>&lt;nixpkgs-overlays></literal>
exists, we look for overlays at that path, as described below.
</para>
<para>
See the section on <literal>NIX_PATH</literal> in the Nix manual for more
details on how to set a value for
<literal>&lt;nixpkgs-overlays>.</literal>
</para>
</listitem>
<listitem>
<para>
If one of <filename>~/.config/nixpkgs/overlays.nix</filename> and
<filename>~/.config/nixpkgs/overlays/</filename> exists, then we look for
overlays at that path, as described below. It is an error if both exist.
</para>
</listitem>
</orderedlist>
</para>
<para> <para>
If we are looking for overlays at a path, then there are two cases: On a NixOS system the value of the <literal>nixpkgs.overlays</literal>
<itemizedlist> option, if present, is passed to the system Nixpkgs directly as an
<listitem> argument. Note that this does not affect the overlays for non-NixOS
<para> operations (e.g. <literal>nix-env</literal>), which are
If the path is a file, then the file is imported as a Nix expression and <link xlink:href="#sec-overlays-lookup">looked</link> up independently.
used as the list of overlays. </para>
</para>
</listitem>
<listitem>
<para>
If the path is a directory, then we take the content of the directory,
order it lexicographically, and attempt to interpret each as an overlay
by:
<itemizedlist>
<listitem>
<para>
Importing the file, if it is a <literal>.nix</literal> file.
</para>
</listitem>
<listitem>
<para>
Importing a top-level <filename>default.nix</filename> file, if it is
a directory.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
<para> <para>
On a NixOS system the value of the <literal>nixpkgs.overlays</literal> The list of overlays can be passed explicitly when importing nixpkgs, for
option, if present, is passed to the system Nixpkgs directly as an argument. example <literal>import &lt;nixpkgs> { overlays = [ overlay1 overlay2 ];
Note that this does not affect the overlays for non-NixOS operations (e.g. }</literal>.
<literal>nix-env</literal>), which are looked up independently. </para>
</para>
<para> <para>
The <filename>overlays.nix</filename> option therefore provides a convenient Further overlays can be added by calling the <literal>pkgs.extend</literal>
way to use the same overlays for a NixOS system configuration and user or <literal>pkgs.appendOverlays</literal>, although it is often preferable
configuration: the same file can be used as to avoid these functions, because they recompute the Nixpkgs fixpoint,
<filename>overlays.nix</filename> and imported as the value of which is somewhat expensive to do.
<literal>nixpkgs.overlays</literal>. </para>
</para> </section>
<section xml:id="sec-overlays-lookup">
<title>Install overlays via configuration lookup</title>
<para>
The list of overlays is determined as follows.
</para>
<para>
<orderedlist>
<listitem>
<para>
First, if an
<link xlink:href="#sec-overlays-argument"><varname>overlays</varname>
argument</link> to the Nixpkgs function itself is given, then that is
used and no path lookup will be performed.
</para>
</listitem>
<listitem>
<para>
Otherwise, if the Nix path entry
<literal>&lt;nixpkgs-overlays></literal> exists, we look for overlays at
that path, as described below.
</para>
<para>
See the section on <literal>NIX_PATH</literal> in the Nix manual for
more details on how to set a value for
<literal>&lt;nixpkgs-overlays>.</literal>
</para>
</listitem>
<listitem>
<para>
If one of <filename>~/.config/nixpkgs/overlays.nix</filename> and
<filename>~/.config/nixpkgs/overlays/</filename> exists, then we look
for overlays at that path, as described below. It is an error if both
exist.
</para>
</listitem>
</orderedlist>
</para>
<para>
If we are looking for overlays at a path, then there are two cases:
<itemizedlist>
<listitem>
<para>
If the path is a file, then the file is imported as a Nix expression and
used as the list of overlays.
</para>
</listitem>
<listitem>
<para>
If the path is a directory, then we take the content of the directory,
order it lexicographically, and attempt to interpret each as an overlay
by:
<itemizedlist>
<listitem>
<para>
Importing the file, if it is a <literal>.nix</literal> file.
</para>
</listitem>
<listitem>
<para>
Importing a top-level <filename>default.nix</filename> file, if it is
a directory.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
<para>
Because overlays that are set in NixOS configuration do not affect
non-NixOS operations such as <literal>nix-env</literal>, the
<filename>overlays.nix</filename> option provides a convenient way to use
the same overlays for a NixOS system configuration and user configuration:
the same file can be used as <filename>overlays.nix</filename> and imported
as the value of <literal>nixpkgs.overlays</literal>.
</para>
<!-- TODO: Example of sharing overlays between NixOS configuration
and configuration lookup. Also reference the example
from the sec-overlays-argument paragraph about NixOS.
-->
</section>
</section> </section>
<!--============================================================--> <!--============================================================-->
<section xml:id="sec-overlays-definition"> <section xml:id="sec-overlays-definition">

View File

@ -181,7 +181,7 @@ $ cat $(PRINT_PATH=1 nix-prefetch-url $i | tail -n 1) \
</section> </section>
<!--============================================================--> <!--============================================================-->
<!-- <!--
<section> <section xml:id="sec-package-notes-gnome">
<title>Gnome</title> <title>Gnome</title>
<para>* Expression is auto-generated</para> <para>* Expression is auto-generated</para>
<para>* How to update</para> <para>* How to update</para>
@ -189,7 +189,7 @@ $ cat $(PRINT_PATH=1 nix-prefetch-url $i | tail -n 1) \
--> -->
<!--============================================================--> <!--============================================================-->
<!-- <!--
<section> <section xml:id="sec-package-notes-gcc">
<title>GCC</title> <title>GCC</title>
<para></para> <para></para>
</section> </section>
@ -205,7 +205,7 @@ $ cat $(PRINT_PATH=1 nix-prefetch-url $i | tail -n 1) \
<para> <para>
Nixpkgs provides a number of packages that will install Eclipse in its Nixpkgs provides a number of packages that will install Eclipse in its
various forms, these range from the bare-bones Eclipse Platform to the more various forms. These range from the bare-bones Eclipse Platform to the more
fully featured Eclipse SDK or Scala-IDE packages and multiple version are fully featured Eclipse SDK or Scala-IDE packages and multiple version are
often available. It is possible to list available Eclipse packages by often available. It is possible to list available Eclipse packages by
issuing the command: issuing the command:
@ -311,17 +311,18 @@ packageOverrides = pkgs: {
<title>Elm</title> <title>Elm</title>
<para> <para>
The Nix expressions for Elm reside in To start a development environment do <command>nix-shell -p elmPackages.elm elmPackages.elm-format</command>
<filename>pkgs/development/compilers/elm</filename>. They are generated </para>
automatically by <command>update-elm.rb</command> script. One should specify
versions of Elm packages inside the script, clear the <para>
<filename>packages</filename> directory and run the script from inside it. To update Elm compiler, see
<literal>elm-reactor</literal> is special because it also has Elm package <filename>nixpkgs/pkgs/development/compilers/elm/README.md</filename>.
dependencies. The process is not automated very much for now -- you should </para>
get the <literal>elm-reactor</literal> source tree (e.g. with
<command>nix-shell</command>) and run <command>elm2nix.rb</command> inside <para>
it. Place the resulting <filename>package.nix</filename> file into To package Elm applications,
<filename>packages/elm-reactor-elm.nix</filename>. <link xlink:href="https://github.com/hercules-ci/elm2nix#elm2nix">read about
elm2nix</link>.
</para> </para>
</section> </section>
<section xml:id="sec-shell-helpers"> <section xml:id="sec-shell-helpers">
@ -413,11 +414,9 @@ packageOverrides = pkgs: {
in your <filename>/etc/nixos/configuration.nix</filename>. You'll also need in your <filename>/etc/nixos/configuration.nix</filename>. You'll also need
<programlisting>hardware.pulseaudio.support32Bit = true;</programlisting> <programlisting>hardware.pulseaudio.support32Bit = true;</programlisting>
if you are using PulseAudio - this will enable 32bit ALSA apps integration. if you are using PulseAudio - this will enable 32bit ALSA apps integration.
To use the Steam controller, you need to add To use the Steam controller or other Steam supported controllers such as
<programlisting>services.udev.extraRules = '' the DualShock 4 or Nintendo Switch Pro, you need to add
SUBSYSTEM=="usb", ATTRS{idVendor}=="28de", MODE="0666" <programlisting>hardware.steam-hardware.enable = true;</programlisting>
KERNEL=="uinput", MODE="0660", GROUP="users", OPTIONS+="static_node=uinput"
'';</programlisting>
to your configuration. to your configuration.
</para> </para>
</section> </section>
@ -643,15 +642,15 @@ cp ${myEmacsConfig} $out/share/emacs/site-lisp/default.el
required dependencies manually - but it's tedious and there is always a required dependencies manually - but it's tedious and there is always a
possibility that an unwanted dependency will sneak in through some other possibility that an unwanted dependency will sneak in through some other
package. To completely override such a package you can use package. To completely override such a package you can use
<varname>overrideScope</varname>. <varname>overrideScope'</varname>.
</para> </para>
<screen> <screen>
overrides = super: self: rec { overrides = self: super: rec {
haskell-mode = self.melpaPackages.haskell-mode; haskell-mode = self.melpaPackages.haskell-mode;
... ...
}; };
((emacsPackagesNgGen emacs).overrideScope overrides).emacsWithPackages (p: with p; [ ((emacsPackagesNgGen emacs).overrideScope' overrides).emacsWithPackages (p: with p; [
# here both these package will use haskell-mode of our own choice # here both these package will use haskell-mode of our own choice
ghc-mod ghc-mod
dante dante
@ -671,6 +670,9 @@ overrides = super: self: rec {
plugins = with availablePlugins; [ python perl ]; plugins = with availablePlugins; [ python perl ];
} }
}</programlisting> }</programlisting>
If the <literal>configure</literal> function returns an attrset without the
<literal>plugins</literal> attribute, <literal>availablePlugins</literal>
will be used automatically.
</para> </para>
<para> <para>
@ -680,10 +682,10 @@ overrides = super: self: rec {
</para> </para>
<para> <para>
The python plugin allows the addition of extra libraries. For instance, the The python and perl plugins allows the addition of extra libraries. For
<literal>inotify.py</literal> script in weechat-scripts requires D-Bus or instance, the <literal>inotify.py</literal> script in weechat-scripts
libnotify, and the <literal>fish.py</literal> script requires pycrypto. To requires D-Bus or libnotify, and the <literal>fish.py</literal> script
use these scripts, use the <literal>python</literal> plugin's requires pycrypto. To use these scripts, use the plugin's
<literal>withPackages</literal> attribute: <literal>withPackages</literal> attribute:
<programlisting>weechat.override { configure = {availablePlugins, ...}: { <programlisting>weechat.override { configure = {availablePlugins, ...}: {
plugins = with availablePlugins; [ plugins = with availablePlugins; [
@ -704,45 +706,110 @@ overrides = super: self: rec {
}; } }; }
</programlisting> </programlisting>
</para> </para>
<para>
WeeChat allows to set defaults on startup using the
<literal>--run-command</literal>. The <literal>configure</literal> method
can be used to pass commands to the program:
<programlisting>weechat.override {
configure = { availablePlugins, ... }: {
init = ''
/set foo bar
/server add freenode chat.freenode.org
'';
};
}</programlisting>
Further values can be added to the list of commands when running
<literal>weechat --run-command "your-commands"</literal>.
</para>
<para>
Additionally it's possible to specify scripts to be loaded when starting
<literal>weechat</literal>. These will be loaded before the commands from
<literal>init</literal>:
<programlisting>weechat.override {
configure = { availablePlugins, ... }: {
scripts = with pkgs.weechatScripts; [
weechat-xmpp weechat-matrix-bridge wee-slack
];
init = ''
/set plugins.var.python.jabber.key "val"
'':
};
}</programlisting>
</para>
<para>
In <literal>nixpkgs</literal> there's a subpackage which contains
derivations for WeeChat scripts. Such derivations expect a
<literal>passthru.scripts</literal> attribute which contains a list of all
scripts inside the store path. Furthermore all scripts have to live in
<literal>$out/share</literal>. An exemplary derivation looks like this:
<programlisting>{ stdenv, fetchurl }:
stdenv.mkDerivation {
name = "exemplary-weechat-script";
src = fetchurl {
url = "https://scripts.tld/your-scripts.tar.gz";
sha256 = "...";
};
passthru.scripts = [ "foo.py" "bar.lua" ];
installPhase = ''
mkdir $out/share
cp foo.py $out/share
cp bar.lua $out/share
'';
}</programlisting>
</para>
</section> </section>
<section xml:id="sec-citrix"> <section xml:id="sec-citrix">
<title>Citrix Receiver</title> <title>Citrix Receiver</title>
<para> <para>
The <link xlink:href="https://www.citrix.com/products/receiver/">Citrix Receiver</link> is a remote The <link xlink:href="https://www.citrix.com/products/receiver/">Citrix
desktop viewer which provides access to Receiver</link> is a remote desktop viewer which provides access to
<link xlink:href="https://www.citrix.com/products/xenapp-xendesktop/">XenDesktop</link> installations. <link xlink:href="https://www.citrix.com/products/xenapp-xendesktop/">XenDesktop</link>
installations.
</para> </para>
<section xml:id="sec-citrix-base"> <section xml:id="sec-citrix-base">
<title>Basic usage</title> <title>Basic usage</title>
<para> <para>
The tarball archive needs to be downloaded manually as the licenses agreements of the vendor The tarball archive needs to be downloaded manually as the licenses
need to be accepted first. This is available at the agreements of the vendor need to be accepted first. This is available at
<link xlink:href="https://www.citrix.com/downloads/citrix-receiver/">download page at citrix.com</link>. the
Then run <literal>nix-prefetch-url file://$PWD/linuxx64-$version.tar.gz</literal>. <link xlink:href="https://www.citrix.com/downloads/citrix-receiver/">download
With the archive available in the store the package can be built and installed with Nix. page at citrix.com</link>. Then run <literal>nix-prefetch-url
file://$PWD/linuxx64-$version.tar.gz</literal>. With the archive available
in the store the package can be built and installed with Nix.
</para> </para>
<para> <para>
<emphasis>Note: it's recommended to install <literal>Citrix Receiver</literal> using <emphasis>Note: it's recommended to install <literal>Citrix
<literal>nix-env -i</literal> or globally to ensure that the <literal>.desktop</literal> files Receiver</literal> using <literal>nix-env -i</literal> or globally to
are installed properly into <literal>$XDG_CONFIG_DIRS</literal>. Otherwise it won't ensure that the <literal>.desktop</literal> files are installed properly
be possible to open <literal>.ica</literal> files into <literal>$XDG_CONFIG_DIRS</literal>. Otherwise it won't be possible to
automatically from the browser to start a Citrix connection.</emphasis> open <literal>.ica</literal> files automatically from the browser to start
a Citrix connection.</emphasis>
</para> </para>
</section> </section>
<section xml:id="sec-citrix-custom-certs"> <section xml:id="sec-citrix-custom-certs">
<title>Custom certificates</title> <title>Custom certificates</title>
<para> <para>
The <literal>Citrix Receiver</literal> in <literal>nixpkgs</literal> trusts several certificates The <literal>Citrix Receiver</literal> in <literal>nixpkgs</literal> trusts
<link xlink:href="https://curl.haxx.se/docs/caextract.html">from the Mozilla database</link> by default. several certificates
However several companies using Citrix might require their own corporate certificate. On distros with imperative <link xlink:href="https://curl.haxx.se/docs/caextract.html">from the
Mozilla database</link> by default. However several companies using Citrix
might require their own corporate certificate. On distros with imperative
packaging these certs can be stored easily in packaging these certs can be stored easily in
<link xlink:href="https://developer-docs.citrix.com/projects/receiver-for-linux-command-reference/en/13.7/"><literal>$ICAROOT</literal></link>, <link xlink:href="https://developer-docs.citrix.com/projects/receiver-for-linux-command-reference/en/13.7/"><literal>$ICAROOT</literal></link>,
however this directory is a store path in <literal>nixpkgs</literal>. In order to work around this issue the package provides a simple however this directory is a store path in <literal>nixpkgs</literal>. In
mechanism to add custom certificates without rebuilding the entire package using <literal>symlinkJoin</literal>: order to work around this issue the package provides a simple mechanism to
add custom certificates without rebuilding the entire package using
<literal>symlinkJoin</literal>:
<programlisting> <programlisting>
<![CDATA[with import <nixpkgs> { config.allowUnfree = true; }; <![CDATA[with import <nixpkgs> { config.allowUnfree = true; };
let extraCerts = [ ./custom-cert-1.pem ./custom-cert-2.pem /* ... */ ]; in let extraCerts = [ ./custom-cert-1.pem ./custom-cert-2.pem /* ... */ ]; in
@ -753,4 +820,102 @@ citrix_receiver.override {
</para> </para>
</section> </section>
</section> </section>
<section xml:id="sec-ibus-typing-booster">
<title>ibus-engines.typing-booster</title>
<para>
This package is an ibus-based completion method to speed up typing.
</para>
<section xml:id="sec-ibus-typing-booster-activate">
<title>Activating the engine</title>
<para>
IBus needs to be configured accordingly to activate
<literal>typing-booster</literal>. The configuration depends on the desktop
manager in use. For detailed instructions, please refer to the
<link xlink:href="https://mike-fabian.github.io/ibus-typing-booster/documentation.html">upstream
docs</link>.
</para>
<para>
On NixOS you need to explicitly enable <literal>ibus</literal> with given
engines before customizing your desktop to use
<literal>typing-booster</literal>. This can be achieved using the
<literal>ibus</literal> module:
<programlisting>{ pkgs, ... }: {
i18n.inputMethod = {
enabled = "ibus";
ibus.engines = with pkgs.ibus-engines; [ typing-booster ];
};
}</programlisting>
</para>
</section>
<section xml:id="sec-ibus-typing-booster-customize-hunspell">
<title>Using custom hunspell dictionaries</title>
<para>
The IBus engine is based on <literal>hunspell</literal> to support
completion in many languages. By default the dictionaries
<literal>de-de</literal>, <literal>en-us</literal>,
<literal>es-es</literal>, <literal>it-it</literal>,
<literal>sv-se</literal> and <literal>sv-fi</literal> are in use. To add
another dictionary, the package can be overridden like this:
<programlisting>ibus-engines.typing-booster.override {
langs = [ "de-at" "en-gb" ];
}</programlisting>
</para>
<para>
<emphasis>Note: each language passed to <literal>langs</literal> must be an
attribute name in <literal>pkgs.hunspellDicts</literal>.</emphasis>
</para>
</section>
<section xml:id="sec-ibus-typing-booster-emoji-picker">
<title>Built-in emoji picker</title>
<para>
The <literal>ibus-engines.typing-booster</literal> package contains a
program named <literal>emoji-picker</literal>. To display all emojis
correctly, a special font such as <literal>noto-fonts-emoji</literal> is
needed:
</para>
<para>
On NixOS it can be installed using the following expression:
<programlisting>{ pkgs, ... }: {
fonts.fonts = with pkgs; [ noto-fonts-emoji ];
}</programlisting>
</para>
</section>
</section>
<section xml:id="dlib">
<title>DLib</title>
<para>
<link xlink:href="http://dlib.net/">DLib</link> is a modern, C++-based toolkit which
provides several machine learning algorithms.
</para>
<section xml:id="compiling-without-avx-support">
<title>Compiling without AVX support</title>
<para>
Especially older CPUs don't support
<link xlink:href="https://en.wikipedia.org/wiki/Advanced_Vector_Extensions">AVX</link>
(<abbrev>Advanced Vector Extensions</abbrev>) instructions that are used by DLib to
optimize their algorithms.
</para>
<para>
On the affected hardware errors like <literal>Illegal instruction</literal> will occur.
In those cases AVX support needs to be disabled:
<programlisting>self: super: {
dlib = super.dlib.override { avxSupport = false; };
}</programlisting>
</para>
</section>
</section>
</chapter> </chapter>

View File

@ -6,13 +6,13 @@
<title>Darwin (macOS)</title> <title>Darwin (macOS)</title>
<para> <para>
Some common issues when packaging software for darwin: Some common issues when packaging software for Darwin:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
The darwin <literal>stdenv</literal> uses clang instead of gcc. When The Darwin <literal>stdenv</literal> uses clang instead of gcc. When
referring to the compiler <varname>$CC</varname> or <command>cc</command> referring to the compiler <varname>$CC</varname> or <command>cc</command>
will work in both cases. Some builds hardcode gcc/g++ in their build will work in both cases. Some builds hardcode gcc/g++ in their build
scripts, that can usually be fixed with using something like scripts, that can usually be fixed with using something like
@ -29,10 +29,9 @@
} }
</programlisting> </programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
On darwin libraries are linked using absolute paths, libraries are On Darwin, libraries are linked using absolute paths, libraries are
resolved by their <literal>install_name</literal> at link time. Sometimes resolved by their <literal>install_name</literal> at link time. Sometimes
packages won't set this correctly causing the library lookups to fail at packages won't set this correctly causing the library lookups to fail at
runtime. This can be fixed by adding extra linker flags or by running runtime. This can be fixed by adding extra linker flags or by running
@ -47,19 +46,19 @@
} }
</programlisting> </programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Even if the libraries are linked using absolute paths and resolved via Even if the libraries are linked using absolute paths and resolved via
their <literal>install_name</literal> correctly, tests can sometimes fail their <literal>install_name</literal> correctly, tests can sometimes fail
to run binaries. This happens because the <varname>checkPhase</varname> to run binaries. This happens because the <varname>checkPhase</varname>
runs before the libraries are installed. runs before the libraries are installed.
</para> </para>
<para> <para>
This can usually be solved by running the tests after the This can usually be solved by running the tests after the
<varname>installPhase</varname> or alternatively by using <varname>installPhase</varname> or alternatively by using
<varname>DYLD_LIBRARY_PATH</varname>. More information about this variable <varname>DYLD_LIBRARY_PATH</varname>. More information about this variable
can be found in the <citerefentry><refentrytitle>dyld</refentrytitle> can be found in the <citerefentry>
<refentrytitle>dyld</refentrytitle>
<manvolnum>1</manvolnum></citerefentry> manpage. <manvolnum>1</manvolnum></citerefentry> manpage.
</para> </para>
<programlisting> <programlisting>
@ -77,7 +76,6 @@
} }
</programlisting> </programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Some packages assume xcode is available and use <command>xcrun</command> Some packages assume xcode is available and use <command>xcrun</command>
@ -98,8 +96,8 @@
</programlisting> </programlisting>
<para> <para>
The package <literal>xcbuild</literal> can be used to build projects that The package <literal>xcbuild</literal> can be used to build projects that
really depend on Xcode, however projects that build some kind of graphical really depend on Xcode. However, this replacement is not 100% compatible
interface won't work without using Xcode in an impure way. with Xcode and can occasionally cause issues.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>

View File

@ -147,9 +147,9 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
You can use <command>nix-prefetch-url</command> (or similar You can use <command>nix-prefetch-url</command>
nix-prefetch-git, etc) <replaceable>url</replaceable> to get the <replaceable>url</replaceable> to get the SHA-256 hash of source
SHA-256 hash of source distributions. There are similar commands as distributions. There are similar commands as
<command>nix-prefetch-git</command> and <command>nix-prefetch-git</command> and
<command>nix-prefetch-hg</command> available in <command>nix-prefetch-hg</command> available in
<literal>nix-prefetch-scripts</literal> package. <literal>nix-prefetch-scripts</literal> package.

View File

@ -2,7 +2,7 @@
<article xmlns="http://docbook.org/ns/docbook" <article xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"> xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Nixpkgs Release Notes</title> <title>Nixpkgs Release Notes</title>
<section> <section xml:id="release-notes-0.14">
<title>Release 0.14 (June 4, 2012)</title> <title>Release 0.14 (June 4, 2012)</title>
<para> <para>
@ -17,7 +17,7 @@
packages by numerous contributors. For details, see the commit logs. packages by numerous contributors. For details, see the commit logs.
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.13">
<title>Release 0.13 (February 5, 2010)</title> <title>Release 0.13 (February 5, 2010)</title>
<para> <para>
@ -51,7 +51,7 @@
</itemizedlist> </itemizedlist>
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.12">
<title>Release 0.12 (April 24, 2009)</title> <title>Release 0.12 (April 24, 2009)</title>
<para> <para>
@ -145,7 +145,7 @@
<literal>nix-dev</literal> mailing list. <literal>nix-dev</literal> mailing list.
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.11">
<title>Release 0.11 (September 11, 2007)</title> <title>Release 0.11 (September 11, 2007)</title>
<para> <para>
@ -344,7 +344,7 @@ export NIX_MIRRORS_sourceforge=http://osdn.dl.sourceforge.net/sourceforge/</prog
Bravenboer, Michael Raskin, Wouter den Breejen and Yury G. Kudryashov. Bravenboer, Michael Raskin, Wouter den Breejen and Yury G. Kudryashov.
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.10">
<title>Release 0.10 (October 12, 2006)</title> <title>Release 0.10 (October 12, 2006)</title>
<note> <note>
@ -547,7 +547,7 @@ stdenv.mkDerivation {
Bravenboer, Merijn de Jonge, Rob Vermaas and Roy van den Broek. Bravenboer, Merijn de Jonge, Rob Vermaas and Roy van den Broek.
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.9">
<title>Release 0.9 (January 31, 2006)</title> <title>Release 0.9 (January 31, 2006)</title>
<para> <para>
@ -676,7 +676,7 @@ stdenv.mkDerivation {
Martin Bravenboer, Rob Vermaas and Roy van den Broek. Martin Bravenboer, Rob Vermaas and Roy van den Broek.
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.8">
<title>Release 0.8 (April 11, 2005)</title> <title>Release 0.8 (April 11, 2005)</title>
<para> <para>
@ -700,7 +700,7 @@ stdenv.mkDerivation {
</itemizedlist> </itemizedlist>
</para> </para>
</section> </section>
<section> <section xml:id="release-notes-0.7">
<title>Release 0.7 (March 14, 2005)</title> <title>Release 0.7 (March 14, 2005)</title>
<itemizedlist> <itemizedlist>

View File

@ -6,31 +6,33 @@
<title>Reviewing contributions</title> <title>Reviewing contributions</title>
<warning> <warning>
<para> <para>
The following section is a draft, and the policy for reviewing is still being The following section is a draft, and the policy for reviewing is still
discussed in issues such as <link being discussed in issues such as
<link
xlink:href="https://github.com/NixOS/nixpkgs/issues/11166">#11166 xlink:href="https://github.com/NixOS/nixpkgs/issues/11166">#11166
</link> and <link </link> and
<link
xlink:href="https://github.com/NixOS/nixpkgs/issues/20836">#20836 xlink:href="https://github.com/NixOS/nixpkgs/issues/20836">#20836
</link>. </link>.
</para> </para>
</warning> </warning>
<para> <para>
The nixpkgs project receives a fairly high number of contributions via The Nixpkgs project receives a fairly high number of contributions via GitHub
GitHub pull-requests. Reviewing and approving these is an important task and pull requests. Reviewing and approving these is an important task and a way
a way to contribute to the project. to contribute to the project.
</para> </para>
<para> <para>
The high change rate of nixpkgs makes any pull request that remains open for The high change rate of Nixpkgs makes any pull request that remains open for
too long subject to conflicts that will require extra work from the submitter too long subject to conflicts that will require extra work from the submitter
or the merger. Reviewing pull requests in a timely manner and being or the merger. Reviewing pull requests in a timely manner and being
responsive to the comments is the key to avoid these. GitHub provides sort responsive to the comments is the key to avoid this issue. GitHub provides
filters that can be used to see the sort filters that can be used to see the
<link <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc">most xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc">most
recently</link> and the recently</link> and the
<link <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-asc">least xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-asc">least
recently</link> updated pull-requests. We highly encourage looking at recently</link> updated pull requests. We highly encourage looking at
<link xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+review%3Anone+status%3Asuccess+-label%3A%222.status%3A+work-in-progress%22+no%3Aproject+no%3Aassignee+no%3Amilestone"> <link xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+review%3Anone+status%3Asuccess+-label%3A%222.status%3A+work-in-progress%22+no%3Aproject+no%3Aassignee+no%3Amilestone">
this list of ready to merge, unreviewed pull requests</link>. this list of ready to merge, unreviewed pull requests</link>.
</para> </para>
@ -40,13 +42,13 @@
to respect every community member and their work. to respect every community member and their work.
</para> </para>
<para> <para>
GitHub provides reactions as a simple and quick way to provide GitHub provides reactions as a simple and quick way to provide feedback to
feedback to pull-requests or any comments. The thumb-down reaction should be pull requests or any comments. The thumb-down reaction should be used with
used with care and if possible accompanied with some explanation so the care and if possible accompanied with some explanation so the submitter has
submitter has directions to improve their contribution. directions to improve their contribution.
</para> </para>
<para> <para>
Pull-request reviews should include a list of what has been reviewed in a pull request reviews should include a list of what has been reviewed in a
comment, so other reviewers and mergers can know the state of the review. comment, so other reviewers and mergers can know the state of the review.
</para> </para>
<para> <para>
@ -54,12 +56,12 @@
meant as examples. Their usage is optional and the reviewer is free to adapt meant as examples. Their usage is optional and the reviewer is free to adapt
them to their liking. them to their liking.
</para> </para>
<section> <section xml:id="reviewing-contributions-package-updates">
<title>Package updates</title> <title>Package updates</title>
<para> <para>
A package update is the most trivial and common type of pull-request. These A package update is the most trivial and common type of pull request. These
pull-requests mainly consist of updating the version part of the package pull requests mainly consist of updating the version part of the package
name and the source hash. name and the source hash.
</para> </para>
@ -75,7 +77,7 @@
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Add labels to the pull-request. (Requires commit rights) Add labels to the pull request. (Requires commit rights)
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -117,8 +119,8 @@
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
License can change with version updates, so it should be checked to match License can change with version updates, so it should be checked to
the upstream license. match the upstream license.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -142,9 +144,9 @@
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Pull-requests are often targeted to the master or staging branch, and pull requests are often targeted to the master or staging branch, and
building the pull-request locally when it is submitted can trigger building the pull request locally when it is submitted can trigger many
many source builds. source builds.
</para> </para>
<para> <para>
It is possible to rebase the changes on nixos-unstable or It is possible to rebase the changes on nixos-unstable or
@ -172,14 +174,14 @@ $ git rebase --onto nixos-unstable BASEBRANCH FETCH_HEAD <co
</callout> </callout>
<callout arearefs='reviewing-rebase-3'> <callout arearefs='reviewing-rebase-3'>
<para> <para>
Fetching the pull-request changes, <varname>PRNUMBER</varname> is the Fetching the pull request changes, <varname>PRNUMBER</varname> is the
number at the end of the pull-request title and number at the end of the pull request title and
<varname>BASEBRANCH</varname> the base branch of the pull-request. <varname>BASEBRANCH</varname> the base branch of the pull request.
</para> </para>
</callout> </callout>
<callout arearefs='reviewing-rebase-4'> <callout arearefs='reviewing-rebase-4'>
<para> <para>
Rebasing the pull-request changes to the nixos-unstable branch. Rebasing the pull request changes to the nixos-unstable branch.
</para> </para>
</callout> </callout>
</calloutlist> </calloutlist>
@ -187,14 +189,15 @@ $ git rebase --onto nixos-unstable BASEBRANCH FETCH_HEAD <co
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
The <link xlink:href="https://github.com/madjar/nox">nox</link> tool can The
be used to review a pull-request content in a single command. It doesn't <link xlink:href="https://github.com/Mic92/nix-review">nix-review</link>
rebase on a channel branch so it might trigger multiple source builds. tool can be used to review a pull request content in a single command.
<varname>PRNUMBER</varname> should be replaced by the number at the end <varname>PRNUMBER</varname> should be replaced by the number at the end
of the pull-request title. of the pull request title. You can also provide the full github pull
request url.
</para> </para>
<screen> <screen>
$ nix-shell -p nox --run "nox-review -k pr PRNUMBER" $ nix-shell -p nix-review --run "nix-review pr PRNUMBER"
</screen> </screen>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -206,7 +209,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<example> <example xml:id="reviewing-contributions-sample-package-update">
<title>Sample template for a package update review</title> <title>Sample template for a package update review</title>
<screen> <screen>
##### Reviewed points ##### Reviewed points
@ -224,11 +227,11 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</screen> </screen>
</example> </example>
</section> </section>
<section> <section xml:id="reviewing-contributions-new-packages">
<title>New packages</title> <title>New packages</title>
<para> <para>
New packages are a common type of pull-requests. These pull requests New packages are a common type of pull requests. These pull requests
consists in adding a new nix-expression for a package. consists in adding a new nix-expression for a package.
</para> </para>
@ -239,7 +242,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Add labels to the pull-request. (Requires commit rights) Add labels to the pull request. (Requires commit rights)
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -277,7 +280,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
A maintainer must be set, this can be the package submitter or a A maintainer must be set. This can be the package submitter or a
community member that accepts to take maintainership of the package. community member that accepts to take maintainership of the package.
</para> </para>
</listitem> </listitem>
@ -318,7 +321,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<example> <example xml:id="reviewing-contributions-sample-new-package">
<title>Sample template for a new package review</title> <title>Sample template for a new package review</title>
<screen> <screen>
##### Reviewed points ##### Reviewed points
@ -344,7 +347,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</screen> </screen>
</example> </example>
</section> </section>
<section> <section xml:id="reviewing-contributions-module-updates">
<title>Module updates</title> <title>Module updates</title>
<para> <para>
@ -359,7 +362,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Add labels to the pull-request. (Requires commit rights) Add labels to the pull request. (Requires commit rights)
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -441,7 +444,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<example> <example xml:id="reviewing-contributions-sample-module-update">
<title>Sample template for a module update review</title> <title>Sample template for a module update review</title>
<screen> <screen>
##### Reviewed points ##### Reviewed points
@ -462,7 +465,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</screen> </screen>
</example> </example>
</section> </section>
<section> <section xml:id="reviewing-contributions-new-modules">
<title>New modules</title> <title>New modules</title>
<para> <para>
@ -472,7 +475,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Add labels to the pull-request. (Requires commit rights) Add labels to the pull request. (Requires commit rights)
</para> </para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
@ -540,7 +543,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<example> <example xml:id="reviewing-contributions-sample-new-module">
<title>Sample template for a new module review</title> <title>Sample template for a new module review</title>
<screen> <screen>
##### Reviewed points ##### Reviewed points
@ -562,7 +565,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
</screen> </screen>
</example> </example>
</section> </section>
<section> <section xml:id="reviewing-contributions-other-submissions">
<title>Other submissions</title> <title>Other submissions</title>
<para> <para>
@ -574,7 +577,7 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
like to be a long-term reviewer for related submissions, please contact the like to be a long-term reviewer for related submissions, please contact the
current reviewers for that topic. They will give you information about the current reviewers for that topic. They will give you information about the
reviewing process. The main reviewers for a topic can be hard to find as reviewing process. The main reviewers for a topic can be hard to find as
there is no list, but checking past pull-requests to see who reviewed or there is no list, but checking past pull requests to see who reviewed or
git-blaming the code to see who committed to that topic can give some hints. git-blaming the code to see who committed to that topic can give some hints.
</para> </para>
@ -583,8 +586,8 @@ $ nix-shell -p nox --run "nox-review -k pr PRNUMBER"
pull requests fitting this category. pull requests fitting this category.
</para> </para>
</section> </section>
<section> <section xml:id="reviewing-contributions--merging-pull-requests">
<title>Merging pull-requests</title> <title>Merging pull requests</title>
<para> <para>
It is possible for community members that have enough knowledge and It is possible for community members that have enough knowledge and
@ -605,10 +608,12 @@ policy.
--> -->
<para> <para>
In a case a contributor leaves definitively the Nix community, he should In a case a contributor definitively leaves the Nix community, they should
create an issue or notify the mailing list with references of packages and create an issue or post on
modules he maintains so the maintainership can be taken over by other <link
contributors. xlink:href="https://discourse.nixos.org">Discourse</link> with
references of packages and modules they maintain so the maintainership can
be taken over by other contributors.
</para> </para>
</section> </section>
</chapter> </chapter>

View File

@ -1,5 +1,5 @@
{ pkgs ? import ../. {} }: { pkgs ? import ../. {} }:
(import ./default.nix).overrideAttrs (x: { (import ./default.nix {}).overrideAttrs (x: {
buildInputs = x.buildInputs ++ [ pkgs.xmloscopy pkgs.ruby ]; buildInputs = x.buildInputs ++ [ pkgs.xmloscopy pkgs.ruby ];
}) })

View File

@ -1,22 +0,0 @@
---
title: pkgs.mkShell
author: zimbatm
date: 2017-10-30
---
# mkShell
pkgs.mkShell is a special kind of derivation that is only useful when using
it combined with nix-shell. It will in fact fail to instantiate when invoked
with nix-build.
## Usage
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar available to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
```

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
body body
{ {
font-family: "Nimbus Sans L", sans-serif; font-family: "Nimbus Sans L", sans-serif;
font-size: 1em;
background: white; background: white;
margin: 2em 1em 2em 1em; margin: 2em 1em 2em 1em;
} }
@ -28,6 +29,25 @@ h2 /* chapters, appendices, subtitle */
font-size: 180%; font-size: 180%;
} }
div.book
{
text-align: center;
}
div.book > div
{
/*
* based on https://medium.com/@zkareemz/golden-ratio-62b3b6d4282a
* we do 70 characters per line to fit code listings better
* 70 * (font-size / 1.618)
* expression for emacs:
* (* 70 (/ 1 1.618))
*/
max-width: 43.2em;
text-align: left;
margin: auto;
}
/* Extra space between chapters, appendices. */ /* Extra space between chapters, appendices. */
div.chapter > div.titlepage h2, div.appendix > div.titlepage h2 div.chapter > div.titlepage h2, div.appendix > div.titlepage h2
{ {
@ -102,8 +122,8 @@ pre.screen, pre.programlisting
{ {
border: 1px solid #b0b0b0; border: 1px solid #b0b0b0;
padding: 3px 3px; padding: 3px 3px;
margin-left: 1.5em; margin-left: 0.5em;
margin-right: 1.5em; margin-right: 0.5em;
background: #f4f4f8; background: #f4f4f8;
font-family: monospace; font-family: monospace;

View File

@ -2,7 +2,7 @@
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-submitting-changes"> xml:id="chap-submitting-changes">
<title>Submitting changes</title> <title>Submitting changes</title>
<section> <section xml:id="submitting-changes-making-patches">
<title>Making patches</title> <title>Making patches</title>
<itemizedlist> <itemizedlist>
@ -205,7 +205,7 @@ Additional information.
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="submitting-changes-submitting-changes">
<title>Submitting changes</title> <title>Submitting changes</title>
<itemizedlist> <itemizedlist>
@ -253,7 +253,7 @@ Additional information.
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="submitting-changes-pull-request-template">
<title>Pull Request Template</title> <title>Pull Request Template</title>
<para> <para>
@ -269,7 +269,7 @@ Additional information.
below: below:
</para> </para>
<section> <section xml:id="submitting-changes-tested-with-sandbox">
<title>Tested using sandboxing</title> <title>Tested using sandboxing</title>
<para> <para>
@ -322,7 +322,7 @@ Additional information.
</para> </para>
</section> </section>
<section> <section xml:id="submitting-changes-platform-diversity">
<title>Built on platform(s)</title> <title>Built on platform(s)</title>
<para> <para>
@ -334,7 +334,7 @@ Additional information.
</para> </para>
</section> </section>
<section> <section xml:id="submitting-changes-nixos-tests">
<title>Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)</title> <title>Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)</title>
<para> <para>
@ -350,30 +350,29 @@ Additional information.
</para> </para>
</section> </section>
<section> <section xml:id="submitting-changes-tested-compilation">
<title>Tested compilation of all pkgs that depend on this change using <command>nox-review</command></title> <title>Tested compilation of all pkgs that depend on this change using <command>nix-review</command></title>
<para> <para>
If you are updating a package's version, you can use nox to make sure all If you are updating a package's version, you can use nix-review to make
packages that depend on the updated package still compile correctly. This sure all packages that depend on the updated package still compile
can be done using the nox utility. The <command>nox-review</command> correctly. The <command>nix-review</command> utility can look for and build
utility can look for and build all dependencies either based on uncommited all dependencies either based on uncommited changes with the
changes with the <literal>wip</literal> option or specifying a github pull <literal>wip</literal> option or specifying a github pull request number.
request number.
</para>
<para>
review uncommitted changes:
<screen>nix-shell -p nox --run "nox-review wip"</screen>
</para> </para>
<para> <para>
review changes from pull request number 12345: review changes from pull request number 12345:
<screen>nix-shell -p nox --run "nox-review pr 12345"</screen> <screen>nix-shell -p nix-review --run "nix-review pr 12345"</screen>
</para>
<para>
review uncommitted changes:
<screen>nix-shell -p nix-review --run "nix-review wip"</screen>
</para> </para>
</section> </section>
<section> <section xml:id="submitting-changes-tested-execution">
<title>Tested execution of all binary files (usually in <filename>./result/bin/</filename>)</title> <title>Tested execution of all binary files (usually in <filename>./result/bin/</filename>)</title>
<para> <para>
@ -387,8 +386,8 @@ Additional information.
</para> </para>
</section> </section>
<section> <section xml:id="submitting-changes-contribution-standards">
<title>Meets nixpkgs contribution standards</title> <title>Meets Nixpkgs contribution standards</title>
<para> <para>
The last checkbox is fits The last checkbox is fits
@ -402,7 +401,7 @@ Additional information.
</para> </para>
</section> </section>
</section> </section>
<section> <section xml:id="submitting-changes-hotfixing-pull-requests">
<title>Hotfixing pull requests</title> <title>Hotfixing pull requests</title>
<itemizedlist> <itemizedlist>
@ -430,7 +429,7 @@ Additional information.
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="submitting-changes-commit-policy">
<title>Commit policy</title> <title>Commit policy</title>
<itemizedlist> <itemizedlist>
@ -456,7 +455,7 @@ Additional information.
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<section> <section xml:id="submitting-changes-master-branch">
<title>Master branch</title> <title>Master branch</title>
<itemizedlist> <itemizedlist>
@ -468,7 +467,7 @@ Additional information.
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="submitting-changes-staging-branch">
<title>Staging branch</title> <title>Staging branch</title>
<itemizedlist> <itemizedlist>
@ -493,7 +492,7 @@ Additional information.
</itemizedlist> </itemizedlist>
</section> </section>
<section> <section xml:id="submitting-changes-stable-release-branches">
<title>Stable release branches</title> <title>Stable release branches</title>
<itemizedlist> <itemizedlist>

44
lib/asserts.nix Normal file
View File

@ -0,0 +1,44 @@
{ lib }:
rec {
/* Print a trace message if pred is false.
Intended to be used to augment asserts with helpful error messages.
Example:
assertMsg false "nope"
=> false
stderr> trace: nope
assert (assertMsg ("foo" == "bar") "foo is not bar, silly"); ""
stderr> trace: foo is not bar, silly
stderr> assert failed at
Type:
assertMsg :: Bool -> String -> Bool
*/
# TODO(Profpatsch): add tests that check stderr
assertMsg = pred: msg:
if pred
then true
else builtins.trace msg false;
/* Specialized `assertMsg` for checking if val is one of the elements
of a list. Useful for checking enums.
Example:
let sslLibrary = "libressl"
in assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ]
=> false
stderr> trace: sslLibrary must be one of "openssl", "bearssl", but is: "libressl"
Type:
assertOneOf :: String -> ComparableVal -> List ComparableVal -> Bool
*/
assertOneOf = name: val: xs: assertMsg
(lib.elem val xs)
"${name} must be one of ${
lib.generators.toPretty {} xs}, but is: ${
lib.generators.toPretty {} val}";
}

View File

@ -94,6 +94,15 @@ rec {
attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs); attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
/* Given a set of attribute names, return the set of the corresponding
attributes from the given set.
Example:
getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
=> { a = 1; b = 2; }
*/
getAttrs = names: attrs: genAttrs names (name: attrs.${name});
/* Collect each attribute named `attr' from a list of attribute /* Collect each attribute named `attr' from a list of attribute
sets. Sets that don't contain the named attribute are ignored. sets. Sets that don't contain the named attribute are ignored.
@ -145,7 +154,7 @@ rec {
foldAttrs = op: nul: list_of_attrs: foldAttrs = op: nul: list_of_attrs:
fold (n: a: fold (n: a:
fold (name: o: fold (name: o:
o // (listToAttrs [{inherit name; value = op n.${name} (a.${name} or nul); }]) o // { ${name} = op n.${name} (a.${name} or nul); }
) a (attrNames n) ) a (attrNames n)
) {} list_of_attrs; ) {} list_of_attrs;
@ -435,12 +444,15 @@ rec {
useful for deep-overriding. useful for deep-overriding.
Example: Example:
x = { a = { b = 4; c = 3; }; } overrideExisting {} { a = 1; }
overrideExisting x { a = { b = 6; d = 2; }; } => {}
=> { a = { b = 6; d = 2; }; } overrideExisting { b = 2; } { a = 1; }
=> { b = 2; }
overrideExisting { a = 3; b = 2; } { a = 1; }
=> { a = 1; b = 2; }
*/ */
overrideExisting = old: new: overrideExisting = old: new:
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old)); mapAttrs (name: value: new.${name} or value) old;
/* Get a package output. /* Get a package output.
If no output is found, fallback to `.out` and then to the default. If no output is found, fallback to `.out` and then to the default.

View File

@ -1,113 +0,0 @@
{lib, pkgs}:
let inherit (lib) nvs; in
{
# composableDerivation basically mixes these features:
# - fix function
# - mergeAttrBy
# - provides shortcuts for "options" such as "--enable-foo" and adding
# buildInputs, see php example
#
# It predates styles which are common today, such as
# * the config attr
# * mkDerivation.override feature
# * overrideDerivation (lib/customization.nix)
#
# Some of the most more important usage examples (which could be rewritten if it was important):
# * php
# * postgis
# * vim_configurable
#
# A minimal example illustrating most features would look like this:
# let base = composableDerivation { (fixed: let inherit (fixed.fixed) name in {
# src = fetchurl {
# }
# buildInputs = [A];
# preConfigre = "echo ${name}";
# # attention, "name" attr is missing, thus you cannot instantiate "base".
# }
# in {
# # These all add name attribute, thus you can instantiate those:
# v1 = base.merge ({ name = "foo-add-B"; buildInputs = [B]; }); // B gets merged into buildInputs
# v2 = base.merge ({ name = "mix-in-pre-configure-lines" preConfigre = ""; });
# v3 = base.replace ({ name = "foo-no-A-only-B;" buildInputs = [B]; });
# }
#
# So yes, you can think about it being something like nixos modules, and
# you'd be merging "features" in one at a time using .merge or .replace
# Thanks Shea for telling me that I rethink the documentation ..
#
# issues:
# * its complicated to understand
# * some "features" such as exact merge behaviour are buried in mergeAttrBy
# and defaultOverridableDelayableArgs assuming the default behaviour does
# the right thing in the common case
# * Eelco once said using such fix style functions are slow to evaluate
# * Too quick & dirty. Hard to understand for others. The benefit was that
# you were able to create a kernel builder like base derivation and replace
# / add patches the way you want without having to declare function arguments
#
# nice features:
# declaring "optional features" is modular. For instance:
# flags.curl = {
# configureFlags = ["--with-curl=${curl.dev}" "--with-curlwrappers"];
# buildInputs = [curl openssl];
# };
# flags.other = { .. }
# (Example taken from PHP)
#
# alternative styles / related features:
# * Eg see function supporting building the kernel
# * versionedDerivation (discussion about this is still going on - or ended)
# * composedArgsAndFun
# * mkDerivation.override
# * overrideDerivation
# * using { .., *Support ? false }: like configurable options.
# To find those examples use grep
#
# To sum up: It exists for historical reasons - and for most commonly used
# tasks the alternatives should be used
#
# If you have questions about this code ping Marc Weber.
composableDerivation = {
mkDerivation ? pkgs.stdenv.mkDerivation,
# list of functions to be applied before defaultOverridableDelayableArgs removes removeAttrs names
# prepareDerivationArgs handles derivation configurations
applyPreTidy ? [ lib.prepareDerivationArgs ],
# consider adding addtional elements by derivation.merge { removeAttrs = ["elem"]; };
removeAttrs ? ["cfg" "flags"]
}: (lib.defaultOverridableDelayableArgs ( a: mkDerivation a)
{
inherit applyPreTidy removeAttrs;
}).merge;
# some utility functions
# use this function to generate flag attrs for prepareDerivationArgs
# E nable D isable F eature
edf = {name, feat ? name, enable ? {}, disable ? {} , value ? ""}:
nvs name {
set = {
configureFlags = ["--enable-${feat}${if value == "" then "" else "="}${value}"];
} // enable;
unset = {
configureFlags = ["--disable-${feat}"];
} // disable;
};
# same for --with and --without-
# W ith or W ithout F eature
wwf = {name, feat ? name, enable ? {}, disable ? {}, value ? ""}:
nvs name {
set = enable // {
configureFlags = ["--with-${feat}${if value == "" then "" else "="}${value}"]
++ lib.maybeAttr "configureFlags" [] enable;
};
unset = disable // {
configureFlags = ["--without-${feat}"]
++ lib.maybeAttr "configureFlags" [] disable;
};
};
}

View File

@ -121,7 +121,7 @@ rec {
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs; auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
origArgs = auto // args; origArgs = auto // args;
pkgs = f origArgs; pkgs = f origArgs;
mkAttrOverridable = name: pkg: makeOverridable (newArgs: (f newArgs).${name}) origArgs; mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
in lib.mapAttrs mkAttrOverridable pkgs; in lib.mapAttrs mkAttrOverridable pkgs;
@ -185,7 +185,7 @@ rec {
/* Make a set of packages with a common scope. All packages called /* Make a set of packages with a common scope. All packages called
with the provided `callPackage' will be evaluated with the same with the provided `callPackage' will be evaluated with the same
arguments. Any package in the set may depend on any other. The arguments. Any package in the set may depend on any other. The
`overrideScope' function allows subsequent modification of the package `overrideScope'` function allows subsequent modification of the package
set in a consistent way, i.e. all packages in the set will be set in a consistent way, i.e. all packages in the set will be
called with the overridden packages. The package sets may be called with the overridden packages. The package sets may be
hierarchical: the packages in the set are called with the scope hierarchical: the packages in the set are called with the scope
@ -195,10 +195,10 @@ rec {
let self = f self // { let self = f self // {
newScope = scope: newScope (self // scope); newScope = scope: newScope (self // scope);
callPackage = self.newScope {}; callPackage = self.newScope {};
# TODO(@Ericson2314): Haromonize argument order of `g` with everything else overrideScope = g: lib.warn
overrideScope = g: "`overrideScope` (from `lib.makeScope`) is deprecated. Do `overrideScope' (self: super: { })` instead of `overrideScope (super: self: { })`. All other overrides have the parameters in that order, including other definitions of `overrideScope`. This was the only definition violating the pattern."
makeScope newScope (makeScope newScope (lib.fixedPoints.extends (lib.flip g) f));
(lib.fixedPoints.extends (lib.flip g) f); overrideScope' = g: makeScope newScope (lib.fixedPoints.extends g f);
packages = f; packages = f;
}; };
in self; in self;

View File

@ -23,27 +23,54 @@ rec {
# -- TRACING -- # -- TRACING --
/* Trace msg, but only if pred is true. /* Conditionally trace the supplied message, based on a predicate.
Type: traceIf :: bool -> string -> a -> a
Example: Example:
traceIf true "hello" 3 traceIf true "hello" 3
trace: hello trace: hello
=> 3 => 3
*/ */
traceIf = pred: msg: x: if pred then trace msg x else x; traceIf =
# Predicate to check
pred:
# Message that should be traced
msg:
# Value to return
x: if pred then trace msg x else x;
/* Trace the value and also return it. /* Trace the supplied value after applying a function to it, and
return the original value.
Type: traceValFn :: (a -> b) -> a -> a
Example: Example:
traceValFn (v: "mystring ${v}") "foo" traceValFn (v: "mystring ${v}") "foo"
trace: mystring foo trace: mystring foo
=> "foo" => "foo"
*/ */
traceValFn = f: x: trace (f x) x; traceValFn =
# Function to apply
f:
# Value to trace and return
x: trace (f x) x;
/* Trace the supplied value and return it.
Type: traceVal :: a -> a
Example:
traceVal 42
# trace: 42
=> 42
*/
traceVal = traceValFn id; traceVal = traceValFn id;
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first. /* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
Type: traceSeq :: a -> b -> b
Example: Example:
trace { a.b.c = 3; } null trace { a.b.c = 3; } null
trace: { a = <CODE>; } trace: { a = <CODE>; }
@ -52,7 +79,11 @@ rec {
trace: { a = { b = { c = 3; }; }; } trace: { a = { b = { c = 3; }; }; }
=> null => null
*/ */
traceSeq = x: y: trace (builtins.deepSeq x x) y; traceSeq =
# The value to trace
x:
# The value to return
y: trace (builtins.deepSeq x x) y;
/* Like `traceSeq`, but only evaluate down to depth n. /* Like `traceSeq`, but only evaluate down to depth n.
This is very useful because lots of `traceSeq` usages This is very useful because lots of `traceSeq` usages
@ -76,27 +107,49 @@ rec {
in trace (generators.toPretty { allowPrettyValues = true; } in trace (generators.toPretty { allowPrettyValues = true; }
(modify depth snip x)) y; (modify depth snip x)) y;
/* A combination of `traceVal` and `traceSeq` */ /* A combination of `traceVal` and `traceSeq` that applies a
traceValSeqFn = f: v: traceValFn f (builtins.deepSeq v v); provided function to the value to be traced after `deepSeq`ing
it.
*/
traceValSeqFn =
# Function to apply
f:
# Value to trace
v: traceValFn f (builtins.deepSeq v v);
/* A combination of `traceVal` and `traceSeq`. */
traceValSeq = traceValSeqFn id; traceValSeq = traceValSeqFn id;
/* A combination of `traceVal` and `traceSeqN` that applies a
provided function to the value to be traced. */
traceValSeqNFn =
# Function to apply
f:
depth:
# Value to trace
v: traceSeqN depth (f v) v;
/* A combination of `traceVal` and `traceSeqN`. */ /* A combination of `traceVal` and `traceSeqN`. */
traceValSeqNFn = f: depth: v: traceSeqN depth (f v) v;
traceValSeqN = traceValSeqNFn id; traceValSeqN = traceValSeqNFn id;
# -- TESTING -- # -- TESTING --
/* Evaluate a set of tests. A test is an attribute set {expr, /* Evaluate a set of tests. A test is an attribute set `{expr,
expected}, denoting an expression and its expected result. The expected}`, denoting an expression and its expected result. The
result is a list of failed tests, each represented as {name, result is a list of failed tests, each represented as `{name,
expected, actual}, denoting the attribute name of the failing expected, actual}`, denoting the attribute name of the failing
test and its expected and actual results. Used for regression test and its expected and actual results.
testing of the functions in lib; see tests.nix for an example.
Only tests having names starting with "test" are run. Used for regression testing of the functions in lib; see
Add attr { tests = ["testName"]; } to run these test only tests.nix for an example. Only tests having names starting with
"test" are run.
Add attr { tests = ["testName"]; } to run these tests only.
*/ */
runTests = tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test: runTests =
# Tests to run
tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test:
let testsToRun = if tests ? tests then tests.tests else []; let testsToRun = if tests ? tests then tests.tests else [];
in if (substring 0 4 name == "test" || elem name testsToRun) in if (substring 0 4 name == "test" || elem name testsToRun)
&& ((testsToRun == []) || elem name tests.tests) && ((testsToRun == []) || elem name tests.tests)
@ -105,8 +158,11 @@ rec {
then [ { inherit name; expected = test.expected; result = test.expr; } ] then [ { inherit name; expected = test.expected; result = test.expr; } ]
else [] ) tests)); else [] ) tests));
# create a test assuming that list elements are true /* Create a test assuming that list elements are `true`.
# usage: { testX = allTrue [ true ]; }
Example:
{ testX = allTrue [ true ]; }
*/
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; }; testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };

View File

@ -38,10 +38,11 @@ let
systems = callLibs ./systems; systems = callLibs ./systems;
# misc # misc
asserts = callLibs ./asserts.nix;
debug = callLibs ./debug.nix; debug = callLibs ./debug.nix;
generators = callLibs ./generators.nix; generators = callLibs ./generators.nix;
misc = callLibs ./deprecated.nix; misc = callLibs ./deprecated.nix;
# domain-specific # domain-specific
fetchers = callLibs ./fetchers.nix; fetchers = callLibs ./fetchers.nix;
@ -58,13 +59,12 @@ let
stringLength sub substring tail; stringLength sub substring tail;
inherit (trivial) id const concat or and bitAnd bitOr bitXor bitNot inherit (trivial) id const concat or and bitAnd bitOr bitXor bitNot
boolToString mergeAttrs flip mapNullable inNixShell min max boolToString mergeAttrs flip mapNullable inNixShell min max
importJSON warn info nixpkgsVersion version mod compare importJSON warn info showWarnings nixpkgsVersion version mod compare
splitByAndCompare functionArgs setFunctionArgs isFunction; splitByAndCompare functionArgs setFunctionArgs isFunction;
inherit (fixedPoints) fix fix' converge extends composeExtensions
inherit (fixedPoints) fix fix' extends composeExtensions
makeExtensible makeExtensibleWithCustomName; makeExtensible makeExtensibleWithCustomName;
inherit (attrsets) attrByPath hasAttrByPath setAttrByPath inherit (attrsets) attrByPath hasAttrByPath setAttrByPath
getAttrFromPath attrVals attrValues catAttrs filterAttrs getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond
genAttrs isDerivation toDerivation optionalAttrs genAttrs isDerivation toDerivation optionalAttrs
@ -80,8 +80,8 @@ let
inherit (strings) concatStrings concatMapStrings concatImapStrings inherit (strings) concatStrings concatMapStrings concatImapStrings
intersperse concatStringsSep concatMapStringsSep intersperse concatStringsSep concatMapStringsSep
concatImapStringsSep makeSearchPath makeSearchPathOutput concatImapStringsSep makeSearchPath makeSearchPathOutput
makeLibraryPath makeBinPath makePerlPath makeFullPerlPath optionalString makeLibraryPath makeBinPath optionalString
hasPrefix hasSuffix stringToCharacters stringAsChars escape hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
escapeShellArg escapeShellArgs replaceChars lowerChars escapeShellArg escapeShellArgs replaceChars lowerChars
upperChars toLower toUpper addContextFrom splitString upperChars toLower toUpper addContextFrom splitString
removePrefix removeSuffix versionOlder versionAtLeast getVersion removePrefix removeSuffix versionOlder versionAtLeast getVersion
@ -94,7 +94,7 @@ let
callPackageWith callPackagesWith extendDerivation hydraJob callPackageWith callPackagesWith extendDerivation hydraJob
makeScope; makeScope;
inherit (meta) addMetaAttrs dontDistribute setName updateName inherit (meta) addMetaAttrs dontDistribute setName updateName
appendToName mapDerivationAttrset lowPrio lowPrioSet hiPrio appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
hiPrioSet; hiPrioSet;
inherit (sources) pathType pathIsDirectory cleanSourceFilter inherit (sources) pathType pathIsDirectory cleanSourceFilter
cleanSource sourceByRegex sourceFilesBySuffices cleanSource sourceByRegex sourceFilesBySuffices
@ -117,20 +117,22 @@ let
unknownModule mkOption; unknownModule mkOption;
inherit (types) isType setType defaultTypeMerge defaultFunctor inherit (types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType; isOptionType mkOptionType;
inherit (asserts)
assertMsg assertOneOf;
inherit (debug) addErrorContextToAttrs traceIf traceVal traceValFn inherit (debug) addErrorContextToAttrs traceIf traceVal traceValFn
traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq
traceValSeqFn traceValSeqN traceValSeqNFn traceShowVal traceValSeqFn traceValSeqN traceValSeqNFn traceShowVal
traceShowValMarked showVal traceCall traceCall2 traceCall3 traceShowValMarked showVal traceCall traceCall2 traceCall3
traceValIfNot runTests testAllTrue traceCallXml attrNamesToStr; traceValIfNot runTests testAllTrue traceCallXml attrNamesToStr;
inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs
defaultOverridableDelayableArgs composedArgsAndFun
maybeAttrNullable maybeAttr ifEnable checkFlag getValue maybeAttrNullable maybeAttr ifEnable checkFlag getValue
checkReqs uniqList uniqListExt condConcat lazyGenericClosure checkReqs uniqList uniqListExt condConcat lazyGenericClosure
innerModifySumArgs modifySumArgs innerClosePropagation innerModifySumArgs modifySumArgs innerClosePropagation
closePropagation mapAttrsFlatten nvs setAttr setAttrMerge closePropagation mapAttrsFlatten nvs setAttr setAttrMerge
mergeAttrsWithFunc mergeAttrsConcatenateValues mergeAttrsWithFunc mergeAttrsConcatenateValues
mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults
mergeAttrsByFuncDefaultsClean mergeAttrBy prepareDerivationArgs mergeAttrsByFuncDefaultsClean mergeAttrBy
nixType imap overridableDelayableArgs; fakeSha256 fakeSha512
nixType imap;
}); });
in lib in lib

View File

@ -35,74 +35,6 @@ rec {
withStdOverrides; 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 lib.isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
tidy = args:
let # apply all functions given in "applyPreTidy" in sequence
applyPreTidyFun = fold ( n: a: x: n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
in removeAttrs (applyPreTidyFun args) ( ["applyPreTidy"] ++ (maybeAttr "removeAttrs" [] args) ); # tidy up args before applying them
fun = n: x:
let newArgs = fixed:
let args = takeFixed fixed;
mergeFun = args.${n};
in if isAttrs x then (mergeFun args x)
else assert lib.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 # shortcut for attrByPath ["name"] default attrs
maybeAttrNullable = maybeAttr; maybeAttrNullable = maybeAttr;
@ -285,7 +217,7 @@ rec {
# }; # };
# will result in # will result in
# { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; } # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
# is used by prepareDerivationArgs, defaultOverridableDelayableArgs and can be used when composing using # is used by defaultOverridableDelayableArgs and can be used when composing using
# foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
mergeAttrByFunc = x: y: mergeAttrByFunc = x: y:
let let
@ -318,58 +250,6 @@ rec {
// listToAttrs (map (n: nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ]) // listToAttrs (map (n: nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
; ;
# prepareDerivationArgs tries to make writing configurable derivations easier
# example:
# prepareDerivationArgs {
# mergeAttrBy = {
# myScript = x: y: x ++ "\n" ++ y;
# };
# cfg = {
# readlineSupport = true;
# };
# flags = {
# readline = {
# set = {
# configureFlags = [ "--with-compiler=${compiler}" ];
# buildInputs = [ compiler ];
# pass = { inherit compiler; READLINE=1; };
# assertion = compiler.dllSupport;
# myScript = "foo";
# };
# unset = { configureFlags = ["--without-compiler"]; };
# };
# };
# src = ...
# buildPhase = '' ... '';
# name = ...
# myScript = "bar";
# };
# if you don't have need for unset you can omit the surrounding set = { .. } attr
# all attrs except flags cfg and mergeAttrBy will be merged with the
# additional data from flags depending on config settings
# It's used in composableDerivation in all-packages.nix. It's also used
# heavily in the new python and libs implementation
#
# should we check for misspelled cfg options?
# TODO use args.mergeFun here as well?
prepareDerivationArgs = args:
let args2 = { cfg = {}; flags = {}; } // args;
flagName = name: "${name}Support";
cfgWithDefaults = (listToAttrs (map (n: nameValuePair (flagName n) false) (attrNames args2.flags)))
// args2.cfg;
opts = attrValues (mapAttrs (a: v:
let v2 = if v ? set || v ? unset then v else { set = v; };
n = if cfgWithDefaults.${flagName a} then "set" else "unset";
attr = maybeAttr n {} v2; in
if (maybeAttr "assertion" true attr)
then attr
else throw "assertion of flag ${a} of derivation ${args.name} failed"
) args2.flags );
in removeAttrs
(mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
["flags" "cfg" "mergeAttrBy" ];
nixType = x: nixType = x:
if isAttrs x then if isAttrs x then
if x ? outPath then "derivation" if x ? outPath then "derivation"
@ -390,4 +270,8 @@ rec {
starting at zero. starting at zero.
*/ */
imap = imap1; imap = imap1;
# Fake hashes. Can be used as hash placeholders, when computing hash ahead isn't trivial
fakeSha256 = "0000000000000000000000000000000000000000000000000000000000000000";
fakeSha512 = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
} }

View File

@ -24,6 +24,19 @@ rec {
# for a concrete example. # for a concrete example.
fix' = f: let x = f x // { __unfix__ = f; }; in x; fix' = f: let x = f x // { __unfix__ = f; }; in x;
# Return the fixpoint that `f` converges to when called recursively, starting
# with the input `x`.
#
# nix-repl> converge (x: x / 2) 16
# 0
converge = f: x:
let
x' = f x;
in
if x' == x
then x
else converge f x';
# Modify the contents of an explicitly recursive attribute set in a way that # Modify the contents of an explicitly recursive attribute set in a way that
# honors `self`-references. This is accomplished with a function # honors `self`-references. This is accomplished with a function
# #
@ -41,6 +54,18 @@ rec {
# think of it as an infix operator `g extends f` that mimics the syntax from # think of it as an infix operator `g extends f` that mimics the syntax from
# Java. It may seem counter-intuitive to have the "base class" as the second # Java. It may seem counter-intuitive to have the "base class" as the second
# argument, but it's nice this way if several uses of `extends` are cascaded. # argument, but it's nice this way if several uses of `extends` are cascaded.
#
# To get a better understanding how `extends` turns a function with a fix
# point (the package set we start with) into a new function with a different fix
# point (the desired packages set) lets just see, how `extends g f`
# unfolds with `g` and `f` defined above:
#
# extends g f = self: let super = f self; in super // g self super;
# = self: let super = { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }; in super // g self super
# = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // g self { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
# = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // { foo = "foo" + " + "; }
# = self: { foo = "foo + "; bar = "bar"; foobar = self.foo + self.bar; }
#
extends = f: rattrs: self: let super = rattrs self; in super // f self super; extends = f: rattrs: self: let super = rattrs self; in super // f self super;
# Compose two extending functions of the type expected by 'extends' # Compose two extending functions of the type expected by 'extends'

View File

@ -143,6 +143,7 @@ rec {
}@args: v: with builtins; }@args: v: with builtins;
let isPath = v: typeOf v == "path"; let isPath = v: typeOf v == "path";
in if isInt v then toString v in if isInt v then toString v
else if isFloat v then "~${toString v}"
else if isString v then ''"${libStr.escape [''"''] v}"'' else if isString v then ''"${libStr.escape [''"''] v}"''
else if true == v then "true" else if true == v then "true"
else if false == v then "false" else if false == v then "false"

View File

@ -1,57 +1,21 @@
{ lib { lib, version }:
# we pass the kernel version here to keep a nice syntax `whenOlder "4.13"`
# kernelVersion, e.g., config.boot.kernelPackages.version
, version
, mkValuePreprocess ? null
}:
with lib; with lib;
rec { rec {
# Common patterns # Common patterns/legacy
when = cond: opt: if cond then opt else null; whenAtLeast = ver: mkIf (versionAtLeast version ver);
whenAtLeast = ver: when (versionAtLeast version ver); whenOlder = ver: mkIf (versionOlder version ver);
whenOlder = ver: when (versionOlder version ver); # range is (inclusive, exclusive)
whenBetween = verLow: verHigh: when (versionAtLeast version verLow && versionOlder version verHigh); whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh);
# Keeping these around in case we decide to change this horrible implementation :) # Keeping these around in case we decide to change this horrible implementation :)
option = x: if x == null then null else "?${x}"; option = x:
yes = "y"; x // { optional = true; };
no = "n";
module = "m";
mkValue = val: yes = { tristate = "y"; };
let no = { tristate = "n"; };
isNumber = c: elem c ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"]; module = { tristate = "m"; };
in freeform = x: { freeform = x; };
if val == "" then "\"\""
else if val == yes || val == module || val == no then val
else if all isNumber (stringToCharacters val) then val
else if substring 0 2 val == "0x" then val
else val; # FIXME: fix quoting one day
# generate nix intermediate kernel config file of the form
#
# VIRTIO_MMIO m
# VIRTIO_BLK y
# VIRTIO_CONSOLE n
# NET_9P_VIRTIO? y
#
# Use mkValuePreprocess to preprocess option values, aka mark 'modules' as
# 'yes' or vice-versa
# Borrowed from copumpkin https://github.com/NixOS/nixpkgs/pull/12158
# returns a string, expr should be an attribute set
generateNixKConf = exprs: mkValuePreprocess:
let
mkConfigLine = key: rawval:
let
val = if builtins.isFunction mkValuePreprocess then mkValuePreprocess rawval else rawval;
in
if val == null
then ""
else if hasPrefix "?" val
then "${key}? ${mkValue (removePrefix "?" val)}\n"
else "${key} ${mkValue val}\n";
mkConf = cfg: concatStrings (mapAttrsToList mkConfigLine cfg);
in mkConf exprs;
} }

View File

@ -13,6 +13,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
* add it to this list. The URL mentioned above is a good source for inspiration. * add it to this list. The URL mentioned above is a good source for inspiration.
*/ */
abstyles = spdx {
spdxId = "Abstyles";
fullName = "Abstyles License";
};
afl21 = spdx { afl21 = spdx {
spdxId = "AFL-2.1"; spdxId = "AFL-2.1";
fullName = "Academic Free License v2.1"; fullName = "Academic Free License v2.1";
@ -24,13 +29,13 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
}; };
agpl3 = spdx { agpl3 = spdx {
spdxId = "AGPL-3.0"; spdxId = "AGPL-3.0-only";
fullName = "GNU Affero General Public License v3.0"; fullName = "GNU Affero General Public License v3.0 only";
}; };
agpl3Plus = { agpl3Plus = spdx {
spdxId = "AGPL-3.0-or-later";
fullName = "GNU Affero General Public License v3.0 or later"; fullName = "GNU Affero General Public License v3.0 or later";
inherit (agpl3) url;
}; };
amazonsl = { amazonsl = {
@ -42,6 +47,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
amd = { amd = {
fullName = "AMD License Agreement"; fullName = "AMD License Agreement";
url = http://developer.amd.com/amd-license-agreement/; url = http://developer.amd.com/amd-license-agreement/;
free = false;
}; };
apsl20 = spdx { apsl20 = spdx {
@ -99,14 +105,10 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = ''BSD 4-clause "Original" or "Old" License''; fullName = ''BSD 4-clause "Original" or "Old" License'';
}; };
bsl10 = {
fullName = "Business Source License 1.0";
url = https://mariadb.com/bsl10;
};
bsl11 = { bsl11 = {
fullName = "Business Source License 1.1"; fullName = "Business Source License 1.1";
url = https://mariadb.com/bsl11; url = https://mariadb.com/bsl11;
free = false;
}; };
clArtistic = spdx { clArtistic = spdx {
@ -143,6 +145,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
free = false; free = false;
}; };
cc-by-nc-30 = spdx {
spdxId = "CC-BY-NC-3.0";
fullName = "Creative Commons Attribution Non Commercial 3.0 Unported";
free = false;
};
cc-by-nc-40 = spdx { cc-by-nc-40 = spdx {
spdxId = "CC-BY-NC-4.0"; spdxId = "CC-BY-NC-4.0";
fullName = "Creative Commons Attribution Non Commercial 4.0 International"; fullName = "Creative Commons Attribution Non Commercial 4.0 International";
@ -264,13 +272,23 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
}; };
fdl12 = spdx { fdl12 = spdx {
spdxId = "GFDL-1.2"; spdxId = "GFDL-1.2-only";
fullName = "GNU Free Documentation License v1.2"; fullName = "GNU Free Documentation License v1.2 only";
};
fdl12Plus = spdx {
spdxId = "GFDL-1.2-or-later";
fullName = "GNU Free Documentation License v1.2 or later";
}; };
fdl13 = spdx { fdl13 = spdx {
spdxId = "GFDL-1.3"; spdxId = "GFDL-1.3-only";
fullName = "GNU Free Documentation License v1.3"; fullName = "GNU Free Documentation License v1.3 only";
};
fdl13Plus = spdx {
spdxId = "GFDL-1.3-or-later";
fullName = "GNU Free Documentation License v1.3 or later";
}; };
ffsl = { ffsl = {
@ -295,20 +313,25 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
}; };
gpl1 = spdx { gpl1 = spdx {
spdxId = "GPL-1.0"; spdxId = "GPL-1.0-only";
fullName = "GNU General Public License v1.0 only"; fullName = "GNU General Public License v1.0 only";
}; };
gpl1Plus = spdx { gpl1Plus = spdx {
spdxId = "GPL-1.0+"; spdxId = "GPL-1.0-or-later";
fullName = "GNU General Public License v1.0 or later"; fullName = "GNU General Public License v1.0 or later";
}; };
gpl2 = spdx { gpl2 = spdx {
spdxId = "GPL-2.0"; spdxId = "GPL-2.0-only";
fullName = "GNU General Public License v2.0 only"; fullName = "GNU General Public License v2.0 only";
}; };
gpl2Classpath = spdx {
spdxId = "GPL-2.0-with-classpath-exception";
fullName = "GNU General Public License v2.0 only (with Classpath exception)";
};
gpl2ClasspathPlus = { gpl2ClasspathPlus = {
fullName = "GNU General Public License v2.0 or later (with Classpath exception)"; fullName = "GNU General Public License v2.0 or later (with Classpath exception)";
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception; url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
@ -320,17 +343,17 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
}; };
gpl2Plus = spdx { gpl2Plus = spdx {
spdxId = "GPL-2.0+"; spdxId = "GPL-2.0-or-later";
fullName = "GNU General Public License v2.0 or later"; fullName = "GNU General Public License v2.0 or later";
}; };
gpl3 = spdx { gpl3 = spdx {
spdxId = "GPL-3.0"; spdxId = "GPL-3.0-only";
fullName = "GNU General Public License v3.0 only"; fullName = "GNU General Public License v3.0 only";
}; };
gpl3Plus = spdx { gpl3Plus = spdx {
spdxId = "GPL-3.0+"; spdxId = "GPL-3.0-or-later";
fullName = "GNU General Public License v3.0 or later"; fullName = "GNU General Public License v3.0 or later";
}; };
@ -355,6 +378,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Independent JPEG Group License"; fullName = "Independent JPEG Group License";
}; };
imagemagick = spdx {
fullName = "ImageMagick License";
spdxId = "imagemagick";
};
inria-compcert = { inria-compcert = {
fullName = "INRIA Non-Commercial License Agreement for the CompCert verified compiler"; fullName = "INRIA Non-Commercial License Agreement for the CompCert verified compiler";
url = "http://compcert.inria.fr/doc/LICENSE"; url = "http://compcert.inria.fr/doc/LICENSE";
@ -382,33 +410,45 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "ISC License"; fullName = "ISC License";
}; };
# Proprietary binaries; free to redistribute without modification.
issl = {
fullName = "Intel Simplified Software License";
url = https://software.intel.com/en-us/license/intel-simplified-software-license;
free = false;
};
jasper = spdx {
spdxId = "JasPer-2.0";
fullName = "JasPer License";
};
lgpl2 = spdx { lgpl2 = spdx {
spdxId = "LGPL-2.0"; spdxId = "LGPL-2.0-only";
fullName = "GNU Library General Public License v2 only"; fullName = "GNU Library General Public License v2 only";
}; };
lgpl2Plus = spdx { lgpl2Plus = spdx {
spdxId = "LGPL-2.0+"; spdxId = "LGPL-2.0-or-later";
fullName = "GNU Library General Public License v2 or later"; fullName = "GNU Library General Public License v2 or later";
}; };
lgpl21 = spdx { lgpl21 = spdx {
spdxId = "LGPL-2.1"; spdxId = "LGPL-2.1-only";
fullName = "GNU Library General Public License v2.1 only"; fullName = "GNU Library General Public License v2.1 only";
}; };
lgpl21Plus = spdx { lgpl21Plus = spdx {
spdxId = "LGPL-2.1+"; spdxId = "LGPL-2.1-or-later";
fullName = "GNU Library General Public License v2.1 or later"; fullName = "GNU Library General Public License v2.1 or later";
}; };
lgpl3 = spdx { lgpl3 = spdx {
spdxId = "LGPL-3.0"; spdxId = "LGPL-3.0-only";
fullName = "GNU Lesser General Public License v3.0 only"; fullName = "GNU Lesser General Public License v3.0 only";
}; };
lgpl3Plus = spdx { lgpl3Plus = spdx {
spdxId = "LGPL-3.0+"; spdxId = "LGPL-3.0-or-later";
fullName = "GNU Lesser General Public License v3.0 or later"; fullName = "GNU Lesser General Public License v3.0 or later";
}; };
@ -417,6 +457,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "libpng License"; fullName = "libpng License";
}; };
libpng2 = {
fullName = "libpng License v2"; # 1.6.36+
url = "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt";
};
libtiff = spdx { libtiff = spdx {
spdxId = "libtiff"; spdxId = "libtiff";
fullName = "libtiff License"; fullName = "libtiff License";
@ -480,6 +525,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
free = false; free = false;
}; };
nasa13 = spdx {
spdxId = "NASA-1.3";
fullName = "NASA Open Source Agreement 1.3";
free = false;
};
ncsa = spdx { ncsa = spdx {
spdxId = "NCSA"; spdxId = "NCSA";
fullName = "University of Illinois/NCSA Open Source License"; fullName = "University of Illinois/NCSA Open Source License";
@ -495,6 +546,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Non-Profit Open Software License 3.0"; fullName = "Non-Profit Open Software License 3.0";
}; };
ocamlpro_nc = {
fullName = "OCamlPro Non Commercial license version 1";
url = "https://alt-ergo.ocamlpro.com/http/alt-ergo-2.2.0/OCamlPro-Non-Commercial-License.pdf";
free = false;
};
ofl = spdx { ofl = spdx {
spdxId = "OFL-1.1"; spdxId = "OFL-1.1";
fullName = "SIL Open Font License 1.1"; fullName = "SIL Open Font License 1.1";
@ -510,6 +567,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "OpenSSL License"; fullName = "OpenSSL License";
}; };
osl2 = spdx {
spdxId = "OSL-2.0";
fullName = "Open Software License 2.0";
};
osl21 = spdx { osl21 = spdx {
spdxId = "OSL-2.1"; spdxId = "OSL-2.1";
fullName = "Open Software License 2.1"; fullName = "Open Software License 2.1";
@ -546,6 +608,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Public Domain"; fullName = "Public Domain";
}; };
purdueBsd = {
fullName = " Purdue BSD-Style License"; # also know as lsof license
url = https://enterprise.dejacode.com/licenses/public/purdue-bsd;
};
qpl = spdx { qpl = spdx {
spdxId = "QPL-1.0"; spdxId = "QPL-1.0";
fullName = "Q Public License 1.0"; fullName = "Q Public License 1.0";
@ -561,6 +628,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "Ruby License"; fullName = "Ruby License";
}; };
sendmail = spdx {
spdxId = "Sendmail";
fullName = "Sendmail License";
};
sgi-b-20 = spdx { sgi-b-20 = spdx {
spdxId = "SGI-B-2.0"; spdxId = "SGI-B-2.0";
fullName = "SGI Free Software License B v2.0"; fullName = "SGI Free Software License B v2.0";
@ -650,7 +722,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
}; };
wxWindows = spdx { wxWindows = spdx {
spdxId = "WXwindows"; spdxId = "wxWindows";
fullName = "wxWindows Library Licence, Version 3.1"; fullName = "wxWindows Library Licence, Version 3.1";
}; };

View File

@ -1,4 +1,5 @@
# General list operations. # General list operations.
{ lib }: { lib }:
with lib.trivial; with lib.trivial;
let let
@ -6,23 +7,25 @@ let
in in
rec { rec {
inherit (builtins) head tail length isList elemAt concatLists filter elem genList; inherit (builtins) head tail length isList elemAt concatLists filter elem genList map;
/* Create a list consisting of a single element. `singleton x' is /* Create a list consisting of a single element. `singleton x` is
sometimes more convenient with respect to indentation than `[x]' sometimes more convenient with respect to indentation than `[x]`
when x spans multiple lines. when x spans multiple lines.
Type: singleton :: a -> [a]
Example: Example:
singleton "foo" singleton "foo"
=> [ "foo" ] => [ "foo" ]
*/ */
singleton = x: [x]; singleton = x: [x];
/* right fold a binary function `op' between successive elements of /* right fold a binary function `op` between successive elements of
`list' with `nul' as the starting value, i.e., `list` with `nul' as the starting value, i.e.,
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'. `foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
Type:
foldr :: (a -> b -> b) -> b -> [a] -> b Type: foldr :: (a -> b -> b) -> b -> [a] -> b
Example: Example:
concat = foldr (a: b: a + b) "z" concat = foldr (a: b: a + b) "z"
@ -42,16 +45,15 @@ rec {
else op (elemAt list n) (fold' (n + 1)); else op (elemAt list n) (fold' (n + 1));
in fold' 0; in fold' 0;
/* `fold' is an alias of `foldr' for historic reasons */ /* `fold` is an alias of `foldr` for historic reasons */
# FIXME(Profpatsch): deprecate? # FIXME(Profpatsch): deprecate?
fold = foldr; fold = foldr;
/* left fold, like `foldr', but from the left: /* left fold, like `foldr`, but from the left:
`foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`. `foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
Type: Type: foldl :: (b -> a -> b) -> b -> [a] -> b
foldl :: (b -> a -> b) -> b -> [a] -> b
Example: Example:
lconcat = foldl (a: b: a + b) "z" lconcat = foldl (a: b: a + b) "z"
@ -70,16 +72,20 @@ rec {
else op (foldl' (n - 1)) (elemAt list n); else op (foldl' (n - 1)) (elemAt list n);
in foldl' (length list - 1); in foldl' (length list - 1);
/* Strict version of `foldl'. /* Strict version of `foldl`.
The difference is that evaluation is forced upon access. Usually used The difference is that evaluation is forced upon access. Usually used
with small whole results (in contract with lazily-generated list or large with small whole results (in contract with lazily-generated list or large
lists where only a part is consumed.) lists where only a part is consumed.)
Type: foldl' :: (b -> a -> b) -> b -> [a] -> b
*/ */
foldl' = builtins.foldl' or foldl; foldl' = builtins.foldl' or foldl;
/* Map with index starting from 0 /* Map with index starting from 0
Type: imap0 :: (int -> a -> b) -> [a] -> [b]
Example: Example:
imap0 (i: v: "${v}-${toString i}") ["a" "b"] imap0 (i: v: "${v}-${toString i}") ["a" "b"]
=> [ "a-0" "b-1" ] => [ "a-0" "b-1" ]
@ -88,6 +94,8 @@ rec {
/* Map with index starting from 1 /* Map with index starting from 1
Type: imap1 :: (int -> a -> b) -> [a] -> [b]
Example: Example:
imap1 (i: v: "${v}-${toString i}") ["a" "b"] imap1 (i: v: "${v}-${toString i}") ["a" "b"]
=> [ "a-1" "b-2" ] => [ "a-1" "b-2" ]
@ -96,6 +104,8 @@ rec {
/* Map and concatenate the result. /* Map and concatenate the result.
Type: concatMap :: (a -> [b]) -> [a] -> [b]
Example: Example:
concatMap (x: [x] ++ ["z"]) ["a" "b"] concatMap (x: [x] ++ ["z"]) ["a" "b"]
=> [ "a" "z" "b" "z" ] => [ "a" "z" "b" "z" ]
@ -118,15 +128,21 @@ rec {
/* Remove elements equal to 'e' from a list. Useful for buildInputs. /* Remove elements equal to 'e' from a list. Useful for buildInputs.
Type: remove :: a -> [a] -> [a]
Example: Example:
remove 3 [ 1 3 4 3 ] remove 3 [ 1 3 4 3 ]
=> [ 1 4 ] => [ 1 4 ]
*/ */
remove = e: filter (x: x != e); remove =
# Element to remove from the list
e: filter (x: x != e);
/* Find the sole element in the list matching the specified /* Find the sole element in the list matching the specified
predicate, returns `default' if no such element exists, or predicate, returns `default` if no such element exists, or
`multiple' if there are multiple matching elements. `multiple` if there are multiple matching elements.
Type: findSingle :: (a -> bool) -> a -> a -> [a] -> a
Example: Example:
findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ] findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ]
@ -136,14 +152,24 @@ rec {
findSingle (x: x == 3) "none" "multiple" [ 1 9 ] findSingle (x: x == 3) "none" "multiple" [ 1 9 ]
=> "none" => "none"
*/ */
findSingle = pred: default: multiple: list: findSingle =
# Predicate
pred:
# Default value to return if element was not found.
default:
# Default value to return if more than one element was found
multiple:
# Input list
list:
let found = filter pred list; len = length found; let found = filter pred list; len = length found;
in if len == 0 then default in if len == 0 then default
else if len != 1 then multiple else if len != 1 then multiple
else head found; else head found;
/* Find the first element in the list matching the specified /* Find the first element in the list matching the specified
predicate or returns `default' if no such element exists. predicate or return `default` if no such element exists.
Type: findFirst :: (a -> bool) -> a -> [a] -> a
Example: Example:
findFirst (x: x > 3) 7 [ 1 6 4 ] findFirst (x: x > 3) 7 [ 1 6 4 ]
@ -151,12 +177,20 @@ rec {
findFirst (x: x > 9) 7 [ 1 6 4 ] findFirst (x: x > 9) 7 [ 1 6 4 ]
=> 7 => 7
*/ */
findFirst = pred: default: list: findFirst =
# Predicate
pred:
# Default value to return
default:
# Input list
list:
let found = filter pred list; let found = filter pred list;
in if found == [] then default else head found; in if found == [] then default else head found;
/* Return true iff function `pred' returns true for at least element /* Return true if function `pred` returns true for at least one
of `list'. element of `list`.
Type: any :: (a -> bool) -> [a] -> bool
Example: Example:
any isString [ 1 "a" { } ] any isString [ 1 "a" { } ]
@ -166,8 +200,10 @@ rec {
*/ */
any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false); any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
/* Return true iff function `pred' returns true for all elements of /* Return true if function `pred` returns true for all elements of
`list'. `list`.
Type: all :: (a -> bool) -> [a] -> bool
Example: Example:
all (x: x < 3) [ 1 2 ] all (x: x < 3) [ 1 2 ]
@ -177,19 +213,25 @@ rec {
*/ */
all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true); all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
/* Count how many times function `pred' returns true for the elements /* Count how many elements of `list` match the supplied predicate
of `list'. function.
Type: count :: (a -> bool) -> [a] -> int
Example: Example:
count (x: x == 3) [ 3 2 3 4 6 ] count (x: x == 3) [ 3 2 3 4 6 ]
=> 2 => 2
*/ */
count = pred: foldl' (c: x: if pred x then c + 1 else c) 0; count =
# Predicate
pred: foldl' (c: x: if pred x then c + 1 else c) 0;
/* Return a singleton list or an empty list, depending on a boolean /* Return a singleton list or an empty list, depending on a boolean
value. Useful when building lists with optional elements value. Useful when building lists with optional elements
(e.g. `++ optional (system == "i686-linux") flashplayer'). (e.g. `++ optional (system == "i686-linux") flashplayer').
Type: optional :: bool -> a -> [a]
Example: Example:
optional true "foo" optional true "foo"
=> [ "foo" ] => [ "foo" ]
@ -200,13 +242,19 @@ rec {
/* Return a list or an empty list, depending on a boolean value. /* Return a list or an empty list, depending on a boolean value.
Type: optionals :: bool -> [a] -> [a]
Example: Example:
optionals true [ 2 3 ] optionals true [ 2 3 ]
=> [ 2 3 ] => [ 2 3 ]
optionals false [ 2 3 ] optionals false [ 2 3 ]
=> [ ] => [ ]
*/ */
optionals = cond: elems: if cond then elems else []; optionals =
# Condition
cond:
# List to return if condition is true
elems: if cond then elems else [];
/* If argument is a list, return it; else, wrap it in a singleton /* If argument is a list, return it; else, wrap it in a singleton
@ -223,20 +271,28 @@ rec {
/* Return a list of integers from `first' up to and including `last'. /* Return a list of integers from `first' up to and including `last'.
Type: range :: int -> int -> [int]
Example: Example:
range 2 4 range 2 4
=> [ 2 3 4 ] => [ 2 3 4 ]
range 3 2 range 3 2
=> [ ] => [ ]
*/ */
range = first: last: range =
# First integer in the range
first:
# Last integer in the range
last:
if first > last then if first > last then
[] []
else else
genList (n: first + n) (last - first + 1); genList (n: first + n) (last - first + 1);
/* Splits the elements of a list in two lists, `right' and /* Splits the elements of a list in two lists, `right` and
`wrong', depending on the evaluation of a predicate. `wrong`, depending on the evaluation of a predicate.
Type: (a -> bool) -> [a] -> { right :: [a], wrong :: [a] }
Example: Example:
partition (x: x > 2) [ 5 1 2 3 4 ] partition (x: x > 2) [ 5 1 2 3 4 ]
@ -252,7 +308,7 @@ rec {
/* Splits the elements of a list into many lists, using the return value of a predicate. /* Splits the elements of a list into many lists, using the return value of a predicate.
Predicate should return a string which becomes keys of attrset `groupBy' returns. Predicate should return a string which becomes keys of attrset `groupBy' returns.
`groupBy'' allows to customise the combining function and initial value `groupBy'` allows to customise the combining function and initial value
Example: Example:
groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ] groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
@ -268,10 +324,6 @@ rec {
xfce = [ { name = "xfce"; script = "xfce4-session &"; } ]; xfce = [ { name = "xfce"; script = "xfce4-session &"; } ];
} }
groupBy' allows to customise the combining function and initial value
Example:
groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ] groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
=> { true = 12; false = 3; } => { true = 12; false = 3; }
*/ */
@ -289,17 +341,27 @@ rec {
the merging stops at the shortest. How both lists are merged is defined the merging stops at the shortest. How both lists are merged is defined
by the first argument. by the first argument.
Type: zipListsWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Example: Example:
zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"] zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
=> ["he" "lo"] => ["he" "lo"]
*/ */
zipListsWith = f: fst: snd: zipListsWith =
# Function to zip elements of both lists
f:
# First list
fst:
# Second list
snd:
genList genList
(n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd)); (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
/* Merges two lists of the same size together. If the sizes aren't the same /* Merges two lists of the same size together. If the sizes aren't the same
the merging stops at the shortest. the merging stops at the shortest.
Type: zipLists :: [a] -> [b] -> [{ fst :: a, snd :: b}]
Example: Example:
zipLists [ 1 2 ] [ "a" "b" ] zipLists [ 1 2 ] [ "a" "b" ]
=> [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ] => [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ]
@ -308,6 +370,8 @@ rec {
/* Reverse the order of the elements of a list. /* Reverse the order of the elements of a list.
Type: reverseList :: [a] -> [a]
Example: Example:
reverseList [ "b" "o" "j" ] reverseList [ "b" "o" "j" ]
@ -321,8 +385,7 @@ rec {
`before a b == true` means that `b` depends on `a` (there's an `before a b == true` means that `b` depends on `a` (there's an
edge from `b` to `a`). edge from `b` to `a`).
Examples: Example:
listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ] listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ]
== { minimal = "/"; # minimal element == { minimal = "/"; # minimal element
visited = [ "/home/user" ]; # seen elements (in reverse order) visited = [ "/home/user" ]; # seen elements (in reverse order)
@ -336,7 +399,6 @@ rec {
rest = [ "/home" "other" ]; # everything else rest = [ "/home" "other" ]; # everything else
*/ */
listDfs = stopOnCycles: before: list: listDfs = stopOnCycles: before: list:
let let
dfs' = us: visited: rest: dfs' = us: visited: rest:
@ -361,7 +423,7 @@ rec {
`before a b == true` means that `b` should be after `a` `before a b == true` means that `b` should be after `a`
in the result. in the result.
Examples: Example:
toposort hasPrefix [ "/home/user" "other" "/" "/home" ] toposort hasPrefix [ "/home/user" "other" "/" "/home" ]
== { result = [ "/" "/home" "/home/user" "other" ]; } == { result = [ "/" "/home" "/home/user" "other" ]; }
@ -376,7 +438,6 @@ rec {
toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; } toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; }
*/ */
toposort = before: list: toposort = before: list:
let let
dfsthis = listDfs true before list; dfsthis = listDfs true before list;
@ -467,26 +528,38 @@ rec {
/* Return the first (at most) N elements of a list. /* Return the first (at most) N elements of a list.
Type: take :: int -> [a] -> [a]
Example: Example:
take 2 [ "a" "b" "c" "d" ] take 2 [ "a" "b" "c" "d" ]
=> [ "a" "b" ] => [ "a" "b" ]
take 2 [ ] take 2 [ ]
=> [ ] => [ ]
*/ */
take = count: sublist 0 count; take =
# Number of elements to take
count: sublist 0 count;
/* Remove the first (at most) N elements of a list. /* Remove the first (at most) N elements of a list.
Type: drop :: int -> [a] -> [a]
Example: Example:
drop 2 [ "a" "b" "c" "d" ] drop 2 [ "a" "b" "c" "d" ]
=> [ "c" "d" ] => [ "c" "d" ]
drop 2 [ ] drop 2 [ ]
=> [ ] => [ ]
*/ */
drop = count: list: sublist count (length list) list; drop =
# Number of elements to drop
count:
# Input list
list: sublist count (length list) list;
/* Return a list consisting of at most count elements of list, /* Return a list consisting of at most `count` elements of `list`,
starting at index start. starting at index `start`.
Type: sublist :: int -> int -> [a] -> [a]
Example: Example:
sublist 1 3 [ "a" "b" "c" "d" "e" ] sublist 1 3 [ "a" "b" "c" "d" "e" ]
@ -494,7 +567,13 @@ rec {
sublist 1 3 [ ] sublist 1 3 [ ]
=> [ ] => [ ]
*/ */
sublist = start: count: list: sublist =
# Index at which to start the sublist
start:
# Number of elements to take
count:
# Input list
list:
let len = length list; in let len = length list; in
genList genList
(n: elemAt list (n + start)) (n: elemAt list (n + start))
@ -504,23 +583,34 @@ rec {
/* Return the last element of a list. /* Return the last element of a list.
This function throws an error if the list is empty.
Type: last :: [a] -> a
Example: Example:
last [ 1 2 3 ] last [ 1 2 3 ]
=> 3 => 3
*/ */
last = list: last = list:
assert list != []; elemAt list (length list - 1); assert lib.assertMsg (list != []) "lists.last: list must not be empty!";
elemAt list (length list - 1);
/* Return all elements but the last /* Return all elements but the last.
This function throws an error if the list is empty.
Type: init :: [a] -> [a]
Example: Example:
init [ 1 2 3 ] init [ 1 2 3 ]
=> [ 1 2 ] => [ 1 2 ]
*/ */
init = list: assert list != []; take (length list - 1) list; init = list:
assert lib.assertMsg (list != []) "lists.init: list must not be empty!";
take (length list - 1) list;
/* return the image of the cross product of some lists by a function /* Return the image of the cross product of some lists by a function.
Example: Example:
crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]] crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
@ -531,8 +621,9 @@ rec {
/* Remove duplicate elements from the list. O(n^2) complexity. /* Remove duplicate elements from the list. O(n^2) complexity.
Example: Type: unique :: [a] -> [a]
Example:
unique [ 3 2 3 4 ] unique [ 3 2 3 4 ]
=> [ 3 2 4 ] => [ 3 2 4 ]
*/ */
@ -542,8 +633,7 @@ rec {
else else
let let
x = head list; x = head list;
xs = unique (drop 1 list); in [x] ++ unique (remove x list);
in [x] ++ remove x xs;
/* Intersects list 'e' and another list. O(nm) complexity. /* Intersects list 'e' and another list. O(nm) complexity.

View File

@ -41,16 +41,18 @@ rec {
let x = builtins.parseDrvName name; in "${x.name}-${suffix}-${x.version}"); let x = builtins.parseDrvName name; in "${x.name}-${suffix}-${x.version}");
/* Apply a function to each derivation and only to derivations in an attrset /* Apply a function to each derivation and only to derivations in an attrset.
*/ */
mapDerivationAttrset = f: set: lib.mapAttrs (name: pkg: if lib.isDerivation pkg then (f pkg) else pkg) set; mapDerivationAttrset = f: set: lib.mapAttrs (name: pkg: if lib.isDerivation pkg then (f pkg) else pkg) set;
/* Set the nix-env priority of the package.
*/
setPrio = priority: addMetaAttrs { inherit priority; };
/* Decrease the nix-env priority of the package, i.e., other /* Decrease the nix-env priority of the package, i.e., other
versions/variants of the package will be preferred. versions/variants of the package will be preferred.
*/ */
lowPrio = drv: addMetaAttrs { priority = 10; } drv; lowPrio = setPrio 10;
/* Apply lowPrio to an attrset with derivations /* Apply lowPrio to an attrset with derivations
*/ */
@ -60,8 +62,7 @@ rec {
/* Increase the nix-env priority of the package, i.e., this /* Increase the nix-env priority of the package, i.e., this
version/variant of the package will be preferred. version/variant of the package will be preferred.
*/ */
hiPrio = drv: addMetaAttrs { priority = -10; } drv; hiPrio = setPrio (-10);
/* Apply hiPrio to an attrset with derivations /* Apply hiPrio to an attrset with derivations
*/ */

View File

@ -1,2 +1,2 @@
# Expose the minimum required version for evaluating Nixpkgs # Expose the minimum required version for evaluating Nixpkgs
"1.11" "2.0"

View File

@ -192,29 +192,55 @@ rec {
(concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules); (concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);
mergeModules' = prefix: options: configs: mergeModules' = prefix: options: configs:
listToAttrs (map (name: { let
/* byName is like foldAttrs, but will look for attributes to merge in the
specified attribute name.
byName "foo" (module: value: ["module.hidden=${module.hidden},value=${value}"])
[
{
hidden="baz";
foo={qux="bar"; gla="flop";};
}
{
hidden="fli";
foo={qux="gne"; gli="flip";};
}
]
===>
{
gla = [ "module.hidden=baz,value=flop" ];
gli = [ "module.hidden=fli,value=flip" ];
qux = [ "module.hidden=baz,value=bar" "module.hidden=fli,value=gne" ];
}
*/
byName = attr: f: modules:
foldl' (acc: module:
acc // (mapAttrs (n: v:
(acc.${n} or []) ++ f module v
) module.${attr}
)
) {} modules;
# an attrset 'name' => list of submodules that declare name.
declsByName = byName "options" (module: option:
[{ inherit (module) file; options = option; }]
) options;
# an attrset 'name' => list of submodules that define name.
defnsByName = byName "config" (module: value:
map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
) configs;
# extract the definitions for each loc
defnsByName' = byName "config" (module: value:
[{ inherit (module) file; inherit value; }]
) configs;
in
(flip mapAttrs declsByName (name: decls:
# We're descending into attribute name. # We're descending into attribute name.
inherit name;
value =
let let
loc = prefix ++ [name]; loc = prefix ++ [name];
# Get all submodules that declare name. defns = defnsByName.${name} or [];
decls = concatMap (m: defns' = defnsByName'.${name} or [];
if m.options ? ${name}
then [ { inherit (m) file; options = m.options.${name}; } ]
else []
) options;
# Get all submodules that define name.
defns = concatMap (m:
if m.config ? ${name}
then map (config: { inherit (m) file; inherit config; })
(pushDownProperties m.config.${name})
else []
) configs;
nrOptions = count (m: isOption m.options) decls; nrOptions = count (m: isOption m.options) decls;
# Extract the definitions for this loc
defns' = map (m: { inherit (m) file; value = m.config.${name}; })
(filter (m: m.config ? ${name}) configs);
in in
if nrOptions == length decls then if nrOptions == length decls then
let opt = fixupOptionType loc (mergeOptionDecls loc decls); let opt = fixupOptionType loc (mergeOptionDecls loc decls);
@ -226,8 +252,8 @@ rec {
in in
throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'." throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
else else
mergeModules' loc decls defns; mergeModules' loc decls defns
}) (concatMap (m: attrNames m.options) options)) ))
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; }; // { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
/* Merge multiple option declarations into a single declaration. In /* Merge multiple option declarations into a single declaration. In
@ -338,7 +364,6 @@ rec {
values = defs'''; values = defs''';
inherit (defs'') highestPrio; inherit (defs'') highestPrio;
}; };
defsFinal = defsFinal'.values; defsFinal = defsFinal'.values;
# Type-check the remaining definitions, and merge them. # Type-check the remaining definitions, and merge them.
@ -426,8 +451,7 @@ rec {
filterOverrides' = defs: filterOverrides' = defs:
let let
defaultPrio = 100; getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPriority;
getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio;
highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs; highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs;
strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def; strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def;
in { in {
@ -510,6 +534,8 @@ rec {
mkBefore = mkOrder 500; mkBefore = mkOrder 500;
mkAfter = mkOrder 1500; mkAfter = mkOrder 1500;
# The default priority for things that don't have a priority specified.
defaultPriority = 100;
# Convenient property used to transfer all definitions and their # Convenient property used to transfer all definitions and their
# properties from one option to another. This property is useful for # properties from one option to another. This property is useful for
@ -532,8 +558,20 @@ rec {
# #
mkAliasDefinitions = mkAliasAndWrapDefinitions id; mkAliasDefinitions = mkAliasAndWrapDefinitions id;
mkAliasAndWrapDefinitions = wrap: option: mkAliasAndWrapDefinitions = wrap: option:
mkIf (isOption option && option.isDefined) (wrap (mkMerge option.definitions)); mkAliasIfDef option (wrap (mkMerge option.definitions));
# Similar to mkAliasAndWrapDefinitions but copies over the priority from the
# option as well.
#
# If a priority is not set, it assumes a priority of defaultPriority.
mkAliasAndWrapDefsWithPriority = wrap: option:
let
prio = option.highestPrio or defaultPriority;
defsWithPrio = map (mkOverride prio) option.definitions;
in mkAliasIfDef option (wrap (mkMerge defsWithPrio));
mkAliasIfDef = option:
mkIf (isOption option && option.isDefined);
/* Compatibility. */ /* Compatibility. */
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; }; fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };
@ -572,6 +610,9 @@ rec {
forwards any definitions of boot.copyKernels to forwards any definitions of boot.copyKernels to
boot.loader.grub.copyKernels while printing a warning. boot.loader.grub.copyKernels while printing a warning.
This also copies over the priority from the aliased option to the
non-aliased option.
*/ */
mkRenamedOptionModule = from: to: doRename { mkRenamedOptionModule = from: to: doRename {
inherit from to; inherit from to;
@ -666,7 +707,7 @@ rec {
use = id; use = id;
}; };
doRename = { from, to, visible, warn, use }: doRename = { from, to, visible, warn, use, withPriority ? true }:
{ config, options, ... }: { config, options, ... }:
let let
fromOpt = getAttrFromPath from options; fromOpt = getAttrFromPath from options;
@ -684,7 +725,9 @@ rec {
warnings = optional (warn && fromOpt.isDefined) warnings = optional (warn && fromOpt.isDefined)
"The option `${showOption from}' defined in ${showFiles fromOpt.files} has been renamed to `${showOption to}'."; "The option `${showOption from}' defined in ${showFiles fromOpt.files} has been renamed to `${showOption to}'.";
} }
(mkAliasAndWrapDefinitions (setAttrByPath to) fromOpt) (if withPriority
then mkAliasAndWrapDefsWithPriority (setAttrByPath to) fromOpt
else mkAliasAndWrapDefinitions (setAttrByPath to) fromOpt)
]; ];
}; };

View File

@ -8,33 +8,72 @@ with lib.strings;
rec { rec {
/* Returns true when the given argument is an option
Type: isOption :: a -> bool
Example:
isOption 1 // => false
isOption (mkOption {}) // => true
*/
isOption = lib.isType "option"; isOption = lib.isType "option";
/* Creates an Option attribute set. mkOption accepts an attribute set with the following keys:
All keys default to `null` when not given.
Example:
mkOption { } // => { _type = "option"; }
mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
*/
mkOption = 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. # Default value used when no definition is given in the configuration.
, example ? null # Example value used in the manual. default ? null,
, description ? null # String describing the option. # Textual representation of the default, for the manual.
, relatedPackages ? null # Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix). defaultText ? null,
, type ? null # Option type, providing type-checking and value merging. # Example value used in the manual.
, apply ? null # Function that converts the option value to something else. example ? null,
, internal ? null # Whether the option is for NixOS developers only. # String describing the option.
, visible ? null # Whether the option shows up in the manual. description ? null,
, readOnly ? null # Whether the option can be set only once # Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix).
, options ? null # Obsolete, used by types.optionSet. relatedPackages ? null,
# Option type, providing type-checking and value merging.
type ? null,
# Function that converts the option value to something else.
apply ? null,
# Whether the option is for NixOS developers only.
internal ? null,
# Whether the option shows up in the manual.
visible ? null,
# Whether the option can be set only once
readOnly ? null,
# Deprecated, used by types.optionSet.
options ? null
} @ attrs: } @ attrs:
attrs // { _type = "option"; }; attrs // { _type = "option"; };
mkEnableOption = name: mkOption { /* Creates an Option attribute set for a boolean value option i.e an
option to be toggled on or off:
Example:
mkEnableOption "foo"
=> { _type = "option"; default = false; description = "Whether to enable foo."; example = true; type = { ... }; }
*/
mkEnableOption =
# Name for the created option
name: mkOption {
default = false; default = false;
example = true; example = true;
description = "Whether to enable ${name}."; description = "Whether to enable ${name}.";
type = lib.types.bool; type = lib.types.bool;
}; };
# This option accept anything, but it does not produce any result. This /* This option accepts anything, but it does not produce any result.
# is useful for sharing a module across different module sets without
# having to implement similar features as long as the value of the options This is useful for sharing a module across different module sets
# are not expected. without having to implement similar features as long as the
values of the options are not accessed. */
mkSinkUndeclaredOptions = attrs: mkOption ({ mkSinkUndeclaredOptions = attrs: mkOption ({
internal = true; internal = true;
visible = false; visible = false;
@ -74,7 +113,24 @@ rec {
else else
val) (head defs).value defs; val) (head defs).value defs;
/* Extracts values of all "value" keys of the given list.
Type: getValues :: [ { value :: a } ] -> [a]
Example:
getValues [ { value = 1; } { value = 2; } ] // => [ 1 2 ]
getValues [ ] // => [ ]
*/
getValues = map (x: x.value); getValues = map (x: x.value);
/* Extracts values of all "file" keys of the given list
Type: getFiles :: [ { file :: a } ] -> [a]
Example:
getFiles [ { file = "file1"; } { file = "file2"; } ] // => [ "file1" "file2" ]
getFiles [ ] // => [ ]
*/
getFiles = map (x: x.file); getFiles = map (x: x.file);
# Generate documentation template from the list of option declaration like # Generate documentation template from the list of option declaration like
@ -87,7 +143,7 @@ rec {
docOption = rec { docOption = rec {
loc = opt.loc; loc = opt.loc;
name = showOption opt.loc; name = showOption opt.loc;
description = opt.description or (throw "Option `${name}' has no description."); description = opt.description or (lib.warn "Option `${name}' has no description." "This option has no description.");
declarations = filter (x: x != unknownModule) opt.declarations; declarations = filter (x: x != unknownModule) opt.declarations;
internal = opt.internal or false; internal = opt.internal or false;
visible = opt.visible or true; visible = opt.visible or true;
@ -107,10 +163,13 @@ rec {
/* This function recursively removes all derivation attributes from /* This function recursively removes all derivation attributes from
`x' except for the `name' attribute. This is to make the `x` except for the `name` attribute.
generation of `options.xml' much more efficient: the XML
representation of derivations is very large (on the order of This is to make the generation of `options.xml` much more
megabytes) and is not actually used by the manual generator. */ 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: scrubOptionValue = x:
if isDerivation x then if isDerivation x then
{ type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; } { type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; }
@ -119,20 +178,21 @@ rec {
else x; else x;
/* For use in the example option attribute. It causes the given /* For use in the `example` option attribute. It causes the given
text to be included verbatim in documentation. This is necessary text to be included verbatim in documentation. This is necessary
for example values that are not simple values, e.g., for example values that are not simple values, e.g., functions.
functions. */ */
literalExample = text: { _type = "literalExample"; inherit text; }; literalExample = text: { _type = "literalExample"; inherit text; };
# Helper functions.
/* Helper functions. */ /* Convert an option, described as a list of the option parts in to a
safe, human readable version.
# Convert an option, described as a list of the option parts in to a Example:
# safe, human readable version. ie: (showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
# (showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
# (showOption ["foo" "bar" "baz"]) == "foo.bar.baz" */
# (showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
showOption = parts: let showOption = parts: let
escapeOptionPart = part: escapeOptionPart = part:
let let

View File

@ -12,8 +12,8 @@ rec {
# Bring in a path as a source, filtering out all Subversion and CVS # Bring in a path as a source, filtering out all Subversion and CVS
# directories, as well as backup files (*~). # directories, as well as backup files (*~).
cleanSourceFilter = name: type: let baseName = baseNameOf (toString name); in ! ( cleanSourceFilter = name: type: let baseName = baseNameOf (toString name); in ! (
# Filter out Subversion and CVS directories. # Filter out version control software files/directories
(type == "directory" && (baseName == ".git" || baseName == ".svn" || baseName == "CVS" || baseName == ".hg")) || (baseName == ".git" || type == "directory" && (baseName == ".svn" || baseName == "CVS" || baseName == ".hg")) ||
# Filter out editor backup / swap files. # Filter out editor backup / swap files.
lib.hasSuffix "~" baseName || lib.hasSuffix "~" baseName ||
builtins.match "^\\.sw[a-z]$" baseName != null || builtins.match "^\\.sw[a-z]$" baseName != null ||
@ -26,6 +26,10 @@ rec {
(type == "symlink" && lib.hasPrefix "result" baseName) (type == "symlink" && lib.hasPrefix "result" baseName)
); );
# Filters a source tree removing version control files and directories using cleanSourceWith
#
# Example:
# cleanSource ./.
cleanSource = src: cleanSourceWith { filter = cleanSourceFilter; inherit src; }; cleanSource = src: cleanSourceWith { filter = cleanSourceFilter; inherit src; };
# Like `builtins.filterSource`, except it will compose with itself, # Like `builtins.filterSource`, except it will compose with itself,
@ -69,7 +73,7 @@ rec {
# Get the commit id of a git repo # Get the commit id of a git repo
# Example: commitIdFromGitRepo <nixpkgs/.git> # Example: commitIdFromGitRepo <nixpkgs/.git>
commitIdFromGitRepo = commitIdFromGitRepo =
let readCommitFromFile = path: file: let readCommitFromFile = file: path:
with builtins; with builtins;
let fileName = toString path + "/" + file; let fileName = toString path + "/" + file;
packedRefsName = toString path + "/packed-refs"; packedRefsName = toString path + "/packed-refs";
@ -81,7 +85,7 @@ rec {
matchRef = match "^ref: (.*)$" fileContent; matchRef = match "^ref: (.*)$" fileContent;
in if isNull matchRef in if isNull matchRef
then fileContent then fileContent
else readCommitFromFile path (lib.head matchRef) else readCommitFromFile (lib.head matchRef) path
# Sometimes, the file isn't there at all and has been packed away in the # Sometimes, the file isn't there at all and has been packed away in the
# packed-refs file, so we have to grep through it: # packed-refs file, so we have to grep through it:
else if lib.pathExists packedRefsName else if lib.pathExists packedRefsName
@ -92,7 +96,7 @@ rec {
then throw ("Could not find " + file + " in " + packedRefsName) then throw ("Could not find " + file + " in " + packedRefsName)
else lib.head matchRef else lib.head matchRef
else throw ("Not a .git directory: " + path); else throw ("Not a .git directory: " + path);
in lib.flip readCommitFromFile "HEAD"; in readCommitFromFile "HEAD";
pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir); pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir);

View File

@ -12,6 +12,8 @@ rec {
/* Concatenate a list of strings. /* Concatenate a list of strings.
Type: concatStrings :: [string] -> string
Example: Example:
concatStrings ["foo" "bar"] concatStrings ["foo" "bar"]
=> "foobar" => "foobar"
@ -20,15 +22,19 @@ rec {
/* Map a function over a list and concatenate the resulting strings. /* Map a function over a list and concatenate the resulting strings.
Type: concatMapStrings :: (a -> string) -> [a] -> string
Example: Example:
concatMapStrings (x: "a" + x) ["foo" "bar"] concatMapStrings (x: "a" + x) ["foo" "bar"]
=> "afooabar" => "afooabar"
*/ */
concatMapStrings = f: list: concatStrings (map f list); concatMapStrings = f: list: concatStrings (map f list);
/* Like `concatMapStrings' except that the f functions also gets the /* Like `concatMapStrings` except that the f functions also gets the
position as a parameter. position as a parameter.
Type: concatImapStrings :: (int -> a -> string) -> [a] -> string
Example: Example:
concatImapStrings (pos: x: "${toString pos}-${x}") ["foo" "bar"] concatImapStrings (pos: x: "${toString pos}-${x}") ["foo" "bar"]
=> "1-foo2-bar" => "1-foo2-bar"
@ -37,17 +43,25 @@ rec {
/* Place an element between each element of a list /* Place an element between each element of a list
Type: intersperse :: a -> [a] -> [a]
Example: Example:
intersperse "/" ["usr" "local" "bin"] intersperse "/" ["usr" "local" "bin"]
=> ["usr" "/" "local" "/" "bin"]. => ["usr" "/" "local" "/" "bin"].
*/ */
intersperse = separator: list: intersperse =
# Separator to add between elements
separator:
# Input list
list:
if list == [] || length list == 1 if list == [] || length list == 1
then list then list
else tail (lib.concatMap (x: [separator x]) list); else tail (lib.concatMap (x: [separator x]) list);
/* Concatenate a list of strings with a separator between each element /* Concatenate a list of strings with a separator between each element
Type: concatStringsSep :: string -> [string] -> string
Example: Example:
concatStringsSep "/" ["usr" "local" "bin"] concatStringsSep "/" ["usr" "local" "bin"]
=> "usr/local/bin" => "usr/local/bin"
@ -55,43 +69,77 @@ rec {
concatStringsSep = builtins.concatStringsSep or (separator: list: concatStringsSep = builtins.concatStringsSep or (separator: list:
concatStrings (intersperse separator list)); concatStrings (intersperse separator list));
/* First maps over the list and then concatenates it. /* Maps a function over a list of strings and then concatenates the
result with the specified separator interspersed between
elements.
Type: concatMapStringsSep :: string -> (string -> string) -> [string] -> string
Example: Example:
concatMapStringsSep "-" (x: toUpper x) ["foo" "bar" "baz"] concatMapStringsSep "-" (x: toUpper x) ["foo" "bar" "baz"]
=> "FOO-BAR-BAZ" => "FOO-BAR-BAZ"
*/ */
concatMapStringsSep = sep: f: list: concatStringsSep sep (map f list); concatMapStringsSep =
# Separator to add between elements
sep:
# Function to map over the list
f:
# List of input strings
list: concatStringsSep sep (map f list);
/* First imaps over the list and then concatenates it. /* Same as `concatMapStringsSep`, but the mapping function
additionally receives the position of its argument.
Type: concatIMapStringsSep :: string -> (int -> string -> string) -> [string] -> string
Example: Example:
concatImapStringsSep "-" (pos: x: toString (x / pos)) [ 6 6 6 ] concatImapStringsSep "-" (pos: x: toString (x / pos)) [ 6 6 6 ]
=> "6-3-2" => "6-3-2"
*/ */
concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap1 f list); concatImapStringsSep =
# Separator to add between elements
sep:
# Function that receives elements and their positions
f:
# List of input strings
list: concatStringsSep sep (lib.imap1 f list);
/* Construct a Unix-style search path consisting of each `subDir" /* Construct a Unix-style, colon-separated search path consisting of
directory of the given list of packages. the given `subDir` appended to each of the given paths.
Type: makeSearchPath :: string -> [string] -> string
Example: Example:
makeSearchPath "bin" ["/root" "/usr" "/usr/local"] makeSearchPath "bin" ["/root" "/usr" "/usr/local"]
=> "/root/bin:/usr/bin:/usr/local/bin" => "/root/bin:/usr/bin:/usr/local/bin"
makeSearchPath "bin" ["/"] makeSearchPath "bin" [""]
=> "//bin" => "/bin"
*/ */
makeSearchPath = subDir: packages: makeSearchPath =
concatStringsSep ":" (map (path: path + "/" + subDir) (builtins.filter (x: x != null) packages)); # Directory name to append
subDir:
# List of base paths
paths:
concatStringsSep ":" (map (path: path + "/" + subDir) (builtins.filter (x: x != null) paths));
/* Construct a Unix-style search path, using given package output. /* Construct a Unix-style search path by appending the given
If no output is found, fallback to `.out` and then to the default. `subDir` to the specified `output` of each of the packages. If no
output by the given name is found, fallback to `.out` and then to
the default.
Type: string -> string -> [package] -> string
Example: Example:
makeSearchPathOutput "dev" "bin" [ pkgs.openssl pkgs.zlib ] makeSearchPathOutput "dev" "bin" [ pkgs.openssl pkgs.zlib ]
=> "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev/bin:/nix/store/wwh7mhwh269sfjkm6k5665b5kgp7jrk2-zlib-1.2.8/bin" => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev/bin:/nix/store/wwh7mhwh269sfjkm6k5665b5kgp7jrk2-zlib-1.2.8/bin"
*/ */
makeSearchPathOutput = output: subDir: pkgs: makeSearchPath subDir (map (lib.getOutput output) pkgs); makeSearchPathOutput =
# Package output to use
output:
# Directory name to append
subDir:
# List of packages
pkgs: makeSearchPath subDir (map (lib.getOutput output) pkgs);
/* Construct a library search path (such as RPATH) containing the /* Construct a library search path (such as RPATH) containing the
libraries for a set of packages libraries for a set of packages
@ -114,64 +162,80 @@ rec {
*/ */
makeBinPath = makeSearchPathOutput "bin" "bin"; makeBinPath = makeSearchPathOutput "bin" "bin";
/* Construct a perl search path (such as $PERL5LIB)
FIXME(zimbatm): this should be moved in perl-specific code
Example:
pkgs = import <nixpkgs> { }
makePerlPath [ pkgs.perlPackages.libnet ]
=> "/nix/store/n0m1fk9c960d8wlrs62sncnadygqqc6y-perl-Net-SMTP-1.25/lib/perl5/site_perl"
*/
makePerlPath = makeSearchPathOutput "lib" "lib/perl5/site_perl";
/* Construct a perl search path recursively including all dependencies (such as $PERL5LIB)
Example:
pkgs = import <nixpkgs> { }
makeFullPerlPath [ pkgs.perlPackages.CGI ]
=> "/nix/store/fddivfrdc1xql02h9q500fpnqy12c74n-perl-CGI-4.38/lib/perl5/site_perl:/nix/store/8hsvdalmsxqkjg0c5ifigpf31vc4vsy2-perl-HTML-Parser-3.72/lib/perl5/site_perl:/nix/store/zhc7wh0xl8hz3y3f71nhlw1559iyvzld-perl-HTML-Tagset-3.20/lib/perl5/site_perl"
*/
makeFullPerlPath = deps: makePerlPath (lib.misc.closePropagation deps);
/* Depending on the boolean `cond', return either the given string /* Depending on the boolean `cond', return either the given string
or the empty string. Useful to concatenate against a bigger string. or the empty string. Useful to concatenate against a bigger string.
Type: optionalString :: bool -> string -> string
Example: Example:
optionalString true "some-string" optionalString true "some-string"
=> "some-string" => "some-string"
optionalString false "some-string" optionalString false "some-string"
=> "" => ""
*/ */
optionalString = cond: string: if cond then string else ""; optionalString =
# Condition
cond:
# String to return if condition is true
string: if cond then string else "";
/* Determine whether a string has given prefix. /* Determine whether a string has given prefix.
Type: hasPrefix :: string -> string -> bool
Example: Example:
hasPrefix "foo" "foobar" hasPrefix "foo" "foobar"
=> true => true
hasPrefix "foo" "barfoo" hasPrefix "foo" "barfoo"
=> false => false
*/ */
hasPrefix = pref: str: hasPrefix =
substring 0 (stringLength pref) str == pref; # Prefix to check for
pref:
# Input string
str: substring 0 (stringLength pref) str == pref;
/* Determine whether a string has given suffix. /* Determine whether a string has given suffix.
Type: hasSuffix :: string -> string -> bool
Example: Example:
hasSuffix "foo" "foobar" hasSuffix "foo" "foobar"
=> false => false
hasSuffix "foo" "barfoo" hasSuffix "foo" "barfoo"
=> true => true
*/ */
hasSuffix = suffix: content: hasSuffix =
# Suffix to check for
suffix:
# Input string
content:
let let
lenContent = stringLength content; lenContent = stringLength content;
lenSuffix = stringLength suffix; lenSuffix = stringLength suffix;
in lenContent >= lenSuffix && in lenContent >= lenSuffix &&
substring (lenContent - lenSuffix) lenContent content == suffix; substring (lenContent - lenSuffix) lenContent content == suffix;
/* Determine whether a string contains the given infix
Type: hasInfix :: string -> string -> bool
Example:
hasInfix "bc" "abcd"
=> true
hasInfix "ab" "abcd"
=> true
hasInfix "cd" "abcd"
=> true
hasInfix "foo" "abcd"
=> false
*/
hasInfix = infix: content:
let
drop = x: substring 1 (stringLength x) x;
in hasPrefix infix content
|| content != "" && hasInfix infix (drop content);
/* Convert a string to a list of characters (i.e. singleton strings). /* Convert a string to a list of characters (i.e. singleton strings).
This allows you to, e.g., map a function over each character. However, 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 note that this will likely be horribly inefficient; Nix is not a
@ -180,6 +244,8 @@ rec {
Also note that Nix treats strings as a list of bytes and thus doesn't Also note that Nix treats strings as a list of bytes and thus doesn't
handle unicode. handle unicode.
Type: stringtoCharacters :: string -> [string]
Example: Example:
stringToCharacters "" stringToCharacters ""
=> [ ] => [ ]
@ -194,18 +260,25 @@ rec {
/* Manipulate a string character by character and replace them by /* Manipulate a string character by character and replace them by
strings before concatenating the results. strings before concatenating the results.
Type: stringAsChars :: (string -> string) -> string -> string
Example: Example:
stringAsChars (x: if x == "a" then "i" else x) "nax" stringAsChars (x: if x == "a" then "i" else x) "nax"
=> "nix" => "nix"
*/ */
stringAsChars = f: s: stringAsChars =
concatStrings ( # Function to map over each individual character
f:
# Input string
s: concatStrings (
map f (stringToCharacters s) map f (stringToCharacters s)
); );
/* Escape occurrence of the elements of list in string by /* Escape occurrence of the elements of `list` in `string` by
prefixing it with a backslash. prefixing it with a backslash.
Type: escape :: [string] -> string -> string
Example: Example:
escape ["(" ")"] "(foo)" escape ["(" ")"] "(foo)"
=> "\\(foo\\)" => "\\(foo\\)"
@ -214,6 +287,8 @@ rec {
/* Quote string to be used safely within the Bourne shell. /* Quote string to be used safely within the Bourne shell.
Type: escapeShellArg :: string -> string
Example: Example:
escapeShellArg "esc'ape\nme" escapeShellArg "esc'ape\nme"
=> "'esc'\\''ape\nme'" => "'esc'\\''ape\nme'"
@ -222,6 +297,8 @@ rec {
/* Quote all arguments to be safely passed to the Bourne shell. /* Quote all arguments to be safely passed to the Bourne shell.
Type: escapeShellArgs :: [string] -> string
Example: Example:
escapeShellArgs ["one" "two three" "four'five"] escapeShellArgs ["one" "two three" "four'five"]
=> "'one' 'two three' 'four'\\''five'" => "'one' 'two three' 'four'\\''five'"
@ -230,13 +307,15 @@ rec {
/* Turn a string into a Nix expression representing that string /* Turn a string into a Nix expression representing that string
Type: string -> string
Example: Example:
escapeNixString "hello\${}\n" escapeNixString "hello\${}\n"
=> "\"hello\\\${}\\n\"" => "\"hello\\\${}\\n\""
*/ */
escapeNixString = s: escape ["$"] (builtins.toJSON s); escapeNixString = s: escape ["$"] (builtins.toJSON s);
/* Obsolete - use replaceStrings instead. */ # Obsolete - use replaceStrings instead.
replaceChars = builtins.replaceStrings or ( replaceChars = builtins.replaceStrings or (
del: new: s: del: new: s:
let let
@ -256,6 +335,8 @@ rec {
/* Converts an ASCII string to lower-case. /* Converts an ASCII string to lower-case.
Type: toLower :: string -> string
Example: Example:
toLower "HOME" toLower "HOME"
=> "home" => "home"
@ -264,6 +345,8 @@ rec {
/* Converts an ASCII string to upper-case. /* Converts an ASCII string to upper-case.
Type: toUpper :: string -> string
Example: Example:
toUpper "home" toUpper "home"
=> "HOME" => "HOME"
@ -273,7 +356,7 @@ rec {
/* Appends string context from another string. This is an implementation /* Appends string context from another string. This is an implementation
detail of Nix. detail of Nix.
Strings in Nix carry an invisible `context' which is a list of strings Strings in Nix carry an invisible `context` which is a list of strings
representing store paths. If the string is later used in a derivation representing store paths. If the string is later used in a derivation
attribute, the derivation will properly populate the inputDrvs and attribute, the derivation will properly populate the inputDrvs and
inputSrcs. inputSrcs.
@ -319,8 +402,9 @@ rec {
in in
recurse 0 0; recurse 0 0;
/* Return the suffix of the second argument if the first argument matches /* Return a string without the specified prefix, if the prefix matches.
its prefix.
Type: string -> string -> string
Example: Example:
removePrefix "foo." "foo.bar.baz" removePrefix "foo." "foo.bar.baz"
@ -328,18 +412,23 @@ rec {
removePrefix "xxx" "foo.bar.baz" removePrefix "xxx" "foo.bar.baz"
=> "foo.bar.baz" => "foo.bar.baz"
*/ */
removePrefix = pre: s: removePrefix =
# Prefix to remove if it matches
prefix:
# Input string
str:
let let
preLen = stringLength pre; preLen = stringLength prefix;
sLen = stringLength s; sLen = stringLength str;
in in
if hasPrefix pre s then if hasPrefix prefix str then
substring preLen (sLen - preLen) s substring preLen (sLen - preLen) str
else else
s; str;
/* Return the prefix of the second argument if the first argument matches /* Return a string without the specified suffix, if the suffix matches.
its suffix.
Type: string -> string -> string
Example: Example:
removeSuffix "front" "homefront" removeSuffix "front" "homefront"
@ -347,17 +436,21 @@ rec {
removeSuffix "xxx" "homefront" removeSuffix "xxx" "homefront"
=> "homefront" => "homefront"
*/ */
removeSuffix = suf: s: removeSuffix =
# Suffix to remove if it matches
suffix:
# Input string
str:
let let
sufLen = stringLength suf; sufLen = stringLength suffix;
sLen = stringLength s; sLen = stringLength str;
in in
if sufLen <= sLen && suf == substring (sLen - sufLen) sufLen s then if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str then
substring 0 (sLen - sufLen) s substring 0 (sLen - sufLen) str
else else
s; str;
/* Return true iff string v1 denotes a version older than v2. /* Return true if string v1 denotes a version older than v2.
Example: Example:
versionOlder "1.1" "1.2" versionOlder "1.1" "1.2"
@ -367,7 +460,7 @@ rec {
*/ */
versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1; versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1;
/* Return true iff string v1 denotes a version equal to or newer than v2. /* Return true if string v1 denotes a version equal to or newer than v2.
Example: Example:
versionAtLeast "1.1" "1.0" versionAtLeast "1.1" "1.0"
@ -410,7 +503,7 @@ rec {
components = splitString "/" url; components = splitString "/" url;
filename = lib.last components; filename = lib.last components;
name = builtins.head (splitString sep filename); name = builtins.head (splitString sep filename);
in assert name != filename; name; in assert name != filename; name;
/* Create an --{enable,disable}-<feat> string that can be passed to /* Create an --{enable,disable}-<feat> string that can be passed to
standard GNU Autoconf scripts. standard GNU Autoconf scripts.
@ -459,6 +552,11 @@ rec {
/* Create a fixed width string with additional prefix to match /* Create a fixed width string with additional prefix to match
required width. required width.
This function will fail if the input string is longer than the
requested length.
Type: fixedWidthString :: int -> string -> string
Example: Example:
fixedWidthString 5 "0" (toString 15) fixedWidthString 5 "0" (toString 15)
=> "00015" => "00015"
@ -468,7 +566,10 @@ rec {
strw = lib.stringLength str; strw = lib.stringLength str;
reqWidth = width - (lib.stringLength filler); reqWidth = width - (lib.stringLength filler);
in in
assert strw <= width; assert lib.assertMsg (strw <= width)
"fixedWidthString: requested string length (${
toString width}) must not be shorter than actual length (${
toString strw})";
if strw == width then str else filler + fixedWidthString reqWidth filler str; if strw == width then str else filler + fixedWidthString reqWidth filler str;
/* Format a number adding leading zeroes up to fixed width. /* Format a number adding leading zeroes up to fixed width.
@ -499,12 +600,16 @@ rec {
=> false => false
*/ */
isStorePath = x: isStorePath = x:
isCoercibleToString x if isCoercibleToString x then
&& builtins.substring 0 1 (toString x) == "/" let str = toString x; in
&& dirOf (builtins.toPath x) == builtins.storeDir; builtins.substring 0 1 str == "/"
&& dirOf str == builtins.storeDir
else
false;
/* Convert string to int /* Parse a string string as an int.
Obviously, it is a bit hacky to use fromJSON that way.
Type: string -> int
Example: Example:
toInt "1337" toInt "1337"
@ -514,17 +619,18 @@ rec {
toInt "3.14" toInt "3.14"
=> error: floating point JSON numbers are not supported => error: floating point JSON numbers are not supported
*/ */
# Obviously, it is a bit hacky to use fromJSON this way.
toInt = str: toInt = str:
let may_be_int = builtins.fromJSON str; in let may_be_int = builtins.fromJSON str; in
if builtins.isInt may_be_int if builtins.isInt may_be_int
then may_be_int then may_be_int
else throw "Could not convert ${str} to int."; else throw "Could not convert ${str} to int.";
/* Read a list of paths from `file', relative to the `rootPath'. Lines /* Read a list of paths from `file`, relative to the `rootPath`.
beginning with `#' are treated as comments and ignored. Whitespace Lines beginning with `#` are treated as comments and ignored.
is significant. Whitespace is significant.
NOTE: this function is not performant and should be avoided NOTE: This function is not performant and should be avoided.
Example: Example:
readPathsFromFile /prefix readPathsFromFile /prefix
@ -537,16 +643,17 @@ rec {
*/ */
readPathsFromFile = rootPath: file: readPathsFromFile = rootPath: file:
let let
root = toString rootPath;
lines = lib.splitString "\n" (builtins.readFile file); lines = lib.splitString "\n" (builtins.readFile file);
removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line)); removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line));
relativePaths = removeComments lines; relativePaths = removeComments lines;
absolutePaths = builtins.map (path: builtins.toPath (root + "/" + path)) relativePaths; absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths;
in in
absolutePaths; absolutePaths;
/* Read the contents of a file removing the trailing \n /* Read the contents of a file removing the trailing \n
Type: fileContents :: path -> string
Example: Example:
$ echo "1.0" > ./version $ echo "1.0" > ./version

View File

@ -24,14 +24,20 @@ rec {
config = parse.tripleFromSystem final.parsed; config = parse.tripleFromSystem final.parsed;
# Just a guess, based on `system` # Just a guess, based on `system`
platform = platforms.selectBySystem final.system; platform = platforms.selectBySystem final.system;
# Determine whether we are compatible with the provided CPU
isCompatible = platform: parse.isCompatible final.parsed.cpu platform.parsed.cpu;
# Derived meta-data # Derived meta-data
libc = libc =
/**/ if final.isDarwin then "libSystem" /**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt" else if final.isMinGW then "msvcrt"
else if final.isWasi then "wasilibc"
else if final.isMusl then "musl" else if final.isMusl then "musl"
else if final.isUClibc then "uclibc" else if final.isUClibc then "uclibc"
else if final.isAndroid then "bionic" else if final.isAndroid then "bionic"
else if final.isLinux /* default */ then "glibc" else if final.isLinux /* default */ then "glibc"
else if final.isMsp430 then "newlib"
else if final.isAvr then "avrlibc"
else if final.isNetBSD then "nblibc"
# TODO(@Ericson2314) think more about other operating systems # TODO(@Ericson2314) think more about other operating systems
else "native/impure"; else "native/impure";
extensions = { extensions = {
@ -46,6 +52,73 @@ rec {
# Misc boolean options # Misc boolean options
useAndroidPrebuilt = false; useAndroidPrebuilt = false;
useiOSPrebuilt = false; useiOSPrebuilt = false;
# Output from uname
uname = {
# uname -s
system = {
"linux" = "Linux";
"windows" = "Windows";
"darwin" = "Darwin";
"netbsd" = "NetBSD";
"freebsd" = "FreeBSD";
"openbsd" = "OpenBSD";
"wasi" = "Wasi";
}.${final.parsed.kernel.name} or null;
# uname -p
processor = final.parsed.cpu.name;
# uname -r
release = null;
};
kernelArch =
if final.isAarch32 then "arm"
else if final.isAarch64 then "arm64"
else if final.isx86_32 then "x86"
else if final.isx86_64 then "ia64"
else final.parsed.cpu.name;
qemuArch =
if final.isArm then "arm"
else if final.isx86_64 then "x86_64"
else if final.isx86 then "i386"
else {
"powerpc" = "ppc";
"powerpcle" = "ppc";
"powerpc64" = "ppc64";
"powerpc64le" = "ppc64le";
}.${final.parsed.cpu.name} or final.parsed.cpu.name;
emulator = pkgs: let
qemu-user = pkgs.qemu.override {
smartcardSupport = false;
spiceSupport = false;
openGLSupport = false;
virglSupport = false;
vncSupport = false;
gtkSupport = false;
sdlSupport = false;
pulseSupport = false;
smbdSupport = false;
seccompSupport = false;
hostCpuTargets = ["${final.qemuArch}-linux-user"];
};
wine-name = "wine${toString final.parsed.cpu.bits}";
wine = (pkgs.winePackagesFor wine-name).minimal;
in
if final.parsed.kernel.name == pkgs.stdenv.hostPlatform.parsed.kernel.name &&
pkgs.stdenv.hostPlatform.isCompatible final
then "${pkgs.runtimeShell} -c '\"$@\"' --"
else if final.isWindows
then "${wine}/bin/${wine-name}"
else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux
then "${qemu-user}/bin/qemu-${final.qemuArch}"
else if final.isWasi
then "${pkgs.wasmtime}/bin/wasmtime"
else throw "Don't know how to run ${final.config} executables.";
} // mapAttrs (n: v: v final.parsed) inspect.predicates } // mapAttrs (n: v: v final.parsed) inspect.predicates
// args; // args;
in assert final.useAndroidPrebuilt -> final.isAndroid; in assert final.useAndroidPrebuilt -> final.isAndroid;

View File

@ -15,6 +15,10 @@ let
"x86_64-cygwin" "x86_64-darwin" "x86_64-freebsd" "x86_64-linux" "x86_64-cygwin" "x86_64-darwin" "x86_64-freebsd" "x86_64-linux"
"x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris" "x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris"
"x86_64-windows" "i686-windows"
"wasm64-wasi" "wasm32-wasi"
]; ];
allParsed = map parse.mkSystemFromString all; allParsed = map parse.mkSystemFromString all;
@ -36,13 +40,15 @@ in rec {
cygwin = filterDoubles predicates.isCygwin; cygwin = filterDoubles predicates.isCygwin;
darwin = filterDoubles predicates.isDarwin; darwin = filterDoubles predicates.isDarwin;
freebsd = filterDoubles predicates.isFreeBSD; freebsd = filterDoubles predicates.isFreeBSD;
# Should be better, but MinGW is unclear, and HURD is bit-rotted. # Should be better, but MinGW is unclear.
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }); gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
illumos = filterDoubles predicates.isSunOS; illumos = filterDoubles predicates.isSunOS;
linux = filterDoubles predicates.isLinux; linux = filterDoubles predicates.isLinux;
netbsd = filterDoubles predicates.isNetBSD; netbsd = filterDoubles predicates.isNetBSD;
openbsd = filterDoubles predicates.isOpenBSD; openbsd = filterDoubles predicates.isOpenBSD;
unix = filterDoubles predicates.isUnix; unix = filterDoubles predicates.isUnix;
wasi = filterDoubles predicates.isWasi;
windows = filterDoubles predicates.isWindows;
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "powerpc64le-linux"]; mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"];
} }

View File

@ -2,7 +2,14 @@
# `crossSystem`. They are put here for user convenience, but also used by cross # `crossSystem`. They are put here for user convenience, but also used by cross
# tests and linux cross stdenv building, so handle with care! # tests and linux cross stdenv building, so handle with care!
{ lib }: { lib }:
let platforms = import ./platforms.nix { inherit lib; }; in let
platforms = import ./platforms.nix { inherit lib; };
riscv = bits: {
config = "riscv${bits}-unknown-linux-gnu";
platform = platforms.riscv-multiplatform bits;
};
in
rec { rec {
# #
@ -28,7 +35,7 @@ rec {
}; };
armv7l-hf-multiplatform = rec { armv7l-hf-multiplatform = rec {
config = "armv7a-unknown-linux-gnueabihf"; config = "armv7l-unknown-linux-gnueabihf";
platform = platforms.armv7l-hf-multiplatform; platform = platforms.armv7l-hf-multiplatform;
}; };
@ -37,18 +44,10 @@ rec {
platform = platforms.aarch64-multiplatform; platform = platforms.aarch64-multiplatform;
}; };
armv5te-android-prebuilt = rec {
config = "armv5tel-unknown-linux-androideabi";
sdkVer = "21";
ndkVer = "10e";
platform = platforms.armv5te-android;
useAndroidPrebuilt = true;
};
armv7a-android-prebuilt = rec { armv7a-android-prebuilt = rec {
config = "armv7a-unknown-linux-androideabi"; config = "armv7a-unknown-linux-androideabi";
sdkVer = "24"; sdkVer = "24";
ndkVer = "17"; ndkVer = "18b";
platform = platforms.armv7a-android; platform = platforms.armv7a-android;
useAndroidPrebuilt = true; useAndroidPrebuilt = true;
}; };
@ -56,7 +55,7 @@ rec {
aarch64-android-prebuilt = rec { aarch64-android-prebuilt = rec {
config = "aarch64-unknown-linux-android"; config = "aarch64-unknown-linux-android";
sdkVer = "24"; sdkVer = "24";
ndkVer = "17"; ndkVer = "18b";
platform = platforms.aarch64-multiplatform; platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true; useAndroidPrebuilt = true;
}; };
@ -92,13 +91,56 @@ rec {
musl64 = { config = "x86_64-unknown-linux-musl"; }; musl64 = { config = "x86_64-unknown-linux-musl"; };
musl32 = { config = "i686-unknown-linux-musl"; }; musl32 = { config = "i686-unknown-linux-musl"; };
riscv = bits: {
config = "riscv${bits}-unknown-linux-gnu";
platform = platforms.riscv-multiplatform bits;
};
riscv64 = riscv "64"; riscv64 = riscv "64";
riscv32 = riscv "32"; riscv32 = riscv "32";
msp430 = {
config = "msp430-elf";
libc = "newlib";
};
avr = {
config = "avr";
};
arm-embedded = {
config = "arm-none-eabi";
libc = "newlib";
};
armhf-embedded = {
config = "arm-none-eabihf";
libc = "newlib";
};
aarch64-embedded = {
config = "aarch64-none-elf";
libc = "newlib";
};
aarch64be-embedded = {
config = "aarch64_be-none-elf";
libc = "newlib";
};
ppc-embedded = {
config = "powerpc-none-eabi";
libc = "newlib";
};
ppcle-embedded = {
config = "powerpcle-none-eabi";
libc = "newlib";
};
i686-embedded = {
config = "i686-elf";
libc = "newlib";
};
x86_64-embedded = {
config = "x86_64-elf";
libc = "newlib";
};
# #
# Darwin # Darwin
@ -162,4 +204,21 @@ rec {
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
platform = {}; platform = {};
}; };
# BSDs
amd64-netbsd = {
config = "x86_64-unknown-netbsd";
libc = "nblibc";
};
#
# WASM
#
wasi32 = {
config = "wasm32-unknown-wasi";
useLLVM = true;
};
} }

View File

@ -20,7 +20,7 @@ in rec {
cygwin = [ patterns.isCygwin ]; cygwin = [ patterns.isCygwin ];
darwin = [ patterns.isDarwin ]; darwin = [ patterns.isDarwin ];
freebsd = [ patterns.isFreeBSD ]; freebsd = [ patterns.isFreeBSD ];
# Should be better, but MinGW is unclear, and HURD is bit-rotted. # Should be better, but MinGW is unclear.
gnu = [ gnu = [
{ kernel = parse.kernels.linux; abi = abis.gnu; } { kernel = parse.kernels.linux; abi = abis.gnu; }
{ kernel = parse.kernels.linux; abi = abis.gnueabi; } { kernel = parse.kernels.linux; abi = abis.gnueabi; }
@ -32,6 +32,7 @@ in rec {
openbsd = [ patterns.isOpenBSD ]; openbsd = [ patterns.isOpenBSD ];
unix = patterns.isUnix; # Actually a list unix = patterns.isUnix; # Actually a list
windows = [ patterns.isWindows ]; windows = [ patterns.isWindows ];
wasi = [ patterns.isWasi ];
inherit (lib.systems.doubles) mesaPlatforms; inherit (lib.systems.doubles) mesaPlatforms;
} }

View File

@ -9,7 +9,8 @@ let abis = lib.mapAttrs (_: abi: builtins.removeAttrs abi [ "assertions" ]) abis
rec { rec {
patterns = rec { patterns = rec {
isi686 = { cpu = cpuTypes.i686; }; isi686 = { cpu = cpuTypes.i686; };
isx86_64 = { cpu = cpuTypes.x86_64; }; isx86_32 = { cpu = { family = "x86"; bits = 32; }; };
isx86_64 = { cpu = { family = "x86"; bits = 64; }; };
isPowerPC = { cpu = cpuTypes.powerpc; }; isPowerPC = { cpu = cpuTypes.powerpc; };
isPower = { cpu = { family = "power"; }; }; isPower = { cpu = { family = "power"; }; };
isx86 = { cpu = { family = "x86"; }; }; isx86 = { cpu = { family = "x86"; }; };
@ -19,6 +20,9 @@ rec {
isRiscV = { cpu = { family = "riscv"; }; }; isRiscV = { cpu = { family = "riscv"; }; };
isSparc = { cpu = { family = "sparc"; }; }; isSparc = { cpu = { family = "sparc"; }; };
isWasm = { cpu = { family = "wasm"; }; }; isWasm = { cpu = { family = "wasm"; }; };
isMsp430 = { cpu = { family = "msp430"; }; };
isAvr = { cpu = { family = "avr"; }; };
isAlpha = { cpu = { family = "alpha"; }; };
is32bit = { cpu = { bits = 32; }; }; is32bit = { cpu = { bits = 32; }; };
is64bit = { cpu = { bits = 64; }; }; is64bit = { cpu = { bits = 64; }; };
@ -27,19 +31,19 @@ rec {
isBSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; }; isBSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; };
isDarwin = { kernel = { families = { inherit (kernelFamilies) darwin; }; }; }; isDarwin = { kernel = { families = { inherit (kernelFamilies) darwin; }; }; };
isUnix = [ isBSD isDarwin isLinux isSunOS isHurd isCygwin ]; isUnix = [ isBSD isDarwin isLinux isSunOS isCygwin ];
isMacOS = { kernel = kernels.macos; }; isMacOS = { kernel = kernels.macos; };
isiOS = { kernel = kernels.ios; }; isiOS = { kernel = kernels.ios; };
isLinux = { kernel = kernels.linux; }; isLinux = { kernel = kernels.linux; };
isSunOS = { kernel = kernels.solaris; }; isSunOS = { kernel = kernels.solaris; };
isFreeBSD = { kernel = kernels.freebsd; }; isFreeBSD = { kernel = kernels.freebsd; };
isHurd = { kernel = kernels.hurd; };
isNetBSD = { kernel = kernels.netbsd; }; isNetBSD = { kernel = kernels.netbsd; };
isOpenBSD = { kernel = kernels.openbsd; }; isOpenBSD = { kernel = kernels.openbsd; };
isWindows = { kernel = kernels.windows; }; isWindows = { kernel = kernels.windows; };
isCygwin = { kernel = kernels.windows; abi = abis.cygnus; }; isCygwin = { kernel = kernels.windows; abi = abis.cygnus; };
isMinGW = { kernel = kernels.windows; abi = abis.gnu; }; isMinGW = { kernel = kernels.windows; abi = abis.gnu; };
isWasi = { kernel = kernels.wasi; };
isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ]; isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ];
isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ]; isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];

View File

@ -69,20 +69,24 @@ rec {
cpuTypes = with significantBytes; setTypes types.openCpuType { cpuTypes = with significantBytes; setTypes types.openCpuType {
arm = { bits = 32; significantByte = littleEndian; family = "arm"; }; arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; version = "5"; }; armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; version = "5"; arch = "armv5t"; };
armv6m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; }; armv6m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; arch = "armv6-m"; };
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; }; armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "6"; arch = "armv6"; };
armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; }; armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-a"; };
armv7r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; }; armv7r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-r"; };
armv7m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; }; armv7m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7-m"; };
armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; }; armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; version = "7"; arch = "armv7"; };
armv8a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; }; armv8a = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
armv8r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; }; armv8r = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
armv8m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; }; armv8m = { bits = 32; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-m"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; version = "8"; }; aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
aarch64_be = { bits = 64; significantByte = bigEndian; family = "arm"; version = "8"; arch = "armv8-a"; };
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; }; i386 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i386"; };
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; }; i486 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i486"; };
i586 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i586"; };
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; arch = "i686"; };
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; arch = "x86-64"; };
mips = { bits = 32; significantByte = bigEndian; family = "mips"; }; mips = { bits = 32; significantByte = bigEndian; family = "mips"; };
mipsel = { bits = 32; significantByte = littleEndian; family = "mips"; }; mipsel = { bits = 32; significantByte = littleEndian; family = "mips"; };
@ -92,6 +96,7 @@ rec {
powerpc = { bits = 32; significantByte = bigEndian; family = "power"; }; powerpc = { bits = 32; significantByte = bigEndian; family = "power"; };
powerpc64 = { bits = 64; significantByte = bigEndian; family = "power"; }; powerpc64 = { bits = 64; significantByte = bigEndian; family = "power"; };
powerpc64le = { bits = 64; significantByte = littleEndian; family = "power"; }; powerpc64le = { bits = 64; significantByte = littleEndian; family = "power"; };
powerpcle = { bits = 32; significantByte = littleEndian; family = "power"; };
riscv32 = { bits = 32; significantByte = littleEndian; family = "riscv"; }; riscv32 = { bits = 32; significantByte = littleEndian; family = "riscv"; };
riscv64 = { bits = 64; significantByte = littleEndian; family = "riscv"; }; riscv64 = { bits = 64; significantByte = littleEndian; family = "riscv"; };
@ -101,8 +106,93 @@ rec {
wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; }; wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; };
wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; }; wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; };
alpha = { bits = 64; significantByte = littleEndian; family = "alpha"; };
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
avr = { bits = 8; family = "avr"; };
}; };
# Determine where two CPUs are compatible with each other. That is,
# can we run code built for system b on system a? For that to
# happen, then the set of all possible possible programs that system
# b accepts must be a subset of the set of all programs that system
# a accepts. This compatibility relation forms a category where each
# CPU is an object and each arrow from a to b represents
# compatibility. CPUs with multiple modes of Endianness are
# isomorphic while all CPUs are endomorphic because any program
# built for a CPU can run on that CPU.
isCompatible = a: b: with cpuTypes; lib.any lib.id [
# x86
(b == i386 && isCompatible a i486)
(b == i486 && isCompatible a i586)
(b == i586 && isCompatible a i686)
# XXX: Not true in some cases. Like in WSL mode.
(b == i686 && isCompatible a x86_64)
# ARMv4
(b == arm && isCompatible a armv5tel)
# ARMv5
(b == armv5tel && isCompatible a armv6l)
# ARMv6
(b == armv6l && isCompatible a armv6m)
(b == armv6m && isCompatible a armv7l)
# ARMv7
(b == armv7l && isCompatible a armv7a)
(b == armv7l && isCompatible a armv7r)
(b == armv7l && isCompatible a armv7m)
(b == armv7a && isCompatible a armv8a)
(b == armv7r && isCompatible a armv8a)
(b == armv7m && isCompatible a armv8a)
(b == armv7a && isCompatible a armv8r)
(b == armv7r && isCompatible a armv8r)
(b == armv7m && isCompatible a armv8r)
(b == armv7a && isCompatible a armv8m)
(b == armv7r && isCompatible a armv8m)
(b == armv7m && isCompatible a armv8m)
# ARMv8
(b == armv8r && isCompatible a armv8a)
(b == armv8m && isCompatible a armv8a)
# XXX: not always true! Some arm64 cpus dont support arm32 mode.
(b == aarch64 && a == armv8a)
(b == armv8a && isCompatible a aarch64)
(b == aarch64 && a == aarch64_be)
(b == aarch64_be && isCompatible a aarch64)
# PowerPC
(b == powerpc && isCompatible a powerpc64)
(b == powerpcle && isCompatible a powerpc)
(b == powerpc && a == powerpcle)
(b == powerpc64le && isCompatible a powerpc64)
(b == powerpc64 && a == powerpc64le)
# MIPS
(b == mips && isCompatible a mips64)
(b == mips && a == mipsel)
(b == mipsel && isCompatible a mips)
(b == mips64 && a == mips64el)
(b == mips64el && isCompatible a mips64)
# RISCV
(b == riscv32 && isCompatible a riscv64)
# SPARC
(b == sparc && isCompatible a sparc64)
# WASM
(b == wasm32 && isCompatible a wasm64)
# identity
(b == a)
];
################################################################################ ################################################################################
types.openVendor = mkOptionType { types.openVendor = mkOptionType {
@ -117,6 +207,7 @@ rec {
apple = {}; apple = {};
pc = {}; pc = {};
none = {};
unknown = {}; unknown = {};
}; };
@ -135,6 +226,7 @@ rec {
elf = {}; elf = {};
macho = {}; macho = {};
pe = {}; pe = {};
wasm = {};
unknown = {}; unknown = {};
}; };
@ -172,12 +264,12 @@ rec {
macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; }; macos = { execFormat = macho; families = { inherit darwin; }; name = "darwin"; };
ios = { execFormat = macho; families = { inherit darwin; }; }; ios = { execFormat = macho; families = { inherit darwin; }; };
freebsd = { execFormat = elf; families = { inherit bsd; }; }; freebsd = { execFormat = elf; families = { inherit bsd; }; };
hurd = { execFormat = elf; families = { }; };
linux = { execFormat = elf; families = { }; }; linux = { execFormat = elf; families = { }; };
netbsd = { execFormat = elf; families = { inherit bsd; }; }; netbsd = { execFormat = elf; families = { inherit bsd; }; };
none = { execFormat = unknown; families = { }; }; none = { execFormat = unknown; families = { }; };
openbsd = { execFormat = elf; families = { inherit bsd; }; }; openbsd = { execFormat = elf; families = { inherit bsd; }; };
solaris = { execFormat = elf; families = { }; }; solaris = { execFormat = elf; families = { }; };
wasi = { execFormat = wasm; families = { }; };
windows = { execFormat = pe; families = { }; }; windows = { execFormat = pe; families = { }; };
} // { # aliases } // { # aliases
# 'darwin' is the kernel for all of them. We choose macOS by default. # 'darwin' is the kernel for all of them. We choose macOS by default.
@ -200,7 +292,15 @@ rec {
abis = setTypes types.openAbi { abis = setTypes types.openAbi {
cygnus = {}; cygnus = {};
msvc = {}; msvc = {};
eabi = {};
# Note: eabi is specific to ARM and PowerPC.
# On PowerPC, this corresponds to PPCEABI.
# On ARM, this corresponds to ARMEABI.
eabi = { float = "soft"; };
eabihf = { float = "hard"; };
# Other architectures should use ELF in embedded situations.
elf = {};
androideabi = {}; androideabi = {};
android = { android = {
@ -256,11 +356,20 @@ rec {
setType "system" components; setType "system" components;
mkSkeletonFromList = l: { mkSkeletonFromList = l: {
"1" = if elemAt l 0 == "avr"
then { cpu = elemAt l 0; kernel = "none"; abi = "unknown"; }
else throw "Target specification with 1 components is ambiguous";
"2" = # We only do 2-part hacks for things Nix already supports "2" = # We only do 2-part hacks for things Nix already supports
if elemAt l 1 == "cygwin" if elemAt l 1 == "cygwin"
then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; } then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
else if elemAt l 1 == "gnu" # MSVC ought to be the default ABI so this case isn't needed. But then it
then { cpu = elemAt l 0; kernel = "hurd"; abi = "gnu"; } # becomes difficult to handle the gnu* variants for Aarch32 correctly for
# minGW. So it's easier to make gnu* the default for the MinGW, but
# hack-in MSVC for the non-MinGW case right here.
else if elemAt l 1 == "windows"
then { cpu = elemAt l 0; kernel = "windows"; abi = "msvc"; }
else if (elemAt l 1) == "elf"
then { cpu = elemAt l 0; vendor = "unknown"; kernel = "none"; abi = elemAt l 1; }
else { cpu = elemAt l 0; kernel = elemAt l 1; }; else { cpu = elemAt l 0; kernel = elemAt l 1; };
"3" = # Awkwards hacks, beware! "3" = # Awkwards hacks, beware!
if elemAt l 1 == "apple" if elemAt l 1 == "apple"
@ -268,9 +377,13 @@ rec {
else if (elemAt l 1 == "linux") || (elemAt l 2 == "gnu") else if (elemAt l 1 == "linux") || (elemAt l 2 == "gnu")
then { cpu = elemAt l 0; kernel = elemAt l 1; abi = elemAt l 2; } then { cpu = elemAt l 0; kernel = elemAt l 1; abi = elemAt l 2; }
else if (elemAt l 2 == "mingw32") # autotools breaks on -gnu for window else if (elemAt l 2 == "mingw32") # autotools breaks on -gnu for window
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows"; abi = "gnu"; } then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows"; }
else if (elemAt l 2 == "wasi")
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "wasi"; }
else if hasPrefix "netbsd" (elemAt l 2) else if hasPrefix "netbsd" (elemAt l 2)
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; } then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; }
else if (elem (elemAt l 2) ["eabi" "eabihf" "elf"])
then { cpu = elemAt l 0; vendor = "unknown"; kernel = elemAt l 1; abi = elemAt l 2; }
else throw "Target specification with 3 components is ambiguous"; else throw "Target specification with 3 components is ambiguous";
"4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; }; "4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
}.${toString (length l)} }.${toString (length l)}
@ -302,13 +415,12 @@ rec {
else getKernel args.kernel; else getKernel args.kernel;
abi = abi =
/**/ if args ? abi then getAbi args.abi /**/ if args ? abi then getAbi args.abi
else if isLinux parsed then else if isLinux parsed || isWindows parsed then
if isAarch32 parsed then if isAarch32 parsed then
if lib.versionAtLeast (parsed.cpu.version or "0") "6" if lib.versionAtLeast (parsed.cpu.version or "0") "6"
then abis.gnueabihf then abis.gnueabihf
else abis.gnueabi else abis.gnueabi
else abis.gnu else abis.gnu
else if isWindows parsed then abis.gnu
else abis.unknown; else abis.unknown;
}; };

View File

@ -253,22 +253,11 @@ rec {
kernelTarget = "zImage"; kernelTarget = "zImage";
}; };
# https://developer.android.com/ndk/guides/abis#armeabi
armv5te-android = {
name = "armeabi";
gcc = {
arch = "armv5te";
float = "soft";
float-abi = "soft";
};
};
# https://developer.android.com/ndk/guides/abis#v7a # https://developer.android.com/ndk/guides/abis#v7a
armv7a-android = { armv7a-android = {
name = "armeabi-v7a"; name = "armeabi-v7a";
gcc = { gcc = {
arch = "armv7-a"; arch = "armv7-a";
float = "hard";
float-abi = "softfp"; float-abi = "softfp";
fpu = "vfpv3-d16"; fpu = "vfpv3-d16";
}; };
@ -467,10 +456,13 @@ rec {
}; };
selectBySystem = system: { selectBySystem = system: {
"i486-linux" = pc32;
"i586-linux" = pc32;
"i686-linux" = pc32; "i686-linux" = pc32;
"x86_64-linux" = pc64; "x86_64-linux" = pc64;
"armv5tel-linux" = sheevaplug; "armv5tel-linux" = sheevaplug;
"armv6l-linux" = raspberrypi; "armv6l-linux" = raspberrypi;
"armv7a-linux" = armv7l-hf-multiplatform;
"armv7l-linux" = armv7l-hf-multiplatform; "armv7l-linux" = armv7l-hf-multiplatform;
"aarch64-linux" = aarch64-multiplatform; "aarch64-linux" = aarch64-multiplatform;
"mipsel-linux" = fuloong2f_n32; "mipsel-linux" = fuloong2f_n32;

7
lib/tests/check-eval.nix Normal file
View File

@ -0,0 +1,7 @@
# Throws an error if any of our lib tests fail.
let tests = [ "misc" "systems" ];
all = builtins.concatLists (map (f: import (./. + "/${f}.nix")) tests);
in if all == []
then null
else throw (builtins.toJSON all)

View File

@ -112,7 +112,7 @@ runTests {
storePathAppendix = isStorePath storePathAppendix = isStorePath
"${goodPath}/bin/python"; "${goodPath}/bin/python";
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath))); nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
asPath = isStorePath (builtins.toPath goodPath); asPath = isStorePath (/. + goodPath);
otherPath = isStorePath "/something/else"; otherPath = isStorePath "/something/else";
otherVals = { otherVals = {
attrset = isStorePath {}; attrset = isStorePath {};
@ -236,6 +236,20 @@ runTests {
}; };
}; };
testOverrideExistingEmpty = {
expr = overrideExisting {} { a = 1; };
expected = {};
};
testOverrideExistingDisjoint = {
expr = overrideExisting { b = 2; } { a = 1; };
expected = { b = 2; };
};
testOverrideExistingOverride = {
expr = overrideExisting { a = 3; b = 2; } { a = 1; };
expected = { a = 1; b = 2; };
};
# GENERATORS # GENERATORS
# these tests assume attributes are converted to lists # these tests assume attributes are converted to lists
@ -355,9 +369,10 @@ runTests {
testToPretty = { testToPretty = {
expr = mapAttrs (const (generators.toPretty {})) rec { expr = mapAttrs (const (generators.toPretty {})) rec {
int = 42; int = 42;
float = 0.1337;
bool = true; bool = true;
string = ''fno"rd''; string = ''fno"rd'';
path = /. + "/foo"; # toPath returns a string path = /. + "/foo";
null_ = null; null_ = null;
function = x: x; function = x: x;
functionArgs = { arg ? 4, foo }: arg; functionArgs = { arg ? 4, foo }: arg;
@ -367,6 +382,7 @@ runTests {
}; };
expected = rec { expected = rec {
int = "42"; int = "42";
float = "~0.133700";
bool = "true"; bool = "true";
string = ''"fno\"rd"''; string = ''"fno\"rd"'';
path = "/foo"; path = "/foo";
@ -385,42 +401,4 @@ runTests {
expected = "«foo»"; expected = "«foo»";
}; };
# MISC
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 = builtins.add x.a 3; });
res6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = builtins.add; }; };
y = x.merge {};
in (y.merge) { a = 10; };
resRem7 = res6.replace (a: removeAttrs a ["a"]);
# 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;
};
} }

View File

@ -149,6 +149,12 @@ checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-long-list.ni
# Check loaOf with many merges of lists. # Check loaOf with many merges of lists.
checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-many-list-merges.nix checkConfigOutput "1 2 3 4 5 6 7 8 9 10" config.result ./loaOf-with-many-list-merges.nix
# Check mkAliasOptionModule.
checkConfigOutput "true" config.enable ./alias-with-priority.nix
checkConfigOutput "true" config.enableAlias ./alias-with-priority.nix
checkConfigOutput "false" config.enable ./alias-with-priority-can-override.nix
checkConfigOutput "false" config.enableAlias ./alias-with-priority-can-override.nix
cat <<EOF cat <<EOF
====== module tests ====== ====== module tests ======
$pass Pass $pass Pass

View File

@ -0,0 +1,55 @@
# This is a test to show that mkAliasOptionModule sets the priority correctly
# for aliased options.
#
# This test shows that an alias with a high priority is able to override
# a non-aliased option.
{ config, lib, ... }:
with lib;
{
options = {
# A simple boolean option that can be enabled or disabled.
enable = lib.mkOption {
type = types.nullOr types.bool;
default = null;
example = true;
description = ''
Some descriptive text
'';
};
# mkAliasOptionModule sets warnings, so this has to be defined.
warnings = mkOption {
internal = true;
default = [];
type = types.listOf types.str;
example = [ "The `foo' service is deprecated and will go away soon!" ];
description = ''
This option allows modules to show warnings to users during
the evaluation of the system configuration.
'';
};
};
imports = [
# Create an alias for the "enable" option.
(mkAliasOptionModule [ "enableAlias" ] [ "enable" ])
# Disable the aliased option with a high priority so it
# should override the next import.
( { config, lib, ... }:
{
enableAlias = lib.mkForce false;
}
)
# Enable the normal (non-aliased) option.
( { config, lib, ... }:
{
enable = true;
}
)
];
}

View File

@ -0,0 +1,55 @@
# This is a test to show that mkAliasOptionModule sets the priority correctly
# for aliased options.
#
# This test shows that an alias with a low priority is able to be overridden
# with a non-aliased option.
{ config, lib, ... }:
with lib;
{
options = {
# A simple boolean option that can be enabled or disabled.
enable = lib.mkOption {
type = types.nullOr types.bool;
default = null;
example = true;
description = ''
Some descriptive text
'';
};
# mkAliasOptionModule sets warnings, so this has to be defined.
warnings = mkOption {
internal = true;
default = [];
type = types.listOf types.str;
example = [ "The `foo' service is deprecated and will go away soon!" ];
description = ''
This option allows modules to show warnings to users during
the evaluation of the system configuration.
'';
};
};
imports = [
# Create an alias for the "enable" option.
(mkAliasOptionModule [ "enableAlias" ] [ "enable" ])
# Disable the aliased option, but with a default (low) priority so it
# should be able to be overridden by the next import.
( { config, lib, ... }:
{
enableAlias = lib.mkDefault false;
}
)
# Enable the normal (non-aliased) option.
( { config, lib, ... }:
{
enable = true;
}
)
];
}

View File

@ -12,20 +12,21 @@ let
expected = lib.sort lib.lessThan y; expected = lib.sort lib.lessThan y;
}; };
in with lib.systems.doubles; lib.runTests { in with lib.systems.doubles; lib.runTests {
all = assertTrue (mseteq all (linux ++ darwin ++ cygwin ++ freebsd ++ openbsd ++ netbsd ++ illumos)); testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows);
arm = assertTrue (mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7l-linux" ]); testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7l-linux" ];
i686 = assertTrue (mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" ]); testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" ];
mips = assertTrue (mseteq mips [ "mipsel-linux" ]); testmips = mseteq mips [ "mipsel-linux" ];
x86_64 = assertTrue (mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" ]); testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" ];
cygwin = assertTrue (mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ]); testcygwin = mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ];
darwin = assertTrue (mseteq darwin [ "x86_64-darwin" ]); testdarwin = mseteq darwin [ "x86_64-darwin" ];
freebsd = assertTrue (mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ]); testfreebsd = mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ];
gnu = assertTrue (mseteq gnu (linux /* ++ hurd ++ kfreebsd ++ ... */)); testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
illumos = assertTrue (mseteq illumos [ "x86_64-solaris" ]); testillumos = mseteq illumos [ "x86_64-solaris" ];
linux = assertTrue (mseteq linux [ "i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "mipsel-linux" ]); testlinux = mseteq linux [ "i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "mipsel-linux" ];
netbsd = assertTrue (mseteq netbsd [ "i686-netbsd" "x86_64-netbsd" ]); testnetbsd = mseteq netbsd [ "i686-netbsd" "x86_64-netbsd" ];
openbsd = assertTrue (mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ]); testopenbsd = mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ];
unix = assertTrue (mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos)); testwindows = mseteq windows [ "i686-cygwin" "x86_64-cygwin" "i686-windows" "x86_64-windows" ];
testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin);
} }

View File

@ -9,23 +9,37 @@ rec {
Type: id :: a -> a Type: id :: a -> a
*/ */
id = x: x; id =
# The value to return
x: x;
/* The constant function /* The constant function
Ignores the second argument.
Or: Construct a function that always returns a static value. Ignores the second argument. If called with only one argument,
constructs a function that always returns a static value.
Type: const :: a -> b -> a Type: const :: a -> b -> a
Example: Example:
let f = const 5; in f 10 let f = const 5; in f 10
=> 5 => 5
*/ */
const = x: y: x; const =
# Value to return
x:
# Value to ignore
y: x;
## Named versions corresponding to some builtin operators. ## Named versions corresponding to some builtin operators.
/* Concatenate two lists */ /* Concatenate two lists
Type: concat :: [a] -> [a] -> [a]
Example:
concat [ 1 2 ] [ 3 4 ]
=> [ 1 2 3 4 ]
*/
concat = x: y: x ++ y; concat = x: y: x ++ y;
/* boolean or */ /* boolean or */
@ -36,44 +50,57 @@ rec {
/* bitwise and */ /* bitwise and */
bitAnd = builtins.bitAnd bitAnd = builtins.bitAnd
or import ./zip-int-bits.nix or (import ./zip-int-bits.nix
(a: b: if a==1 && b==1 then 1 else 0); (a: b: if a==1 && b==1 then 1 else 0));
/* bitwise or */ /* bitwise or */
bitOr = builtins.bitOr bitOr = builtins.bitOr
or import ./zip-int-bits.nix or (import ./zip-int-bits.nix
(a: b: if a==1 || b==1 then 1 else 0); (a: b: if a==1 || b==1 then 1 else 0));
/* bitwise xor */ /* bitwise xor */
bitXor = builtins.bitXor bitXor = builtins.bitXor
or import ./zip-int-bits.nix or (import ./zip-int-bits.nix
(a: b: if a!=b then 1 else 0); (a: b: if a!=b then 1 else 0));
/* bitwise not */ /* bitwise not */
bitNot = builtins.sub (-1); bitNot = builtins.sub (-1);
/* Convert a boolean to a string. /* Convert a boolean to a string.
Note that toString on a bool returns "1" and "".
This function uses the strings "true" and "false" to represent
boolean values. Calling `toString` on a bool instead returns "1"
and "" (sic!).
Type: boolToString :: bool -> string
*/ */
boolToString = b: if b then "true" else "false"; boolToString = b: if b then "true" else "false";
/* Merge two attribute sets shallowly, right side trumps left /* Merge two attribute sets shallowly, right side trumps left
mergeAttrs :: attrs -> attrs -> attrs
Example: Example:
mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; } mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
=> { a = 1; b = 3; c = 4; } => { a = 1; b = 3; c = 4; }
*/ */
mergeAttrs = x: y: x // y; mergeAttrs =
# Left attribute set
x:
# Right attribute set (higher precedence for equal keys)
y: x // y;
/* Flip the order of the arguments of a binary function. /* Flip the order of the arguments of a binary function.
Type: flip :: (a -> b -> c) -> (b -> a -> c)
Example: Example:
flip concat [1] [2] flip concat [1] [2]
=> [ 2 1 ] => [ 2 1 ]
*/ */
flip = f: a: b: f b a; flip = f: a: b: f b a;
/* Apply function if argument is non-null. /* Apply function if the supplied argument is non-null.
Example: Example:
mapNullable (x: x+1) null mapNullable (x: x+1) null
@ -81,7 +108,11 @@ rec {
mapNullable (x: x+1) 22 mapNullable (x: x+1) 22
=> 23 => 23
*/ */
mapNullable = f: a: if isNull a then a else f a; mapNullable =
# Function to call
f:
# Argument to check for null before passing it to `f`
a: if isNull a then a else f a;
# Pull in some builtins not included elsewhere. # Pull in some builtins not included elsewhere.
inherit (builtins) inherit (builtins)
@ -92,29 +123,58 @@ rec {
## nixpks version strings ## nixpks version strings
# The current full nixpkgs version number. /* Returns the current full nixpkgs version number. */
version = release + versionSuffix; version = release + versionSuffix;
# The current nixpkgs version number as string. /* Returns the current nixpkgs release number as string. */
release = lib.strings.fileContents ../.version; release = lib.strings.fileContents ../.version;
# The current nixpkgs version suffix as string. /* Returns the current nixpkgs release code name.
On each release the first letter is bumped and a new animal is chosen
starting with that new letter.
*/
codeName = "Loris";
/* Returns the current nixpkgs version suffix as string. */
versionSuffix = versionSuffix =
let suffixFile = ../.version-suffix; let suffixFile = ../.version-suffix;
in if pathExists suffixFile in if pathExists suffixFile
then lib.strings.fileContents suffixFile then lib.strings.fileContents suffixFile
else "pre-git"; else "pre-git";
/* Attempts to return the the current revision of nixpkgs and
returns the supplied default value otherwise.
Type: revisionWithDefault :: string -> string
*/
revisionWithDefault =
# Default value to return if revision can not be determined
default:
let
revisionFile = "${toString ./..}/.git-revision";
gitRepo = "${toString ./..}/.git";
in if lib.pathIsDirectory gitRepo
then lib.commitIdFromGitRepo gitRepo
else if lib.pathExists revisionFile then lib.fileContents revisionFile
else default;
nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version; nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
# Whether we're being called by nix-shell. /* Determine whether the function is being called from inside a Nix
shell.
Type: inNixShell :: bool
*/
inNixShell = builtins.getEnv "IN_NIX_SHELL" != ""; inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
## Integer operations ## Integer operations
# Return minimum/maximum of two numbers. /* Return minimum of two numbers. */
min = x: y: if x < y then x else y; min = x: y: if x < y then x else y;
/* Return maximum of two numbers. */
max = x: y: if x > y then x else y; max = x: y: if x > y then x else y;
/* Integer modulus /* Integer modulus
@ -148,8 +208,9 @@ rec {
second subtype, compare elements of a single subtype with `yes` second subtype, compare elements of a single subtype with `yes`
and `no` respectively. and `no` respectively.
Example: Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
Example:
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
cmp "a" "z" => -1 cmp "a" "z" => -1
@ -160,34 +221,48 @@ rec {
# while # while
compare "fooa" "a" => 1 compare "fooa" "a" => 1
*/ */
splitByAndCompare = p: yes: no: a: b: splitByAndCompare =
# Predicate
p:
# Comparison function if predicate holds for both values
yes:
# Comparison function if predicate holds for neither value
no:
# First value to compare
a:
# Second value to compare
b:
if p a if p a
then if p b then yes a b else -1 then if p b then yes a b else -1
else if p b then 1 else no a b; else if p b then 1 else no a b;
/* Reads a JSON file. */ /* Reads a JSON file.
Type :: path -> any
*/
importJSON = path: importJSON = path:
builtins.fromJSON (builtins.readFile path); builtins.fromJSON (builtins.readFile path);
## Warnings and asserts ## Warnings
/* See https://github.com/NixOS/nix/issues/749. Eventually we'd like these # See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
to expand to Nix builtins that carry metadata so that Nix can filter out # to expand to Nix builtins that carry metadata so that Nix can filter out
the INFO messages without parsing the message string. # the INFO messages without parsing the message string.
#
# Usage:
# {
# foo = lib.warn "foo is deprecated" oldFoo;
# }
#
# TODO: figure out a clever way to integrate location information from
# something like __unsafeGetAttrPos.
Usage: warn = msg: builtins.trace "warning: ${msg}";
{
foo = lib.warn "foo is deprecated" oldFoo;
}
TODO: figure out a clever way to integrate location information from
something like __unsafeGetAttrPos.
*/
warn = msg: builtins.trace "WARNING: ${msg}";
info = msg: builtins.trace "INFO: ${msg}"; info = msg: builtins.trace "INFO: ${msg}";
showWarnings = warnings: res: lib.fold (w: x: warn w x) res warnings;
## Function annotations ## Function annotations

View File

@ -119,7 +119,9 @@ rec {
let let
betweenDesc = lowest: highest: betweenDesc = lowest: highest:
"${toString lowest} and ${toString highest} (both inclusive)"; "${toString lowest} and ${toString highest} (both inclusive)";
between = lowest: highest: assert lowest <= highest; between = lowest: highest:
assert lib.assertMsg (lowest <= highest)
"ints.between: lowest must be smaller than highest";
addCheck int (x: x >= lowest && x <= highest) // { addCheck int (x: x >= lowest && x <= highest) // {
name = "intBetween"; name = "intBetween";
description = "integer between ${betweenDesc lowest highest}"; description = "integer between ${betweenDesc lowest highest}";
@ -167,6 +169,9 @@ rec {
# s32 = sign 32 4294967296; # s32 = sign 32 4294967296;
}; };
# Alias of u16 for a port number
port = ints.u16;
float = mkOptionType rec { float = mkOptionType rec {
name = "float"; name = "float";
description = "floating point number"; description = "floating point number";
@ -192,7 +197,10 @@ rec {
# separator between the values). # separator between the values).
separatedString = sep: mkOptionType rec { separatedString = sep: mkOptionType rec {
name = "separatedString"; name = "separatedString";
description = "string"; description = if sep == ""
then "Concatenated string" # for types.string.
else "strings concatenated with ${builtins.toJSON sep}"
;
check = isString; check = isString;
merge = loc: defs: concatStringsSep sep (getValues defs); merge = loc: defs: concatStringsSep sep (getValues defs);
functor = (defaultFunctor name) // { functor = (defaultFunctor name) // {
@ -276,8 +284,7 @@ rec {
(mergeDefinitions (loc ++ [name]) elemType defs).optionalValue (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
) )
# Push down position info. # Push down position info.
(map (def: listToAttrs (mapAttrsToList (n: def': (map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs)));
{ name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs)));
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
getSubModules = elemType.getSubModules; getSubModules = elemType.getSubModules;
substSubModules = m: attrsOf (elemType.substSubModules m); substSubModules = m: attrsOf (elemType.substSubModules m);
@ -439,7 +446,9 @@ rec {
# Either value of type `finalType` or `coercedType`, the latter is # Either value of type `finalType` or `coercedType`, the latter is
# converted to `finalType` using `coerceFunc`. # converted to `finalType` using `coerceFunc`.
coercedTo = coercedType: coerceFunc: finalType: coercedTo = coercedType: coerceFunc: finalType:
assert coercedType.getSubModules == null; assert lib.assertMsg (coercedType.getSubModules == null)
"coercedTo: coercedType must not have submodules (its a ${
coercedType.description})";
mkOptionType rec { mkOptionType rec {
name = "coercedTo"; name = "coercedTo";
description = "${finalType.description} or ${coercedType.description} convertible to it"; description = "${finalType.description} or ${coercedType.description} convertible to it";
@ -464,7 +473,6 @@ rec {
name = builtins.trace "types.optionSet is deprecated; use types.submodule instead" "optionSet"; name = builtins.trace "types.optionSet is deprecated; use types.submodule instead" "optionSet";
description = "option set"; description = "option set";
}; };
# Augment the given type with an additional type check function. # Augment the given type with an additional type check function.
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; }; addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#! /usr/bin/env nix-shell #! /usr/bin/env nix-shell
#! nix-shell -i perl -p perl perlPackages.NetAmazonS3 perlPackages.FileSlurp nixUnstable nixUnstable.perl-bindings #! nix-shell -i perl -p perl perlPackages.NetAmazonS3 perlPackages.FileSlurp perlPackages.JSON perlPackages.LWPProtocolHttps nixUnstable nixUnstable.perl-bindings
# This command uploads tarballs to tarballs.nixos.org, the # This command uploads tarballs to tarballs.nixos.org, the
# content-addressed cache used by fetchurl as a fallback for when # content-addressed cache used by fetchurl as a fallback for when
@ -101,8 +101,8 @@ sub uploadFile {
my ($name, $dest) = @_; my ($name, $dest) = @_;
#print STDERR "linking $name to $dest...\n"; #print STDERR "linking $name to $dest...\n";
$bucket->add_key($name, "", { $bucket->add_key($name, "", {
'x-amz-website-redirect-location' => "/" . $dest, 'x-amz-website-redirect-location' => "/" . $dest,
'x-amz-acl' => "public-read" 'x-amz-acl' => "public-read"
}) })
or die "failed to create redirect from $name to $dest\n"; or die "failed to create redirect from $name to $dest\n";
$cache{$name} = 1; $cache{$name} = 1;
@ -116,8 +116,8 @@ sub uploadFile {
# Upload the file as sha512/<hash-in-base-16>. # Upload the file as sha512/<hash-in-base-16>.
print STDERR "uploading $fn to $mainKey...\n"; print STDERR "uploading $fn to $mainKey...\n";
$bucket->add_key_filename($mainKey, $fn, { $bucket->add_key_filename($mainKey, $fn, {
'x-amz-meta-original-name' => $name, 'x-amz-meta-original-name' => $name,
'x-amz-acl' => "public-read" 'x-amz-acl' => "public-read"
}) })
or die "failed to upload $fn to $mainKey\n"; or die "failed to upload $fn to $mainKey\n";
$cache{$mainKey} = 1; $cache{$mainKey} = 1;

View File

@ -0,0 +1,11 @@
#! /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
# With the default heap size (380MB), nix-instantiate fails:
# Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS
export GC_INITIAL_HEAP_SIZE=${GC_INITIAL_HEAP_SIZE:-2000000000} # 2GB
nix-instantiate --strict --eval-only --xml --show-trace "$(dirname "$0")"/eval-release.nix 2>&1 > /dev/null

View File

@ -14,12 +14,13 @@ fi
tmp=$(mktemp -d) tmp=$(mktemp -d)
pushd $tmp >/dev/null pushd $tmp >/dev/null
wget -nH -r -c --no-parent "${WGET_ARGS[@]}" >/dev/null wget -nH -r -c --no-parent "${WGET_ARGS[@]}" -A '*.tar.xz.sha256' -A '*.mirrorlist' >/dev/null
find -type f -name '*.mirrorlist' -delete
csv=$(mktemp) csv=$(mktemp)
find . -type f | while read src; do find . -type f | while read src; do
# Sanitize file name # Sanitize file name
filename=$(basename "$src" | tr '@' '_') filename=$(gawk '{ print $2 }' "$src" | tr '@' '_')
nameVersion="${filename%.tar.*}" nameVersion="${filename%.tar.*}"
name=$(echo "$nameVersion" | sed -e 's,-[[:digit:]].*,,' | sed -e 's,-opensource-src$,,' | sed -e 's,-everywhere-src$,,') name=$(echo "$nameVersion" | sed -e 's,-[[:digit:]].*,,' | sed -e 's,-opensource-src$,,' | sed -e 's,-everywhere-src$,,')
version=$(echo "$nameVersion" | sed -e 's,^\([[:alpha:]][[:alnum:]]*-\)\+,,') version=$(echo "$nameVersion" | sed -e 's,^\([[:alpha:]][[:alnum:]]*-\)\+,,')
@ -38,8 +39,8 @@ gawk -F , "{ print \$1 }" $csv | sort | uniq | while read name; do
latestVersion=$(echo "$versions" | sort -rV | head -n 1) latestVersion=$(echo "$versions" | sort -rV | head -n 1)
src=$(gawk -F , "/^$name,$latestVersion,/ { print \$3 }" $csv) src=$(gawk -F , "/^$name,$latestVersion,/ { print \$3 }" $csv)
filename=$(gawk -F , "/^$name,$latestVersion,/ { print \$4 }" $csv) filename=$(gawk -F , "/^$name,$latestVersion,/ { print \$4 }" $csv)
url="${src:2}" url="$(dirname "${src:2}")/$filename"
sha256=$(nix-hash --type sha256 --base32 --flat "$src") sha256=$(gawk '{ print $1 }' "$src")
cat >>"$SRCS" <<EOF cat >>"$SRCS" <<EOF
$name = { $name = {
version = "$latestVersion"; version = "$latestVersion";

View File

@ -31,7 +31,7 @@ let
if !canEval x then [] if !canEval x then []
else if isDerivation x then optional (canEval x.drvPath) x else if isDerivation x then optional (canEval x.drvPath) x
else if isList x then concatLists (map derivationsIn' x) else if isList x then concatLists (map derivationsIn' x)
else if isAttrs x then concatLists (mapAttrsToList (n: v: derivationsIn' v) x) else if isAttrs x then concatLists (mapAttrsToList (n: v: addErrorContext "while finding tarballs in '${n}':" (derivationsIn' v)) x)
else [ ]; else [ ];
keyDrv = drv: if canEval drv.drvPath then { key = drv.drvPath; value = drv; } else { }; keyDrv = drv: if canEval drv.drvPath then { key = drv.drvPath; value = drv; } else { };

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