Merge branch 'staging' into ios-13

This commit is contained in:
Matthew Bauer 2020-09-10 23:24:26 -05:00 committed by GitHub
commit 86d8c55470
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5295 changed files with 137796 additions and 81901 deletions

View file

@ -43,15 +43,50 @@ indent_style = space
# Disable file types or individual files
# some of these files may be auto-generated and/or require significant changes
[*.{c,h}]
insert_final_newline = unset
trim_trailing_whitespace = unset
[*.{key,ovpn}]
insert_final_newline = unset
end_of_line = unset
[*.lock]
indent_size = unset
[deps.nix]
insert_final_newline = unset
[eggs.nix]
trim_trailing_whitespace = unset
[gemset.nix]
insert_final_newline = unset
[node-{composition,packages}.nix]
insert_final_newline = unset
[nixos/modules/services/networking/ircd-hybrid/*.{conf,in}]
trim_trailing_whitespace = unset
[nixos/tests/systemd-networkd-vrf.nix]
trim_trailing_whitespace = unset
[pkgs/applications/editors/emacs-modes/recipes-archive-melpa.json]
indent_size = unset
[pkgs/build-support/dotnetenv/Wrapper/**]
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
[pkgs/build-support/upstream-updater/**]
trim_trailing_whitespace = unset
[pkgs/development/compilers/elm/registry.dat]
end_of_line = unset
insert_final_newline = unset
[pkgs/development/lisp-modules/quicklisp-to-nix.nix]
indent_size = unset
@ -70,5 +105,8 @@ insert_final_newline = unset
indent_size = unset
trim_trailing_whitespace = unset
[pkgs/top-level/emscripten-packages.nix]
trim_trailing_whitespace = unset
[pkgs/top-level/perl-packages.nix]
indent_size = unset

20
.github/CODEOWNERS vendored
View file

@ -10,6 +10,12 @@
# This file
/.github/CODEOWNERS @edolstra
# GitHub actions
/.github/workflows @Mic92 @zowoq
# EditorConfig
/.editorconfig @Mic92 @zowoq
# Libraries
/lib @edolstra @nbp @infinisil
/lib/systems @nbp @ericson2314 @matthewbauer
@ -189,10 +195,16 @@
/pkgs/top-level/php-packages.nix @NixOS/php
# Podman, CRI-O modules and related
/nixos/modules/virtualisation/containers.nix @NixOS/podman
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman
/nixos/modules/virtualisation/podman.nix @NixOS/podman
/nixos/tests/podman.nix @NixOS/podman
/nixos/modules/virtualisation/containers.nix @NixOS/podman @zowoq
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman @zowoq
/nixos/modules/virtualisation/podman.nix @NixOS/podman @zowoq
/nixos/tests/cri-o.nix @NixOS/podman @zowoq
/nixos/tests/podman.nix @NixOS/podman @zowoq
# Blockchains
/pkgs/applications/blockchains @mmahut
# Go
/pkgs/development/compilers/go @kalbasit @Mic92 @zowoq
/pkgs/development/go-modules @kalbasit @Mic92 @zowoq
/pkgs/development/go-packages @kalbasit @Mic92 @zowoq

32
.github/stale.yml vendored
View file

@ -9,17 +9,33 @@ exemptLabels:
# Label to use when marking an issue as stale
staleLabel: "2.status: stale"
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: |
Thank you for your contributions.
pulls:
markComment: |
Hello, I'm a bot and I thank you in the name of the community for your contributions.
This has been automatically marked as stale because it has had no activity for 180 days.
Nixpkgs is a busy repository, and unfortunately sometimes PRs get left behind for too long. Nevertheless, we'd like to help committers reach the PRs that are still important. This PR has had no activity for 180 days, and so I marked it as stale, but you can rest assured it will never be closed by a non-human.
If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.
If this is still important to you and you'd like to remove the stale label, we ask that you leave a comment. Your comment can be as simple as "still important to me". But there's a bit more you can do:
Here are suggestions that might help resolve this more quickly:
If you received an approval by an unprivileged maintainer and you are just waiting for a merge, you can @ mention someone with merge permissions and ask them to help. You might be able to find someone relevant by using [Git blame](https://git-scm.com/docs/git-blame) on the relevant files, or via [GitHub's web interface](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file). You can see if someone's a member of the [nixpkgs-committers](https://github.com/orgs/NixOS/teams/nixpkgs-committers) team, by hovering with the mouse over their username on the web interface, or by searching them directly on [the list](https://github.com/orgs/NixOS/teams/nixpkgs-committers).
If your PR wasn't reviewed at all, it might help to find someone who's perhaps a user of the package or module you are changing, or alternatively, ask once more for a review by the maintainer of the package/module this is about. If you don't know any, you can use [Git blame](https://git-scm.com/docs/git-blame) on the relevant files, or [GitHub's web interface](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file) to find someone who touched the relevant files in the past.
If your PR has had reviews and nevertheless got stale, make sure you've responded to all of the reviewer's requests / questions. Usually when PR authors show responsibility and dedication, reviewers (privileged or not) show dedication as well. If you've pushed a change, it's possible the reviewer wasn't notified about your push via email, so you can always [officially request them for a review](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/requesting-a-pull-request-review), or just @ mention them and say you've addressed their comments.
Lastly, you can always ask for help at [our Discourse Forum](https://discourse.nixos.org/), or more specifically, [at this thread](https://discourse.nixos.org/t/prs-in-distress/3604) or at [#nixos' IRC channel](https://webchat.freenode.net/#nixos).
issues:
markComment: |
Hello, I'm a bot and I thank you in the name of the community for opening this issue.
To help our human contributors focus on the most-relevant reports, I check up on old issues to see if they're still relevant. This issue has had no activity for 180 days, and so I marked it as stale, but you can rest assured it will never be closed by a non-human.
The community would appreciate your effort in checking if the issue is still valid. If it isn't, please close it.
If the issue persists, and you'd like to remove the stale label, you simply need to leave a comment. Your comment can be as simple as "still important to me". If you'd like it to get more attention, you can ask for help by searching for maintainers and people that previously touched related code and @ mention them in a comment. You can use [Git blame](https://git-scm.com/docs/git-blame) or [GitHub's web interface](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file) on the relevant files to find them.
Lastly, you can always ask for help at [our Discourse Forum](https://discourse.nixos.org/) or at [#nixos' IRC channel](https://webchat.freenode.net/#nixos).
1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
2. Ask on the [NixOS Discourse](https://discourse.nixos.org/).
3. Ask on the [#nixos channel](irc://irc.freenode.net/#nixos) on [irc.freenode.net](https://freenode.net).
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

27
.github/workflows/editorconfig.yml vendored Normal file
View file

@ -0,0 +1,27 @@
name: "Checking EditorConfig"
on:
pull_request:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: technote-space/get-diff-action@v3.1.0
- name: Fetch editorconfig-checker
if: env.GIT_DIFF
env:
ECC_VERSION: "2.1.0"
ECC_URL: "https://github.com/editorconfig-checker/editorconfig-checker/releases/download"
run: |
curl -sSf -O -L -C - "$ECC_URL/$ECC_VERSION/ec-linux-amd64.tar.gz" && \
tar xzf ec-linux-amd64.tar.gz && \
mv ./bin/ec-linux-amd64 ./bin/editorconfig-checker
- name: Checking EditorConfig
if: env.GIT_DIFF
run: |
./bin/editorconfig-checker -disable-indentation \
${{ env.GIT_DIFF }}

21
.github/workflows/pending-clear.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: "clear pending status"
on:
check_suite:
types: [ completed ]
jobs:
action:
runs-on: ubuntu-latest
steps:
- name: clear pending status
if: github.repository_owner == 'NixOS' && github.event.check_suite.app.name == 'OfBorg'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $GITHUB_TOKEN" \
-d '{"state": "success", "target_url": " ", "description": " ", "context": "Wait for ofborg"}' \
"https://api.github.com/repos/NixOS/nixpkgs/statuses/${{ github.event.check_suite.head_sha }}"

20
.github/workflows/pending-set.yml vendored Normal file
View file

@ -0,0 +1,20 @@
name: "set pending status"
on:
pull_request_target:
jobs:
action:
runs-on: ubuntu-latest
steps:
- name: set pending status
if: github.repository_owner == 'NixOS'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $GITHUB_TOKEN" \
-d '{"state": "failure", "target_url": " ", "description": "This failed status will be cleared when ofborg finishes eval.", "context": "Wait for ofborg"}' \
"https://api.github.com/repos/NixOS/nixpkgs/statuses/${{ github.event.pull_request.head.sha }}"

1
.gitignore vendored
View file

@ -12,6 +12,7 @@ result-*
.DS_Store
.mypy_cache
__pycache__
/pkgs/development/libraries/qt-5/*/tmp/
/pkgs/desktops/kde-5/*/tmp/

View file

@ -1,4 +1,4 @@
MD_TARGETS=$(addsuffix .xml, $(basename $(wildcard ./*.md ./**/*.md)))
MD_TARGETS=$(addsuffix .xml, $(basename $(shell find . -type f -regex '.*\.md$$')))
.PHONY: all
all: validate format out/html/index.html out/epub/manual.epub

View file

@ -0,0 +1,94 @@
# Cataclysm: Dark Days Ahead
## How to install Cataclysm DDA
To install the latest stable release of Cataclysm DDA to your profile, execute
`nix-env -f "<nixpkgs>" -iA cataclysm-dda`. For the curses build (build
without tiles), install `cataclysmDDA.stable.curses`. Note: `cataclysm-dda` is
an alias to `cataclysmDDA.stable.tiles`.
If you like access to a development build of your favorite git revision,
override `cataclysm-dda-git` (or `cataclysmDDA.git.curses` if you like curses
build):
```nix
cataclysm-dda-git.override {
version = "YYYY-MM-DD";
rev = "YOUR_FAVORITE_REVISION";
sha256 = "CHECKSUM_OF_THE_REVISION";
}
```
The sha256 checksum can be obtained by
```sh
nix-prefetch-url --unpack "https://github.com/CleverRaven/Cataclysm-DDA/archive/${YOUR_FAVORITE_REVISION}.tar.gz"
```
The default configuration directory is `~/.cataclysm-dda`. If you prefer
`$XDG_CONFIG_HOME/cataclysm-dda`, override the derivation:
```nix
cataclysm-dda.override {
useXdgDir = true;
}
```
## Customizing with mods
To install Cataclysm DDA with mods of your choice, you can use `withMods`
attribute:
```nix
cataclysm-dda.withMods (mods: with mods; [
tileset.UndeadPeople
])
```
All mods, soundpacks, and tilesets available in nixpkgs are found in
`cataclysmDDA.pkgs`.
Here is an example to modify existing mods and/or add more mods not available
in nixpkgs:
```nix
let
customMods = self: super: lib.recursiveUpdate super {
# Modify existing mod
tileset.UndeadPeople = super.tileset.UndeadPeople.overrideAttrs (old: {
# If you like to apply a patch to the tileset for example
patches = [ ./path/to/your.patch ];
});
# Add another mod
mod.Awesome = cataclysmDDA.buildMod {
modName = "Awesome";
version = "0.x";
src = fetchFromGitHub {
owner = "Someone";
repo = "AwesomeMod";
rev = "...";
sha256 = "...";
};
# Path to be installed in the unpacked source (default: ".")
modRoot = "contents/under/this/path/will/be/installed";
};
# Add another soundpack
soundpack.Fantastic = cataclysmDDA.buildSoundPack {
# ditto
};
# Add another tileset
tileset.SuperDuper = cataclysmDDA.buildTileSet {
# ditto
};
};
in
cataclysm-dda.withMods (mods: with mods.extend customMods; [
tileset.UndeadPeople
mod.Awesome
soundpack.Fantastic
tileset.SuperDuper
])
```

View file

@ -4,34 +4,36 @@
<title>Citrix Workspace</title>
<para>
<note>
<para>
Please note that the <literal>citrix_receiver</literal> package has been deprecated since its development was <link xlink:href="https://docs.citrix.com/en-us/citrix-workspace-app.html">discontinued by upstream</link> and has been replaced by <link xlink:href="https://www.citrix.com/products/workspace-app/">the citrix workspace app</link>.
</para>
</note>
<link xlink:href="https://www.citrix.com/products/receiver/">Citrix Receiver</link> and <link xlink:href="https://www.citrix.com/products/workspace-app/">Citrix Workspace App</link> are a remote desktop viewers which provide access to <link xlink:href="https://www.citrix.com/products/xenapp-xendesktop/">XenDesktop</link> installations.
The <link xlink:href="https://www.citrix.com/products/workspace-app/">Citrix Workspace App</link> is a remote desktop viewer which provides access to <link xlink:href="https://www.citrix.com/products/xenapp-xendesktop/">XenDesktop</link> installations.
</para>
<section xml:id="sec-citrix-base">
<title>Basic usage</title>
<para>
The tarball archive needs to be downloaded manually as the license agreements of the vendor for <link xlink:href="https://www.citrix.com/downloads/citrix-receiver/">Citrix Receiver</link> or <link xlink:href="https://www.citrix.de/downloads/workspace-app/linux/workspace-app-for-linux-latest.html">Citrix Workspace</link> need to be accepted first. Then run <command>nix-prefetch-url file://$PWD/linuxx64-$version.tar.gz</command>. With the archive available in the store the package can be built and installed with Nix.
The tarball archive needs to be downloaded manually as the license agreements of the vendor for <link xlink:href="https://www.citrix.de/downloads/workspace-app/linux/workspace-app-for-linux-latest.html">Citrix Workspace</link> needs to be accepted first. Then run <command>nix-prefetch-url file://$PWD/linuxx64-$version.tar.gz</command>. With the archive available in the store the package can be built and installed with Nix.
</para>
</section>
<warning>
<title>Caution with <command>nix-shell</command> installs</title>
<para>
It's recommended to install <literal>Citrix Receiver</literal> and/or <literal>Citrix Workspace</literal> using <literal>nix-env -i</literal> or globally to ensure that the <literal>.desktop</literal> files are installed properly into <literal>$XDG_CONFIG_DIRS</literal>. Otherwise it won't be possible to open <literal>.ica</literal> files automatically from the browser to start a Citrix connection.
</para>
</warning>
<section xml:id="sec-citrix-selfservice">
<title>Citrix Selfservice</title>
<para>
The <link xlink:href="https://support.citrix.com/article/CTX200337">selfservice</link> is an application managing Citrix desktops and applications. Please note that this feature only works with at least <package>citrix_workspace_20_06_0</package> and later versions.
</para>
<para>
In order to set this up, you first have to <link xlink:href="https://its.uiowa.edu/support/article/102186">download the <literal>.cr</literal> file from the Netscaler Gateway</link>. After that you can configure the <command>selfservice</command> like this:
<screen>
<prompt>$ </prompt>storebrowse -C ~/Downloads/receiverconfig.cr
<prompt>$ </prompt>selfservice
</screen>
</para>
</section>
<section xml:id="sec-citrix-custom-certs">
<title>Custom certificates</title>
<para>
The <literal>Citrix Workspace App</literal> in <literal>nixpkgs</literal> trust several certificates <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 <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 mechanism to add custom certificates without rebuilding the entire package using <literal>symlinkJoin</literal>:
The <literal>Citrix Workspace App</literal> in <literal>nixpkgs</literal> trusts several certificates <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 <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 mechanism to add custom certificates without rebuilding the entire package using <literal>symlinkJoin</literal>:
<programlisting>
<![CDATA[with import <nixpkgs> { config.allowUnfree = true; };
let extraCerts = [ ./custom-cert-1.pem ./custom-cert-2.pem /* ... */ ]; in

View file

@ -18,6 +18,7 @@
<xi:include href="opengl.xml" />
<xi:include href="shell-helpers.xml" />
<xi:include href="steam.xml" />
<xi:include href="cataclysm-dda.section.xml" />
<xi:include href="urxvt.xml" />
<xi:include href="weechat.xml" />
<xi:include href="xorg.xml" />

View file

@ -45,13 +45,7 @@
<title>How to play</title>
<para>
For 64-bit systems it's important to have
<programlisting>hardware.opengl.driSupport32Bit = true;</programlisting>
in your <filename>/etc/nixos/configuration.nix</filename>. You'll also need
<programlisting>hardware.pulseaudio.support32Bit = true;</programlisting>
if you are using PulseAudio - this will enable 32bit ALSA apps integration. To use the Steam controller or other Steam supported controllers such as the DualShock 4 or Nintendo Switch Pro, you need to add
<programlisting>hardware.steam-hardware.enable = true;</programlisting>
to your configuration.
Use <programlisting>programs.steam.enable = true;</programlisting> if you want to add steam to systemPackages and also enable a few workarrounds aswell as Steam controller support or other Steam supported controllers such as the DualShock 4 or Nintendo Switch Pr.
</para>
</section>

View file

@ -50,7 +50,7 @@ map (p: p.name) pkgs.rxvt-unicode.plugins
In addition to <literal>plugins</literal> the options
<literal>extraDeps</literal> and <literal>perlDeps</literal> can be used
to install extra packages.
<literal>extraDeps</literal> can be used, for example, to provide
<literal>extraDeps</literal> can be used, for example, to provide
<literal>xsel</literal> (a clipboard manager) to the clipboard plugin,
without installing it globally:
<programlisting>rxvt-unicode.override { configure = { availablePlugins, ... }: {

View file

@ -191,6 +191,8 @@ androidenv.emulateApp {
}
```
Additional flags may be applied to the Android SDK's emulator through the runtime environment variable `$NIX_ANDROID_EMULATOR_FLAGS`.
It is also possible to specify an APK to deploy inside the emulator
and the package and activity names to launch it:

View file

@ -68,7 +68,7 @@
<title>How to Install BEAM Packages</title>
<para>
BEAM builders are not registered at the top level, simply because they are not relevant to the vast majority of Nix users.
BEAM builders are not registered at the top level, simply because they are not relevant to the vast majority of Nix users.
To install any of those builders into your profile, refer to them by their attribute path <literal>beamPackages.rebar3</literal>:
</para>

View file

@ -21,11 +21,11 @@ Modes of use of `emscripten`:
* **Declarative usage**:
This mode is far more power full since this makes use of `nix` for dependency management of emscripten libraries and targets by using the `mkDerivation` which is implemented by `pkgs.emscriptenStdenv` and `pkgs.buildEmscriptenPackage`. The source for the packages is in `pkgs/top-level/emscripten-packages.nix` and the abstraction behind it in `pkgs/development/em-modules/generic/default.nix`.
* build and install all packages:
* `nix-env -iA emscriptenPackages`
* dev-shell for zlib implementation hacking:
* `nix-shell -A emscriptenPackages.zlib`
* build and install all packages:
* `nix-env -iA emscriptenPackages`
* dev-shell for zlib implementation hacking:
* `nix-shell -A emscriptenPackages.zlib`
## Imperative usage
@ -90,7 +90,7 @@ See the `zlib` example:
libz.so.${old.version} -I . -o example.js
echo "Using node to execute the test"
${pkgs.nodejs}/bin/node ./example.js
${pkgs.nodejs}/bin/node ./example.js
set +x
if [ $? -ne 0 ]; then
@ -112,7 +112,7 @@ See the `zlib` example:
### Usage 2: pkgs.buildEmscriptenPackage
This `xmlmirror` example features a emscriptenPackage which is defined completely from this context and no `pkgs.zlib.override` is used.
This `xmlmirror` example features a emscriptenPackage which is defined completely from this context and no `pkgs.zlib.override` is used.
xmlmirror = pkgs.buildEmscriptenPackage rec {
name = "xmlmirror";
@ -163,7 +163,7 @@ This `xmlmirror` example features a emscriptenPackage which is defined completel
checkPhase = ''
'';
};
};
### Declarative debugging
@ -182,4 +182,3 @@ Use `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz` and from
Using this toolchain makes it easy to leverage `nix` from NixOS, MacOSX or even Windows (WSL+ubuntu+nix). This toolchain is reproducible, behaves like the rest of the packages from nixpkgs and contains a set of well working examples to learn and adapt from.
If in trouble, ask the maintainers.

View file

@ -40,6 +40,10 @@ pet = buildGoModule rec {
subPackages = [ "." ]; <co xml:id='ex-buildGoModule-2' />
deleteVendor = true; <co xml:id='ex-buildGoModule-3' />
runVend = true; <co xml:id='ex-buildGoModule-4' />
meta = with lib; {
description = "Simple command-line snippet manager, written in Go";
homepage = "https://github.com/knqyf263/pet";
@ -64,6 +68,16 @@ pet = buildGoModule rec {
<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>
<callout arearefs='ex-buildGoModule-3'>
<para>
<varname>deleteVendor</varname> removes the pre-existing vendor directory and fetches the dependencies. This should only be used if the dependencies included in the vendor folder are broken or incomplete.
</para>
</callout>
<callout arearefs='ex-buildGoModule-4'>
<para>
<varname>runVend</varname> runs the vend command to generate the vendor directory. This is useful if your code depends on c code and go mod tidy does not include the needed sources to build.
</para>
</callout>
</calloutlist>
</para>
@ -72,7 +86,7 @@ pet = buildGoModule rec {
When `null` is used as a value, rather than fetching the dependencies
and vendoring them, we use the vendoring included within the source repo.
If you'd like to not have to update this field on dependency changes,
If you'd like to not have to update this field on dependency changes,
run `go mod vendor` in your source repo and set 'vendorSha256 = null;'
</para>
</section>

View file

@ -25,12 +25,13 @@ build system it uses. Here are some examples:
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`
requires `node-gyp-build`, so we override its expression in `default.nix`:
requires `node-gyp-build`, so [we override](https://github.com/NixOS/nixpkgs/blob/32f5e5da4a1b3f0595527f5195ac3a91451e9b56/pkgs/development/node-packages/default.nix#L37-L40) its expression in [`default.nix`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/node-packages/default.nix):
```nix
dat = nodePackages.dat.override (oldAttrs: {
buildInputs = oldAttrs.buildInputs ++ [ nodePackages.node-gyp-build ];
});
dat = super.dat.override {
buildInputs = [ self.node-gyp-build pkgs.libtool pkgs.autoconf pkgs.automake ];
meta.broken = since "12";
};
```
To add a package from NPM to nixpkgs:

View file

@ -3,159 +3,193 @@
xml:id="sec-language-perl">
<title>Perl</title>
<para>
Nixpkgs provides a function <varname>buildPerlPackage</varname>, a generic package builder function for any Perl package that has a standard <varname>Makefile.PL</varname>. Its implemented in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/perl-modules/generic"><filename>pkgs/development/perl-modules/generic</filename></link>.
</para>
<para>
Perl packages from CPAN are defined in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>, rather than <filename>pkgs/all-packages.nix</filename>. Most Perl packages are so straight-forward to build that they are defined here directly, rather than having a separate function for each package called from <filename>perl-packages.nix</filename>. However, more complicated packages should be put in a separate file, typically in <filename>pkgs/development/perl-modules</filename>. Here is an example of the former:
<programlisting>
ClassC3 = buildPerlPackage rec {
name = "Class-C3-0.21";
src = fetchurl {
url = "mirror://cpan/authors/id/F/FL/FLORA/${name}.tar.gz";
sha256 = "1bl8z095y4js66pwxnm7s853pi9czala4sqc743fdlnk27kq94gz";
};
};
</programlisting>
Note the use of <literal>mirror://cpan/</literal>, and the <literal>${name}</literal> in the URL definition to ensure that the name attribute is consistent with the source that were actually downloading. Perl packages are made available in <filename>all-packages.nix</filename> through the variable <varname>perlPackages</varname>. For instance, if you have a package that needs <varname>ClassC3</varname>, you would typically write
<programlisting>
foo = import ../path/to/foo.nix {
inherit stdenv fetchurl ...;
inherit (perlPackages) ClassC3;
};
</programlisting>
in <filename>all-packages.nix</filename>. You can test building a Perl package as follows:
<screen>
<prompt>$ </prompt>nix-build -A perlPackages.ClassC3
</screen>
<varname>buildPerlPackage</varname> adds <literal>perl-</literal> to the start of the name attribute, so the package above is actually called <literal>perl-Class-C3-0.21</literal>. So to install it, you can say:
<screen>
<prompt>$ </prompt>nix-env -i perl-Class-C3
</screen>
(Of course you can also install using the attribute name: <literal>nix-env -i -A perlPackages.ClassC3</literal>.)
</para>
<para>
So what does <varname>buildPerlPackage</varname> do? It does the following:
<orderedlist>
<listitem>
<para>
In the configure phase, it calls <literal>perl Makefile.PL</literal> to generate a Makefile. You can set the variable <varname>makeMakerFlags</varname> to pass flags to <filename>Makefile.PL</filename>
</para>
</listitem>
<listitem>
<para>
It adds the contents of the <envar>PERL5LIB</envar> environment variable to <literal>#! .../bin/perl</literal> line of Perl scripts as <literal>-I<replaceable>dir</replaceable></literal> flags. This ensures that a script can find its dependencies. (This can cause this shebang line to become too long for Darwin to handle; see the note below.)
</para>
</listitem>
<listitem>
<para>
In the fixup phase, it writes the propagated build inputs (<varname>propagatedBuildInputs</varname>) to the file <filename>$out/nix-support/propagated-user-env-packages</filename>. <command>nix-env</command> recursively installs all packages listed in this file when you install a package that has it. This ensures that a Perl package can find its dependencies.
</para>
</listitem>
</orderedlist>
</para>
<para>
<varname>buildPerlPackage</varname> is built on top of <varname>stdenv</varname>, so everything can be customised in the usual way. For instance, the <literal>BerkeleyDB</literal> module has a <varname>preConfigure</varname> hook to generate a configuration file used by <filename>Makefile.PL</filename>:
<programlisting>
{ buildPerlPackage, fetchurl, db }:
buildPerlPackage rec {
name = "BerkeleyDB-0.36";
src = fetchurl {
url = "mirror://cpan/authors/id/P/PM/PMQS/${name}.tar.gz";
sha256 = "07xf50riarb60l1h6m2dqmql8q5dij619712fsgw7ach04d8g3z1";
};
preConfigure = ''
echo "LIB = ${db.out}/lib" > config.in
echo "INCLUDE = ${db.dev}/include" >> config.in
'';
}
</programlisting>
</para>
<para>
Dependencies on other Perl packages can be specified in the <varname>buildInputs</varname> and <varname>propagatedBuildInputs</varname> attributes. If something is exclusively a build-time dependency, use <varname>buildInputs</varname>; if its (also) a runtime dependency, use <varname>propagatedBuildInputs</varname>. For instance, this builds a Perl module that has runtime dependencies on a bunch of other modules:
<programlisting>
ClassC3Componentised = buildPerlPackage rec {
name = "Class-C3-Componentised-1.0004";
src = fetchurl {
url = "mirror://cpan/authors/id/A/AS/ASH/${name}.tar.gz";
sha256 = "0xql73jkcdbq4q9m0b0rnca6nrlvf5hyzy8is0crdk65bynvs8q1";
};
propagatedBuildInputs = [
ClassC3 ClassInspector TestException MROCompat
];
};
</programlisting>
</para>
<para>
On Darwin, if a script has too many <literal>-I<replaceable>dir</replaceable></literal> flags in its first line (its “shebang line”), it will not run. This can be worked around by calling the <literal>shortenPerlShebang</literal> function from the <literal>postInstall</literal> phase:
<programlisting>
{ stdenv, buildPerlPackage, fetchurl, shortenPerlShebang }:
ImageExifTool = buildPerlPackage {
pname = "Image-ExifTool";
version = "11.50";
src = fetchurl {
url = "https://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-11.50.tar.gz";
sha256 = "0d8v48y94z8maxkmw1rv7v9m0jg2dc8xbp581njb6yhr7abwqdv3";
};
buildInputs = stdenv.lib.optional stdenv.isDarwin shortenPerlShebang;
postInstall = stdenv.lib.optional stdenv.isDarwin ''
shortenPerlShebang $out/bin/exiftool
'';
};
</programlisting>
This will remove the <literal>-I</literal> flags from the shebang line, rewrite them in the <literal>use lib</literal> form, and put them on the next line instead. This function can be given any number of Perl scripts as arguments; it will modify them in-place.
</para>
<section xml:id="ssec-generation-from-CPAN">
<title>Generation from CPAN</title>
<section xml:id="ssec-perl-running">
<title>Running perl programs on the shell</title>
<para>
Nix expressions for Perl packages can be generated (almost) automatically from CPAN. This is done by the program <command>nix-generate-from-cpan</command>, which can be installed as follows:
When executing a Perl script, it is possible you get an error such as <literal>./myscript.pl: bad interpreter: /usr/bin/perl: no such file or directory</literal>. This happens when the script expects Perl to be installed at <filename>/usr/bin/perl</filename>, which is not the case when using Perl from nixpkgs. You can fix the script by changing the first line to:
<programlisting>
#!/usr/bin/env perl
</programlisting>
to take the Perl installation from the <literal>PATH</literal> environment variable, or invoke Perl directly with:
<screen>
<prompt>$ </prompt>perl ./myscript.pl
</screen>
</para>
<screen>
<prompt>$ </prompt>nix-env -i nix-generate-from-cpan
</screen>
<para>
When the script is using a Perl library that is not installed globally, you might get an error such as <literal>Can't locate DB_File.pm in @INC (you may need to install the DB_File module)</literal>. In that case, you can use <command>nix-shell</command> to start an ad-hoc shell with that library installed, for instance:
<screen>
<prompt>$ </prompt>nix-shell -p perl perlPackages.DBFile --run ./myscript.pl
</screen>
</para>
<para>
This program takes a Perl module name, looks it up on CPAN, fetches and unpacks the corresponding package, and prints a Nix expression on standard output. For example:
<screen>
<prompt>$ </prompt>nix-generate-from-cpan XML::Simple
XMLSimple = buildPerlPackage rec {
name = "XML-Simple-2.22";
src = fetchurl {
url = "mirror://cpan/authors/id/G/GR/GRANTM/${name}.tar.gz";
sha256 = "b9450ef22ea9644ae5d6ada086dc4300fa105be050a2030ebd4efd28c198eb49";
};
propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ];
meta = {
description = "An API for simple XML files";
license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
};
};
</screen>
The output can be pasted into <filename>pkgs/top-level/perl-packages.nix</filename> or wherever else you need it.
If you are always using the script in places where <command>nix-shell</command> is available, you can embed the <command>nix-shell</command> invocation in the shebang like this:
<programlisting>
#!/usr/bin/env nix-shell
#! nix-shell -i perl -p perl perlPackages.DBFile
</programlisting>
</para>
</section>
<section xml:id="ssec-perl-cross-compilation">
<title>Cross-compiling modules</title>
<section xml:id="ssec-perl-packaging">
<title>Packaging Perl programs</title>
<para>
Nixpkgs has experimental support for cross-compiling Perl modules. In many cases, it will just work out of the box, even for modules with native extensions. Sometimes, however, the Makefile.PL for a module may (indirectly) import a native module. In that case, you will need to make a stub for that module that will satisfy the Makefile.PL and install it into <filename>lib/perl5/site_perl/cross_perl/${perl.version}</filename>. See the <varname>postInstall</varname> for <varname>DBI</varname> for an example.
Nixpkgs provides a function <varname>buildPerlPackage</varname>, a generic package builder function for any Perl package that has a standard <varname>Makefile.PL</varname>. Its implemented in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/perl-modules/generic"><filename>pkgs/development/perl-modules/generic</filename></link>.
</para>
<para>
Perl packages from CPAN are defined in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>, rather than <filename>pkgs/all-packages.nix</filename>. Most Perl packages are so straight-forward to build that they are defined here directly, rather than having a separate function for each package called from <filename>perl-packages.nix</filename>. However, more complicated packages should be put in a separate file, typically in <filename>pkgs/development/perl-modules</filename>. Here is an example of the former:
<programlisting>
ClassC3 = buildPerlPackage rec {
name = "Class-C3-0.21";
src = fetchurl {
url = "mirror://cpan/authors/id/F/FL/FLORA/${name}.tar.gz";
sha256 = "1bl8z095y4js66pwxnm7s853pi9czala4sqc743fdlnk27kq94gz";
};
};
</programlisting>
Note the use of <literal>mirror://cpan/</literal>, and the <literal>${name}</literal> in the URL definition to ensure that the name attribute is consistent with the source that were actually downloading. Perl packages are made available in <filename>all-packages.nix</filename> through the variable <varname>perlPackages</varname>. For instance, if you have a package that needs <varname>ClassC3</varname>, you would typically write
<programlisting>
foo = import ../path/to/foo.nix {
inherit stdenv fetchurl ...;
inherit (perlPackages) ClassC3;
};
</programlisting>
in <filename>all-packages.nix</filename>. You can test building a Perl package as follows:
<screen>
<prompt>$ </prompt>nix-build -A perlPackages.ClassC3
</screen>
<varname>buildPerlPackage</varname> adds <literal>perl-</literal> to the start of the name attribute, so the package above is actually called <literal>perl-Class-C3-0.21</literal>. So to install it, you can say:
<screen>
<prompt>$ </prompt>nix-env -i perl-Class-C3
</screen>
(Of course you can also install using the attribute name: <literal>nix-env -i -A perlPackages.ClassC3</literal>.)
</para>
<para>
So what does <varname>buildPerlPackage</varname> do? It does the following:
<orderedlist>
<listitem>
<para>
In the configure phase, it calls <literal>perl Makefile.PL</literal> to generate a Makefile. You can set the variable <varname>makeMakerFlags</varname> to pass flags to <filename>Makefile.PL</filename>
</para>
</listitem>
<listitem>
<para>
It adds the contents of the <envar>PERL5LIB</envar> environment variable to <literal>#! .../bin/perl</literal> line of Perl scripts as <literal>-I<replaceable>dir</replaceable></literal> flags. This ensures that a script can find its dependencies. (This can cause this shebang line to become too long for Darwin to handle; see the note below.)
</para>
</listitem>
<listitem>
<para>
In the fixup phase, it writes the propagated build inputs (<varname>propagatedBuildInputs</varname>) to the file <filename>$out/nix-support/propagated-user-env-packages</filename>. <command>nix-env</command> recursively installs all packages listed in this file when you install a package that has it. This ensures that a Perl package can find its dependencies.
</para>
</listitem>
</orderedlist>
</para>
<para>
<varname>buildPerlPackage</varname> is built on top of <varname>stdenv</varname>, so everything can be customised in the usual way. For instance, the <literal>BerkeleyDB</literal> module has a <varname>preConfigure</varname> hook to generate a configuration file used by <filename>Makefile.PL</filename>:
<programlisting>
{ buildPerlPackage, fetchurl, db }:
buildPerlPackage rec {
name = "BerkeleyDB-0.36";
src = fetchurl {
url = "mirror://cpan/authors/id/P/PM/PMQS/${name}.tar.gz";
sha256 = "07xf50riarb60l1h6m2dqmql8q5dij619712fsgw7ach04d8g3z1";
};
preConfigure = ''
echo "LIB = ${db.out}/lib" > config.in
echo "INCLUDE = ${db.dev}/include" >> config.in
'';
}
</programlisting>
</para>
<para>
Dependencies on other Perl packages can be specified in the <varname>buildInputs</varname> and <varname>propagatedBuildInputs</varname> attributes. If something is exclusively a build-time dependency, use <varname>buildInputs</varname>; if its (also) a runtime dependency, use <varname>propagatedBuildInputs</varname>. For instance, this builds a Perl module that has runtime dependencies on a bunch of other modules:
<programlisting>
ClassC3Componentised = buildPerlPackage rec {
name = "Class-C3-Componentised-1.0004";
src = fetchurl {
url = "mirror://cpan/authors/id/A/AS/ASH/${name}.tar.gz";
sha256 = "0xql73jkcdbq4q9m0b0rnca6nrlvf5hyzy8is0crdk65bynvs8q1";
};
propagatedBuildInputs = [
ClassC3 ClassInspector TestException MROCompat
];
};
</programlisting>
</para>
<para>
On Darwin, if a script has too many <literal>-I<replaceable>dir</replaceable></literal> flags in its first line (its “shebang line”), it will not run. This can be worked around by calling the <literal>shortenPerlShebang</literal> function from the <literal>postInstall</literal> phase:
<programlisting>
{ stdenv, buildPerlPackage, fetchurl, shortenPerlShebang }:
ImageExifTool = buildPerlPackage {
pname = "Image-ExifTool";
version = "11.50";
src = fetchurl {
url = "https://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-11.50.tar.gz";
sha256 = "0d8v48y94z8maxkmw1rv7v9m0jg2dc8xbp581njb6yhr7abwqdv3";
};
buildInputs = stdenv.lib.optional stdenv.isDarwin shortenPerlShebang;
postInstall = stdenv.lib.optional stdenv.isDarwin ''
shortenPerlShebang $out/bin/exiftool
'';
};
</programlisting>
This will remove the <literal>-I</literal> flags from the shebang line, rewrite them in the <literal>use lib</literal> form, and put them on the next line instead. This function can be given any number of Perl scripts as arguments; it will modify them in-place.
</para>
<section xml:id="ssec-generation-from-CPAN">
<title>Generation from CPAN</title>
<para>
Nix expressions for Perl packages can be generated (almost) automatically from CPAN. This is done by the program <command>nix-generate-from-cpan</command>, which can be installed as follows:
</para>
<screen>
<prompt>$ </prompt>nix-env -i nix-generate-from-cpan
</screen>
<para>
This program takes a Perl module name, looks it up on CPAN, fetches and unpacks the corresponding package, and prints a Nix expression on standard output. For example:
<screen>
<prompt>$ </prompt>nix-generate-from-cpan XML::Simple
XMLSimple = buildPerlPackage rec {
name = "XML-Simple-2.22";
src = fetchurl {
url = "mirror://cpan/authors/id/G/GR/GRANTM/${name}.tar.gz";
sha256 = "b9450ef22ea9644ae5d6ada086dc4300fa105be050a2030ebd4efd28c198eb49";
};
propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ];
meta = {
description = "An API for simple XML files";
license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
};
};
</screen>
The output can be pasted into <filename>pkgs/top-level/perl-packages.nix</filename> or wherever else you need it.
</para>
</section>
<section xml:id="ssec-perl-cross-compilation">
<title>Cross-compiling modules</title>
<para>
Nixpkgs has experimental support for cross-compiling Perl modules. In many cases, it will just work out of the box, even for modules with native extensions. Sometimes, however, the Makefile.PL for a module may (indirectly) import a native module. In that case, you will need to make a stub for that module that will satisfy the Makefile.PL and install it into <filename>lib/perl5/site_perl/cross_perl/${perl.version}</filename>. See the <varname>postInstall</varname> for <varname>DBI</varname> for an example.
</para>
</section>
</section>
</section>

View file

@ -538,8 +538,123 @@ buildPythonPackage rec {
```
Note also the line `doCheck = false;`, we explicitly disabled running the test-suite.
#### Testing Python Packages
#### Develop local package
It is highly encouraged to have testing as part of the package build. This
helps to avoid situations where the package was able to build and install,
but is not usable at runtime. Currently, all packages will use the `test`
command provided by the setup.py (i.e. `python setup.py test`). However,
this is currently deprecated https://github.com/pypa/setuptools/pull/1878
and your package should provide its own checkPhase.
*NOTE:* The `checkPhase` for python maps to the `installCheckPhase` on a
normal derivation. This is due to many python packages not behaving well
to the pre-installed version of the package. Version info, and natively
compiled extensions generally only exist in the install directory, and
thus can cause issues when a test suite asserts on that behavior.
*NOTE:* Tests should only be disabled if they don't agree with nix
(e.g. external dependencies, network access, flakey tests), however,
as many tests should be enabled as possible. Failing tests can still be
a good indication that the package is not in a valid state.
#### Using pytest
Pytest is the most common test runner for python repositories. A trivial
test run would be:
```
checkInputs = [ pytest ];
checkPhase = "pytest";
```
However, many repositories' test suites do not translate well to nix's build
sandbox, and will generally need many tests to be disabled.
To filter tests using pytest, one can do the following:
```
checkInputs = [ pytest ];
# avoid tests which need additional data or touch network
checkPhase = ''
pytest tests/ --ignore=tests/integration -k 'not download and not update'
'';
```
`--ignore` will tell pytest to ignore that file or directory from being
collected as part of a test run. This is useful is a file uses a package
which is not available in nixpkgs, thus skipping that test file is much
easier than having to create a new package.
`-k` is used to define a predicate for test names. In this example, we are
filtering out tests which contain `download` or `update` in their test case name.
Only one `-k` argument is allows, and thus a long predicate should be concatenated
with "\" and wrapped to the next line.
*NOTE:* In pytest==6.0.1, the use of "\" to continue a line (e.g. `-k 'not download \'`) has
been removed, in this case, it's recommended to use `pytestCheckHook`.
#### Using pytestCheckHook
`pytestCheckHook` is a convenient hook which will substitute the setuptools
`test` command for a checkPhase which runs `pytest`. This is also beneficial
when a package may need many items disabled to run the test suite.
Using the example above, the analagous pytestCheckHook usage would be:
```
checkInputs = [ pytestCheckHook ];
# requires additional data
pytestFlagsArray = [ "tests/" "--ignore=tests/integration" ];
disabledTests = [
# touches network
"download"
"update"
];
```
This is expecially useful when tests need to be conditionallydisabled,
for example:
```
disabledTests = [
# touches network
"download"
"update"
] ++ lib.optionals (pythonAtLeast "3.8") [
# broken due to python3.8 async changes
"async"
] ++ lib.optionals stdenv.isDarwin [
# can fail when building with other packages
"socket"
];
```
Trying to concatenate the related strings to disable tests in a regular checkPhase
would be much harder to read. This also enables us to comment on why specific tests
are disabled.
#### Using pythonImportsCheck
Although unit tests are highly prefered to valid correctness of a package. Not
all packages have test suites that can be ran easily, and some have none at all.
To help ensure the package still works, `pythonImportsCheck` can attempt to import
the listed modules.
```
pythonImportsCheck = [ "requests" "urllib" ];
```
roughly translates to:
```
postCheck = ''
PYTHONPATH=$out/${python.sitePackages}:$PYTHONPATH
python -c "import requests; import urllib"
'';
```
However, this is done in it's own phase, and not dependent on whether `doCheck = true;`
This can also be useful in verifying that the package doesn't assume commonly
present packages (e.g. `setuptools`)
### Develop local package
As a Python developer you're likely aware of [development mode](http://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode)
(`python setup.py develop`); instead of installing the package this command
@ -640,8 +755,8 @@ and in this case the `python38` interpreter is automatically used.
### Interpreters
Versions 2.7, 3.5, 3.6, 3.7 and 3.8 of the CPython interpreter are available as
respectively `python27`, `python35`, `python36`, `python37` and `python38`. The
Versions 2.7, 3.6, 3.7 and 3.8 of the CPython interpreter are available as
respectively `python27`, `python36`, `python37` and `python38`. The
aliases `python2` and `python3` correspond to respectively `python27` and
`python38`. The default interpreter, `python`, maps to `python2`. The PyPy
interpreters compatible with Python 2.7 and 3 are available as `pypy27` and
@ -689,15 +804,16 @@ attribute set is created for each available Python interpreter. The available
sets are
* `pkgs.python27Packages`
* `pkgs.python35Packages`
* `pkgs.python36Packages`
* `pkgs.python37Packages`
* `pkgs.python38Packages`
* `pkgs.python39Packages`
* `pkgs.pypyPackages`
and the aliases
* `pkgs.python2Packages` pointing to `pkgs.python27Packages`
* `pkgs.python3Packages` pointing to `pkgs.python37Packages`
* `pkgs.python3Packages` pointing to `pkgs.python38Packages`
* `pkgs.pythonPackages` pointing to `pkgs.python2Packages`
#### `buildPythonPackage` function
@ -1016,7 +1132,7 @@ are used in `buildPythonPackage`.
- `pipBuildHook` to build a wheel using `pip` and PEP 517. Note a build system
(e.g. `setuptools` or `flit`) should still be added as `nativeBuildInput`.
- `pipInstallHook` to install wheels.
- `pytestCheckHook` to run tests with `pytest`.
- `pytestCheckHook` to run tests with `pytest`. See [example usage](#using-pytestcheckhook).
- `pythonCatchConflictsHook` to check whether a Python package is not already existing.
- `pythonImportsCheckHook` to check whether importing the listed modules works.
- `pythonRemoveBinBytecode` to remove bytecode from the `/bin` folder.

View file

@ -43,7 +43,6 @@ rustPlatform.buildRustPackage rec {
homepage = "https://github.com/BurntSushi/ripgrep";
license = licenses.unlicense;
maintainers = [ maintainers.tailhook ];
platforms = platforms.all;
};
}
```
@ -79,7 +78,7 @@ pkgs.rustPlatform.buildRustPackage {
When using `buildRustPackage`, the `checkPhase` is enabled by default and runs
`cargo test` on the package to build. To make sure that we don't compile the
sources twice and to actually test the artifacts that will be used at runtime,
sources twice and to actually test the artifacts that will be used at runtime,
the tests will be ran in the `release` mode by default.
However, in some cases the test-suite of a package doesn't work properly in the

View file

@ -263,6 +263,8 @@ Sometimes plugins require an override that must be changed when the plugin is up
To add a new plugin, run `./update.py --add "[owner]/[name]"`. **NOTE**: This script automatically commits to your git repository. Be sure to check out a fresh branch before running.
Finally, there are some plugins that are also packaged in nodePackages because they have Javascript-related build steps, such as running webpack. Those plugins are not listed in `vim-plugin-names` or managed by `update.py` at all, and are included separately in `overrides.nix`. Currently, all these plugins are related to the `coc.nvim` ecosystem of Language Server Protocol integration with vim/neovim.
## Important repositories
- [vim-pi](https://bitbucket.org/vimcommunity/vim-pi) is a plugin repository

View file

@ -220,7 +220,7 @@ fi
preConfigure=preConfigure
preConfigure() {
# Determine the frontends to build.
langs="c"
if test -n "$langCC"; then
@ -262,7 +262,7 @@ postInstall() {
#if test -z "$profiledCompiler"; then
#makeFlags="bootstrap"
#else
#else
#makeFlags="profiledbootstrap"
#fi

View file

@ -155,17 +155,17 @@ hello-2.3 A program that produces a familiar, friendly greeting
<itemizedlist>
<listitem>
<para>
Single license referenced by attribute (preferred) <literal>stdenv.lib.licenses.gpl3</literal>.
Single license referenced by attribute (preferred) <literal>stdenv.lib.licenses.gpl3Only</literal>.
</para>
</listitem>
<listitem>
<para>
Single license referenced by its attribute shortName (frowned upon) <literal>"gpl3"</literal>.
Single license referenced by its attribute shortName (frowned upon) <literal>"gpl3Only"</literal>.
</para>
</listitem>
<listitem>
<para>
Single license referenced by its attribute spdxId (frowned upon) <literal>"GPL-3.0"</literal>.
Single license referenced by its attribute spdxId (frowned upon) <literal>"GPL-3.0-only"</literal>.
</para>
</listitem>
<listitem>

View file

@ -22,39 +22,69 @@
The reduction effects could be instead achieved by building the parts in completely separate derivations. That would often additionally reduce build-time closures, but it tends to be much harder to write such derivations, as build systems typically assume all parts are being built at once. This compromise approach of single source package producing multiple binary packages is also utilized often by rpm and deb.
</para>
</note>
<para>
A number of attributes can be used to work with a derivation with multiple outputs. The attribute <varname>outputs</varname> is a list of strings, which are the names of the outputs. For each of these names, an identically named attribute is created, corresponding to that output. The attribute <varname>meta.outputsToInstall</varname> is used to determine the default set of outputs to install when using the derivation name unqualified.
</para>
</section>
<section xml:id="sec-multiple-outputs-installing">
<title>Installing a split package</title>
<para>
When installing a package via <varname>systemPackages</varname> or <command>nix-env</command> you have several options:
When installing a package with multiple outputs, the package's <varname>meta.outputsToInstall</varname> attribute determines which outputs are actually installed. <varname>meta.outputsToInstall</varname> is a list whose <link xlink:href="https://github.com/NixOS/nixpkgs/blob/f1680774340d5443a1409c3421ced84ac1163ba9/pkgs/stdenv/generic/make-derivation.nix#L310-L320">default installs binaries and the associated man pages</link>. The following sections describe ways to install different outputs.
</para>
<itemizedlist>
<listitem>
<para>
You can install particular outputs explicitly, as each is available in the Nix language as an attribute of the package. The <varname>outputs</varname> attribute contains a list of output names.
</para>
</listitem>
<listitem>
<para>
You can let it use the default outputs. These are handled by <varname>meta.outputsToInstall</varname> attribute that contains a list of output names.
</para>
<para>
TODO: more about tweaking the attribute, etc.
</para>
</listitem>
<listitem>
<para>
NixOS provides configuration option <varname>environment.extraOutputsToInstall</varname> that allows adding extra outputs of <varname>environment.systemPackages</varname> atop the default ones. It's mainly meant for documentation and debug symbols, and it's also modified by specific options.
</para>
<note>
<section xml:id="sec-multiple-outputs-installing-nixos">
<title>Selecting outputs to install via NixOS</title>
<para>
NixOS provides two ways to select the outputs to install for packages listed in <varname>environment.systemPackages</varname>:
</para>
<itemizedlist>
<listitem>
<para>
At this moment there is no similar configurability for packages installed by <command>nix-env</command>. You can still use approach from <xref linkend="sec-modify-via-packageOverrides" /> to override <varname>meta.outputsToInstall</varname> attributes, but that's a rather inconvenient way.
The configuration option <varname>environment.extraOutputsToInstall</varname> is appended to each package's <varname>meta.outputsToInstall</varname> attribute to determine the outputs to install. It can for example be used to install <literal>info</literal> documentation or debug symbols for all packages.
</para>
</note>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>
The outputs can be listed as packages in <varname>environment.systemPackages</varname>. For example, the <literal>"out"</literal> and <literal>"info"</literal> outputs for the <varname>coreutils</varname> package can be installed by including <varname>coreutils</varname> and <varname>coreutils.info</varname> in <varname>environment.systemPackages</varname>.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-multiple-outputs-installing-nix-env">
<title>Selecting outputs to install via <command>nix-env</command></title>
<para>
<command>nix-env</command> lacks an easy way to select the outputs to install. When installing a package, <command>nix-env</command> always installs the outputs listed in <varname>meta.outputsToInstall</varname>, even when the user explicitly selects an output.
</para>
<warning>
<para>
<command>nix-env</command> silenty disregards the outputs selected by the user, and instead installs the outputs from <varname>meta.outputsToInstall</varname>. For example,
</para>
<programlisting>$ nix-env -iA nixpkgs.coreutils.info</programlisting>
<para>
installs the <literal>"out"</literal> output (<varname>coreutils.meta.outputsToInstall</varname> is <literal>[ "out" ]</literal>) instead of the requested <literal>"info"</literal>.
</para>
</warning>
<para>
The only recourse to select an output with <command>nix-env</command> is to override the package's <varname>meta.outputsToInstall</varname>, using the functions described in <xref linkend="chap-overrides" />. For example, the following overlay adds the <literal>"info"</literal> output for the <varname>coreutils</varname> package:
</para>
<programlisting>self: super:
{
coreutils = super.coreutils.overrideAttrs (oldAttrs: {
meta = oldAttrs.meta // { outputsToInstall = oldAttrs.meta.outputsToInstall or [ "out" ] ++ [ "info" ]; };
});
}
</programlisting>
</section>
</section>
<section xml:id="sec-multiple-outputs-using-split-packages">
<title>Using a split package</title>

View file

@ -254,7 +254,7 @@ let f(h, h + 1, i) = i + h
<variablelist>
<title>Variables specifying dependencies</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsBuildBuild">
<term>
<varname>depsBuildBuild</varname>
</term>
@ -267,7 +267,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-nativeBuildInputs">
<term>
<varname>nativeBuildInputs</varname>
</term>
@ -280,7 +280,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsBuildTarget">
<term>
<varname>depsBuildTarget</varname>
</term>
@ -296,7 +296,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsHostHost">
<term>
<varname>depsHostHost</varname>
</term>
@ -306,7 +306,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-buildInputs">
<term>
<varname>buildInputs</varname>
</term>
@ -319,7 +319,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsTargetTarget">
<term>
<varname>depsTargetTarget</varname>
</term>
@ -329,7 +329,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsBuildBuildPropagated">
<term>
<varname>depsBuildBuildPropagated</varname>
</term>
@ -339,7 +339,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-propagatedNativeBuildInputs">
<term>
<varname>propagatedNativeBuildInputs</varname>
</term>
@ -349,7 +349,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsBuildTargetPropagated">
<term>
<varname>depsBuildTargetPropagated</varname>
</term>
@ -359,7 +359,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsHostHostPropagated">
<term>
<varname>depsHostHostPropagated</varname>
</term>
@ -369,7 +369,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-propagatedBuildInputs">
<term>
<varname>propagatedBuildInputs</varname>
</term>
@ -379,7 +379,7 @@ let f(h, h + 1, i) = i + h
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-depsTargetTargetPropagated">
<term>
<varname>depsTargetTargetPropagated</varname>
</term>
@ -396,7 +396,7 @@ let f(h, h + 1, i) = i + h
<variablelist>
<title>Variables affecting <literal>stdenv</literal> initialisation</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-NIX_DEBUG">
<term>
<varname>NIX_DEBUG</varname>
</term>
@ -410,7 +410,7 @@ let f(h, h + 1, i) = i + h
<variablelist>
<title>Attributes affecting build properties</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-enableParallelBuilding">
<term>
<varname>enableParallelBuilding</varname>
</term>
@ -427,7 +427,7 @@ let f(h, h + 1, i) = i + h
<variablelist>
<title>Special variables</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-passthru">
<term>
<varname>passthru</varname>
</term>
@ -504,7 +504,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
There are a number of variables that control what phases are executed and in what order:
<variablelist>
<title>Variables affecting phase control</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-phases">
<term>
<varname>phases</varname>
</term>
@ -517,7 +517,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-prePhases">
<term>
<varname>prePhases</varname>
</term>
@ -527,7 +527,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preConfigurePhases">
<term>
<varname>preConfigurePhases</varname>
</term>
@ -537,7 +537,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preBuildPhases">
<term>
<varname>preBuildPhases</varname>
</term>
@ -547,7 +547,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preInstallPhases">
<term>
<varname>preInstallPhases</varname>
</term>
@ -557,7 +557,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preFixupPhases">
<term>
<varname>preFixupPhases</varname>
</term>
@ -567,7 +567,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preDistPhases">
<term>
<varname>preDistPhases</varname>
</term>
@ -577,7 +577,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postPhases">
<term>
<varname>postPhases</varname>
</term>
@ -635,7 +635,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
<variablelist>
<title>Variables controlling the unpack phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-src">
<term>
<varname>srcs</varname> / <varname>src</varname>
</term>
@ -645,7 +645,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-sourceRoot">
<term>
<varname>sourceRoot</varname>
</term>
@ -655,7 +655,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-setSourceRoot">
<term>
<varname>setSourceRoot</varname>
</term>
@ -665,7 +665,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preUnpack">
<term>
<varname>preUnpack</varname>
</term>
@ -675,7 +675,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postUnpack">
<term>
<varname>postUnpack</varname>
</term>
@ -685,7 +685,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontUnpack">
<term>
<varname>dontUnpack</varname>
</term>
@ -695,7 +695,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontMakeSourcesWritable">
<term>
<varname>dontMakeSourcesWritable</varname>
</term>
@ -705,7 +705,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-unpackCmd">
<term>
<varname>unpackCmd</varname>
</term>
@ -727,7 +727,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
<variablelist>
<title>Variables controlling the patch phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontPatch">
<term>
<varname>dontPatch</varname>
</term>
@ -737,7 +737,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-patches">
<term>
<varname>patches</varname>
</term>
@ -747,7 +747,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-patchFlags">
<term>
<varname>patchFlags</varname>
</term>
@ -757,7 +757,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-prePatch">
<term>
<varname>prePatch</varname>
</term>
@ -767,7 +767,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postPatch">
<term>
<varname>postPatch</varname>
</term>
@ -789,7 +789,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
<variablelist>
<title>Variables controlling the configure phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-configureScript">
<term>
<varname>configureScript</varname>
</term>
@ -799,7 +799,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-configureFlags">
<term>
<varname>configureFlags</varname>
</term>
@ -809,7 +809,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontConfigure">
<term>
<varname>dontConfigure</varname>
</term>
@ -819,7 +819,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-configureFlagsArray">
<term>
<varname>configureFlagsArray</varname>
</term>
@ -829,7 +829,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontAddPrefix">
<term>
<varname>dontAddPrefix</varname>
</term>
@ -839,7 +839,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-prefix">
<term>
<varname>prefix</varname>
</term>
@ -849,7 +849,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-prefixKey">
<term>
<varname>prefixKey</varname>
</term>
@ -859,7 +859,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontAddDisableDepTrack">
<term>
<varname>dontAddDisableDepTrack</varname>
</term>
@ -869,7 +869,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontFixLibtool">
<term>
<varname>dontFixLibtool</varname>
</term>
@ -885,7 +885,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontDisableStatic">
<term>
<varname>dontDisableStatic</varname>
</term>
@ -898,7 +898,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-configurePlatforms">
<term>
<varname>configurePlatforms</varname>
</term>
@ -913,7 +913,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preConfigure">
<term>
<varname>preConfigure</varname>
</term>
@ -923,7 +923,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postConfigure">
<term>
<varname>postConfigure</varname>
</term>
@ -945,7 +945,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
<variablelist>
<title>Variables controlling the build phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontBuild">
<term>
<varname>dontBuild</varname>
</term>
@ -955,7 +955,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-makefile">
<term>
<varname>makefile</varname>
</term>
@ -965,7 +965,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-makeFlags">
<term>
<varname>makeFlags</varname>
</term>
@ -983,7 +983,7 @@ makeFlags = [ "PREFIX=$(out)" ];
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-makeFlagsArray">
<term>
<varname>makeFlagsArray</varname>
</term>
@ -999,7 +999,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-buildFlags">
<term>
<varname>buildFlags</varname> / <varname>buildFlagsArray</varname>
</term>
@ -1009,7 +1009,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preBuild">
<term>
<varname>preBuild</varname>
</term>
@ -1019,7 +1019,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postBuild">
<term>
<varname>postBuild</varname>
</term>
@ -1049,7 +1049,7 @@ preBuild = ''
<variablelist>
<title>Variables controlling the check phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-doCheck">
<term>
<varname>doCheck</varname>
</term>
@ -1067,11 +1067,11 @@ preBuild = ''
</term>
<listitem>
<para>
See the build phase for details.
See the <link xlink:href="#var-stdenv-makeFlags">build phase</link> for details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-checkTarget">
<term>
<varname>checkTarget</varname>
</term>
@ -1081,7 +1081,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-checkFlags">
<term>
<varname>checkFlags</varname> / <varname>checkFlagsArray</varname>
</term>
@ -1091,7 +1091,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-checkInputs">
<term>
<varname>checkInputs</varname>
</term>
@ -1101,7 +1101,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preCheck">
<term>
<varname>preCheck</varname>
</term>
@ -1111,7 +1111,7 @@ preBuild = ''
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postCheck">
<term>
<varname>postCheck</varname>
</term>
@ -1133,7 +1133,7 @@ preBuild = ''
<variablelist>
<title>Variables controlling the install phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontInstall">
<term>
<varname>dontInstall</varname>
</term>
@ -1149,11 +1149,11 @@ preBuild = ''
</term>
<listitem>
<para>
See the build phase for details.
See the <link xlink:href="#var-stdenv-makeFlags">build phase</link> for details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-installTargets">
<term>
<varname>installTargets</varname>
</term>
@ -1165,7 +1165,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-installFlags">
<term>
<varname>installFlags</varname> / <varname>installFlagsArray</varname>
</term>
@ -1175,7 +1175,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preInstall">
<term>
<varname>preInstall</varname>
</term>
@ -1185,7 +1185,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postInstall">
<term>
<varname>postInstall</varname>
</term>
@ -1229,7 +1229,7 @@ installTargets = "install-bin install-doc";</programlisting>
<variablelist>
<title>Variables controlling the fixup phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontFixup">
<term>
<varname>dontFixup</varname>
</term>
@ -1239,7 +1239,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontStrip">
<term>
<varname>dontStrip</varname>
</term>
@ -1249,7 +1249,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontStripHost">
<term>
<varname>dontStripHost</varname>
</term>
@ -1259,7 +1259,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontStripTarget">
<term>
<varname>dontStripTarget</varname>
</term>
@ -1269,7 +1269,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontMoveSbin">
<term>
<varname>dontMoveSbin</varname>
</term>
@ -1279,7 +1279,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-stripAllList">
<term>
<varname>stripAllList</varname>
</term>
@ -1289,7 +1289,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-stripAllFlags">
<term>
<varname>stripAllFlags</varname>
</term>
@ -1299,7 +1299,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-stripDebugList">
<term>
<varname>stripDebugList</varname>
</term>
@ -1309,7 +1309,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-stripDebugFlags">
<term>
<varname>stripDebugFlags</varname>
</term>
@ -1319,7 +1319,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontPatchELF">
<term>
<varname>dontPatchELF</varname>
</term>
@ -1329,7 +1329,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontPatchShebangs">
<term>
<varname>dontPatchShebangs</varname>
</term>
@ -1339,7 +1339,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontPruneLibtoolFiles">
<term>
<varname>dontPruneLibtoolFiles</varname>
</term>
@ -1349,7 +1349,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-forceShare">
<term>
<varname>forceShare</varname>
</term>
@ -1359,7 +1359,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-setupHook">
<term>
<varname>setupHook</varname>
</term>
@ -1370,7 +1370,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preFixup">
<term>
<varname>preFixup</varname>
</term>
@ -1380,7 +1380,7 @@ installTargets = "install-bin install-doc";</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postFixup">
<term>
<varname>postFixup</varname>
</term>
@ -1419,7 +1419,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
<variablelist>
<title>Variables controlling the installCheck phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-doInstallCheck">
<term>
<varname>doInstallCheck</varname>
</term>
@ -1431,7 +1431,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-installCheckTarget">
<term>
<varname>installCheckTarget</varname>
</term>
@ -1441,7 +1441,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-installCheckFlags">
<term>
<varname>installCheckFlags</varname> / <varname>installCheckFlagsArray</varname>
</term>
@ -1451,7 +1451,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-installCheckInputs">
<term>
<varname>installCheckInputs</varname>
</term>
@ -1461,7 +1461,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preInstallCheck">
<term>
<varname>preInstallCheck</varname>
</term>
@ -1471,7 +1471,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postInstallCheck">
<term>
<varname>postInstallCheck</varname>
</term>
@ -1493,7 +1493,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
<variablelist>
<title>Variables controlling the distribution phase</title>
<varlistentry>
<varlistentry xml:id="var-stdenv-distTarget">
<term>
<varname>distTarget</varname>
</term>
@ -1503,7 +1503,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-distFlags">
<term>
<varname>distFlags</varname> / <varname>distFlagsArray</varname>
</term>
@ -1513,7 +1513,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-tarballs">
<term>
<varname>tarballs</varname>
</term>
@ -1523,7 +1523,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-dontCopyDist">
<term>
<varname>dontCopyDist</varname>
</term>
@ -1533,7 +1533,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-preDist">
<term>
<varname>preDist</varname>
</term>
@ -1543,7 +1543,7 @@ set debug-file-directory ~/.nix-profile/lib/debug
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry xml:id="var-stdenv-postDist">
<term>
<varname>postDist</varname>
</term>
@ -2018,6 +2018,9 @@ addEnvHooks "$hostOffset" myBashFunction
<para>
In certain situations you may want to run the main command (<command>autoPatchelf</command>) of the setup hook on a file or a set of directories instead of unconditionally patching all outputs. This can be done by setting the <varname>dontAutoPatchelf</varname> environment variable to a non-empty value.
</para>
<para>
By default <command>autoPatchelf</command> will fail as soon as any ELF file requires a dependency which cannot be resolved via the given build inputs. In some situations you might prefer to just leave missing dependencies unpatched and continue to patch the rest. This can be achieved by setting the <envar>autoPatchelfIgnoreMissingDeps</envar> environment variable to a non-empty value.
</para>
<para>
The <command>autoPatchelf</command> command also recognizes a <parameter class="command">--no-recurse</parameter> command line flag, which prevents it from recursing into subdirectories.
</para>

View file

@ -162,10 +162,10 @@
</programlisting>
</para>
<para>
The following example configuration blacklists the <literal>gpl3</literal> and <literal>agpl3</literal> licenses:
The following example configuration blacklists the <literal>gpl3Only</literal> and <literal>agpl3Only</literal> licenses:
<programlisting>
{
blacklistedLicenses = with stdenv.lib.licenses; [ agpl3 gpl3 ];
blacklistedLicenses = with stdenv.lib.licenses; [ agpl3Only gpl3Only ];
}
</programlisting>
</para>

View file

@ -178,26 +178,40 @@ self: super:
<para>
<link
xlink:href="https://software.intel.com/en-us/mkl">Intel
MKL</link> (only works on x86 architecture, unfree)
MKL</link> (only works on the x86_64 architecture, unfree)
</para>
<para>
The Nixpkgs attribute is <literal>mkl</literal>.
</para>
</listitem>
<listitem>
<para>
<link
xlink:href="https://developer.amd.com/amd-aocl/blas-library/">AMD
BLIS/LIBFLAME</link> (optimized for modern AMD x86_64 CPUs)
</para>
<para>
The AMD BLIS library, with attribute <literal>amd-blis</literal>,
provides a BLAS implementation. The complementary AMD LIBFLAME
library, with attribute <literal>amd-libflame</literal>, provides
a LAPACK implementation.
</para>
</listitem>
</itemizedlist>
<para>
Introduced in <link
xlink:href="https://github.com/NixOS/nixpkgs/pull/83888">PR
#83888</link>, we are able to override the blas and lapack
packages to use different implementations, through the
blasProvider and lapackProvider argument. This can be used
#83888</link>, we are able to override the <literal>blas</literal>
and <literal>lapack</literal> packages to use different implementations,
through the <literal>blasProvider</literal> and
<literal>lapackProvider</literal> argument. This can be used
to select a different provider. BLAS providers will have
symlinks in <literal>$out/lib/libblas.so.3</literal> and
<literal>$out/lib/libcblas.so.3</literal> to their respective
BLAS libraries. Likewise, LAPACK providers will have symlinks
in <literal>$out/lib/liblapack.so.3</literal> and
<literal>$out/lib/liblapacke.so.3</literal> to their respective
LAPCK libraries. For example, Intel MKL is both a BLAS and
LAPACK libraries. For example, Intel MKL is both a BLAS and
LAPACK provider. An overlay can be created to use Intel MKL
that looks like:
</para>
@ -216,8 +230,9 @@ self: super:
<para>
This overlay uses Intels MKL library for both BLAS and LAPACK
interfaces. Note that the same can be accomplished at runtime
using <literal>LD_LIBRARY_PATH</literal> of libblas.so.3 and
liblapack.so.3. For instance:
using <literal>LD_LIBRARY_PATH</literal> of
<literal>libblas.so.3</literal> and
<literal>liblapack.so.3</literal>. For instance:
</para>
<programlisting>
$ LD_LIBRARY_PATH=$(nix-build -A mkl)/lib:$LD_LIBRARY_PATH nix-shell -p octave --run octave

View file

@ -12,23 +12,30 @@
lib = import ./lib;
systems = [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ];
systems = [
"x86_64-linux"
"i686-linux"
"x86_64-darwin"
"aarch64-linux"
"armv6l-linux"
"armv7l-linux"
];
forAllSystems = f: lib.genAttrs systems (system: f system);
in
{
lib = lib // {
lib = lib.extend (final: prev: {
nixosSystem = { modules, ... } @ args:
import ./nixos/lib/eval-config.nix (args // {
modules = modules ++
[ { system.nixos.versionSuffix =
".${lib.substring 0 8 (self.lastModifiedDate or self.lastModified)}.${self.shortRev or "dirty"}";
system.nixos.revision = lib.mkIf (self ? rev) self.rev;
".${final.substring 0 8 (self.lastModifiedDate or self.lastModified)}.${self.shortRev or "dirty"}";
system.nixos.revision = final.mkIf (self ? rev) self.rev;
}
];
});
};
});
checks.x86_64-linux.tarball = jobs.tarball;

View file

@ -67,7 +67,7 @@ let
inherit (trivial) id const pipe concat or and bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip mapNullable inNixShell min max
importJSON warn info showWarnings nixpkgsVersion version mod compare
splitByAndCompare functionArgs setFunctionArgs isFunction;
splitByAndCompare functionArgs setFunctionArgs isFunction toHexString toBaseDigits;
inherit (fixedPoints) fix fix' converge extends composeExtensions
makeExtensible makeExtensibleWithCustomName;
inherit (attrsets) attrByPath hasAttrByPath setAttrByPath

View file

@ -48,8 +48,10 @@ rec {
else if isAttrs v then err "attrsets" v
# functions cant be printed of course
else if isFunction v then err "functions" v
# lets not talk about floats. There is no sensible `toString` for them.
else if isFloat v then err "floats" v
# Floats currently can't be converted to precise strings,
# condition warning on nix version once this isn't a problem anymore
# See https://github.com/NixOS/nix/pull/3480
else if isFloat v then libStr.floatToString v
else err "this value is" (toString v);

View file

@ -28,7 +28,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "Academic Free License v3.0";
};
agpl3 = spdx {
agpl3Only = spdx {
spdxId = "AGPL-3.0-only";
fullName = "GNU Affero General Public License v3.0 only";
};
@ -85,6 +85,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''Beerware License'';
};
blueOak100 = spdx {
spdxId = "BlueOak-1.0.0";
fullName = "Blue Oak Model License 1.0.0";
};
bsd0 = spdx {
spdxId = "0BSD";
fullName = "BSD Zero Clause License";
@ -110,6 +115,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''BSD 4-clause "Original" or "Old" License'';
};
bsdProtection = spdx {
spdxId = "BSD-Protection";
fullName = "BSD Protection License";
};
bsl11 = {
fullName = "Business Source License 1.1";
url = "https://mariadb.com/bsl11";
@ -281,12 +291,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "European Union Public License 1.2";
};
fdl11 = spdx {
fdl11Only = spdx {
spdxId = "GFDL-1.1-only";
fullName = "GNU Free Documentation License v1.1 only";
};
fdl12 = spdx {
fdl12Only = spdx {
spdxId = "GFDL-1.2-only";
fullName = "GNU Free Documentation License v1.2 only";
};
@ -296,7 +306,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Free Documentation License v1.2 or later";
};
fdl13 = spdx {
fdl13Only = spdx {
spdxId = "GFDL-1.3-only";
fullName = "GNU Free Documentation License v1.3 only";
};
@ -327,7 +337,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
free = false;
};
gpl1 = spdx {
gpl1Only = spdx {
spdxId = "GPL-1.0-only";
fullName = "GNU General Public License v1.0 only";
};
@ -337,7 +347,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU General Public License v1.0 or later";
};
gpl2 = spdx {
gpl2Only = spdx {
spdxId = "GPL-2.0-only";
fullName = "GNU General Public License v2.0 only";
};
@ -362,7 +372,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU General Public License v2.0 or later";
};
gpl3 = spdx {
gpl3Only = spdx {
spdxId = "GPL-3.0-only";
fullName = "GNU General Public License v3.0 only";
};
@ -426,6 +436,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
};
# Proprietary binaries; free to redistribute without modification.
databricks = {
fullName = "Databricks Proprietary License";
url = "https://pypi.org/project/databricks-connect";
free = false;
};
issl = {
fullName = "Intel Simplified Software License";
url = "https://software.intel.com/en-us/license/intel-simplified-software-license";
@ -437,7 +453,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "JasPer License";
};
lgpl2 = spdx {
lgpl2Only = spdx {
spdxId = "LGPL-2.0-only";
fullName = "GNU Library General Public License v2 only";
};
@ -447,7 +463,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Library General Public License v2 or later";
};
lgpl21 = spdx {
lgpl21Only = spdx {
spdxId = "LGPL-2.1-only";
fullName = "GNU Lesser General Public License v2.1 only";
};
@ -457,7 +473,7 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Lesser General Public License v2.1 or later";
};
lgpl3 = spdx {
lgpl3Only = spdx {
spdxId = "LGPL-3.0-only";
fullName = "GNU Lesser General Public License v3.0 only";
};
@ -782,4 +798,16 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
spdxId = "ZPL-2.1";
fullName = "Zope Public License 2.1";
};
} // {
# TODO: remove legacy aliases
agpl3 = lib.licenses.agpl3Only;
fdl11 = lib.licenses.fdl11Only;
fdl12 = lib.licenses.fdl12Only;
fdl13 = lib.licenses.fdl13Only;
gpl1 = lib.licenses.gpl1Only;
gpl2 = lib.licenses.gpl2Only;
gpl3 = lib.licenses.gpl3Only;
lgpl2 = lib.licenses.lgpl2Only;
lgpl21 = lib.licenses.lgpl21Only;
lgpl3 = lib.licenses.lgpl3Only;
}

View file

@ -58,6 +58,23 @@ rec {
default = check;
description = "Whether to check whether all option definitions have matching declarations.";
};
_module.freeformType = mkOption {
# Disallow merging for now, but could be implemented nicely with a `types.optionType`
type = types.nullOr (types.uniq types.attrs);
internal = true;
default = null;
description = ''
If set, merge all definitions that don't have an associated option
together using this type. The result then gets combined with the
values of all declared options to produce the final <literal>
config</literal> value.
If this is <literal>null</literal>, definitions without an option
will throw an error unless <option>_module.check</option> is
turned off.
'';
};
};
config = {
@ -65,35 +82,55 @@ rec {
};
};
collected = collectModules
(specialArgs.modulesPath or "")
(modules ++ [ internalModule ])
({ inherit config options lib; } // specialArgs);
merged =
let collected = collectModules
(specialArgs.modulesPath or "")
(modules ++ [ internalModule ])
({ inherit lib options config; } // specialArgs);
in mergeModules prefix (reverseList collected);
options = mergeModules prefix (reverseList collected);
options = merged.matchedOptions;
# Traverse options and extract the option values into the final
# config set. At the same time, check whether all option
# definitions have matching declarations.
# !!! _module.check's value can't depend on any other config values
# without an infinite recursion. One way around this is to make the
# 'config' passed around to the modules be unconditionally unchecked,
# and only do the check in 'result'.
config = yieldConfig prefix options;
yieldConfig = prefix: set:
let res = removeAttrs (mapAttrs (n: v:
if isOption v then v.value
else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"];
in
if options._module.check.value && set ? _definedNames then
foldl' (res: m:
foldl' (res: name:
if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
res m.names)
res set._definedNames
else
res;
result = {
config =
let
# For definitions that have an associated option
declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
# If freeformType is set, this is for definitions that don't have an associated option
freeformConfig =
let
defs = map (def: {
file = def.file;
value = setAttrByPath def.prefix def.value;
}) merged.unmatchedDefns;
in if defs == [] then {}
else declaredConfig._module.freeformType.merge prefix defs;
in if declaredConfig._module.freeformType == null then declaredConfig
# Because all definitions that had an associated option ended in
# declaredConfig, freeformConfig can only contain the non-option
# paths, meaning recursiveUpdate will never override any value
else recursiveUpdate freeformConfig declaredConfig;
checkUnmatched =
if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
let
firstDef = head merged.unmatchedDefns;
baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' defined in `${firstDef.file}' does not exist.";
in
if attrNames options == [ "_module" ]
then throw ''
${baseMsg}
However there are no options defined in `${showOption prefix}'. Are you sure you've
declared your options properly? This can happen if you e.g. declared your options in `types.submodule'
under `config' rather than `options'.
''
else throw baseMsg
else null;
result = builtins.seq checkUnmatched {
inherit options;
config = removeAttrs config [ "_module" ];
inherit (config) _module;
@ -174,12 +211,16 @@ rec {
/* Massage a module into canonical form, that is, a set consisting
of options, config and imports attributes. */
unifyModuleSyntax = file: key: m:
let addMeta = config: if m ? meta
then mkMerge [ config { meta = m.meta; } ]
else config;
let
addMeta = config: if m ? meta
then mkMerge [ config { meta = m.meta; } ]
else config;
addFreeformType = config: if m ? freeformType
then mkMerge [ config { _module.freeformType = m.freeformType; } ]
else config;
in
if m ? config || m ? options then
let badAttrs = removeAttrs m ["_file" "key" "disabledModules" "imports" "options" "config" "meta"]; in
let badAttrs = removeAttrs m ["_file" "key" "disabledModules" "imports" "options" "config" "meta" "freeformType"]; in
if badAttrs != {} then
throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by introducing a top-level `config' or `options' attribute. Add configuration attributes immediately on the top level instead, or move all of them (namely: ${toString (attrNames badAttrs)}) into the explicit `config' attribute."
else
@ -188,7 +229,7 @@ rec {
disabledModules = m.disabledModules or [];
imports = m.imports or [];
options = m.options or {};
config = addMeta (m.config or {});
config = addFreeformType (addMeta (m.config or {}));
}
else
{ _file = m._file or file;
@ -196,7 +237,7 @@ rec {
disabledModules = m.disabledModules or [];
imports = m.require or [] ++ m.imports or [];
options = {};
config = addMeta (removeAttrs m ["_file" "key" "disabledModules" "require" "imports"]);
config = addFreeformType (addMeta (removeAttrs m ["_file" "key" "disabledModules" "require" "imports" "freeformType"]));
};
applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
@ -233,7 +274,23 @@ rec {
declarations in all modules, combining them into a single set.
At the same time, for each option declaration, it will merge the
corresponding option definitions in all machines, returning them
in the value attribute of each option. */
in the value attribute of each option.
This returns a set like
{
# A recursive set of options along with their final values
matchedOptions = {
foo = { _type = "option"; value = "option value of foo"; ... };
bar.baz = { _type = "option"; value = "option value of bar.baz"; ... };
...
};
# A list of definitions that weren't matched by any option
unmatchedDefns = [
{ file = "file.nix"; prefix = [ "qux" ]; value = "qux"; }
...
];
}
*/
mergeModules = prefix: modules:
mergeModules' prefix modules
(concatMap (m: map (config: { file = m._file; inherit config; }) (pushDownProperties m.config)) modules);
@ -280,9 +337,9 @@ rec {
defnsByName' = byName "config" (module: value:
[{ inherit (module) file; inherit value; }]
) configs;
in
(flip mapAttrs declsByName (name: decls:
# We're descending into attribute name.
resultsByName = flip mapAttrs declsByName (name: decls:
# We're descending into attribute name.
let
loc = prefix ++ [name];
defns = defnsByName.${name} or [];
@ -291,7 +348,10 @@ rec {
in
if nrOptions == length decls then
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
in evalOptionValue loc opt defns'
in {
matchedOptions = evalOptionValue loc opt defns';
unmatchedDefns = [];
}
else if nrOptions != 0 then
let
firstOption = findFirst (m: isOption m.options) "" decls;
@ -299,9 +359,27 @@ rec {
in
throw "The option `${showOption loc}' in `${firstOption._file}' is a prefix of options in `${firstNonOption._file}'."
else
mergeModules' loc decls defns
))
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };
mergeModules' loc decls defns);
matchedOptions = mapAttrs (n: v: v.matchedOptions) resultsByName;
# an attrset 'name' => list of unmatched definitions for 'name'
unmatchedDefnsByName =
# Propagate all unmatched definitions from nested option sets
mapAttrs (n: v: v.unmatchedDefns) resultsByName
# Plus the definitions for the current prefix that don't have a matching option
// removeAttrs defnsByName' (attrNames matchedOptions);
in {
inherit matchedOptions;
# Transforms unmatchedDefnsByName into a list of definitions
unmatchedDefns = concatLists (mapAttrsToList (name: defs:
map (def: def // {
# Set this so we know when the definition first left unmatched territory
prefix = [name] ++ (def.prefix or []);
}) defs
) unmatchedDefnsByName);
};
/* Merge multiple option declarations into a single declaration. In
general, there should be only one declaration of each option.
@ -535,7 +613,6 @@ rec {
if tp.name == "option set" || tp.name == "submodule" then
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
else if optionSetIn "attrsOf" then types.attrsOf (types.submodule options)
else if optionSetIn "loaOf" then types.loaOf (types.submodule options)
else if optionSetIn "listOf" then types.listOf (types.submodule options)
else if optionSetIn "nullOr" then types.nullOr (types.submodule options)
else tp;

View file

@ -145,10 +145,14 @@ rec {
# packed-refs file, so we have to grep through it:
then
let fileContent = readFile packedRefsName;
matchRef = match (".*\n([^\n ]*) " + file + "\n.*") fileContent;
in if matchRef == null
matchRef = builtins.match "([a-z0-9]+) ${file}";
isRef = s: builtins.isString s && (matchRef s) != null;
# there is a bug in libstdc++ leading to stackoverflow for long strings:
# https://github.com/NixOS/nix/issues/2147#issuecomment-659868795
refs = builtins.filter isRef (builtins.split "\n" fileContent);
in if refs == []
then throw ("Could not find " + file + " in " + packedRefsName)
else lib.head matchRef
else lib.head (matchRef (lib.head refs))
else throw ("Not a .git directory: " + path);
in readCommitFromFile "HEAD";

View file

@ -612,6 +612,22 @@ rec {
*/
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
/* Convert a float to a string, but emit a warning when precision is lost
during the conversion
Example:
floatToString 0.000001
=> "0.000001"
floatToString 0.0000001
=> trace: warning: Imprecise conversion from float to string 0.000000
"0.000000"
*/
floatToString = float: let
result = toString float;
precise = float == builtins.fromJSON result;
in if precise then result
else lib.warn "Imprecise conversion from float to string ${result}" result;
/* Check whether a value can be coerced to a string */
isCoercibleToString = x:
builtins.elem (builtins.typeOf x) [ "path" "string" "null" "int" "float" "bool" ] ||
@ -673,14 +689,15 @@ rec {
"/prefix/nix-profiles-library-paths.patch"
"/prefix/compose-search-path.patch" ]
*/
readPathsFromFile = rootPath: file:
let
lines = lib.splitString "\n" (builtins.readFile file);
removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line));
relativePaths = removeComments lines;
absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths;
in
absolutePaths;
readPathsFromFile = lib.warn "lib.readPathsFromFile is deprecated, use a list instead"
(rootPath: file:
let
lines = lib.splitString "\n" (builtins.readFile file);
removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line));
relativePaths = removeComments lines;
absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths;
in
absolutePaths);
/* Read the contents of a file removing the trailing \n

View file

@ -0,0 +1,77 @@
{ lib }:
rec {
# platform.gcc.arch to its features (as in /proc/cpuinfo)
features = {
default = [ ];
# x86_64 Intel
westmere = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
sandybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
ivybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
haswell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
broadwell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
skylake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
skylake-avx512 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
# x86_64 AMD
btver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
btver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
bdver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
bdver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
bdver3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
bdver4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" "fma4" ];
znver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
znver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
# other
armv5te = [ ];
armv6 = [ ];
armv7-a = [ ];
armv8-a = [ ];
mips32 = [ ];
loongson2f = [ ];
};
# a superior CPU has all the features of an inferior and is able to build and test code for it
inferiors = {
# x86_64 Intel
default = [ ];
westmere = [ ];
sandybridge = [ "westmere" ] ++ inferiors.westmere;
ivybridge = [ "sandybridge" ] ++ inferiors.sandybridge;
haswell = [ "ivybridge" ] ++ inferiors.ivybridge;
broadwell = [ "haswell" ] ++ inferiors.haswell;
skylake = [ "broadwell" ] ++ inferiors.broadwell;
skylake-avx512 = [ "skylake" ] ++ inferiors.skylake;
# x86_64 AMD
btver1 = [ ];
btver2 = [ ]; # TODO: fill this (need testing)
bdver1 = [ ]; # TODO: fill this (need testing)
bdver2 = [ ]; # TODO: fill this (need testing)
bdver3 = [ ]; # TODO: fill this (need testing)
bdver4 = [ ]; # TODO: fill this (need testing)
znver1 = [ ]; # TODO: fill this (need testing)
znver2 = [ ]; # TODO: fill this (need testing)
# other
armv5te = [ ];
armv6 = [ ];
armv7-a = [ ];
armv8-a = [ ];
mips32 = [ ];
loongson2f = [ ];
};
predicates = let
featureSupport = feature: x: builtins.elem feature features.${x};
in {
sse3Support = featureSupport "sse3";
ssse3Support = featureSupport "ssse3";
sse4_1Support = featureSupport "sse4_1";
sse4_2Support = featureSupport "sse4_2";
sse4_aSupport = featureSupport "sse4a";
avxSupport = featureSupport "avx";
avx2Support = featureSupport "avx2";
avx512Support = featureSupport "avx512";
aesSupport = featureSupport "aes";
fmaSupport = featureSupport "fma";
fma4Support = featureSupport "fma4";
};
}

View file

@ -7,6 +7,7 @@ rec {
inspect = import ./inspect.nix { inherit lib; };
platforms = import ./platforms.nix { inherit lib; };
examples = import ./examples.nix { inherit lib; };
architectures = import ./architectures.nix { inherit lib; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary.
@ -32,6 +33,7 @@ rec {
/**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt"
else if final.isWasi then "wasilibc"
else if final.isRedox then "relibc"
else if final.isMusl then "musl"
else if final.isUClibc then "uclibc"
else if final.isAndroid then "bionic"
@ -65,6 +67,7 @@ rec {
freebsd = "FreeBSD";
openbsd = "OpenBSD";
wasi = "Wasi";
redox = "Redox";
genode = "Genode";
}.${final.parsed.kernel.name} or null;
@ -74,6 +77,7 @@ rec {
# uname -r
release = null;
};
isStatic = final.isWasm || final.isRedox;
kernelArch =
if final.isAarch32 then "arm"
@ -123,6 +127,7 @@ rec {
else throw "Don't know how to run ${final.config} executables.";
} // mapAttrs (n: v: v final.parsed) inspect.predicates
// mapAttrs (n: v: v final.platform.gcc.arch or "default") architectures.predicates
// args;
in assert final.useAndroidPrebuilt -> final.isAndroid;
assert lib.foldl

View file

@ -22,6 +22,8 @@ let
"wasm64-wasi" "wasm32-wasi"
"x86_64-redox"
"powerpc64le-linux"
"riscv32-linux" "riscv64-linux"
@ -36,7 +38,7 @@ let
"js-ghcjs"
"aarch64-genode" "x86_64-genode"
"aarch64-genode" "i686-genode" "x86_64-genode"
];
allParsed = map parse.mkSystemFromString all;
@ -69,6 +71,7 @@ in {
openbsd = filterDoubles predicates.isOpenBSD;
unix = filterDoubles predicates.isUnix;
wasi = filterDoubles predicates.isWasi;
redox = filterDoubles predicates.isRedox;
windows = filterDoubles predicates.isWindows;
genode = filterDoubles predicates.isGenode;

View file

@ -46,7 +46,7 @@ rec {
armv7a-android-prebuilt = {
config = "armv7a-unknown-linux-androideabi";
sdkVer = "24";
sdkVer = "29";
ndkVer = "18b";
platform = platforms.armv7a-android;
useAndroidPrebuilt = true;
@ -54,7 +54,7 @@ rec {
aarch64-android-prebuilt = {
config = "aarch64-unknown-linux-android";
sdkVer = "24";
sdkVer = "29";
ndkVer = "18b";
platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true;
@ -163,6 +163,15 @@ rec {
libc = "newlib";
};
#
# Redox
#
x86_64-unknown-redox = {
config = "x86_64-unknown-redox";
libc = "relibc";
};
#
# Darwin
#

View file

@ -33,7 +33,7 @@ rec {
isBSD = { kernel = { families = { inherit (kernelFamilies) bsd; }; }; };
isDarwin = { kernel = { families = { inherit (kernelFamilies) darwin; }; }; };
isUnix = [ isBSD isDarwin isLinux isSunOS isCygwin ];
isUnix = [ isBSD isDarwin isLinux isSunOS isCygwin isRedox ];
isMacOS = { kernel = kernels.macos; };
isiOS = { kernel = kernels.ios; };
@ -46,6 +46,7 @@ rec {
isCygwin = { kernel = kernels.windows; abi = abis.cygnus; };
isMinGW = { kernel = kernels.windows; abi = abis.gnu; };
isWasi = { kernel = kernels.wasi; };
isRedox = { kernel = kernels.redox; };
isGhcjs = { kernel = kernels.ghcjs; };
isGenode = { kernel = kernels.genode; };
isNone = { kernel = kernels.none; };

View file

@ -277,6 +277,7 @@ rec {
openbsd = { execFormat = elf; families = { inherit bsd; }; };
solaris = { execFormat = elf; families = { }; };
wasi = { execFormat = wasm; families = { }; };
redox = { execFormat = elf; families = { }; };
windows = { execFormat = pe; families = { }; };
ghcjs = { execFormat = unknown; families = { }; };
genode = { execFormat = elf; families = { }; };
@ -390,6 +391,8 @@ rec {
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 (elemAt l 2 == "redox")
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "redox"; }
else if hasPrefix "netbsd" (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"])

View file

@ -102,6 +102,16 @@ runTests {
expected = 9;
};
testToHexString = {
expr = toHexString 250;
expected = "FA";
};
testToBaseDigits = {
expr = toBaseDigits 2 6;
expected = [ 1 1 0 ];
};
# STRINGS
testConcatMapStrings = {

View file

@ -210,6 +210,29 @@ checkConfigOutput "empty" config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-c
checkConfigError 'The option value .* in .* is not of type .*' \
config.value ./declare-int-unsigned-value.nix ./define-value-list.nix ./define-value-int-positive.nix
## Freeform modules
# Assigning without a declared option should work
checkConfigOutput 24 config.value ./freeform-attrsOf.nix ./define-value-string.nix
# No freeform assigments shouldn't make it error
checkConfigOutput '{ }' config ./freeform-attrsOf.nix
# but only if the type matches
checkConfigError 'The option value .* in .* is not of type .*' config.value ./freeform-attrsOf.nix ./define-value-list.nix
# and properties should be applied
checkConfigOutput yes config.value ./freeform-attrsOf.nix ./define-value-string-properties.nix
# Options should still be declarable, and be able to have a type that doesn't match the freeform type
checkConfigOutput false config.enable ./freeform-attrsOf.nix ./define-value-string.nix ./declare-enable.nix
checkConfigOutput 24 config.value ./freeform-attrsOf.nix ./define-value-string.nix ./declare-enable.nix
# and this should work too with nested values
checkConfigOutput false config.nest.foo ./freeform-attrsOf.nix ./freeform-nested.nix
checkConfigOutput bar config.nest.bar ./freeform-attrsOf.nix ./freeform-nested.nix
# Check whether a declared option can depend on an freeform-typed one
checkConfigOutput null config.foo ./freeform-attrsOf.nix ./freeform-str-dep-unstr.nix
checkConfigOutput 24 config.foo ./freeform-attrsOf.nix ./freeform-str-dep-unstr.nix ./define-value-string.nix
# Check whether an freeform-typed value can depend on a declared option, this can only work with lazyAttrsOf
checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.nix ./freeform-unstr-dep-str.nix
checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix
checkConfigOutput 24 config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix
cat <<EOF
====== module tests ======
$pass Pass

View file

@ -7,7 +7,7 @@
# Always defined, but the value depends on the presence of an option.
config = {
value = if options ? enable then 360 else 7;
}
}
# Only define if possible.
// lib.optionalAttrs (options ? enable) {
enable = true;

View file

@ -0,0 +1,12 @@
{ lib, ... }: {
imports = [{
value = lib.mkDefault "def";
}];
value = lib.mkMerge [
(lib.mkIf false "nope")
"yes"
];
}

View file

@ -0,0 +1,3 @@
{ lib, ... }: {
freeformType = with lib.types; attrsOf (either str (attrsOf str));
}

View file

@ -0,0 +1,3 @@
{ lib, ... }: {
freeformType = with lib.types; lazyAttrsOf (either str (lazyAttrsOf str));
}

View file

@ -0,0 +1,7 @@
{ lib, ... }: {
options.nest.foo = lib.mkOption {
type = lib.types.bool;
default = false;
};
config.nest.bar = "bar";
}

View file

@ -0,0 +1,8 @@
{ lib, config, ... }: {
options.foo = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
config.foo = lib.mkIf (config ? value) config.value;
}

View file

@ -0,0 +1,8 @@
{ lib, config, ... }: {
options.value = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
config.foo = lib.mkIf (config.value != null) config.value;
}

View file

@ -17,7 +17,6 @@ pkgs.runCommandNoCC "nixpkgs-lib-tests" {
export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_DB_DIR=$TEST_ROOT/db
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix

View file

@ -12,22 +12,23 @@ let
expected = lib.sort lib.lessThan y;
};
in with lib.systems.doubles; lib.runTests {
testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js ++ genode);
testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js ++ genode ++ redox);
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-none" "armv7a-linux" "armv7l-linux" "arm-none" "armv7a-darwin" ];
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
testmips = mseteq mips [ "mipsel-linux" ];
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
testcygwin = mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ];
testdarwin = mseteq darwin [ "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" ];
testfreebsd = mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ];
testgenode = mseteq genode [ "aarch64-genode" "x86_64-genode" ];
testgenode = mseteq genode [ "aarch64-genode" "i686-genode" "x86_64-genode" ];
testredox = mseteq redox [ "x86_64-redox" ];
testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
testillumos = mseteq illumos [ "x86_64-solaris" ];
testlinux = mseteq linux [ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "i686-linux" "mipsel-linux" "riscv32-linux" "riscv64-linux" "x86_64-linux" "powerpc64le-linux" ];
testnetbsd = mseteq netbsd [ "i686-netbsd" "x86_64-netbsd" ];
testopenbsd = mseteq openbsd [ "i686-openbsd" "x86_64-openbsd" ];
testwindows = mseteq windows [ "i686-cygwin" "x86_64-cygwin" "i686-windows" "x86_64-windows" ];
testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin);
testunix = mseteq unix (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ cygwin ++ redox);
}

View file

@ -332,4 +332,55 @@ rec {
*/
isFunction = f: builtins.isFunction f ||
(f ? __functor && isFunction (f.__functor f));
/* Convert the given positive integer to a string of its hexadecimal
representation. For example:
toHexString 0 => "0"
toHexString 16 => "10"
toHexString 250 => "FA"
*/
toHexString = i:
let
toHexDigit = d:
if d < 10
then toString d
else
{
"10" = "A";
"11" = "B";
"12" = "C";
"13" = "D";
"14" = "E";
"15" = "F";
}.${toString d};
in
lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
/* `toBaseDigits base i` converts the positive integer i to a list of its
digits in the given base. For example:
toBaseDigits 10 123 => [ 1 2 3 ]
toBaseDigits 2 6 => [ 1 1 0 ]
toBaseDigits 16 250 => [ 15 10 ]
*/
toBaseDigits = base: i:
let
go = i:
if i < base
then [i]
else
let
r = i - ((i / base) * base);
q = (i - r) / base;
in
[r] ++ go q;
in
assert (base >= 2);
assert (i >= 0);
lib.reverseList (go i);
}

View file

@ -252,8 +252,8 @@ rec {
merge = mergeEqualOption;
};
# drop this in the future:
list = builtins.trace "`types.list` is deprecated; use `types.listOf` instead" types.listOf;
# TODO: drop this in the future:
list = builtins.trace "`types.list` has been removed; please use `types.listOf` instead" types.listOf;
listOf = elemType: mkOptionType rec {
name = "listOf";
@ -326,110 +326,15 @@ rec {
functor = (defaultFunctor name) // { wrapped = elemType; };
};
# List or attribute set of ...
loaOf = elemType:
let
convertAllLists = loc: defs:
let
padWidth = stringLength (toString (length defs));
unnamedPrefix = i: "unnamed-" + fixedWidthNumber padWidth i + ".";
in
imap1 (i: convertIfList loc (unnamedPrefix i)) defs;
convertIfList = loc: unnamedPrefix: def:
if isList def.value then
let
padWidth = stringLength (toString (length def.value));
unnamed = i: unnamedPrefix + fixedWidthNumber padWidth i;
anyString = placeholder "name";
nameAttrs = [
{ path = [ "environment" "etc" ];
name = "target";
}
{ path = [ "containers" anyString "bindMounts" ];
name = "mountPoint";
}
{ path = [ "programs" "ssh" "knownHosts" ];
# hostNames is actually a list so we would need to handle it only when singleton
name = "hostNames";
}
{ path = [ "fileSystems" ];
name = "mountPoint";
}
{ path = [ "boot" "specialFileSystems" ];
name = "mountPoint";
}
{ path = [ "services" "znapzend" "zetup" ];
name = "dataset";
}
{ path = [ "services" "znapzend" "zetup" anyString "destinations" ];
name = "label";
}
{ path = [ "services" "geoclue2" "appConfig" ];
name = "desktopID";
}
];
matched = let
equals = a: b: b == anyString || a == b;
fallback = { name = "name"; };
in findFirst ({ path, ... }: all (v: v == true) (zipListsWith equals loc path)) fallback nameAttrs;
nameAttr = matched.name;
nameValueOld = value:
if isList value then
if length value > 0 then
"[ " + concatMapStringsSep " " escapeNixString value + " ]"
else
"[ ]"
else
escapeNixString value;
nameValueNew = value: unnamed:
if isList value then
if length value > 0 then
head value
else
unnamed
else
value;
res =
{ inherit (def) file;
value = listToAttrs (
imap1 (elemIdx: elem:
{ name = nameValueNew (elem.${nameAttr} or (unnamed elemIdx)) (unnamed elemIdx);
value = elem;
}) def.value);
};
option = concatStringsSep "." loc;
sample = take 3 def.value;
more = lib.optionalString (length def.value > 3) "... ";
list = concatMapStrings (x: ''{ ${nameAttr} = ${nameValueOld (x.${nameAttr} or "unnamed")}; ...} '') sample;
set = concatMapStrings (x: ''${nameValueNew (x.${nameAttr} or "unnamed") "unnamed"} = {...}; '') sample;
msg = ''
In file ${def.file}
a list is being assigned to the option config.${option}.
This will soon be an error as type loaOf is deprecated.
See https://github.com/NixOS/nixpkgs/pull/63103 for more information.
Do
${option} =
{ ${set}${more}}
instead of
${option} =
[ ${list}${more}]
'';
in
lib.warn msg res
else
def;
attrOnly = attrsOf elemType;
in mkOptionType rec {
name = "loaOf";
description = "list or attribute set of ${elemType.description}s";
check = x: isList x || isAttrs x;
merge = loc: defs: attrOnly.merge loc (convertAllLists loc defs);
emptyValue = { value = {}; };
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: loaOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
};
# TODO: drop this in the future:
loaOf =
let msg =
''
`types.loaOf` has been removed and mixing lists with attribute values
is no longer possible; please use `types.attrsOf` instead.
See https://github.com/NixOS/nixpkgs/issues/1800 for the motivation.
'';
in builtins.trace msg types.attrsOf;
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
uniq = elemType: mkOptionType rec {
@ -486,9 +391,15 @@ rec {
else value
) defs;
freeformType = (evalModules {
inherit modules specialArgs;
args.name = "name";
})._module.freeformType;
in
mkOptionType rec {
name = "submodule";
description = freeformType.description or name;
check = x: isAttrs x || isFunction x || path.check x;
merge = loc: defs:
(evalModules {

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,10 @@ lua-cmsgpack,,,,,
lua-iconv,,,,,
lua-lsp,,http://luarocks.org/dev,,,
lua-messagepack,,,,,
lua-resty-http,,,,,
lua-resty-jwt,,,,,
lua-resty-openidc,,,,,
lua-resty-session,,,,,
lua-term,,,,,
lua-toml,,,,,
lua-zlib,,,,,koral
@ -79,5 +83,4 @@ say,,,,,
std__debug,std._debug,,,,
std_normalize,std.normalize,,,,
stdlib,,,,,vyp
pulseaudio,,,,,doronbehar
vstruct,,,,,

1 # nix name luarocks name server version luaversion maintainers
35 lua-iconv
36 lua-lsp http://luarocks.org/dev
37 lua-messagepack
38 lua-resty-http
39 lua-resty-jwt
40 lua-resty-openidc
41 lua-resty-session
42 lua-term
43 lua-toml
44 lua-zlib koral
83 std__debug std._debug
84 std_normalize std.normalize
85 stdlib vyp
pulseaudio doronbehar
86 vstruct

View file

@ -60,7 +60,7 @@ nixexpr() {
"darwin-tested" "unstable" "stdenvBootstrapTools"
"moduleSystem" "lib-tests" # these just confuse the output
];
in
tweak (builtins.removeAttrs hydraJobs blacklist)
EONIX
@ -124,4 +124,3 @@ if [ -n "$optPrint" ]; then
echo
cat "$newlist"
fi

View file

@ -9,7 +9,13 @@
# TODO: add assert statements
let
pkgs = import ./../../default.nix (if include-overlays then { } else { overlays = []; });
pkgs = import ./../../default.nix (
if include-overlays == false then
{ overlays = []; }
else if include-overlays == true then
{ } # Let Nixpkgs include overlays impurely.
else { overlays = include-overlays; }
);
inherit (pkgs) lib;

View file

@ -54,10 +54,21 @@ with lib.maintainers; {
hedning
jtojnar
worldofpeace
dasj19
];
scope = "Maintain GNOME desktop environment and platform.";
};
jitsi = {
members = [
mmilata
petabyteboy
prusnak
ryantm
];
scope = "Maintain Jitsi.";
};
matrix = {
members = [
ma27

View file

@ -58,9 +58,9 @@
Like <literal>boot.debug1</literal> or
<literal>boot.debug1devices</literal>, but runs stage1 until all
filesystems that are mounted during initrd are mounted (see
<option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option>
<option><link linkend="opt-fileSystems._name_.neededForBoot">neededForBoot</link></option>
). As a motivating example, this could be useful if you've forgotten to set
<option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option>
<option><link linkend="opt-fileSystems._name_.neededForBoot">neededForBoot</link></option>
on a file system.
</para>
</listitem>

View file

@ -27,7 +27,7 @@
<screen>
# nixos-container create foo --config '
<xref linkend="opt-services.openssh.enable"/> = true;
<link linkend="opt-users.users._name__.openssh.authorizedKeys.keys">users.users.root.openssh.authorizedKeys.keys</link> = ["ssh-dss AAAAB3N…"];
<link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">users.users.root.openssh.authorizedKeys.keys</link> = ["ssh-dss AAAAB3N…"];
'
</screen>
By default the next free address in the <literal>10.233.0.0/16</literal> subnet will be chosen

View file

@ -18,6 +18,7 @@
<xi:include href="user-mgmt.xml" />
<xi:include href="file-systems.xml" />
<xi:include href="x-windows.xml" />
<xi:include href="gpu-accel.xml" />
<xi:include href="xfce.xml" />
<xi:include href="networking.xml" />
<xi:include href="linux-kernel.xml" />

View file

@ -23,12 +23,12 @@
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd-fstab-generator.html">systemd-fstab-generator</link>.
The filesystem will be mounted automatically unless
<literal>"noauto"</literal> is present in <link
linkend="opt-fileSystems._name__.options">options</link>.
linkend="opt-fileSystems._name_.options">options</link>.
<literal>"noauto"</literal> filesystems can be mounted explicitly using
<command>systemctl</command> e.g. <command>systemctl start
data.mount</command>.
Mount points are created automatically if they dont already exist. For
<option><link linkend="opt-fileSystems._name__.device">device</link></option>,
<option><link linkend="opt-fileSystems._name_.device">device</link></option>,
its best to use the topology-independent device aliases in
<filename>/dev/disk/by-label</filename> and
<filename>/dev/disk/by-uuid</filename>, as these dont change if the
@ -36,7 +36,7 @@
</para>
<para>
You can usually omit the file system type
(<option><link linkend="opt-fileSystems._name__.fsType">fsType</link></option>),
(<option><link linkend="opt-fileSystems._name_.fsType">fsType</link></option>),
since <command>mount</command> can usually detect the type and load the
necessary kernel module automatically. However, if the file system is needed
at early boot (in the initial ramdisk) and is not <literal>ext2</literal>,
@ -49,7 +49,7 @@
System startup will fail if any of the filesystems fails to mount, dropping
you to the emergency shell. You can make a mount asynchronous and
non-critical by adding
<literal><link linkend="opt-fileSystems._name__.options">options</link> = [
<literal><link linkend="opt-fileSystems._name_.options">options</link> = [
"nofail" ];</literal>.
</para>
</note>

View file

@ -0,0 +1,258 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-gpu-accel">
<title>GPU acceleration</title>
<para>
NixOS provides various APIs that benefit from GPU hardware
acceleration, such as VA-API and VDPAU for video playback; OpenGL and
Vulkan for 3D graphics; and OpenCL for general-purpose computing.
This chapter describes how to set up GPU hardware acceleration (as far
as this is not done automatically) and how to verify that hardware
acceleration is indeed used.
</para>
<para>
Most of the aforementioned APIs are agnostic with regards to which
display server is used. Consequently, these instructions should apply
both to the X Window System and Wayland compositors.
</para>
<section xml:id="sec-gpu-accel-opencl">
<title>OpenCL</title>
<para>
<link xlink:href="https://en.wikipedia.org/wiki/OpenCL">OpenCL</link> is a
general compute API. It is used by various applications such as
Blender and Darktable to accelerate certain operations.
</para>
<para>
OpenCL applications load drivers through the <emphasis>Installable Client
Driver</emphasis> (ICD) mechanism. In this mechanism, an ICD file
specifies the path to the OpenCL driver for a particular GPU family.
In NixOS, there are two ways to make ICD files visible to the ICD
loader. The first is through the <varname>OCL_ICD_VENDORS</varname>
environment variable. This variable can contain a directory which
is scanned by the ICL loader for ICD files. For example:
<screen><prompt>$</prompt> export \
OCL_ICD_VENDORS=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A rocm-opencl-icd`/etc/OpenCL/vendors/</screen>
</para>
<para>
The second mechanism is to add the OpenCL driver package to
<xref linkend="opt-hardware.opengl.extraPackages"/>. This links the
ICD file under <filename>/run/opengl-driver</filename>, where it will
be visible to the ICD loader.
</para>
<para>
The proper installation of OpenCL drivers can be verified through
the <command>clinfo</command> command of the <package>clinfo</package>
package. This command will report the number of hardware devices
that is found and give detailed information for each device:
</para>
<screen><prompt>$</prompt> clinfo | head -n3
Number of platforms 1
Platform Name AMD Accelerated Parallel Processing
Platform Vendor Advanced Micro Devices, Inc.</screen>
<section xml:id="sec-gpu-accel-opencl-amd">
<title>AMD</title>
<para>
Modern AMD <link
xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics
Core Next</link> (GCN) GPUs are supported through the
<package>rocm-opencl-icd</package> package. Adding this package to
<xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL
support:
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
rocm-opencl-icd
];</programlisting>
</para>
</section>
<section xml:id="sec-gpu-accel-opencl-intel">
<title>Intel</title>
<para>
<link
xlink:href="https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units#Gen8">Intel
Gen8 and later GPUs</link> are supported by the Intel NEO OpenCL
runtime that is provided by the
<package>intel-compute-runtime</package> package. For Gen7 GPUs,
the deprecated Beignet runtime can be used, which is provided
by the <package>beignet</package> package. The proprietary Intel
OpenCL runtime, in the <package>intel-ocl</package> package, is
an alternative for Gen7 GPUs.
</para>
<para>
The <package>intel-compute-runtime</package>, <package>beignet</package>,
or <package>intel-ocl</package> package can be added to
<xref linkend="opt-hardware.opengl.extraPackages"/> to enable OpenCL
support. For example, for Gen8 and later GPUs, the following
configuration can be used:
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
intel-compute-runtime
];</programlisting>
</para>
</section>
</section>
<section xml:id="sec-gpu-accel-vulkan">
<title>Vulkan</title>
<para>
<link xlink:href="https://en.wikipedia.org/wiki/Vulkan_(API)">Vulkan</link> is a
graphics and compute API for GPUs. It is used directly by games or indirectly though
compatibility layers like <link xlink:href="https://github.com/doitsujin/dxvk/wiki">DXVK</link>.
</para>
<para>
By default, if <xref linkend="opt-hardware.opengl.driSupport"/> is enabled,
<package>mesa</package> is installed and provides Vulkan for supported hardware.
</para>
<para>
Similar to OpenCL, Vulkan drivers are loaded through the <emphasis>Installable Client
Driver</emphasis> (ICD) mechanism. ICD files for Vulkan are JSON files that specify
the path to the driver library and the supported Vulkan version. All successfully
loaded drivers are exposed to the application as different GPUs.
In NixOS, there are two ways to make ICD files visible to Vulkan applications: an
environment variable and a module option.
</para>
<para>
The first option is through the <varname>VK_ICD_FILENAMES</varname>
environment variable. This variable can contain multiple JSON files, separated by
<literal>:</literal>. For example:
<screen><prompt>$</prompt> export \
VK_ICD_FILENAMES=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A amdvlk`/share/vulkan/icd.d/amd_icd64.json</screen>
</para>
<para>
The second mechanism is to add the Vulkan driver package to
<xref linkend="opt-hardware.opengl.extraPackages"/>. This links the
ICD file under <filename>/run/opengl-driver</filename>, where it will
be visible to the ICD loader.
</para>
<para>
The proper installation of Vulkan drivers can be verified through
the <command>vulkaninfo</command> command of the <package>vulkan-tools</package>
package. This command will report the hardware devices and drivers found,
in this example output amdvlk and radv:
</para>
<screen><prompt>$</prompt> vulkaninfo | grep GPU
GPU id : 0 (Unknown AMD GPU)
GPU id : 1 (AMD RADV NAVI10 (LLVM 9.0.1))
...
GPU0:
deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
deviceName = Unknown AMD GPU
GPU1:
deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU</screen>
<para>
A simple graphical application that uses Vulkan is <command>vkcube</command>
from the <package>vulkan-tools</package> package.
</para>
<section xml:id="sec-gpu-accel-vulkan-amd">
<title>AMD</title>
<para>
Modern AMD <link
xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics
Core Next</link> (GCN) GPUs are supported through either radv, which is
part of <package>mesa</package>, or the <package>amdvlk</package> package.
Adding the <package>amdvlk</package> package to
<xref linkend="opt-hardware.opengl.extraPackages"/> makes both drivers
available for applications and lets them choose. A specific driver can
be forced as follows:
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
<package>amdvlk</package>
];
# For amdvlk
<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES =
"/run/opengl-driver/share/vulkan/icd.d/amd_icd64.json";
# For radv
<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES =
"/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";
</programlisting>
</para>
</section>
</section>
<section xml:id="sec-gpu-accel-common-issues">
<title>Common issues</title>
<section xml:id="sec-gpu-accel-common-issues-permissions">
<title>User permissions</title>
<para>
Except where noted explicitly, it should not be necessary to
adjust user permissions to use these acceleration APIs. In the default
configuration, GPU devices have world-read/write permissions
(<filename>/dev/dri/renderD*</filename>) or are tagged as
<code>uaccess</code> (<filename>/dev/dri/card*</filename>). The
access control lists of devices with the <varname>uaccess</varname>
tag will be updated automatically when a user logs in through
<command>systemd-logind</command>. For example, if the user
<emphasis>jane</emphasis> is logged in, the access control list
should look as follows:
<screen><prompt>$</prompt> getfacl /dev/dri/card0
# file: dev/dri/card0
# owner: root
# group: video
user::rw-
user:jane:rw-
group::rw-
mask::rw-
other::---</screen>
If you disabled (this functionality of) <command>systemd-logind</command>,
you may need to add the user to the <code>video</code> group and
log in again.
</para>
</section>
<section xml:id="sec-gpu-accel-common-issues-mixing-nixpkgs">
<title>Mixing different versions of nixpkgs</title>
<para>
The <emphasis>Installable Client Driver</emphasis> (ICD)
mechanism used by OpenCL and Vulkan loads runtimes into its address
space using <code>dlopen</code>. Mixing an ICD loader mechanism and
runtimes from different version of nixpkgs may not work. For example,
if the ICD loader uses an older version of <package>glibc</package>
than the runtime, the runtime may not be loadable due to
missing symbols. Unfortunately, the loader will generally be quiet
about such issues.
</para>
<para>
If you suspect that you are running into library version mismatches
between an ICL loader and a runtime, you could run an application with
the <code>LD_DEBUG</code> variable set to get more diagnostic
information. For example, OpenCL can be tested with
<code>LD_DEBUG=files clinfo</code>, which should report missing
symbols.
</para>
</section>
</section>
</chapter>

View file

@ -10,7 +10,7 @@
automatically configure network interfaces. However, you can configure an
interface manually as follows:
<programlisting>
<link linkend="opt-networking.interfaces._name__.ipv4.addresses">networking.interfaces.eth0.ipv4.addresses</link> = [ {
<link linkend="opt-networking.interfaces._name_.ipv4.addresses">networking.interfaces.eth0.ipv4.addresses</link> = [ {
address = "192.168.1.2";
prefixLength = 24;
} ];

View file

@ -26,7 +26,7 @@
As with IPv4 networking interfaces are automatically configured via DHCPv6.
You can configure an interface manually:
<programlisting>
<link linkend="opt-networking.interfaces._name__.ipv6.addresses">networking.interfaces.eth0.ipv6.addresses</link> = [ {
<link linkend="opt-networking.interfaces._name_.ipv6.addresses">networking.interfaces.eth0.ipv6.addresses</link> = [ {
address = "fe00:aa:bb:cc::2";
prefixLength = 64;
} ];

View file

@ -30,7 +30,7 @@ Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: ***
<filename>/</filename>, add the following to
<filename>configuration.nix</filename>:
<programlisting>
<link linkend="opt-boot.initrd.luks.devices._name__.device">boot.initrd.luks.devices.crypted.device</link> = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d";
<link linkend="opt-boot.initrd.luks.devices._name_.device">boot.initrd.luks.devices.crypted.device</link> = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d";
<xref linkend="opt-fileSystems"/>."/".device = "/dev/mapper/crypted";
</programlisting>
Should grub be used as bootloader, and <filename>/boot</filename> is located
@ -60,13 +60,13 @@ Added to key to device /dev/sda2, slot: 2
To ensure that this file system is decrypted using the FIDO2 compatible key, add the following to <filename>configuration.nix</filename>:
<programlisting>
<link linkend="opt-boot.initrd.luks.fido2Support">boot.initrd.luks.fido2Support</link> = true;
<link linkend="opt-boot.initrd.luks.devices._name__.fido2.credential">boot.initrd.luks.devices."/dev/sda2".fido2.credential</link> = "f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7";
<link linkend="opt-boot.initrd.luks.devices._name_.fido2.credential">boot.initrd.luks.devices."/dev/sda2".fido2.credential</link> = "f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7";
</programlisting>
You can also use the FIDO2 passwordless setup, but for security reasons, you might want to enable it only when your device is PIN protected, such as <link xlink:href="https://trezor.io/">Trezor</link>.
<programlisting>
<link linkend="opt-boot.initrd.luks.devices._name__.fido2.passwordLess">boot.initrd.luks.devices."/dev/sda2".fido2.passwordLess</link> = true;
<link linkend="opt-boot.initrd.luks.devices._name_.fido2.passwordLess">boot.initrd.luks.devices."/dev/sda2".fido2.passwordLess</link> = true;
</programlisting>
</para>
</section>

View file

@ -19,7 +19,7 @@
All users that should have permission to change network settings must belong
to the <code>networkmanager</code> group:
<programlisting>
<link linkend="opt-users.users._name__.extraGroups">users.users.alice.extraGroups</link> = [ "networkmanager" ];
<link linkend="opt-users.users._name_.extraGroups">users.users.alice.extraGroups</link> = [ "networkmanager" ];
</programlisting>
</para>

View file

@ -9,7 +9,6 @@
This profile just enables a <systemitem class="username">demo</systemitem>
user, with password <literal>demo</literal>, uid <literal>1000</literal>,
<systemitem class="groupname">wheel</systemitem> group and
<link linkend="opt-services.xserver.displayManager.sddm.autoLogin"> autologin
in the SDDM display manager</link>.
<link linkend="opt-services.xserver.displayManager.autoLogin">autologin in the SDDM display manager</link>.
</para>
</section>

View file

@ -20,7 +20,7 @@
follows:
<!-- FIXME: this might not work if the user is unmanaged. -->
<programlisting>
<link linkend="opt-users.users._name__.openssh.authorizedKeys.keys">users.users.alice.openssh.authorizedKeys.keys</link> =
<link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">users.users.alice.openssh.authorizedKeys.keys</link> =
[ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
</programlisting>
</para>

View file

@ -11,11 +11,11 @@
that a user account named <literal>alice</literal> shall exist:
<programlisting>
<xref linkend="opt-users.users"/>.alice = {
<link linkend="opt-users.users._name__.isNormalUser">isNormalUser</link> = true;
<link linkend="opt-users.users._name__.home">home</link> = "/home/alice";
<link linkend="opt-users.users._name__.description">description</link> = "Alice Foobar";
<link linkend="opt-users.users._name__.extraGroups">extraGroups</link> = [ "wheel" "networkmanager" ];
<link linkend="opt-users.users._name__.openssh.authorizedKeys.keys">openssh.authorizedKeys.keys</link> = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
<link linkend="opt-users.users._name_.isNormalUser">isNormalUser</link> = true;
<link linkend="opt-users.users._name_.home">home</link> = "/home/alice";
<link linkend="opt-users.users._name_.description">description</link> = "Alice Foobar";
<link linkend="opt-users.users._name_.extraGroups">extraGroups</link> = [ "wheel" "networkmanager" ];
<link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">openssh.authorizedKeys.keys</link> = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
};
</programlisting>
Note that <literal>alice</literal> is a member of the
@ -36,7 +36,7 @@
account will cease to exist. Also, imperative commands for managing users and
groups, such as useradd, are no longer available. Passwords may still be
assigned by setting the user's
<link linkend="opt-users.users._name__.hashedPassword">hashedPassword</link>
<link linkend="opt-users.users._name_.hashedPassword">hashedPassword</link>
option. A hashed password can be generated using <command>mkpasswd -m
sha-512</command> after installing the <literal>mkpasswd</literal> package.
</para>

View file

@ -90,10 +90,9 @@
using lightdm for a user <literal>alice</literal>:
<programlisting>
<xref linkend="opt-services.xserver.displayManager.lightdm.enable"/> = true;
<xref linkend="opt-services.xserver.displayManager.lightdm.autoLogin.enable"/> = true;
<xref linkend="opt-services.xserver.displayManager.lightdm.autoLogin.user"/> = "alice";
<xref linkend="opt-services.xserver.displayManager.autoLogin.enable"/> = true;
<xref linkend="opt-services.xserver.displayManager.autoLogin.user"/> = "alice";
</programlisting>
The options are named identically for all other display managers.
</para>
</simplesect>
<simplesect xml:id="sec-x11--graphics-cards-intel">

View file

@ -0,0 +1,68 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-freeform-modules">
<title>Freeform modules</title>
<para>
Freeform modules allow you to define values for option paths that have not been declared explicitly. This can be used to add attribute-specific types to what would otherwise have to be <literal>attrsOf</literal> options in order to accept all attribute names.
</para>
<para>
This feature can be enabled by using the attribute <literal>freeformType</literal> to define a freeform type. By doing this, all assignments without an associated option will be merged using the freeform type and combined into the resulting <literal>config</literal> set. Since this feature nullifies name checking for entire option trees, it is only recommended for use in submodules.
</para>
<example xml:id="ex-freeform-module">
<title>Freeform submodule</title>
<para>
The following shows a submodule assigning a freeform type that allows arbitrary attributes with <literal>str</literal> values below <literal>settings</literal>, but also declares an option for the <literal>settings.port</literal> attribute to have it type-checked and assign a default value. See <xref linkend="ex-settings-typed-attrs"/> for a more complete example.
</para>
<programlisting>
{ lib, config, ... }: {
options.settings = lib.mkOption {
type = lib.types.submodule {
freeformType = with lib.types; attrsOf str;
# We want this attribute to be checked for the correct type
options.port = lib.mkOption {
type = lib.types.port;
# Declaring the option also allows defining a default value
default = 8080;
};
};
};
}
</programlisting>
<para>
And the following shows what such a module then allows
</para>
<programlisting>
{
# Not a declared option, but the freeform type allows this
settings.logLevel = "debug";
# Not allowed because the the freeform type only allows strings
# settings.enable = true;
# Allowed because there is a port option declared
settings.port = 80;
# Not allowed because the port option doesn't allow strings
# settings.port = "443";
}
</programlisting>
</example>
<note>
<para>
Freeform attributes cannot depend on other attributes of the same set without infinite recursion:
<programlisting>
{
# This throws infinite recursion encountered
settings.logLevel = lib.mkIf (config.settings.port == 80) "debug";
}
</programlisting>
To prevent this, declare options for all attributes that need to depend on others. For above example this means to declare <literal>logLevel</literal> to be an option.
</para>
</note>
</section>

View file

@ -385,17 +385,6 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.loaOf</varname> <replaceable>t</replaceable>
</term>
<listitem>
<para>
An attribute set or a list of <replaceable>t</replaceable> type. Multiple
definitions are merged according to the value.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.nullOr</varname> <replaceable>t</replaceable>

View file

@ -8,24 +8,26 @@
<title>Release process</title>
<para>
Going through an example of releasing NixOS 17.09:
Going through an example of releasing NixOS 19.09:
</para>
<section xml:id="one-month-before-the-beta">
<title>One month before the beta</title>
<itemizedlist spacing="compact">
<itemizedlist>
<listitem>
<para>
Send an email to the nix-devel mailinglist as a warning about upcoming
beta "feature freeze" in a month.
Create an announcement on <link xlink:href="https://discourse.nixos.org">Discourse</link> as a warning about upcoming beta <quote>feature freeze</quote> in a month. <link xlink:href="https://discourse.nixos.org/t/nixos-19-09-feature-freeze/3707">See this post as an example</link>.
</para>
</listitem>
<listitem>
<para>
Discuss with Eelco Dolstra and the community (via IRC, ML) about what
will reach the deadline. Any issue or Pull Request targeting the release
should be included in the release milestone.
Discuss with Eelco Dolstra and the community (via IRC, ML) about what will reach the deadline. Any issue or Pull Request targeting the release should be included in the release milestone.
</para>
</listitem>
<listitem>
<para>
Remove attributes that we know we will not be able to support, especially if there is a stable alternative. E.g. Check that our Linux kernels <link xlink:href="https://www.kernel.org/category/releases.html">projected end-of-life</link> are after our release projected end-of-life.
</para>
</listitem>
</itemizedlist>
@ -34,113 +36,113 @@
<section xml:id="at-beta-release-time">
<title>At beta release time</title>
<itemizedlist spacing="compact">
<orderedlist>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/13559">Create
an issue for tracking Zero Hydra Failures progress. ZHF is an effort to
get build failures down to zero.</link>
From the master branch run:
</para>
<programlisting>
git checkout -b release-19.09
</programlisting>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/10e61bf5be57736035ec7a804cb0bf3d083bf2cf#diff-9c798092bac0caeb5c52d509be0ca263R69">Bump the <literal>system.defaultChannel</literal> attribute in <literal>nixos/modules/misc/version.nix</literal></link>
</para>
</listitem>
<listitem>
<para>
<literal>git tag -a -s -m &quot;Release 17.09-beta&quot; 17.09-beta
&amp;&amp; git push origin 17.09-beta</literal>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/10e61bf5be57736035ec7a804cb0bf3d083bf2cf#diff-831e8d9748240fb23e6734fdc2a6d16eR15">Update <literal>versionSuffix</literal> in <literal>nixos/release.nix</literal></link>
</para>
</listitem>
</orderedlist>
<para>
To get the commit count, use the following command:
</para>
<programlisting>
git rev-list --count release-19.09
</programlisting>
<orderedlist>
<listitem>
<para>
From the master branch run <literal>git checkout -b
release-17.09</literal>.
Edit changelog at <literal>nixos/doc/manual/release-notes/rl-1909.xml</literal>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-org-configurations/pull/18">
Make sure a channel is created at https://nixos.org/channels/. </link>
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/compare/bdf161ed8d21...6b63c4616790">
Bump the <literal>system.defaultChannel</literal> attribute in
<literal>nixos/modules/misc/version.nix</literal> </link>
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/d6b08acd1ccac0d9d502c4b635e00b04d3387f06">
Update <literal>versionSuffix</literal> in
<literal>nixos/release.nix</literal></link>, use
<literal>git rev-list --count 17.09-beta</literal>
to get the commit count.
</para>
</listitem>
<listitem>
<para>
<literal>echo -n &quot;18.03&quot; &gt; .version</literal> on master.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/b8a4095003e27659092892a4708bb3698231a842">
Pick a new name for the unstable branch. </link>
</para>
</listitem>
<listitem>
<para>
Create a new release notes file for the upcoming release + 1, in this
case <literal>rl-1803.xml</literal>.
</para>
</listitem>
<listitem>
<para>
Create two Hydra jobsets: release-17.09 and release-17.09-small with
<literal>stableBranch</literal> set to false.
</para>
</listitem>
<listitem>
<para>
Remove attributes that we know we will not be able to support,
especially if there is a stable alternative. E.g. Check that our
Linux kernels'
<link xlink:href="https://www.kernel.org/category/releases.html">
projected end-of-life</link> are after our release projected
end-of-life
</para>
</listitem>
<listitem>
<para>
Edit changelog at
<literal>nixos/doc/manual/release-notes/rl-1709.xml</literal> (double
check desktop versions are noted)
</para>
<itemizedlist spacing="compact">
<itemizedlist>
<listitem>
<para>
Get all new NixOS modules <literal>git diff
release-17.03..release-17.09 nixos/modules/module-list.nix|grep
^+</literal>
Get all new NixOS modules:
</para>
<programlisting>
git diff release-19.03..release-19.09 nixos/modules/module-list.nix | grep ^+
</programlisting>
</listitem>
<listitem>
<para>
Note systemd, kernel, glibc and Nix upgrades.
Note systemd, kernel, glibc, desktop environment, and Nix upgrades.
</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<listitem>
<para>
Tag the release:
</para>
<programlisting>
git tag --annotate --message="Release 19.09-beta" 19.09-beta
git push upstream 19.09-beta
</programlisting>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/01268fda85b7eee4e462c873d8654f975067731f#diff-2bc0e46110b507d6d5a344264ef15adaR1">On the <literal>master</literal> branch, increment the <literal>.version</literal> file</link>
</para>
<programlisting>
echo -n "20.03" > .version
</programlisting>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/01268fda85b7eee4e462c873d8654f975067731f#diff-03f3d41b68f62079c55001f1a1c55c1dR137">Update <literal>codeName</literal> in <literal>lib/trivial.nix</literal></link> This will be the name for the next release.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/01268fda85b7eee4e462c873d8654f975067731f#diff-e7ee5ff686cdcc513ca089d6e5682587R11">Create a new release notes file for the upcoming release + 1</link>, in our case this is <literal>rl-2003.xml</literal>.
</para>
</listitem>
<listitem>
<para>
Contact the infrastructure team to create the necessary Hydra Jobsets.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-org-configurations/blob/master/channels.nix">Create a channel at https://nixos.org/channels by creating a PR to nixos-org-configurations, changing <literal>channels.nix</literal></link>
</para>
</listitem>
<listitem>
<para>
Get all Hydra jobsets for the release to have their first evaluation.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/13559">Create an issue for tracking Zero Hydra Failures progress. ZHF is an effort to get build failures down to zero.</link>
</para>
</listitem>
</orderedlist>
</section>
<section xml:id="during-beta">
<title>During Beta</title>
<itemizedlist spacing="compact">
<itemizedlist>
<listitem>
<para>
Monitor the master branch for bugfixes and minor updates and cherry-pick
them to the release branch.
Monitor the master branch for bugfixes and minor updates and cherry-pick them to the release branch.
</para>
</listitem>
</itemizedlist>
@ -149,7 +151,7 @@
<section xml:id="before-the-final-release">
<title>Before the final release</title>
<itemizedlist spacing="compact">
<itemizedlist>
<listitem>
<para>
Re-check that the release notes are complete.
@ -157,21 +159,17 @@
</listitem>
<listitem>
<para>
Release Nix (currently only Eelco Dolstra can do that).
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/tools/nix-fallback-paths.nix">
Make sure fallback is updated. </link>
Release Nix (currently only Eelco Dolstra can do that). <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/tools/nix-fallback-paths.nix">Make sure fallback is updated.</link>
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/40fd9ae3ac8048758abdcfc7d28a78b5f22fe97e">
Update README.md with new stable NixOS version information. </link>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/40fd9ae3ac8048758abdcfc7d28a78b5f22fe97e">Update README.md with new stable NixOS version information.</link>
</para>
</listitem>
<listitem>
<para>
Change <literal>stableBranch</literal> to <literal>true</literal> in Hydra and wait for
the channel to update.
Change <literal>stableBranch</literal> to <literal>true</literal> in Hydra and wait for the channel to update.
</para>
</listitem>
</itemizedlist>
@ -180,76 +178,143 @@
<section xml:id="at-final-release-time">
<title>At final release time</title>
<itemizedlist spacing="compact">
<orderedlist>
<listitem>
<para>
<literal>git tag -s -a -m &quot;Release 15.09&quot; 15.09</literal>
Update <xref linkend="sec-upgrading" /> section of the manual to match new stable release version.
</para>
</listitem>
<listitem>
<para>
Update "Chapter 4. Upgrading NixOS" section of the manual to match
new stable release version.
Update <literal>rl-1909.xml</literal> with the release date.
</para>
</listitem>
<listitem>
<para>
Update the
<link xlink:href="https://github.com/NixOS/nixos-homepage/commit/2a37975d5a617ecdfca94696242b6f32ffcba9f1"><code>NIXOS_SERIES</code></link>
in the
<link xlink:href="https://github.com/NixOS/nixos-homepage">nixos-homepage</link>
repository.
Tag the final release
</para>
<programlisting>
git tag --annotate --message="Release 19.09" 19.09
git push upstream 19.09
</programlisting>
</listitem>
<listitem>
<para>
Get number of commits for the release: <literal>git log
release-14.04..release-14.12 --format=%an|wc -l</literal>
Update <link xlink:href="https://github.com/NixOS/nixos-homepage">nixos-homepage</link> for the release.
</para>
<orderedlist>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/47ac3571c4d71e841fd4e6c6e1872e762b9c4942/Makefile#L1">Update <literal>NIXOS_SERIES</literal> in the <literal>Makefile</literal></link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/47ac3571c4d71e841fd4e6c6e1872e762b9c4942/nixos-release.tt#L1">Update <literal>nixos-release.tt</literal> with the new NixOS version</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/47ac3571c4d71e841fd4e6c6e1872e762b9c4942/flake.nix#L10">Update the <literal>flake.nix</literal> input <literal>released-nixpkgs</literal> to 19.09</link>.
</para>
</listitem>
<listitem>
<para>
Run <literal>./update.sh</literal> (this updates flake.lock to updated channel).
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/a5626c71c03a2dd69086564e56f1a230a2bb177a/logo/nixos-logo-19.09-loris-lores.png">Add a compressed version of the NixOS logo for 19.09</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/commit/a5626c71c03a2dd69086564e56f1a230a2bb177a#diff-9cdc6434d3e4fd93a6e5bb0a531a7c71R5">Compose a news item for the website RSS feed</link>.
</para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>
Commits by contributor: <literal>git log release-14.04..release-14.12
--format=%an|sort|uniq -c|sort -rn</literal>
Create a new topic on <link xlink:href="https://discourse.nixos.org/">the Discourse instance</link> to announce the release.
</para>
</listitem>
</orderedlist>
<para>
You should include the following information:
</para>
<itemizedlist>
<listitem>
<para>
Number of commits for the release:
</para>
<programlisting>
bash git log release-19.03..release-19.09 --format=%an | wc -l
</programlisting>
</listitem>
<listitem>
<para>
Create a new topic on <link xlink:href="https://discourse.nixos.org/">the
Discourse instance</link> to announce the release with the above information.
Best to check how previous email was formulated to see what needs to be
included.
Commits by contributor:
</para>
<programlisting>
git shortlog --summary --numbered release-19.03..release-19.09
</programlisting>
</listitem>
</itemizedlist>
<para>
Best to check how the previous post was formulated to see what needs to be included.
</para>
</section>
</section>
<section xml:id="release-managers">
<section xml:id="release-management-team">
<title>Release Management Team</title>
<para>
For each release there are two release managers. After each release the
release manager having managed two releases steps down and the release
management team of the last release appoints a new release manager.
For each release there are two release managers. After each release the release manager having managed two releases steps down and the release management team of the last release appoints a new release manager.
</para>
<para>
This makes sure a release management team always consists of one release
manager who already has managed one release and one release manager being
introduced to their role, making it easier to pass on knowledge and
experience.
This makes sure a release management team always consists of one release manager who already has managed one release and one release manager being introduced to their role, making it easier to pass on knowledge and experience.
</para>
<para>
Release managers for the current NixOS release are tracked by GitHub team
<link xlink:href="https://github.com/orgs/NixOS/teams/nixos-release-managers/members"><literal>@NixOS/nixos-release-managers</literal></link>.
Release managers for the current NixOS release are tracked by GitHub team <link xlink:href="https://github.com/orgs/NixOS/teams/nixos-release-managers/members"><literal>@NixOS/nixos-release-managers</literal></link>.
</para>
<para>
A release manager's role and responsibilities are:
A release managers role and responsibilities are:
</para>
<itemizedlist>
<listitem><para>manage the release process</para></listitem>
<listitem><para>start discussions about features and changes for a given release</para></listitem>
<listitem><para>create a roadmap</para></listitem>
<listitem><para>release in cooperation with Eelco Dolstra</para></listitem>
<listitem><para>decide which bug fixes, features, etc... get backported after a release</para></listitem>
<listitem>
<para>
manage the release process
</para>
</listitem>
<listitem>
<para>
start discussions about features and changes for a given release
</para>
</listitem>
<listitem>
<para>
create a roadmap
</para>
</listitem>
<listitem>
<para>
release in cooperation with Eelco Dolstra
</para>
</listitem>
<listitem>
<para>
decide which bug fixes, features, etc… get backported after a release
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="release-schedule">

View file

@ -0,0 +1,216 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-settings-options">
<title>Options for Program Settings</title>
<para>
Many programs have configuration files where program-specific settings can be declared. File formats can be separated into two categories:
<itemizedlist>
<listitem>
<para>
Nix-representable ones: These can trivially be mapped to a subset of Nix syntax. E.g. JSON is an example, since its values like <literal>{"foo":{"bar":10}}</literal> can be mapped directly to Nix: <literal>{ foo = { bar = 10; }; }</literal>. Other examples are INI, YAML and TOML. The following section explains the convention for these settings.
</para>
</listitem>
<listitem>
<para>
Non-nix-representable ones: These can't be trivially mapped to a subset of Nix syntax. Most generic programming languages are in this group, e.g. bash, since the statement <literal>if true; then echo hi; fi</literal> doesn't have a trivial representation in Nix.
</para>
<para>
Currently there are no fixed conventions for these, but it is common to have a <literal>configFile</literal> option for setting the configuration file path directly. The default value of <literal>configFile</literal> can be an auto-generated file, with convenient options for controlling the contents. For example an option of type <literal>attrsOf str</literal> can be used for representing environment variables which generates a section like <literal>export FOO="foo"</literal>. Often it can also be useful to also include an <literal>extraConfig</literal> option of type <literal>lines</literal> to allow arbitrary text after the autogenerated part of the file.
</para>
</listitem>
</itemizedlist>
</para>
<section xml:id="sec-settings-nix-representable">
<title>Nix-representable Formats (JSON, YAML, TOML, INI, ...)</title>
<para>
By convention, formats like this are handled with a generic <literal>settings</literal> option, representing the full program configuration as a Nix value. The type of this option should represent the format. The most common formats have a predefined type and string generator already declared under <literal>pkgs.formats</literal>:
<variablelist>
<varlistentry>
<term>
<varname>pkgs.formats.json</varname> { }
</term>
<listitem>
<para>
A function taking an empty attribute set (for future extensibility) and returning a set with JSON-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>pkgs.formats.yaml</varname> { }
</term>
<listitem>
<para>
A function taking an empty attribute set (for future extensibility) and returning a set with YAML-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>pkgs.formats.ini</varname> { <replaceable>listsAsDuplicateKeys</replaceable> ? false, ... }
</term>
<listitem>
<para>
A function taking an attribute set with values
<variablelist>
<varlistentry>
<term>
<varname>listsAsDuplicateKeys</varname>
</term>
<listitem>
<para>
A boolean for controlling whether list values can be used to represent duplicate INI keys
</para>
</listitem>
</varlistentry>
</variablelist>
It returns a set with INI-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>pkgs.formats.toml</varname> { }
</term>
<listitem>
<para>
A function taking an empty attribute set (for future extensibility) and returning a set with TOML-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para xml:id="pkgs-formats-result">
These functions all return an attribute set with these values:
<variablelist>
<varlistentry>
<term>
<varname>type</varname>
</term>
<listitem>
<para>
A module system type representing a value of the format
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>generate</varname> <replaceable>filename</replaceable> <replaceable>jsonValue</replaceable>
</term>
<listitem>
<para>
A function that can render a value of the format to a file. Returns a file path.
<note>
<para>
This function puts the value contents in the Nix store. So this should be avoided for secrets.
</para>
</note>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<example xml:id="ex-settings-nix-representable">
<title>Module with conventional <literal>settings</literal> option</title>
<para>
The following shows a module for an example program that uses a JSON configuration file. It demonstrates how above values can be used, along with some other related best practices. See the comments for explanations.
</para>
<programlisting>
{ options, config, lib, pkgs, ... }:
let
cfg = config.services.foo;
# Define the settings format used for this program
settingsFormat = pkgs.formats.json {};
in {
options.services.foo = {
enable = lib.mkEnableOption "foo service";
settings = lib.mkOption {
# Setting this type allows for correct merging behavior
type = settingsFormat.type;
default = {};
description = ''
Configuration for foo, see
&lt;link xlink:href="https://example.com/docs/foo"/&gt;
for supported settings.
'';
};
};
config = lib.mkIf cfg.enable {
# We can assign some default settings here to make the service work by just
# enabling it. We use `mkDefault` for values that can be changed without
# problems
services.foo.settings = {
# Fails at runtime without any value set
log_level = lib.mkDefault "WARN";
# We assume systemd's `StateDirectory` is used, so we require this value,
# therefore no mkDefault
data_path = "/var/lib/foo";
# Since we use this to create a user we need to know the default value at
# eval time
user = lib.mkDefault "foo";
};
environment.etc."foo.json".source =
# The formats generator function takes a filename and the Nix value
# representing the format value and produces a filepath with that value
# rendered in the format
settingsFormat.generate "foo-config.json" cfg.settings;
# We know that the `user` attribute exists because we set a default value
# for it above, allowing us to use it without worries here
users.users.${cfg.settings.user} = {};
# ...
};
}
</programlisting>
</example>
<section xml:id="sec-settings-attrs-options">
<title>Option declarations for attributes</title>
<para>
Some <literal>settings</literal> attributes may deserve some extra care. They may need a different type, default or merging behavior, or they are essential options that should show their documentation in the manual. This can be done using <xref linkend='sec-freeform-modules'/>.
<example xml:id="ex-settings-typed-attrs">
<title>Declaring a type-checked <literal>settings</literal> attribute</title>
<para>
We extend above example using freeform modules to declare an option for the port, which will enforce it to be a valid integer and make it show up in the manual.
</para>
<programlisting>
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
# Declare an option for the port such that the type is checked and this option
# is shown in the manual.
options.port = lib.mkOption {
type = lib.types.port;
default = 8080;
description = ''
Which port this service should listen on.
'';
};
};
default = {};
description = ''
Configuration for Foo, see
&lt;link xlink:href="https://example.com/docs/foo"/&gt;
for supported values.
'';
};
</programlisting>
</example>
</para>
</section>
</section>
</section>

View file

@ -183,4 +183,6 @@ in {
<xi:include href="meta-attributes.xml" />
<xi:include href="importing-modules.xml" />
<xi:include href="replace-modules.xml" />
<xi:include href="freeform-modules.xml" />
<xi:include href="settings-options.xml" />
</chapter>

View file

@ -216,12 +216,12 @@ start_all()
</varlistentry>
<varlistentry>
<term>
<methodname>send_keys</methodname>
<methodname>send_key</methodname>
</term>
<listitem>
<para>
Simulate pressing keys on the virtual keyboard, e.g.,
<literal>send_keys("ctrl-alt-delete")</literal>.
<literal>send_key("ctrl-alt-delete")</literal>.
</para>
</listitem>
</varlistentry>
@ -232,7 +232,7 @@ start_all()
<listitem>
<para>
Simulate typing a sequence of characters on the virtual keyboard, e.g.,
<literal>send_keys("foobar\n")</literal> will type the string
<literal>send_chars("foobar\n")</literal> will type the string
<literal>foobar</literal> followed by the Enter key.
</para>
</listitem>
@ -390,7 +390,7 @@ start_all()
<listitem>
<para>
Copies a file from host to machine, e.g.,
<literal>copy_file_from_host("myfile", "/etc/my/important/file")</literal>.
<literal>copy_from_host("myfile", "/etc/my/important/file")</literal>.
</para>
<para>
The first argument is the file on the host. The file needs to be

View file

@ -78,7 +78,7 @@
<literal>mutableUsers = false</literal>. Another way is to temporarily add
the following to your configuration:
<screen>
<link linkend="opt-users.users._name__.initialHashedPassword">users.users.your-user.initialHashedPassword</link> = "test";
<link linkend="opt-users.users._name_.initialHashedPassword">users.users.your-user.initialHashedPassword</link> = "test";
</screen>
<emphasis>Important:</emphasis> delete the $hostname.qcow2 file if you have
started the virtual machine at least once without the right users, otherwise

View file

@ -211,7 +211,7 @@ nixpkgs https://nixos.org/channels/nixpkgs-unstable</screen>
use <literal>sudo</literal>)
</para>
<programlisting>
<link linkend="opt-users.users._name__.initialHashedPassword">users.users.root.initialHashedPassword</link> = "";
<link linkend="opt-users.users._name_.initialHashedPassword">users.users.root.initialHashedPassword</link> = "";
</programlisting>
</listitem>
<listitem>

View file

@ -16,7 +16,7 @@
</para>
<programlisting>
nix-build -A netboot nixos/release.nix
nix-build -A netboot.x86_64-linux nixos/release.nix
</programlisting>
<para>

View file

@ -49,7 +49,7 @@
</listitem>
<listitem>
<para>
Click on Settings / Display / Screen and select VBoxVGA as Graphics Controller
Click on Settings / Display / Screen and select VMSVGA as Graphics Controller
</para>
</listitem>
<listitem>

View file

@ -42,7 +42,7 @@
</para>
<para>
If the text is too small to be legible, try <command>setfont ter-132n</command>
If the text is too small to be legible, try <command>setfont ter-v32n</command>
to increase the font size.
</para>
@ -550,7 +550,7 @@ Retype new UNIX password: ***</screen>
# Note: setting fileSystems is generally not
# necessary, since nixos-generate-config figures them out
# automatically in hardware-configuration.nix.
#<link linkend="opt-fileSystems._name__.device">fileSystems."/".device</link> = "/dev/disk/by-label/nixos";
#<link linkend="opt-fileSystems._name_.device">fileSystems."/".device</link> = "/dev/disk/by-label/nixos";
# Enable the OpenSSH server.
services.sshd.enable = true;

View file

@ -13,15 +13,15 @@
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-build-vms</command>
<command>nixos-build-vms</command>
<arg>
<option>--show-trace</option>
</arg>
<arg>
<option>--no-out-link</option>
</arg>
<arg>
<option>--help</option>
</arg>

View file

@ -13,21 +13,21 @@
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-enter</command>
<command>nixos-enter</command>
<arg>
<arg choice='plain'>
<option>--root</option>
</arg>
<replaceable>root</replaceable>
</arg>
<arg>
<arg choice='plain'>
<option>--system</option>
</arg>
<replaceable>system</replaceable>
</arg>
<arg>
<arg choice='plain'>
<option>-c</option>
@ -40,13 +40,13 @@
<option>--silent</option>
</arg>
</arg>
<arg>
<arg choice='plain'>
<option>--help</option>
</arg>
</arg>
<arg>
<arg choice='plain'>
<option>--</option>
@ -136,7 +136,7 @@
<filename>/mnt</filename>:
</para>
<screen>
# nixos-enter /mnt
# nixos-enter --root /mnt
</screen>
<para>
Run a shell command:

View file

@ -45,6 +45,10 @@
<replaceable>path</replaceable>
</arg>
<arg>
<option>--flake</option> <replaceable>flake-uri</replaceable>
</arg>
<arg>
<arg choice='plain'>
<option>--channel</option>
@ -199,6 +203,18 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--flake</option> <replaceable>flake-uri</replaceable>#<replaceable>name</replaceable>
</term>
<listitem>
<para>
Build the NixOS system from the specified flake.
The flake must contain an output named
<literal>nixosConfigurations.<replaceable>name</replaceable></literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--channel</option>

View file

@ -315,7 +315,7 @@
switch</command>), because the hardware and boot loader configuration in
the VM are different. The boot loader is installed on an automatically
generated virtual disk containing a <filename>/boot</filename>
partition, which is mounted read-only in the VM.
partition.
</para>
</listitem>
</varlistentry>
@ -521,7 +521,7 @@
<varlistentry>
<term>
<option>--flake</option> <replaceable>flake-uri</replaceable>[<replaceable>name</replaceable>]
<option>--flake</option> <replaceable>flake-uri</replaceable><optional>#<replaceable>name</replaceable></optional>
</term>
<listitem>
<para>

View file

@ -792,11 +792,11 @@ users.users.me =
The <option>services.xserver.displayManager.auto</option> module has been removed.
It was only intended for use in internal NixOS tests, and gave the false impression
of it being a special display manager when it's actually LightDM.
Please use the <xref linkend="opt-services.xserver.displayManager.lightdm.autoLogin"/> options instead,
Please use the <option>services.xserver.displayManager.lightdm.autoLogin</option> options instead,
or any other display manager in NixOS as they all support auto-login. If you used this module specifically
because it permitted root auto-login you can override the lightdm-autologin pam module like:
<programlisting>
<link xlink:href="#opt-security.pam.services._name__.text">security.pam.services.lightdm-autologin.text</link> = lib.mkForce ''
<link xlink:href="#opt-security.pam.services._name_.text">security.pam.services.lightdm-autologin.text</link> = lib.mkForce ''
auth requisite pam_nologin.so
auth required pam_succeed_if.so quiet
auth required pam_permit.so

View file

@ -42,6 +42,11 @@
PHP now defaults to PHP 7.4, updated from 7.3.
</para>
</listitem>
<listitem>
<para>
PHP 7.2 is no longer supported due to upstream not supporting this version for the entire lifecycle of the 20.09 release.
</para>
</listitem>
<listitem>
<para>
Python 3 now defaults to Python 3.8 instead of 3.7.
@ -109,16 +114,106 @@ systemd.services.mysql.serviceConfig.ProtectHome = lib.mkForce "read-only";
systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
</programlisting>
</para>
<para>
The MySQL service no longer runs its <literal>systemd</literal> service startup script as <literal>root</literal> anymore. A dedicated non <literal>root</literal>
super user account is required for operation. This means users with an existing MySQL or MariaDB database server are required to run the following SQL statements
as a super admin user before upgrading:
<programlisting>
CREATE USER IF NOT EXISTS 'mysql'@'localhost' identified with unix_socket;
GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
</programlisting>
If you use MySQL instead of MariaDB please replace <literal>unix_socket</literal> with <literal>auth_socket</literal>. If you have changed the value of <xref linkend="opt-services.mysql.user"/>
from the default of <literal>mysql</literal> to a different user please change <literal>'mysql'@'localhost'</literal> to the corresponding user instead.
</para>
</listitem>
<listitem>
<para>
Two new option <link linkend="opt-documentation.man.generateCaches">documentation.man.generateCaches</link>
The new option <link linkend="opt-documentation.man.generateCaches">documentation.man.generateCaches</link>
has been added to automatically generate the <literal>man-db</literal> caches, which are needed by utilities
like <command>whatis</command> and <command>apropos</command>. The caches are generated during the build of
the NixOS configuration: since this can be expensive when a large number of packages are installed, the
feature is disabled by default.
</para>
</listitem>
<listitem>
<para>
<varname>services.postfix.sslCACert</varname> was replaced by <varname>services.postfix.tlsTrustedAuthorities</varname> which now defaults to system certificate authorities.
</para>
</listitem>
<listitem>
<para>
Subordinate GID and UID mappings are now set up automatically for all normal users.
This will make container tools like Podman work as non-root users out of the box.
</para>
</listitem>
<listitem>
<para>
The various documented workarounds to use steam have been converted to a module. <varname>programs.steam.enable</varname> enables steam, controller support and the workarounds.
</para>
</listitem>
<listitem>
<para>
Support for built-in LCDs in various pieces of Logitech hardware (keyboards and USB speakers). <varname>hardware.logitech.lcd.enable</varname> enables support for all hardware supported by the g15daemon project.
</para>
</listitem>
<listitem>
<para>
Zabbix now defaults to 5.0, updated from 4.4. Please carefully read through
<link xlink:href="https://www.zabbix.com/documentation/current/manual/installation/upgrade/sources">the upgrade guide</link>
and apply any changes required. Be sure to take special note of the section on
<link xlink:href="https://www.zabbix.com/documentation/current/manual/installation/upgrade_notes_500#enabling_extended_range_of_numeric_float_values">enabling extended range of numeric (float) values</link>
as you will need to apply this database migration manually.
</para>
<para>
If you are using Zabbix Server with a MySQL or MariaDB database you should note that using a character set of <literal>utf8</literal> and a collate of <literal>utf8_bin</literal> has become mandatory with
this release. See the upstream <link xlink:href="https://support.zabbix.com/browse/ZBX-17357">issue</link> for further discussion. Before upgrading you should check the character set and collation used by
your database and ensure they are correct:
<programlisting>
SELECT
default_character_set_name,
default_collation_name
FROM
information_schema.schemata
WHERE
schema_name = 'zabbix';
</programlisting>
If these values are not correct you should take a backup of your database and convert the character set and collation as required. Here is an
<link xlink:href="https://www.zabbix.com/forum/zabbix-help/396573-reinstall-after-upgrade?p=396891#post396891">example</link> of how to do so, taken from
the Zabbix forums:
<programlisting>
ALTER DATABASE `zabbix` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
-- the following will produce a list of SQL commands you should subsequently execute
SELECT CONCAT("ALTER TABLE ", TABLE_NAME," CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;") AS ExecuteTheString
FROM information_schema.`COLUMNS`
WHERE table_schema = "zabbix" AND COLLATION_NAME = "utf8_general_ci";
</programlisting>
</para>
</listitem>
<listitem>
<para>
The NixOS module system now supports freeform modules as a mix between <literal>types.attrsOf</literal> and <literal>types.submodule</literal>. These allow you to explicitly declare a subset of options while still permitting definitions without an associated option. See <xref linkend='sec-freeform-modules'/> for how to use them.
</para>
</listitem>
<listitem>
<para>
The GRUB module gained support for basic password protection, which
allows to restrict non-default entries in the boot menu to one or more
users. The users and passwords are defined via the option
<option>boot.loader.grub.users</option>.
Note: Password support is only avaiable in GRUB version 2.
</para>
</listitem>
<listitem>
<para>
Following its deprecation in 20.03, the Perl NixOS test driver has been removed.
All remaining tests have been ported to the Python test framework.
Code outside nixpkgs using <filename>make-test.nix</filename> or
<filename>testing.nix</filename> needs to be ported to
<filename>make-test-python.nix</filename> and
<filename>testing-python.nix</filename> respectively.
</para>
</listitem>
</itemizedlist>
</section>
@ -138,6 +233,11 @@ systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
<para>
There is a new <xref linkend="opt-security.doas.enable"/> module that provides <command>doas</command>, a lighter alternative to <command>sudo</command> with many of the same features.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://hercules-ci.com">Hercules CI</link> Agent is a specialized build agent for projects built with Nix. See the <link xlink:href="https://nixos.org/nixos/options.html#services.hercules-ci-agent">options</link> and <link xlink:href="https://docs.hercules-ci.com/hercules-ci/getting-started/#deploy-agent">setup</link>.
</para>
</listitem>
</itemizedlist>
@ -162,12 +262,10 @@ systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
in the source tree for downloaded modules instead of using go's <link
xlink:href="https://golang.org/cmd/go/#hdr-Module_proxy_protocol">module
proxy protocol</link>. This storage format is simpler and therefore less
likekly to break with future versions of go. As a result
likely to break with future versions of go. As a result
<literal>buildGoModule</literal> switched from
<literal>modSha256</literal> to the <literal>vendorSha256</literal>
attribute to pin fetched version data. <literal>buildGoModule</literal>
still accepts <literal>modSha256</literal> with a warning, but support will
be removed in the next release.
attribute to pin fetched version data.
</para>
</listitem>
<listitem>
@ -176,7 +274,7 @@ systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
<link xlink:href="https://grafana.com/docs/grafana/latest/guides/whats-new-in-v6-4/">deprecated in Grafana</link>
and the <package>phantomjs</package> project is
<link xlink:href="https://github.com/ariya/phantomjs/issues/15344#issue-302015362">currently unmaintained</link>.
It can still be enabled by providing <literal>phantomJsSupport = true</literal> to the package instanciation:
It can still be enabled by providing <literal>phantomJsSupport = true</literal> to the package instantiation:
<programlisting>{
services.grafana.package = pkgs.grafana.overrideAttrs (oldAttrs: rec {
phantomJsSupport = false;
@ -188,7 +286,7 @@ systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
<para>
The <link linkend="opt-services.supybot.enable">supybot</link> module now uses <literal>/var/lib/supybot</literal>
as its default <link linkend="opt-services.supybot.stateDir">stateDir</link> path if <literal>stateVersion</literal>
is 20.09 or higher. It also enables number of
is 20.09 or higher. It also enables a number of
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing">systemd sandboxing options</link>
which may possibly interfere with some plugins. If this is the case you can disable the options through attributes in
<option>systemd.services.supybot.serviceConfig</option>.
@ -296,6 +394,20 @@ php.override {
</para>
</listitem>
<listitem>
<para>
The ACME module has been overhauled for simplicity and maintainability.
Cert generation now implicitly uses the <literal>acme</literal>
user, and the <literal>security.acme.certs._name_.user</literal> option
has been removed. Instead, certificate access from other services is now
managed through group permissions. The module no longer runs lego
twice under certain conditions, and will correctly renew certificates if
their configuration is changed. Services which reload nginx and httpd after
certificate renewal are now properly configured too so you no longer have
to do this manually if you are using HTTPS enabled virtual hosts. A mechanism
for regenerating certs on demand has also been added and documented.
</para>
</listitem>
<listitem>
<para>
Gollum received a major update to version 5.x and you may have to change
@ -502,6 +614,46 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
<listitem>
<para>
In the <literal>resilio</literal> module, <xref linkend="opt-services.resilio.httpListenAddr"/> has been changed to listen to <literal>[::1]</literal> instead of <literal>0.0.0.0</literal>.
</para>
</listitem>
<listitem>
<para>
Users of <link xlink:href="http://openafs.org">OpenAFS 1.6</link> must
upgrade their services to OpenAFS 1.8! In this release, the OpenAFS package
version 1.6.24 is marked broken but can be used during transition to
OpenAFS 1.8.x. Use the options
<option>services.openafsClient.packages.module</option>,
<option>services.openafsClient.packages.programs</option> and
<option>services.openafsServer.package</option> to select a different
OpenAFS package. OpenAFS 1.6 will be removed in the next release. The
package <literal>openafs</literal> and the service options will then
silently point to the OpenAFS 1.8 release.
</para>
<para>
See also the OpenAFS <link
xlink:href="http://docs.openafs.org/AdminGuide/index.html">Administrator
Guide</link> for instructions. Beware of the following when updating
servers:
<itemizedlist>
<listitem>
<para>
The storage format of the server key has changed and the key must be converted before running the new release.
</para>
</listitem>
<listitem>
<para>
When updating multiple database servers, turn off the database servers
from the highest IP down to the lowest with resting periods in
between. Start up in reverse order. Do not concurrently run database
servers working with different OpenAFS releases!
</para>
</listitem>
<listitem>
<para>
Update servers first, then clients.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
@ -514,6 +666,136 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
automatically if <literal>stateVersion</literal> is 20.09 or higher.
</para>
</listitem>
<listitem>
<para>
<literal>udpt</literal> experienced a complete rewrite from C++ to rust. The configuration format changed from ini to toml.
The new configuration documentation can be found at
<link xlink:href="https://naim94a.github.io/udpt/config.html">the official website</link> and example
configuration is packaged in <literal>${udpt}/share/udpt/udpt.toml</literal>.
</para>
</listitem>
<listitem>
<para>
We now have a unified <xref linkend="opt-services.xserver.displayManager.autoLogin"/> option interface
to be used for every display-manager in NixOS.
</para>
</listitem>
<listitem>
<para>
The <literal>bitcoind</literal> module has changed to multi-instance, using submodules.
Therefore, it is now mandatory to name each instance.
To use this new multi-instance config with an existing bitcoind data directory and user,
you have to adjust the original config, e.g.:
<programlisting>
services.bitcoind = {
enable = true;
extraConfig = "...";
...
};
</programlisting>
To something similar:
<programlisting>
services.bitcoind.mainnet = {
enable = true;
dataDir = "/var/lib/bitcoind";
user = "bitcoin";
extraConfig = "...";
...
};
</programlisting>
The key settings are:
<itemizedlist>
<listitem>
<para>
<literal>dataDir</literal> - to continue using the same data directory.
</para>
</listitem>
<listitem>
<para>
<literal>user</literal> - to continue using the same user so that bitcoind maintains access to its files.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>
Graylog introduced a change in the LDAP server certificate validation behaviour for version 3.3.3 which might break existing setups.
When updating Graylog from a version before 3.3.3 make sure to check the Graylog <link xlink:href="https://www.graylog.org/post/announcing-graylog-v3-3-3">release info</link> for information on how to avoid the issue.
</para>
</listitem>
<listitem>
<para>
The <literal>dokuwiki</literal> module has changed to multi-instance, using submodules.
Therefore, it is now mandatory to name each instance. Moreover, forcing SSL by default has been dropped, so
<literal>nginx.forceSSL</literal> and <literal>nginx.enableACME</literal> are no longer set to <literal>true</literal>.
To continue using your service with the original SSL settings, you have to adjust the original config, e.g.:
<programlisting>
services.dokuwiki = {
enable = true;
...
};
</programlisting>
To something similar:
<programlisting>
services.dokuwiki."mywiki" = {
enable = true;
nginx = {
forceSSL = true;
enableACME = true;
};
...
};
</programlisting>
The base package has also been upgraded to the 2020-07-29 "Hogfather" release. Plugins might be incompatible or require upgrading.
</para>
</listitem>
<listitem>
<para>
The <xref linkend="opt-services.postgresql.dataDir"/> option is now set to <literal>"/var/lib/postgresql/${cfg.package.psqlSchema}"</literal> regardless of your
<xref linkend="opt-system.stateVersion"/>. Users with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.03</literal> or below
should double check what the value of their <xref linkend="opt-services.postgresql.dataDir"/> option is (<literal>/var/db/postgresql</literal>) and then explicitly
set this value to maintain compatibility:
<programlisting>
services.postgresql.dataDir = "/var/db/postgresql";
</programlisting>
</para>
<para>
The postgresql module now expects there to be a database super user account called <literal>postgres</literal> regardless of your <xref linkend="opt-system.stateVersion"/>. Users
with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.03</literal> or below should run the following SQL statements as a
database super admin user before upgrading:
<programlisting>
CREATE ROLE postgres LOGIN SUPERUSER;
</programlisting>
</para>
</listitem>
<listitem>
<para>
The USBGuard module now removes options and instead hardcodes values for <literal>IPCAccessControlFiles</literal>, <literal>ruleFiles</literal>, and <literal>auditFilePath</literal>. Audit logs can be found in the journal.
</para>
</listitem>
<listitem>
<para>
The NixOS module system now evaluates option definitions more strictly, allowing it to detect a larger set of problems.
As a result, what previously evaluated may not do so anymore.
See <link xlink:href="https://github.com/NixOS/nixpkgs/pull/82743#issuecomment-674520472">the PR that changed this</link> for more info.
</para>
</listitem>
<listitem>
<para>
For NixOS configuration options, the type <literal>loaOf</literal>, after
its initial deprecation in release 20.03, has been removed. In NixOS and
Nixpkgs options using this type have been converted to <literal>attrsOf</literal>.
For more information on this change have look at these links:
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/1800">issue #1800</link>,
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/63103">PR #63103</link>.
</para>
</listitem>
<listitem>
<para>
<literal>config.systemd.services.${name}.path</literal> now returns a list of paths instead of a colon-separated string.
</para>
</listitem>
</itemizedlist>
</section>
@ -549,6 +831,11 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
The default output of <literal>buildGoPackage</literal> is now <literal>$out</literal> instead of <literal>$bin</literal>.
</para>
</listitem>
<listitem>
<para>
<literal>buildGoModule</literal> <literal>doCheck</literal> now defaults to <literal>true</literal>.
</para>
</listitem>
<listitem>
<para>
Packages built using <literal>buildRustPackage</literal> now use <literal>release</literal>
@ -606,6 +893,37 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
was removed, as udev gained native support to handle FIDO security tokens.
</para>
</listitem>
<listitem>
<para>
The <literal>services.transmission</literal> module
was enhanced with the new options:
<xref linkend="opt-services.transmission.credentialsFile"/>,
<xref linkend="opt-services.transmission.openFirewall"/>,
and <xref linkend="opt-services.transmission.performanceNetParameters"/>.
</para>
<para>
<literal>transmission-daemon</literal> is now started with additional systemd sandbox/hardening options for better security.
Please <link xlink:href="https://github.com/NixOS/nixpkgs/issues">report</link>
any use case where this is not working well.
In particular, the <literal>RootDirectory</literal> option newly set
forbids uploading or downloading a torrent outside of the default directory
configured at <link linkend="opt-services.transmission.settings">settings.download-dir</link>.
If you really need Transmission to access other directories,
you must include those directories into the <literal>BindPaths</literal> of the service:
<programlisting>
systemd.services.transmission.serviceConfig.BindPaths = [ "/path/to/alternative/download-dir" ];
</programlisting>
</para>
<para>
Also, connection to the RPC (Remote Procedure Call) of <literal>transmission-daemon</literal>
is now only available on the local network interface by default.
Use:
<programlisting>
services.transmission.settings.rpc-bind-address = "0.0.0.0";
</programlisting>
to get the previous behavior of listening on all network interfaces.
</para>
</listitem>
<listitem>
<para>
With this release <literal>systemd-networkd</literal> (when enabled through <xref linkend="opt-networking.useNetworkd"/>)
@ -682,6 +1000,85 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
behaviour and keep the same VM state between different test runs.
</para>
</listitem>
<listitem>
<para>
The <link linkend="opt-nix.buildMachines">nix.buildMachines</link> option is now type-checked.
There are no functional changes, however this may require updating some configurations to use correct types for all attributes.
</para>
</listitem>
<listitem>
<para>
The <literal>fontconfig</literal> module stopped generating fontconfig 2.10.x config and cache.
Fontconfig 2.10.x was removed from Nixpkgs - it hasn't been used in any nixpkgs package anymore.
</para>
</listitem>
<listitem>
<para>
Nginx module <literal>nginxModules.fastcgi-cache-purge</literal> renamed to official name <literal>nginxModules.cache-purge</literal>.
Nginx module <literal>nginxModules.ngx_aws_auth</literal> renamed to official name <literal>nginxModules.aws-auth</literal>.
The packages <package>perl</package>, <package>rsync</package> and <package>strace</package> were removed from <option>systemPackages</option>. If you need them, install them again with <code><xref linkend="opt-environment.systemPackages"/> = with pkgs; [ perl rsync strace ];</code> in your <filename>configuration.nix</filename>.
</para>
</listitem>
<listitem>
<para>
The <literal>undervolt</literal> option no longer needs to apply its
settings every 30s. If they still become undone, open an issue and restore
the previous behaviour using <literal>undervolt.useTimer</literal>.
</para>
</listitem>
<listitem>
<para>
Agda has been heavily reworked.
<itemizedlist>
<listitem>
<para>
<literal>agda.mkDerivation</literal> has been heavily changed and
is now located at <package>agdaPackages.mkDerivation</package>.
</para>
</listitem>
<listitem>
<para>
New top-level packages <package>agda</package> and
<literal>agda.withPackages</literal> have been added, the second
of which sets up agda with access to chosen libraries.
</para>
</listitem>
<listitem>
<para>
All agda libraries now live under
<literal>agdaPackages</literal>.
</para>
</listitem>
<listitem>
<para>
Many broken libraries have been removed.
</para>
</listitem>
</itemizedlist>
See the <link
xlink:href="https://nixos.org/nixpkgs/manual/#agda">new
documentation</link> for more information.
</para>
</listitem>
<listitem>
<para>
The <literal>deepin</literal> package set has been removed from
nixpkgs. It was a work in progress to package the
<link xlink:href="https://www.deepin.org/en/dde/">Deepin Desktop Environment (DDE)</link>,
including libraries, tools and applications, and it was still
missing a service to lauch the desktop environment. It has shown
to no longer be a feasible goal due to reasons discussed in
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/94870">issue #94870</link>.
The package <literal>netease-cloud-music</literal> has also been
removed, as it depends on libraries from deepin.
</para>
</listitem>
<listitem>
<para>
The <literal>opendkim</literal> module now uses systemd sandboxing features
to limit the exposure of the system towards the opendkim service.
</para>
</listitem>
</itemizedlist>
</section>
</section>

View file

@ -24,11 +24,11 @@
check ? true
, prefix ? []
, lib ? import ../../lib
, extraModules ? let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
in if e == "" then [] else [(import e)]
}:
let extraArgs_ = extraArgs; pkgs_ = pkgs;
extraModules = let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
in if e == "" then [] else [(import e)];
in
let

View file

@ -5,21 +5,32 @@
config
, # The size of the disk, in megabytes.
diskSize
# if "auto" size is calculated based on the contents copied to it and
# additionalSpace is taken into account.
diskSize ? "auto"
# The files and directories to be placed in the target file system.
, # additional disk space to be added to the image if diskSize "auto"
# is used
additionalSpace ? "512M"
, # size of the boot partition, is only used if partitionTableType is
# either "efi" or "hybrid"
bootSize ? "256M"
, # The files and directories to be placed in the target file system.
# This is a list of attribute sets {source, target} where `source'
# is the file system object (regular file or directory) to be
# grafted in the file system at path `target'.
, contents ? []
contents ? []
, # Type of partition table to use; either "legacy", "efi", or "none".
# For "efi" images, the GPT partition table is used and a mandatory ESP
# partition of reasonable size is created in addition to the root partition.
# If `installBootLoader` is true, GRUB will be installed in EFI mode.
# For "legacy", the msdos partition table is used and a single large root
# partition is created. If `installBootLoader` is true, GRUB will be
# installed in legacy mode.
# partition is created.
# For "hybrid", the GPT partition table is used and a mandatory ESP
# partition of reasonable size is created in addition to the root partition.
# Also a legacy MBR will be present.
# For "none", no partition table is created. Enabling `installBootLoader`
# most likely fails as GRUB will probably refuse to install.
partitionTableType ? "legacy"
@ -43,7 +54,7 @@
format ? "raw"
}:
assert partitionTableType == "legacy" || partitionTableType == "efi" || partitionTableType == "none";
assert partitionTableType == "legacy" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none";
# We use -E offset=X below, which is only supported by e2fsprogs
assert partitionTableType != "none" -> fsType == "ext4";
@ -60,11 +71,12 @@ let format' = format; in let
vdi = "vdi";
vpc = "vhd";
raw = "img";
}.${format};
}.${format} or format;
rootPartition = { # switch-case
legacy = "1";
efi = "2";
hybrid = "3";
}.${partitionTableType};
partitionDiskScript = { # switch-case
@ -76,9 +88,18 @@ let format' = format; in let
efi = ''
parted --script $diskImage -- \
mklabel gpt \
mkpart ESP fat32 8MiB 256MiB \
mkpart ESP fat32 8MiB ${bootSize} \
set 1 boot on \
mkpart primary ext4 256MiB -1
mkpart primary ext4 ${bootSize} -1
'';
hybrid = ''
parted --script $diskImage -- \
mklabel gpt \
mkpart ESP fat32 8MiB ${bootSize} \
set 1 boot on \
mkpart no-fs 0 1024KiB \
set 2 bios_grub on \
mkpart primary ext4 ${bootSize} -1
'';
none = "";
}.${partitionTableType};
@ -129,19 +150,6 @@ let format' = format; in let
}
mkdir $out
diskImage=nixos.raw
truncate -s ${toString diskSize}M $diskImage
${partitionDiskScript}
${if partitionTableType != "none" then ''
# Get start & length of the root partition in sectors to $START and $SECTORS.
eval $(partx $diskImage -o START,SECTORS --nr ${rootPartition} --pairs)
mkfs.${fsType} -F -L ${label} $diskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K
'' else ''
mkfs.${fsType} -F -L ${label} $diskImage
''}
root="$PWD/root"
mkdir -p $root
@ -181,10 +189,36 @@ let format' = format; in let
export NIX_STATE_DIR=$TMPDIR/state
nix-store --load-db < ${closureInfo}/registration
chmod 755 "$TMPDIR"
echo "running nixos-install..."
nixos-install --root $root --no-bootloader --no-root-passwd \
--system ${config.system.build.toplevel} --channel ${channelSources} --substituters ""
diskImage=nixos.raw
${if diskSize == "auto" then ''
${if partitionTableType == "efi" || partitionTableType == "hybrid" then ''
additionalSpace=$(( ($(numfmt --from=iec '${additionalSpace}') + $(numfmt --from=iec '${bootSize}')) / 1000 ))
'' else ''
additionalSpace=$(( $(numfmt --from=iec '${additionalSpace}') / 1000 ))
''}
diskSize=$(( $(set -- $(du -d0 $root); echo "$1") + $additionalSpace ))
truncate -s "$diskSize"K $diskImage
'' else ''
truncate -s ${toString diskSize}M $diskImage
''}
${partitionDiskScript}
${if partitionTableType != "none" then ''
# Get start & length of the root partition in sectors to $START and $SECTORS.
eval $(partx $diskImage -o START,SECTORS --nr ${rootPartition} --pairs)
mkfs.${fsType} -F -L ${label} $diskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K
'' else ''
mkfs.${fsType} -F -L ${label} $diskImage
''}
echo "copying staging root to image..."
cptofs -p ${optionalString (partitionTableType != "none") "-P ${rootPartition}"} -t ${fsType} -i $diskImage $root/* /
'';
@ -218,7 +252,7 @@ in pkgs.vmTools.runInLinuxVM (
# Create the ESP and mount it. Unlike e2fsprogs, mkfs.vfat doesn't support an
# '-E offset=X' option, so we can't do this outside the VM.
${optionalString (partitionTableType == "efi") ''
${optionalString (partitionTableType == "efi" || partitionTableType == "hybrid") ''
mkdir -p /mnt/boot
mkfs.vfat -n ESP /dev/vda1
mount /dev/vda1 /mnt/boot

View file

@ -46,7 +46,10 @@ pkgs.stdenv.mkDerivation {
(
GLOBIGNORE=".:.."
shopt -u dotglob
cp -a --reflink=auto ./files/* -t ./rootImage/
for f in ./files/*; do
cp -a --reflink=auto -t ./rootImage/ "$f"
done
)
# Also include a manifest of the closures in a format suitable for nix-store --load-db

View file

@ -1,4 +1,4 @@
{ stdenv, closureInfo, xorriso, syslinux
{ stdenv, closureInfo, xorriso, syslinux, libossp_uuid
, # The file name of the resulting ISO image.
isoName ? "cd.iso"
@ -48,7 +48,7 @@ assert usbBootable -> isohybridMbrImage != "";
stdenv.mkDerivation {
name = isoName;
builder = ./make-iso9660-image.sh;
buildInputs = [ xorriso syslinux zstd ];
buildInputs = [ xorriso syslinux zstd libossp_uuid ];
inherit isoName bootable bootImage compressImage volumeID efiBootImage efiBootable isohybridMbrImage usbBootable;

View file

@ -99,7 +99,12 @@ done
mkdir -p $out/iso
# daed2280-b91e-42c0-aed6-82c825ca41f3 is an arbitrary namespace, to prevent
# independent applications from generating the same UUID for the same value.
# (the chance of that being problematic seem pretty slim here, but that's how
# version-5 UUID's work)
xorriso="xorriso
-boot_image any gpt_disk_guid=$(uuid -v 5 daed2280-b91e-42c0-aed6-82c825ca41f3 $out | tr -d -)
-as mkisofs
-iso-level 3
-volid ${volumeID}
@ -118,15 +123,6 @@ xorriso="xorriso
$xorriso -output $out/iso/$isoName
if test -n "$usbBootable"; then
echo "Making image hybrid..."
if test -n "$efiBootable"; then
isohybrid --uefi $out/iso/$isoName
else
isohybrid $out/iso/$isoName
fi
fi
if test -n "$compressImage"; then
echo "Compressing image..."
zstd -T$NIX_BUILD_CORES --rm $out/iso/$isoName

View file

@ -36,7 +36,7 @@ let
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages; }
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
);
# Generate DocBook documentation for a list of packages. This is
@ -48,7 +48,7 @@ let
# - a list: that will be interpreted as an attribute path from `pkgs`,
# - an attrset: that can specify `name`, `path`, `package`, `comment`
# (either of `name`, `path` is required, the rest are optional).
genRelatedPackages = packages:
genRelatedPackages = packages: optName:
let
unpack = p: if lib.isString p then { name = p; }
else if lib.isList p then { path = p; }
@ -58,7 +58,7 @@ let
title = args.title or null;
name = args.name or (lib.concatStringsSep "." args.path);
path = args.path or [ args.name ];
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}' found while evaluating `relatedPackages' of option `${optName}'") pkgs);
in "<listitem>"
+ "<para><literal>${lib.optionalString (title != null) "${title} aka "}pkgs.${name} (${package.meta.name})</literal>"
+ lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"

View file

@ -20,7 +20,7 @@
<title>Configuration Options</title>
<variablelist xml:id="configuration-variable-list">
<xsl:for-each select="attrs">
<xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '&lt;', '_'), '>', '_'), '?', '_'))" />
<xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '&lt;', '_'), '>', '_'))" />
<varlistentry>
<term xlink:href="#{$id}">
<xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute>

View file

@ -2,13 +2,18 @@
{ pkgs }:
let
zeroPad = n: if n < 10 then "0${toString n}" else toString n;
zeroPad = n:
pkgs.lib.optionalString (n < 16) "0" +
(if n > 255
then throw "Can't have more than 255 nets or nodes!"
else pkgs.lib.toHexString n);
in
{
rec {
qemuNicMac = net: machine: "52:54:00:12:${zeroPad net}:${zeroPad machine}";
qemuNICFlags = nic: net: machine:
[ "-device virtio-net-pci,netdev=vlan${toString nic},mac=52:54:00:12:${zeroPad net}:${zeroPad machine}"
[ "-device virtio-net-pci,netdev=vlan${toString nic},mac=${qemuNicMac net machine}"
"-netdev vde,id=vlan${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}"
];
@ -17,9 +22,9 @@ in
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'";
qemuBinary = qemuPkg: {
x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu host";
x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max";
armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu host";
x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max";
}.${pkgs.stdenv.hostPlatform.system} or "${qemuPkg}/bin/qemu-kvm";
}

View file

@ -1,75 +0,0 @@
package Logger;
use strict;
use Thread::Queue;
use XML::Writer;
use Encode qw(decode encode);
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
sub new {
my ($class) = @_;
my $logFile = defined $ENV{LOGFILE} ? "$ENV{LOGFILE}" : "/dev/null";
my $log = new XML::Writer(OUTPUT => new IO::File(">$logFile"));
my $self = {
log => $log,
logQueue => Thread::Queue->new()
};
$self->{log}->startTag("logfile");
bless $self, $class;
return $self;
}
sub close {
my ($self) = @_;
$self->{log}->endTag("logfile");
$self->{log}->end;
}
sub drainLogQueue {
my ($self) = @_;
while (defined (my $item = $self->{logQueue}->dequeue_nb())) {
$self->{log}->dataElement("line", sanitise($item->{msg}), 'machine' => $item->{machine}, 'type' => 'serial');
}
}
sub maybePrefix {
my ($msg, $attrs) = @_;
$msg = $attrs->{machine} . ": " . $msg if defined $attrs->{machine};
return $msg;
}
sub nest {
my ($self, $msg, $coderef, $attrs) = @_;
print STDERR maybePrefix("$msg\n", $attrs);
$self->{log}->startTag("nest");
$self->{log}->dataElement("head", $msg, %{$attrs});
my $now = clock_gettime(CLOCK_MONOTONIC);
$self->drainLogQueue();
eval { &$coderef };
my $res = $@;
$self->drainLogQueue();
$self->log(sprintf("(%.2f seconds)", clock_gettime(CLOCK_MONOTONIC) - $now));
$self->{log}->endTag("nest");
die $@ if $@;
}
sub sanitise {
my ($s) = @_;
$s =~ s/[[:cntrl:]\xff]//g;
$s = decode('UTF-8', $s, Encode::FB_DEFAULT);
return encode('UTF-8', $s, Encode::FB_CROAK);
}
sub log {
my ($self, $msg, $attrs) = @_;
chomp $msg;
print STDERR maybePrefix("$msg\n", $attrs);
$self->drainLogQueue();
$self->{log}->dataElement("line", $msg, %{$attrs});
}
1;

View file

@ -1,734 +0,0 @@
package Machine;
use strict;
use threads;
use Socket;
use IO::Handle;
use POSIX qw(dup2);
use FileHandle;
use Cwd;
use File::Basename;
use File::Path qw(make_path);
use File::Slurp;
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
my $showGraphics = defined $ENV{'DISPLAY'};
my $sharedDir;
sub new {
my ($class, $args) = @_;
my $startCommand = $args->{startCommand};
my $name = $args->{name};
if (!$name) {
$startCommand =~ /run-(.*)-vm$/ if defined $startCommand;
$name = $1 || "machine";
}
if (!$startCommand) {
# !!! merge with qemu-vm.nix.
my $netBackend = "-netdev user,id=net0";
my $netFrontend = "-device virtio-net-pci,netdev=net0";
$netBackend .= "," . $args->{netBackendArgs}
if defined $args->{netBackendArgs};
$netFrontend .= "," . $args->{netFrontendArgs}
if defined $args->{netFrontendArgs};
$startCommand =
"qemu-kvm -m 384 $netBackend $netFrontend \$QEMU_OPTS ";
if (defined $args->{hda}) {
if ($args->{hdaInterface} eq "scsi") {
$startCommand .= "-drive id=hda,file="
. Cwd::abs_path($args->{hda})
. ",werror=report,if=none "
. "-device scsi-hd,drive=hda ";
} else {
$startCommand .= "-drive file=" . Cwd::abs_path($args->{hda})
. ",if=" . $args->{hdaInterface}
. ",werror=report ";
}
}
$startCommand .= "-cdrom $args->{cdrom} "
if defined $args->{cdrom};
$startCommand .= "-device piix3-usb-uhci -drive id=usbdisk,file=$args->{usb},if=none,readonly -device usb-storage,drive=usbdisk "
if defined $args->{usb};
$startCommand .= "-bios $args->{bios} "
if defined $args->{bios};
$startCommand .= $args->{qemuFlags} || "";
}
my $tmpDir = $ENV{'TMPDIR'} || "/tmp";
unless (defined $sharedDir) {
$sharedDir = $tmpDir . "/xchg-shared";
make_path($sharedDir, { mode => 0700, owner => $< });
}
my $allowReboot = 0;
$allowReboot = $args->{allowReboot} if defined $args->{allowReboot};
my $self = {
startCommand => $startCommand,
name => $name,
allowReboot => $allowReboot,
booted => 0,
pid => 0,
connected => 0,
socket => undef,
stateDir => "$tmpDir/vm-state-$name",
monitor => undef,
log => $args->{log},
redirectSerial => $args->{redirectSerial} // 1,
};
mkdir $self->{stateDir}, 0700;
bless $self, $class;
return $self;
}
sub log {
my ($self, $msg) = @_;
$self->{log}->log($msg, { machine => $self->{name} });
}
sub nest {
my ($self, $msg, $coderef, $attrs) = @_;
$self->{log}->nest($msg, $coderef, { %{$attrs || {}}, machine => $self->{name} });
}
sub name {
my ($self) = @_;
return $self->{name};
}
sub stateDir {
my ($self) = @_;
return $self->{stateDir};
}
sub start {
my ($self) = @_;
return if $self->{booted};
$self->log("starting vm");
# Create a socket pair for the serial line input/output of the VM.
my ($serialP, $serialC);
socketpair($serialP, $serialC, PF_UNIX, SOCK_STREAM, 0) or die;
# Create a Unix domain socket to which QEMU's monitor will connect.
my $monitorPath = $self->{stateDir} . "/monitor";
unlink $monitorPath;
my $monitorS;
socket($monitorS, PF_UNIX, SOCK_STREAM, 0) or die;
bind($monitorS, sockaddr_un($monitorPath)) or die "cannot bind monitor socket: $!";
listen($monitorS, 1) or die;
# Create a Unix domain socket to which the root shell in the guest will connect.
my $shellPath = $self->{stateDir} . "/shell";
unlink $shellPath;
my $shellS;
socket($shellS, PF_UNIX, SOCK_STREAM, 0) or die;
bind($shellS, sockaddr_un($shellPath)) or die "cannot bind shell socket: $!";
listen($shellS, 1) or die;
# Start the VM.
my $pid = fork();
die if $pid == -1;
if ($pid == 0) {
close $serialP;
close $monitorS;
close $shellS;
if ($self->{redirectSerial}) {
open NUL, "</dev/null" or die;
dup2(fileno(NUL), fileno(STDIN));
dup2(fileno($serialC), fileno(STDOUT));
dup2(fileno($serialC), fileno(STDERR));
}
$ENV{TMPDIR} = $self->{stateDir};
$ENV{SHARED_DIR} = $sharedDir;
$ENV{USE_TMPDIR} = 1;
$ENV{QEMU_OPTS} =
($self->{allowReboot} ? "" : "-no-reboot ") .
"-monitor unix:./monitor -chardev socket,id=shell,path=./shell " .
"-device virtio-serial -device virtconsole,chardev=shell " .
"-device virtio-rng-pci " .
($showGraphics ? "-serial stdio" : "-nographic") . " " . ($ENV{QEMU_OPTS} || "");
chdir $self->{stateDir} or die;
exec $self->{startCommand};
die "running VM script: $!";
}
# Process serial line output.
close $serialC;
threads->create(\&processSerialOutput, $self, $serialP)->detach;
sub processSerialOutput {
my ($self, $serialP) = @_;
while (<$serialP>) {
chomp;
s/\r$//;
print STDERR $self->{name}, "# $_\n";
$self->{log}->{logQueue}->enqueue({msg => $_, machine => $self->{name}}); # !!!
}
}
eval {
local $SIG{CHLD} = sub { die "QEMU died prematurely\n"; };
# Wait until QEMU connects to the monitor.
accept($self->{monitor}, $monitorS) or die;
# Wait until QEMU connects to the root shell socket. QEMU
# does so immediately; this doesn't mean that the root shell
# has connected yet inside the guest.
accept($self->{socket}, $shellS) or die;
$self->{socket}->autoflush(1);
};
die "$@" if $@;
$self->waitForMonitorPrompt;
$self->log("QEMU running (pid $pid)");
$self->{pid} = $pid;
$self->{booted} = 1;
}
# Send a command to the monitor and wait for it to finish. TODO: QEMU
# also has a JSON-based monitor interface now, but it doesn't support
# all commands yet. We should use it once it does.
sub sendMonitorCommand {
my ($self, $command) = @_;
$self->log("sending monitor command: $command");
syswrite $self->{monitor}, "$command\n";
return $self->waitForMonitorPrompt;
}
# Wait until the monitor sends "(qemu) ".
sub waitForMonitorPrompt {
my ($self) = @_;
my $res = "";
my $s;
while (sysread($self->{monitor}, $s, 1024)) {
$res .= $s;
last if $res =~ s/\(qemu\) $//;
}
return $res;
}
# Call the given code reference repeatedly, with 1 second intervals,
# until it returns 1 or a timeout is reached.
sub retry {
my ($coderef) = @_;
my $n;
for ($n = 899; $n >=0; $n--) {
return if &$coderef($n);
sleep 1;
}
die "action timed out after $n seconds";
}
sub connect {
my ($self) = @_;
return if $self->{connected};
$self->nest("waiting for the VM to finish booting", sub {
$self->start;
my $now = clock_gettime(CLOCK_MONOTONIC);
local $SIG{ALRM} = sub { die "timed out waiting for the VM to connect\n"; };
alarm 600;
readline $self->{socket} or die "the VM quit before connecting\n";
alarm 0;
$self->log("connected to guest root shell");
# We're interested in tracking how close we are to `alarm`.
$self->log(sprintf("(connecting took %.2f seconds)", clock_gettime(CLOCK_MONOTONIC) - $now));
$self->{connected} = 1;
});
}
sub waitForShutdown {
my ($self) = @_;
return unless $self->{booted};
$self->nest("waiting for the VM to power off", sub {
waitpid $self->{pid}, 0;
$self->{pid} = 0;
$self->{booted} = 0;
$self->{connected} = 0;
});
}
sub isUp {
my ($self) = @_;
return $self->{booted} && $self->{connected};
}
sub execute_ {
my ($self, $command) = @_;
$self->connect;
print { $self->{socket} } ("( $command ); echo '|!=EOF' \$?\n");
my $out = "";
while (1) {
my $line = readline($self->{socket});
die "connection to VM lost unexpectedly" unless defined $line;
#$self->log("got line: $line");
if ($line =~ /^(.*)\|\!\=EOF\s+(\d+)$/) {
$out .= $1;
$self->log("exit status $2");
return ($2, $out);
}
$out .= $line;
}
}
sub execute {
my ($self, $command) = @_;
my @res;
$self->nest("running command: $command", sub {
@res = $self->execute_($command);
});
return @res;
}
sub succeed {
my ($self, @commands) = @_;
my $res;
foreach my $command (@commands) {
$self->nest("must succeed: $command", sub {
my ($status, $out) = $self->execute_($command);
if ($status != 0) {
$self->log("output: $out");
die "command `$command' did not succeed (exit code $status)\n";
}
$res .= $out;
});
}
return $res;
}
sub mustSucceed {
succeed @_;
}
sub waitUntilSucceeds {
my ($self, $command) = @_;
$self->nest("waiting for success: $command", sub {
retry sub {
my ($status, $out) = $self->execute($command);
return 1 if $status == 0;
};
});
}
sub waitUntilFails {
my ($self, $command) = @_;
$self->nest("waiting for failure: $command", sub {
retry sub {
my ($status, $out) = $self->execute($command);
return 1 if $status != 0;
};
});
}
sub fail {
my ($self, $command) = @_;
$self->nest("must fail: $command", sub {
my ($status, $out) = $self->execute_($command);
die "command `$command' unexpectedly succeeded"
if $status == 0;
});
}
sub mustFail {
fail @_;
}
sub getUnitInfo {
my ($self, $unit, $user) = @_;
my ($status, $lines) = $self->systemctl("--no-pager show \"$unit\"", $user);
return undef if $status != 0;
my $info = {};
foreach my $line (split '\n', $lines) {
$line =~ /^([^=]+)=(.*)$/ or next;
$info->{$1} = $2;
}
return $info;
}
sub systemctl {
my ($self, $q, $user) = @_;
if ($user) {
$q =~ s/'/\\'/g;
return $self->execute("su -l $user -c \$'XDG_RUNTIME_DIR=/run/user/`id -u` systemctl --user $q'");
}
return $self->execute("systemctl $q");
}
# Fail if the given systemd unit is not in the "active" state.
sub requireActiveUnit {
my ($self, $unit) = @_;
$self->nest("checking if unit $unit has reached state 'active'", sub {
my $info = $self->getUnitInfo($unit);
my $state = $info->{ActiveState};
if ($state ne "active") {
die "Expected unit $unit to to be in state 'active' but it is in state $state\n";
};
});
}
# Wait for a systemd unit to reach the "active" state.
sub waitForUnit {
my ($self, $unit, $user) = @_;
$self->nest("waiting for unit $unit", sub {
retry sub {
my $info = $self->getUnitInfo($unit, $user);
my $state = $info->{ActiveState};
die "unit $unit reached state $state\n" if $state eq "failed";
if ($state eq "inactive") {
# If there are no pending jobs, then assume this unit
# will never reach active state.
my ($status, $jobs) = $self->systemctl("list-jobs --full 2>&1", $user);
if ($jobs =~ /No jobs/) { # FIXME: fragile
# Handle the case where the unit may have started
# between the previous getUnitInfo() and
# list-jobs.
my $info2 = $self->getUnitInfo($unit);
die "unit $unit is inactive and there are no pending jobs\n"
if $info2->{ActiveState} eq $state;
}
}
return 1 if $state eq "active";
};
});
}
sub waitForJob {
my ($self, $jobName) = @_;
return $self->waitForUnit($jobName);
}
# Wait until the specified file exists.
sub waitForFile {
my ($self, $fileName) = @_;
$self->nest("waiting for file $fileName", sub {
retry sub {
my ($status, $out) = $self->execute("test -e $fileName");
return 1 if $status == 0;
}
});
}
sub startJob {
my ($self, $jobName, $user) = @_;
$self->systemctl("start $jobName", $user);
# FIXME: check result
}
sub stopJob {
my ($self, $jobName, $user) = @_;
$self->systemctl("stop $jobName", $user);
}
# Wait until the machine is listening on the given TCP port.
sub waitForOpenPort {
my ($self, $port) = @_;
$self->nest("waiting for TCP port $port", sub {
retry sub {
my ($status, $out) = $self->execute("nc -z localhost $port");
return 1 if $status == 0;
}
});
}
# Wait until the machine is not listening on the given TCP port.
sub waitForClosedPort {
my ($self, $port) = @_;
retry sub {
my ($status, $out) = $self->execute("nc -z localhost $port");
return 1 if $status != 0;
}
}
sub shutdown {
my ($self) = @_;
return unless $self->{booted};
print { $self->{socket} } ("poweroff\n");
$self->waitForShutdown;
}
sub crash {
my ($self) = @_;
return unless $self->{booted};
$self->log("forced crash");
$self->sendMonitorCommand("quit");
$self->waitForShutdown;
}
# Make the machine unreachable by shutting down eth1 (the multicast
# interface used to talk to the other VMs). We keep eth0 up so that
# the test driver can continue to talk to the machine.
sub block {
my ($self) = @_;
$self->sendMonitorCommand("set_link virtio-net-pci.1 off");
}
# Make the machine reachable.
sub unblock {
my ($self) = @_;
$self->sendMonitorCommand("set_link virtio-net-pci.1 on");
}
# Take a screenshot of the X server on :0.0.
sub screenshot {
my ($self, $filename) = @_;
my $dir = $ENV{'out'} || Cwd::abs_path(".");
$filename = "$dir/${filename}.png" if $filename =~ /^\w+$/;
my $tmp = "${filename}.ppm";
my $name = basename($filename);
$self->nest("making screenshot $name", sub {
$self->sendMonitorCommand("screendump $tmp");
system("pnmtopng $tmp > ${filename}") == 0
or die "cannot convert screenshot";
unlink $tmp;
}, { image => $name } );
}
# Get the text of TTY<n>
sub getTTYText {
my ($self, $tty) = @_;
my ($status, $out) = $self->execute("fold -w\$(stty -F /dev/tty${tty} size | awk '{print \$2}') /dev/vcs${tty}");
return $out;
}
# Wait until TTY<n>'s text matches a particular regular expression
sub waitUntilTTYMatches {
my ($self, $tty, $regexp) = @_;
$self->nest("waiting for $regexp to appear on tty $tty", sub {
retry sub {
my ($retries_remaining) = @_;
if ($retries_remaining == 0) {
$self->log("Last chance to match /$regexp/ on TTY$tty, which currently contains:");
$self->log($self->getTTYText($tty));
}
return 1 if $self->getTTYText($tty) =~ /$regexp/;
}
});
}
# Debugging: Dump the contents of the TTY<n>
sub dumpTTYContents {
my ($self, $tty) = @_;
$self->execute("fold -w 80 /dev/vcs${tty} | systemd-cat");
}
# Take a screenshot and return the result as text using optical character
# recognition.
sub getScreenText {
my ($self) = @_;
system("command -v tesseract &> /dev/null") == 0
or die "getScreenText used but enableOCR is false";
my $text;
$self->nest("performing optical character recognition", sub {
my $tmpbase = Cwd::abs_path(".")."/ocr";
my $tmpin = $tmpbase."in.ppm";
$self->sendMonitorCommand("screendump $tmpin");
my $magickArgs = "-filter Catrom -density 72 -resample 300 "
. "-contrast -normalize -despeckle -type grayscale "
. "-sharpen 1 -posterize 3 -negate -gamma 100 "
. "-blur 1x65535";
my $tessArgs = "-c debug_file=/dev/null --psm 11 --oem 2";
$text = `convert $magickArgs $tmpin tiff:- | tesseract - - $tessArgs`;
my $status = $? >> 8;
unlink $tmpin;
die "OCR failed with exit code $status" if $status != 0;
});
return $text;
}
# Wait until a specific regexp matches the textual contents of the screen.
sub waitForText {
my ($self, $regexp) = @_;
$self->nest("waiting for $regexp to appear on the screen", sub {
retry sub {
my ($retries_remaining) = @_;
if ($retries_remaining == 0) {
$self->log("Last chance to match /$regexp/ on the screen, which currently contains:");
$self->log($self->getScreenText);
}
return 1 if $self->getScreenText =~ /$regexp/;
}
});
}
# Wait until it is possible to connect to the X server. Note that
# testing the existence of /tmp/.X11-unix/X0 is insufficient.
sub waitForX {
my ($self, $regexp) = @_;
$self->nest("waiting for the X11 server", sub {
retry sub {
my ($status, $out) = $self->execute("journalctl -b SYSLOG_IDENTIFIER=systemd | grep 'Reached target Current graphical'");
return 0 if $status != 0;
($status, $out) = $self->execute("[ -e /tmp/.X11-unix/X0 ]");
return 1 if $status == 0;
}
});
}
sub getWindowNames {
my ($self) = @_;
my $res = $self->mustSucceed(
q{xwininfo -root -tree | sed 's/.*0x[0-9a-f]* \"\([^\"]*\)\".*/\1/; t; d'});
return split /\n/, $res;
}
sub waitForWindow {
my ($self, $regexp) = @_;
$self->nest("waiting for a window to appear", sub {
retry sub {
my @names = $self->getWindowNames;
my ($retries_remaining) = @_;
if ($retries_remaining == 0) {
$self->log("Last chance to match /$regexp/ on the the window list, which currently contains:");
$self->log(join(", ", @names));
}
foreach my $n (@names) {
return 1 if $n =~ /$regexp/;
}
}
});
}
sub copyFileFromHost {
my ($self, $from, $to) = @_;
my $s = `cat $from` or die;
$s =~ s/'/'\\''/g;
$self->mustSucceed("echo '$s' > $to");
}
my %charToKey = (
'A' => "shift-a", 'N' => "shift-n", '-' => "0x0C", '_' => "shift-0x0C", '!' => "shift-0x02",
'B' => "shift-b", 'O' => "shift-o", '=' => "0x0D", '+' => "shift-0x0D", '@' => "shift-0x03",
'C' => "shift-c", 'P' => "shift-p", '[' => "0x1A", '{' => "shift-0x1A", '#' => "shift-0x04",
'D' => "shift-d", 'Q' => "shift-q", ']' => "0x1B", '}' => "shift-0x1B", '$' => "shift-0x05",
'E' => "shift-e", 'R' => "shift-r", ';' => "0x27", ':' => "shift-0x27", '%' => "shift-0x06",
'F' => "shift-f", 'S' => "shift-s", '\'' => "0x28", '"' => "shift-0x28", '^' => "shift-0x07",
'G' => "shift-g", 'T' => "shift-t", '`' => "0x29", '~' => "shift-0x29", '&' => "shift-0x08",
'H' => "shift-h", 'U' => "shift-u", '\\' => "0x2B", '|' => "shift-0x2B", '*' => "shift-0x09",
'I' => "shift-i", 'V' => "shift-v", ',' => "0x33", '<' => "shift-0x33", '(' => "shift-0x0A",
'J' => "shift-j", 'W' => "shift-w", '.' => "0x34", '>' => "shift-0x34", ')' => "shift-0x0B",
'K' => "shift-k", 'X' => "shift-x", '/' => "0x35", '?' => "shift-0x35",
'L' => "shift-l", 'Y' => "shift-y", ' ' => "spc",
'M' => "shift-m", 'Z' => "shift-z", "\n" => "ret",
);
sub sendKeys {
my ($self, @keys) = @_;
foreach my $key (@keys) {
$key = $charToKey{$key} if exists $charToKey{$key};
$self->sendMonitorCommand("sendkey $key");
}
}
sub sendChars {
my ($self, $chars) = @_;
$self->nest("sending keys $chars", sub {
$self->sendKeys(split //, $chars);
});
}
# Sleep N seconds (in virtual guest time, not real time).
sub sleep {
my ($self, $time) = @_;
$self->succeed("sleep $time");
}
# Forward a TCP port on the host to a TCP port on the guest. Useful
# during interactive testing.
sub forwardPort {
my ($self, $hostPort, $guestPort) = @_;
$hostPort = 8080 unless defined $hostPort;
$guestPort = 80 unless defined $guestPort;
$self->sendMonitorCommand("hostfwd_add tcp::$hostPort-:$guestPort");
}
1;

View file

@ -1,191 +0,0 @@
#! /somewhere/perl -w
use strict;
use Machine;
use Term::ReadLine;
use IO::File;
use IO::Pty;
use Logger;
use Cwd;
use POSIX qw(_exit dup2);
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
$SIG{PIPE} = 'IGNORE'; # because Unix domain sockets may die unexpectedly
STDERR->autoflush(1);
my $log = new Logger;
# Start vde_switch for each network required by the test.
my %vlans;
foreach my $vlan (split / /, $ENV{VLANS} || "") {
next if defined $vlans{$vlan};
# Start vde_switch as a child process. We don't run it in daemon
# mode because we want the child process to be cleaned up when we
# die. Since we have to make sure that the control socket is
# ready, we send a dummy command to vde_switch (via stdin) and
# wait for a reply. Note that vde_switch requires stdin to be a
# TTY, so we create one.
$log->log("starting VDE switch for network $vlan");
my $socket = Cwd::abs_path "./vde$vlan.ctl";
my $pty = new IO::Pty;
my ($stdoutR, $stdoutW); pipe $stdoutR, $stdoutW;
my $pid = fork(); die "cannot fork" unless defined $pid;
if ($pid == 0) {
dup2(fileno($pty->slave), 0);
dup2(fileno($stdoutW), 1);
exec "vde_switch -s $socket --dirmode 0700" or _exit(1);
}
close $stdoutW;
print $pty "version\n";
readline $stdoutR or die "cannot start vde_switch";
$ENV{"QEMU_VDE_SOCKET_$vlan"} = $socket;
$vlans{$vlan} = $pty;
die unless -e "$socket/ctl";
}
my %vms;
my $context = "";
sub createMachine {
my ($args) = @_;
my $vm = Machine->new({%{$args}, log => $log, redirectSerial => ($ENV{USE_SERIAL} // "0") ne "1"});
$vms{$vm->name} = $vm;
$context .= "my \$" . $vm->name . " = \$vms{'" . $vm->name . "'}; ";
return $vm;
}
foreach my $vmScript (@ARGV) {
my $vm = createMachine({startCommand => $vmScript});
}
sub startAll {
$log->nest("starting all VMs", sub {
$_->start foreach values %vms;
});
}
# Wait until all VMs have terminated.
sub joinAll {
$log->nest("waiting for all VMs to finish", sub {
$_->waitForShutdown foreach values %vms;
});
}
# In interactive tests, this allows the non-interactive test script to
# be executed conveniently.
sub testScript {
eval "$context $ENV{testScript};\n";
warn $@ if $@;
}
my $nrTests = 0;
my $nrSucceeded = 0;
sub subtest {
my ($name, $coderef) = @_;
$log->nest("subtest: $name", sub {
$nrTests++;
eval { &$coderef };
if ($@) {
$log->log("error: $@", { error => 1 });
} else {
$nrSucceeded++;
}
});
}
sub runTests {
if (defined $ENV{tests}) {
$log->nest("running the VM test script", sub {
eval "$context $ENV{tests}";
if ($@) {
$log->log("error: $@", { error => 1 });
die $@;
}
}, { expanded => 1 });
} else {
my $term = Term::ReadLine->new('nixos-vm-test');
$term->ReadHistory;
while (defined ($_ = $term->readline("> "))) {
eval "$context $_\n";
warn $@ if $@;
}
$term->WriteHistory;
}
# Copy the kernel coverage data for each machine, if the kernel
# has been compiled with coverage instrumentation.
$log->nest("collecting coverage data", sub {
foreach my $vm (values %vms) {
my $gcovDir = "/sys/kernel/debug/gcov";
next unless $vm->isUp();
my ($status, $out) = $vm->execute("test -e $gcovDir");
next if $status != 0;
# Figure out where to put the *.gcda files so that the
# report generator can find the corresponding kernel
# sources.
my $kernelDir = $vm->mustSucceed("echo \$(dirname \$(readlink -f /run/current-system/kernel))/.build/linux-*");
chomp $kernelDir;
my $coverageDir = "/tmp/xchg/coverage-data/$kernelDir";
# Copy all the *.gcda files.
$vm->execute("for d in $gcovDir/nix/store/*/.build/linux-*; do for i in \$(cd \$d && find -name '*.gcda'); do echo \$i; mkdir -p $coverageDir/\$(dirname \$i); cp -v \$d/\$i $coverageDir/\$i; done; done");
}
});
$log->nest("syncing", sub {
foreach my $vm (values %vms) {
next unless $vm->isUp();
$vm->execute("sync");
}
});
if ($nrTests != 0) {
$log->log("$nrSucceeded out of $nrTests tests succeeded",
($nrSucceeded < $nrTests ? { error => 1 } : { }));
}
}
# Create an empty raw virtual disk with the given name and size (in
# MiB).
sub createDisk {
my ($name, $size) = @_;
system("qemu-img create -f raw $name ${size}M") == 0
or die "cannot create image of size $size";
}
END {
$log->nest("cleaning up", sub {
foreach my $vm (values %vms) {
if ($vm->{pid}) {
$log->log("killing " . $vm->{name} . " (pid " . $vm->{pid} . ")");
kill 9, $vm->{pid};
}
}
});
$log->close();
}
my $now1 = clock_gettime(CLOCK_MONOTONIC);
runTests;
my $now2 = clock_gettime(CLOCK_MONOTONIC);
printf STDERR "test script finished in %.2fs\n", $now2 - $now1;
exit ($nrSucceeded < $nrTests ? 1 : 0);

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