push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,277 @@
# Agda {#agda}
## How to use Agda {#how-to-use-agda}
Agda is available as the [agda](https://search.nixos.org/packages?channel=unstable&show=agda&from=0&size=30&sort=relevance&query=agda)
package.
The `agda` package installs an Agda-wrapper, which calls `agda` with `--library-file`
set to a generated library-file within the nix store, this means your library-file in
`$HOME/.agda/libraries` will be ignored. By default the agda package installs Agda
with no libraries, i.e. the generated library-file is empty. To use Agda with libraries,
the `agda.withPackages` function can be used. This function either takes:
* A list of packages,
* or a function which returns a list of packages when given the `agdaPackages` attribute set,
* or an attribute set containing a list of packages and a GHC derivation for compilation (see below).
* or an attribute set containing a function which returns a list of packages when given the `agdaPackages` attribute set and a GHC derivation for compilation (see below).
For example, suppose we wanted a version of Agda which has access to the standard library. This can be obtained with the expressions:
```nix
agda.withPackages [ agdaPackages.standard-library ]
```
or
```nix
agda.withPackages (p: [ p.standard-library ])
```
or can be called as in the [Compiling Agda](#compiling-agda) section.
If you want to use a different version of a library (for instance a development version)
override the `src` attribute of the package to point to your local repository
```nix
agda.withPackages (p: [
(p.standard-library.overrideAttrs (oldAttrs: {
version = "local version";
src = /path/to/local/repo/agda-stdlib;
}))
])
```
You can also reference a GitHub repository
```nix
agda.withPackages (p: [
(p.standard-library.overrideAttrs (oldAttrs: {
version = "1.5";
src = fetchFromGitHub {
repo = "agda-stdlib";
owner = "agda";
rev = "v1.5";
hash = "sha256-nEyxYGSWIDNJqBfGpRDLiOAnlHJKEKAOMnIaqfVZzJk=";
};
}))
])
```
If you want to use a library not added to Nixpkgs, you can add a
dependency to a local library by calling `agdaPackages.mkDerivation`.
```nix
agda.withPackages (p: [
(p.mkDerivation {
pname = "your-agda-lib";
version = "1.0.0";
src = /path/to/your-agda-lib;
})
])
```
Again you can reference GitHub
```nix
agda.withPackages (p: [
(p.mkDerivation {
pname = "your-agda-lib";
version = "1.0.0";
src = fetchFromGitHub {
repo = "repo";
owner = "owner";
version = "...";
rev = "...";
hash = "...";
};
})
])
```
See [Building Agda Packages](#building-agda-packages) for more information on `mkDerivation`.
Agda will not by default use these libraries. To tell Agda to use a library we have some options:
* Call `agda` with the library flag:
```ShellSession
$ agda -l standard-library -i . MyFile.agda
```
* Write a `my-library.agda-lib` file for the project you are working on which may look like:
```
name: my-library
include: .
depend: standard-library
```
* Create the file `~/.agda/defaults` and add any libraries you want to use by default.
More information can be found in the [official Agda documentation on library management](https://agda.readthedocs.io/en/v2.6.1/tools/package-system.html).
## Compiling Agda {#compiling-agda}
Agda modules can be compiled using the GHC backend with the `--compile` flag. A version of `ghc` with `ieee754` is made available to the Agda program via the `--with-compiler` flag.
This can be overridden by a different version of `ghc` as follows:
```nix
agda.withPackages {
pkgs = [
# ...
];
ghc = haskell.compiler.ghcHEAD;
}
```
To install Agda without GHC, use `ghc = null;`.
## Writing Agda packages {#writing-agda-packages}
To write a nix derivation for an Agda library, first check that the library has a (single) `*.agda-lib` file.
A derivation can then be written using `agdaPackages.mkDerivation`. This has similar arguments to `stdenv.mkDerivation` with the following additions:
* `libraryName` should be the name that appears in the `*.agda-lib` file, defaulting to `pname`.
* `libraryFile` should be the file name of the `*.agda-lib` file, defaulting to `${libraryName}.agda-lib`.
Here is an example `default.nix`
```nix
{
nixpkgs ? <nixpkgs>,
}:
with (import nixpkgs { });
agdaPackages.mkDerivation {
version = "1.0";
pname = "my-agda-lib";
src = ./.;
buildInputs = [ agdaPackages.standard-library ];
}
```
### Building Agda packages {#building-agda-packages}
The default build phase for `agdaPackages.mkDerivation` runs `agda --build-library`.
If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden.
Additionally, a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the library.
`agda` and the Agda libraries contained in `buildInputs` are made available during the build phase.
### Installing Agda packages {#installing-agda-packages}
The default install phase copies Agda source files, Agda interface files (`*.agdai`) and `*.agda-lib` files to the output directory.
This can be overridden.
By default, Agda sources are files ending on `.agda`, or literate Agda files ending on `.lagda`, `.lagda.tex`, `.lagda.org`, `.lagda.md`, `.lagda.rst`. The list of recognised Agda source extensions can be extended by setting the `extraExtensions` config variable.
## Maintaining the Agda package set on Nixpkgs {#maintaining-the-agda-package-set-on-nixpkgs}
We are aiming at providing all common Agda libraries as packages on `nixpkgs`,
and keeping them up to date.
Contributions and maintenance help is always appreciated,
but the maintenance effort is typically low since the Agda ecosystem is quite small.
The `nixpkgs` Agda package set tries to take up a role similar to that of [Stackage](https://www.stackage.org/) in the Haskell world.
It is a curated set of libraries that:
1. Always work together.
2. Are as up-to-date as possible.
While the Haskell ecosystem is huge, and Stackage is highly automated,
the Agda package set is small and can (still) be maintained by hand.
### Adding Agda packages to Nixpkgs {#adding-agda-packages-to-nixpkgs}
To add an Agda package to `nixpkgs`, the derivation should be written to `pkgs/development/libraries/agda/${library-name}/default.nix` and an entry should be added to `pkgs/top-level/agda-packages.nix`. Here it is called in a scope with access to all other Agda libraries, so the derivation could look like:
```nix
{
mkDerivation,
standard-library,
fetchFromGitHub,
}:
mkDerivation {
pname = "my-library";
version = "1.0";
src = <...>;
buildInputs = [ standard-library ];
meta = <...>;
}
```
You can look at other files under `pkgs/development/libraries/agda/` for more inspiration.
Note that the derivation function is called with `mkDerivation` set to `agdaPackages.mkDerivation`, therefore you
could use a similar set as in your `default.nix` from [Writing Agda Packages](#writing-agda-packages) with
`agdaPackages.mkDerivation` replaced with `mkDerivation`.
Here is an example skeleton derivation for iowa-stdlib:
```nix
mkDerivation {
version = "1.5.0";
pname = "iowa-stdlib";
src = <...>;
libraryFile = "";
libraryName = "IAL-1.3";
buildPhase = ''
runHook preBuild
patchShebangs find-deps.sh
make
runHook postBuild
'';
}
```
This library has a file called `.agda-lib`, and so we give an empty string to `libraryFile` as nothing precedes `.agda-lib` in the filename. This file contains `name: IAL-1.3`, and so we let `libraryName = "IAL-1.3"`. This library does not use an `Everything.agda` file and instead has a Makefile, so there is no need to set `everythingFile` and we set a custom `buildPhase`.
When writing an Agda package, it is essential to make sure that no `.agda-lib` file gets added to the store as a single file (for example by using `writeText`). This causes Agda to think that the nix store is a Agda library and it will attempt to write to it whenever it typechecks something. See [https://github.com/agda/agda/issues/4613](https://githcub.com/agda/agda/issues/4613).
In the pull request adding this library,
you can test whether it builds correctly by writing in a comment:
```
@ofborg build agdaPackages.my-library
```
### Maintaining Agda packages {#agda-maintaining-packages}
As mentioned before, the aim is to have a compatible, and up-to-date package set.
These two conditions sometimes exclude each other:
For example, if we update `agdaPackages.standard-library` because there was an upstream release,
this will typically break many reverse dependencies,
i.e. downstream Agda libraries that depend on the standard library.
In `nixpkgs` we are typically among the first to notice this,
since we have build tests in place to check this.
In a pull request updating e.g. the standard library, you should write the following comment:
```
@ofborg build agdaPackages.standard-library.passthru.tests
```
This will build all reverse dependencies of the standard library,
for example `agdaPackages.agda-categories`, or `agdaPackages.generic`.
In some cases it is useful to build _all_ Agda packages.
This can be done with the following Github comment:
```
@ofborg build agda.passthru.tests.allPackages
```
Sometimes, the builds of the reverse dependencies fail because they have not yet been updated and released.
You should drop the maintainers a quick issue notifying them of the breakage,
citing the build error (which you can get from the ofborg logs).
If you are motivated, you might even send a pull request that fixes it.
Usually, the maintainers will answer within a week or two with a new release.
Bumping the version of that reverse dependency should be a further commit on your PR.
In the rare case that a new release is not to be expected within an acceptable time,
mark the broken package as broken by setting `meta.broken = true;`.
This will exclude it from the build test.
It can be added later when it is fixed,
and does not hinder the advancement of the whole package set in the meantime.

View File

@@ -0,0 +1,384 @@
# Android {#android}
The Android build environment provides three major features and a number of
supporting features.
## Using androidenv with Android Studio {#using-androidenv-with-android-studio}
Use the `android-studio-full` attribute for a very complete Android SDK, including system images:
```nix
{ buildInputs = [ android-studio-full ]; }
```
This is identical to:
```nix
{ buildInputs = [ androidStudioPackages.stable.full ]; }
```
Alternatively, you can pass composeAndroidPackages to the `withSdk` passthrough:
```nix
{
buildInputs = [
(android-studio.withSdk (androidenv.composeAndroidPackages { includeNDK = true; }).androidsdk)
];
}
```
These will export `ANDROID_SDK_ROOT` and `ANDROID_NDK_ROOT` to the SDK and NDK directories
in the specified Android build environment.
## Deploying an Android SDK installation with plugins {#deploying-an-android-sdk-installation-with-plugins}
Alternatively, you can deploy the SDK separately with a desired set of plugins, or subsets of an SDK.
```nix
with import <nixpkgs> { };
let
androidComposition = androidenv.composeAndroidPackages {
platformVersions = [
"34"
"35"
"latest"
];
systemImageTypes = [ "google_apis_playstore" ];
abiVersions = [
"armeabi-v7a"
"arm64-v8a"
];
includeNDK = true;
includeExtras = [ "extras;google;auto" ];
};
in
androidComposition.androidsdk
```
The above function invocation states that we want an Android SDK with the above
specified plugin versions. By default, most plugins are disabled. Notable
exceptions are the tools, platform-tools and build-tools sub packages.
The following parameters are supported:
* `cmdLineToolsVersion` specifies the version of the `cmdline-tools` package to use.
It defaults to the latest.
* `toolsVersion`, specifies the version of the `tools` package. Notice `tools` is
obsolete, and currently only `26.1.1` is available, so there's not a lot of
options here, however, you can set it as `null` if you don't want it. It defaults
to the latest.
* `platformToolsVersion` specifies the version of the `platform-tools` plugin.
It defaults to the latest.
* `buildToolsVersions` specifies the versions of the `build-tools` plugins to
use. It defaults to the latest.
* `includeEmulator` specifies whether to deploy the emulator package (`false`
by default). When enabled, the version of the emulator to deploy can be
specified by setting the `emulatorVersion` parameter. If set to
`"if-supported"`, it will deploy the emulator if it's supported by the system.
* `includeCmake` specifies whether CMake should be included. It defaults to true
on x86-64 and Darwin platforms, and also supports `"if-supported"`.
* `cmakeVersions` specifies which CMake versions should be deployed.
It defaults to the latest.
* `includeNDK` specifies that the Android NDK bundle should be included.
Defaults to `false` though can be set to `true` or `"if-supported"`.
* `ndkVersions` specifies the NDK versions that we want to use. These are linked
under the `ndk` directory of the SDK root, and the first is linked under the
`ndk-bundle` directory. It defaults to the latest.
* `ndkVersion` is equivalent to specifying one entry in `ndkVersions`, and
`ndkVersions` overrides this parameter if provided.
* `includeExtras` is an array of identifier strings referring to arbitrary
add-on packages that should be installed. Note that extras may not be compatible
with all platforms (for example, the Google TV head unit, which does not
have an aarch64-linux compile).
* `platformVersions` specifies which platform SDK versions should be included.
It defaults to including only the latest API level, though you can add more.
* `numLatestPlatformVersions` specifies how many of the latest API levels to include,
if you are using the default for `platformVersions`. It defaults to 1, though you can
increase this to, for example, 5 to get the last 5 years of Android API packages.
* `minPlatformVersion` and `maxPlatformVersion` take priority over `platformVersions`
if both are provided. Note that `maxPlatformVersion` always defaults to the latest
Android SDK platform version, allowing you to specify `minPlatformVersion` to describe
the minimum SDK version your Android composition supports.
For each platform version that has been specified, we can apply the following
options:
* `includeSystemImages` specifies whether a system image for each platform SDK
should be included.
* `includeSources` specifies whether the sources for each SDK version should be
included.
* `useGoogleAPIs` specifies that for each selected platform version the
Google API should be included.
* `useGoogleTVAddOns` specifies that for each selected platform version the
Google TV add-on should be included.
For each requested system image we can specify the following options:
* `systemImageTypes` specifies what kind of system images should be included.
Defaults to: `default`.
* `abiVersions` specifies what kind of ABI version of each system image should
be included. Defaults to `armeabi-v7a` and `arm64-v8a`.
Most of the function arguments have reasonable default settings, preferring the latest
versions of tools when possible. You can additionally specify "latest" for any plugin version
that you do not care about, and just want the latest of.
You can specify license names:
* `extraLicenses` is a list of license names.
You can get these names from repo.json or `querypackages.sh licenses`. The SDK
license (`android-sdk-license`) is accepted for you if you set accept_license
to true. If you are doing something like working with preview SDKs, you will
want to add `android-sdk-preview-license` or whichever license applies here.
Additionally, you can override the repositories that composeAndroidPackages will
pull from:
* `repoJson` specifies a path to a generated repo.json file. You can generate this
by running `generate.sh`, which in turn will call into `mkrepo.rb`.
* `repoXmls` is an attribute set containing paths to repo XML files. If specified,
it takes priority over `repoJson`, and will trigger a local build writing out a
repo.json to the Nix store based on the given repository XMLs. Note that this uses
import-from-derivation.
```nix
{
repoXmls = {
packages = [ ./xml/repository2-1.xml ];
images = [
./xml/android-sys-img2-1.xml
./xml/android-tv-sys-img2-1.xml
./xml/android-wear-sys-img2-1.xml
./xml/android-wear-cn-sys-img2-1.xml
./xml/google_apis-sys-img2-1.xml
./xml/google_apis_playstore-sys-img2-1.xml
];
addons = [ ./xml/addon2-1.xml ];
};
}
```
When building the above expression with:
```bash
$ nix-build
```
The Android SDK gets deployed with all desired plugin versions.
We can also deploy subsets of the Android SDK. For example, to only the
`platform-tools` package, you can evaluate the following expression:
```nix
with import <nixpkgs> { };
let
androidComposition = androidenv.composeAndroidPackages {
# ...
};
in
androidComposition.platform-tools
```
## Using predefined Android package compositions {#using-predefined-android-package-compositions}
In addition to composing an Android package set manually, it is also possible
to use a predefined composition that contains a fairly complete set of Android packages:
The following Nix expression can be used to deploy the entire SDK:
```nix
with import <nixpkgs> { };
androidenv.androidPkgs.androidsdk
```
It is also possible to use one plugin only:
```nix
with import <nixpkgs> { };
androidenv.androidPkgs.platform-tools
```
## Spawning emulator instances {#spawning-emulator-instances}
For testing purposes, it can also be quite convenient to automatically generate
scripts that spawn emulator instances with all desired configuration settings.
An emulator spawn script can be configured by invoking the `emulateApp {}`
function:
```nix
with import <nixpkgs> { };
androidenv.emulateApp {
name = "emulate-MyAndroidApp";
platformVersion = "28";
abiVersion = "x86"; # armeabi-v7a, mips, x86_64
systemImageType = "google_apis_playstore";
}
```
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:
```nix
with import <nixpkgs> { };
androidenv.emulateApp {
name = "emulate-MyAndroidApp";
platformVersion = "24";
abiVersion = "armeabi-v7a"; # mips, x86, x86_64
systemImageType = "default";
app = ./MyApp.apk;
package = "MyApp";
activity = "MainActivity";
}
```
In addition to prebuilt APKs, you can also bind the APK parameter to a
`buildApp {}` function invocation shown in the previous example.
## Notes on environment variables in Android projects {#notes-on-environment-variables-in-android-projects}
* `ANDROID_HOME` should point to the Android SDK. In your Nix expressions, this should be
`${androidComposition.androidsdk}/libexec/android-sdk`. Note that `ANDROID_SDK_ROOT` is deprecated,
but if you rely on tools that need it, you can export it too.
* `ANDROID_NDK_ROOT` should point to the Android NDK, if you're doing NDK development.
In your Nix expressions, this should be `${ANDROID_HOME}/ndk-bundle`.
If you are running the Android Gradle plugin, you need to export GRADLE_OPTS to override aapt2
to point to the aapt2 binary in the Nix store as well, or use a FHS environment so the packaged
aapt2 can run. If you don't want to use a FHS environment, something like this should work:
```nix
let
buildToolsVersion = "30.0.3";
# Use buildToolsVersion when you define androidComposition
androidComposition = <...>;
in
pkgs.mkShell rec {
ANDROID_HOME = "${androidComposition.androidsdk}/libexec/android-sdk";
ANDROID_NDK_ROOT = "${ANDROID_HOME}/ndk-bundle";
# Use the same buildToolsVersion here
GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_HOME}/build-tools/${buildToolsVersion}/aapt2";
}
```
If you are using cmake, you need to add it to PATH in a shell hook or FHS env profile.
The path is suffixed with a build number, but properly prefixed with the version.
So, something like this should suffice:
```nix
let
cmakeVersion = "3.10.2";
# Use cmakeVersion when you define androidComposition
androidComposition = <...>;
in
pkgs.mkShell rec {
ANDROID_HOME = "${androidComposition.androidsdk}/libexec/android-sdk";
ANDROID_NDK_ROOT = "${ANDROID_HOME}/ndk-bundle";
# Use the same cmakeVersion here
shellHook = ''
export PATH="$(echo "$ANDROID_HOME/cmake/${cmakeVersion}".*/bin):$PATH"
'';
}
```
Note that running Android Studio with ANDROID_HOME set will automatically write a
`local.properties` file with `sdk.dir` set to $ANDROID_HOME if one does not already
exist. If you are using the NDK as well, you may have to add `ndk.dir` to this file.
An example `shell.nix` that does all this for you is provided in `examples/shell.nix`.
This shell.nix includes a shell hook that overwrites local.properties with the correct
sdk.dir and ndk.dir values. This will ensure that the SDK and NDK directories will
both be correct when you run Android Studio inside nix-shell.
## Notes on improving build.gradle compatibility {#notes-on-improving-build.gradle-compatibility}
Ensure that your buildToolsVersion and ndkVersion match what is declared in androidenv.
If you are using cmake, make sure its declared version is correct too.
Otherwise, you may get cryptic errors from aapt2 and the Android Gradle plugin warning
that it cannot install the build tools because the SDK directory is not writeable.
```gradle
android {
buildToolsVersion "30.0.3"
ndkVersion = "22.0.7026061"
externalNativeBuild {
cmake {
version "3.10.2"
}
}
}
```
## Querying the available versions of each plugin {#querying-the-available-versions-of-each-plugin}
All androidenv packages are available on [search.nixos.org](https://search.nixos.org).
Note that `aarch64-linux` compatibility is currently spotty, though `x86_64-linux` and `aarch64-darwin`
are well supported. This is because Google's repository definitions mark some packages for "all" architectures
that are really only for `x86_64` or `aarch64`.
## Updating the generated expressions {#updating-the-generated-expressions}
repo.json is generated from XML files that the Android Studio package manager uses.
To update the expressions run the `update.sh` script that is stored in the
`pkgs/development/mobile/androidenv/` subdirectory:
```bash
./update.sh
```
This is run automatically by the nixpkgs update script.
## Building an Android application with Ant {#building-an-android-application-with-ant}
In addition to the SDK, it is also possible to build an Ant-based Android
project and automatically deploy all the Android plugins that a project
requires. Most newer Android projects use Gradle, and this is included for historical
purposes.
```nix
with import <nixpkgs> { };
androidenv.buildApp {
name = "MyAndroidApp";
src = ./myappsources;
release = true;
# If release is set to true, you need to specify the following parameters
keyStore = ./keystore;
keyAlias = "myfirstapp";
keyStorePassword = "mykeystore";
keyAliasPassword = "myfirstapp";
# Any Android SDK parameters that install all the relevant plugins that a
# build requires
platformVersions = [ "24" ];
# When we include the NDK, then ndk-build is invoked before Ant gets invoked
includeNDK = true;
}
```
Aside from the app-specific build parameters (`name`, `src`, `release` and
keystore parameters), the `buildApp {}` function supports all the function
parameters that the SDK composition function (the function shown in the
previous section) supports.
This build function is particularly useful when it is desired to use
[Hydra](https://nixos.org/hydra): the Nix-based continuous integration solution
to build Android apps. An Android APK gets exposed as a build product and can be
installed on any Android device with a web browser by navigating to the build
result page.

View File

@@ -0,0 +1,43 @@
# Astal {#astal}
Astal is a collection of building blocks for creating custom desktop shells.
## Bundling {#astal-bundling}
Bundling an Astal application is done using the `ags` tool. You can use it like this:
```nix
ags.bundle {
pname = "hyprpanel";
version = "1.0.0";
src = fetchFromGitHub {
#...
};
# change your entry file (default is `app.ts`)
entry = "app.ts";
dependencies = [
# list here astal modules that your package depends on
# `astal3`, `astal4` and `astal.io` are automatically included
astal.apps
astal.battery
astal.bluetooth
# you can also list here other runtime dependencies
hypridle
hyprpicker
hyprsunset
];
# GTK 4 support is opt-in
enableGtk4 = true;
meta = {
#...
};
}
```
You can also pass all other arguments that are supported by `stdenv.mkDerivation`.

View File

@@ -0,0 +1,415 @@
# BEAM Languages (Erlang, Elixir & LFE) {#sec-beam}
## Introduction {#beam-introduction}
In this document and related Nix expressions, we use the term, _BEAM_, to describe the environment. BEAM is the name of the Erlang Virtual Machine and, as far as we're concerned, from a packaging perspective, all languages that run on the BEAM are interchangeable. That which varies, like the build system, is transparent to users of any given BEAM package, so we make no distinction.
## Available versions and deprecations schedule {#available-versions-and-deprecations-schedule}
### Elixir {#elixir}
Nixpkgs follows the [official elixir deprecation schedule](https://hexdocs.pm/elixir/compatibility-and-deprecations.html) and keeps the last 5 released versions of Elixir available.
## Structure {#beam-structure}
All BEAM-related expressions are available via the top-level `beam` attribute, which includes:
- `interpreters`: a set of compilers running on the BEAM, including multiple Erlang/OTP versions (`beam.interpreters.erlang_22`, etc), Elixir (`beam.interpreters.elixir`) and LFE (Lisp Flavoured Erlang) (`beam.interpreters.lfe`).
- `packages`: a set of package builders (Mix and rebar3), each compiled with a specific Erlang/OTP version, e.g. `beam.packages.erlang22`.
The default Erlang compiler, defined by `beam.interpreters.erlang`, is aliased as `erlang`. The default BEAM package set is defined by `beam.packages.erlang` and aliased at the top level as `beamPackages`.
To create a package builder built with a custom Erlang version, use the lambda, `beam.packagesWith`, which accepts an Erlang/OTP derivation and produces a package builder similar to `beam.packages.erlang`.
Many Erlang/OTP distributions available in `beam.interpreters` have versions with ODBC and/or Java enabled or without wx (no observer support). For example, there's `beam.interpreters.erlang_22_odbc_javac`, which corresponds to `beam.interpreters.erlang_22` and `beam.interpreters.erlang_22_nox`, which corresponds to `beam.interpreters.erlang_22`.
## Build Tools {#build-tools}
### Rebar3 {#build-tools-rebar3}
We provide a version of Rebar3, under `rebar3`. We also provide a helper to fetch Rebar3 dependencies from a lockfile under `fetchRebar3Deps`.
We also provide a version on Rebar3 with plugins included, under `rebar3WithPlugins`. This package is a function which takes two arguments: `plugins`, a list of nix derivations to include as plugins (loaded only when specified in `rebar.config`), and `globalPlugins`, which should always be loaded by rebar3. Example: `rebar3WithPlugins { globalPlugins = [beamPackages.pc]; }`.
When adding a new plugin it is important that the `packageName` attribute is the same as the atom used by rebar3 to refer to the plugin.
### Mix & Erlang.mk {#build-tools-other}
Erlang.mk works exactly as expected. There is a bootstrap process that needs to be run, which is supported by the `buildErlangMk` derivation.
For Elixir applications use `mixRelease` to make a release. See examples for more details.
There is also a `buildMix` helper, whose behavior is closer to that of `buildErlangMk` and `buildRebar3`. The primary difference is that mixRelease makes a release, while buildMix only builds the package, making it useful for libraries and other dependencies.
## How to Install BEAM Packages {#how-to-install-beam-packages}
BEAM builders are not registered at the top level, because they are not relevant to the vast majority of Nix users.
To use any of those builders into your environment, refer to them by their attribute path under `beamPackages`, e.g. `beamPackages.rebar3`:
::: {.example #ex-beam-ephemeral-shell}
# Ephemeral shell
```ShellSession
$ nix-shell -p beamPackages.rebar3
```
:::
::: {.example #ex-beam-declarative-shell}
# Declarative shell
```nix
let
pkgs = import <nixpkgs> {
config = { };
overlays = [ ];
};
in
pkgs.mkShell { packages = [ pkgs.beamPackages.rebar3 ]; }
```
:::
## Packaging BEAM Applications {#packaging-beam-applications}
### Erlang Applications {#packaging-erlang-applications}
#### Rebar3 Packages {#rebar3-packages}
The Nix function, `buildRebar3`, defined in `beam.packages.erlang.buildRebar3` and aliased at the top level, can be used to build a derivation that understands how to build a Rebar3 project.
If a package needs to compile native code via Rebar3's port compilation mechanism, add `compilePort = true;` to the derivation.
#### Erlang.mk Packages {#erlang-mk-packages}
Erlang.mk functions similarly to Rebar3, except we use `buildErlangMk` instead of `buildRebar3`.
#### Mix Packages {#mix-packages}
`mixRelease` is used to make a release in the mix sense. Dependencies will need to be fetched with `fetchMixDeps` and passed to it.
#### mixRelease - Elixir Phoenix example {#mix-release-elixir-phoenix-example}
there are 3 steps: frontend dependencies (javascript), backend dependencies (elixir), and the final derivation that puts both of those together
##### mixRelease - Frontend dependencies (javascript) {#mix-release-javascript-deps}
For phoenix projects, inside of Nixpkgs you can either use yarn2nix (mkYarnModule) or node2nix. An example with yarn2nix can be found [here](https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/web-apps/plausible/default.nix#L39). An example with node2nix will follow. To package something outside of nixpkgs, you have alternatives like [npmlock2nix](https://github.com/nix-community/npmlock2nix) or [nix-npm-buildpackage](https://github.com/serokell/nix-npm-buildpackage)
##### mixRelease - backend dependencies (mix) {#mix-release-mix-deps}
There are 2 ways to package backend dependencies. With mix2nix and with a fixed-output-derivation (FOD).
###### mix2nix {#mix2nix}
`mix2nix` is a cli tool available in Nixpkgs. It will generate a Nix expression from a `mix.lock` file. It is quite standard in the 2nix tool series.
Note that currently mix2nix can't handle git dependencies inside the mix.lock file. If you have git dependencies, you can either add them manually (see [example](https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/pleroma/default.nix#L20)) or use the FOD method.
The advantage of using mix2nix is that nix will know your whole dependency graph. On a dependency update, this won't trigger a full rebuild and download of all the dependencies, where FOD will do so.
Practical steps:
- run `mix2nix > mix_deps.nix` in the upstream repo.
- pass `mixNixDeps = with pkgs; import ./mix_deps.nix { inherit lib beamPackages; };` as an argument to mixRelease.
If there are git dependencies.
- You'll need to fix the version artificially in mix.exs and regenerate the mix.lock with fixed version (on upstream). This will enable you to run `mix2nix > mix_deps.nix`.
- From the mix_deps.nix file, remove the dependencies that had git versions and pass them as an override to the import function.
```nix
{
mixNixDeps = import ./mix.nix {
inherit beamPackages lib;
overrides = (
final: prev: {
# mix2nix does not support git dependencies yet,
# so we need to add them manually
prometheus_ex = beamPackages.buildMix rec {
name = "prometheus_ex";
version = "3.0.5";
# Change the argument src with the git src that you actually need
src = fetchFromGitLab {
domain = "git.pleroma.social";
group = "pleroma";
owner = "elixir-libraries";
repo = "prometheus.ex";
rev = "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5";
hash = "sha256-U17LlN6aGUKUFnT4XyYXppRN+TvUBIBRHEUsfeIiGOw=";
};
# you can re-use the same beamDeps argument as generated
beamDeps = with final; [ prometheus ];
};
}
);
};
}
```
You will need to run the build process once to fix the hash to correspond to your new git src.
###### FOD {#fixed-output-derivation}
A fixed output derivation will download mix dependencies from the internet. To ensure reproducibility, a hash will be supplied. Note that mix is relatively reproducible. An FOD generating a different hash on each run hasn't been observed (as opposed to npm where the chances are relatively high). See [elixir-ls](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/beam-modules/elixir-ls/default.nix) for a usage example of FOD.
Practical steps
- start with the following argument to mixRelease
```nix
{
mixFodDeps = fetchMixDeps {
pname = "mix-deps-${pname}";
inherit src version;
hash = lib.fakeHash;
};
}
```
The first build will complain about the hash value, you can replace with the suggested value after that.
Note that if after you've replaced the value, nix suggests another hash, then mix is not fetching the dependencies reproducibly. An FOD will not work in that case and you will have to use mix2nix.
##### mixRelease - example {#mix-release-example}
Here is how your `default.nix` file would look for a Phoenix project.
```nix
with import <nixpkgs> { };
let
# beam.interpreters.erlang_26 is available if you need a particular version
packages = beam.packagesWith beam.interpreters.erlang;
pname = "your_project";
version = "0.0.1";
src = builtins.fetchgit {
url = "ssh://git@github.com/your_id/your_repo";
rev = "replace_with_your_commit";
};
# if using mix2nix you can use the mixNixDeps attribute
mixFodDeps = packages.fetchMixDeps {
pname = "mix-deps-${pname}";
inherit src version;
# nix will complain and tell you the right value to replace this with
hash = lib.fakeHash;
mixEnv = ""; # default is "prod", when empty includes all dependencies, such as "dev", "test".
# if you have build time environment variables add them here
MY_ENV_VAR = "my_value";
};
nodeDependencies = (pkgs.callPackage ./assets/default.nix { }).shell.nodeDependencies;
in
packages.mixRelease {
inherit
src
pname
version
mixFodDeps
;
# if you have build time environment variables add them here
MY_ENV_VAR = "my_value";
postBuild = ''
ln -sf ${nodeDependencies}/lib/node_modules assets/node_modules
npm run deploy --prefix ./assets
# for external task you need a workaround for the no deps check flag
# https://github.com/phoenixframework/phoenix/issues/2690
mix do deps.loadpaths --no-deps-check, phx.digest
mix phx.digest --no-deps-check
'';
}
```
Setup will require the following steps:
- Move your secrets to runtime environment variables. For more information refer to the [runtime.exs docs](https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-runtime-configuration). On a fresh Phoenix build that would mean that both `DATABASE_URL` and `SECRET_KEY` need to be moved to `runtime.exs`.
- `cd assets` and `nix-shell -p node2nix --run "node2nix --development"` will generate a Nix expression containing your frontend dependencies
- commit and push those changes
- you can now `nix-build .`
- To run the release, set the `RELEASE_TMP` environment variable to a directory that your program has write access to. It will be used to store the BEAM settings.
#### Example of creating a service for an Elixir - Phoenix project {#example-of-creating-a-service-for-an-elixir---phoenix-project}
In order to create a service with your release, you could add a `service.nix`
in your project with the following
```nix
{
config,
pkgs,
lib,
...
}:
let
release = pkgs.callPackage ./default.nix;
release_name = "app";
working_directory = "/home/app";
in
{
systemd.services.${release_name} = {
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"postgresql.target"
];
# note that if you are connecting to a postgres instance on a different host
# postgresql.target should not be included in the requires.
requires = [
"network-online.target"
"postgresql.target"
];
description = "my app";
environment = {
# RELEASE_TMP is used to write the state of the
# VM configuration when the system is running
# it needs to be a writable directory
RELEASE_TMP = working_directory;
# can be generated in an elixir console with
# Base.encode32(:crypto.strong_rand_bytes(32))
RELEASE_COOKIE = "my_cookie";
MY_VAR = "my_var";
};
serviceConfig = {
Type = "exec";
DynamicUser = true;
WorkingDirectory = working_directory;
# Implied by DynamicUser, but just to emphasize due to RELEASE_TMP
PrivateTmp = true;
ExecStart = ''
${release}/bin/${release_name} start
'';
ExecStop = ''
${release}/bin/${release_name} stop
'';
ExecReload = ''
${release}/bin/${release_name} restart
'';
Restart = "on-failure";
RestartSec = 5;
};
unitConfig = {
StartLimitBurst = 3;
StartLimitInterval = 10;
};
# disksup requires bash
path = [ pkgs.bash ];
};
# in case you have migration scripts or you want to use a remote shell
environment.systemPackages = [ release ];
}
```
## How to Develop {#how-to-develop}
### Creating a Shell {#creating-a-shell}
Usually, we need to create a `shell.nix` file and do our development inside the environment specified therein. Just install your version of Erlang and any other interpreters, and then use your normal build tools. As an example, with Elixir:
```nix
{
pkgs ? import <nixpkgs> { },
}:
with pkgs;
let
elixir = beam.packages.erlang_27.elixir_1_18;
in
mkShell { buildInputs = [ elixir ]; }
```
### Using an overlay {#beam-using-overlays}
If you need to use an overlay to change some attributes of a derivation, e.g. if you need a bugfix from a version that is not yet available in Nixpkgs, you can override attributes such as `version` (and the corresponding `hash`) and then use this overlay in your development environment:
#### `shell.nix` {#beam-using-overlays-shell.nix}
```nix
let
elixir_1_18_1_overlay = (
self: super: {
elixir_1_18 = super.elixir_1_18.override {
version = "1.18.1";
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
}
);
pkgs = import <nixpkgs> { overlays = [ elixir_1_18_1_overlay ]; };
in
with pkgs;
mkShell { buildInputs = [ elixir_1_18 ]; }
```
#### Elixir - Phoenix project {#elixir---phoenix-project}
Here is an example `shell.nix`.
```nix
with import <nixpkgs> { };
let
# define packages to install
basePackages = [
git
# replace with beam.packages.erlang.elixir_1_18 if you need
beam.packages.erlang.elixir
nodejs
postgresql_14
# only used for frontend dependencies
# you are free to use yarn2nix as well
nodePackages.node2nix
# formatting js file
nodePackages.prettier
];
inputs = basePackages ++ lib.optionals stdenv.hostPlatform.isLinux [ inotify-tools ];
# define shell startup command
hooks = ''
# this allows mix to work on the local directory
mkdir -p .nix-mix .nix-hex
export MIX_HOME=$PWD/.nix-mix
export HEX_HOME=$PWD/.nix-mix
# make hex from Nixpkgs available
# `mix local.hex` will install hex into MIX_HOME and should take precedence
export MIX_PATH="${beam.packages.erlang.hex}/lib/erlang/lib/hex/ebin"
export PATH=$MIX_HOME/bin:$HEX_HOME/bin:$PATH
export LANG=C.UTF-8
# keep your shell history in iex
export ERL_AFLAGS="-kernel shell_history enabled"
# postges related
# keep all your db data in a folder inside the project
export PGDATA="$PWD/db"
# phoenix related env vars
export POOL_SIZE=15
export DB_URL="postgresql://postgres:postgres@localhost:5432/db"
export PORT=4000
export MIX_ENV=dev
# add your project env vars here, word readable in the nix store.
export ENV_VAR="your_env_var"
'';
in
mkShell {
buildInputs = inputs;
shellHook = hooks;
}
```
Initializing the project will require the following steps:
- create the db directory `initdb ./db` (inside your mix project folder)
- create the postgres user `createuser postgres -ds`
- create the db `createdb db`
- start the postgres instance `pg_ctl -l "$PGDATA/server.log" start`
- add the `/db` folder to your `.gitignore`
- you can start your Phoenix server and get a shell with `iex -S mix phx.server`

View File

@@ -0,0 +1,84 @@
# CHICKEN {#sec-chicken}
[CHICKEN](https://call-cc.org/) is a
[R⁵RS](https://schemers.org/Documents/Standards/R5RS/HTML/)-compliant Scheme
compiler. It includes an interactive mode and a custom package format, "eggs".
## Using Eggs {#sec-chicken-using}
Eggs described in Nixpkgs are available inside the
`chickenPackages.chickenEggs` attrset. Including an egg as a build input is
done in the typical Nix fashion. For example, to include support for [SRFI
189](https://srfi.schemers.org/srfi-189/srfi-189.html) in a derivation, one
might write:
```nix
{
buildInputs = [
chicken
chickenPackages.chickenEggs.srfi-189
];
}
```
Both `chicken` and its eggs have a setup hook which configures the environment
variables `CHICKEN_INCLUDE_PATH` and `CHICKEN_REPOSITORY_PATH`.
## Updating Eggs {#sec-chicken-updating-eggs}
Nixpkgs only knows about a subset of all published eggs. It uses
[egg2nix](https://github.com/the-kenny/egg2nix) to generate a
package set from a list of eggs to include.
The package set is regenerated by running the following shell commands:
```
$ nix-shell -p chickenPackages.egg2nix
$ cd pkgs/development/compilers/chicken/5/
$ egg2nix eggs.scm > eggs.nix
```
## Adding Eggs {#sec-chicken-adding-eggs}
When we run `egg2nix`, we obtain one collection of eggs with
mutually-compatible versions. This means that when we add new eggs, we may
need to update existing eggs. To keep those separate, follow the procedure for
updating eggs before including more eggs.
To include more eggs, edit `pkgs/development/compilers/chicken/5/eggs.scm`.
The first section of this file lists eggs which are required by `egg2nix`
itself; all other eggs go into the second section. After editing, follow the
procedure for updating eggs.
## Override Scope {#sec-chicken-override-scope}
The chicken package and its eggs, respectively, reside in a scope. This means,
the scope can be overridden to affect other packages in it.
This example shows how to use a local copy of `srfi-180` and have it affect
all the other eggs:
```nix
let
myChickenPackages = pkgs.chickenPackages.overrideScope (
self: super: {
# The chicken package itself can be overridden to affect the whole ecosystem.
# chicken = super.chicken.overrideAttrs {
# src = ...
# };
chickenEggs = super.chickenEggs.overrideScope (
eggself: eggsuper: {
srfi-180 = eggsuper.srfi-180.overrideAttrs {
# path to a local copy of srfi-180
src = <...>;
};
}
);
}
);
# Here, `myChickenPackages.chickenEggs.json-rpc`, which depends on `srfi-180` will use
# the local copy of `srfi-180`.
in
<...>
```

View File

@@ -0,0 +1,184 @@
# Coq and coq packages {#sec-language-coq}
## Coq derivation: `coq` {#coq-derivation-coq}
The Coq derivation is overridable through the `coq.override overrides`, where overrides is an attribute set which contains the arguments to override. We recommend overriding either of the following:
* `version` (optional, defaults to the latest version of Coq selected for nixpkgs, see `pkgs/top-level/coq-packages` to witness this choice), which follows the conventions explained in the `coqPackages` section below,
* `customOCamlPackages` (optional, defaults to `null`, which lets Coq choose a version automatically), which can be set to any of the ocaml packages attribute of `ocaml-ng` (such as `ocaml-ng.ocamlPackages_4_10` which is the default for Coq 8.11 for example).
* `coq-version` (optional, defaults to the short version e.g. "8.10"), is a version number of the form "x.y" that indicates which Coq's version build behavior to mimic when using a source which is not a release. E.g. `coq.override { version = "d370a9d1328a4e1cdb9d02ee032f605a9d94ec7a"; coq-version = "8.10"; }`.
The associated package set can be obtained using `mkCoqPackages coq`, where `coq` is the derivation to use.
## Coq packages attribute sets: `coqPackages` {#coq-packages-attribute-sets-coqpackages}
The recommended way of defining a derivation for a Coq library, is to use the `coqPackages.mkCoqDerivation` function, which is essentially a specialization of `mkDerivation` taking into account most of the specifics of Coq libraries. The following attributes are supported:
* `pname` (required) is the name of the package,
* `version` (optional, defaults to `null`), is the version to fetch and build,
this attribute is interpreted in several ways depending on its type and pattern:
* if it is a known released version string, i.e. from the `release` attribute below, the according release is picked, and the `version` attribute of the resulting derivation is set to this release string,
* if it is a majorMinor `"x.y"` prefix of a known released version (as defined above), then the latest `"x.y.z"` known released version is selected (for the ordering given by `versionAtLeast`),
* if it is a path or a string representing an absolute path (i.e. starting with `"/"`), the provided path is selected as a source, and the `version` attribute of the resulting derivation is set to `"dev"`,
* if it is a string of the form `owner:branch` then it tries to download the `branch` of owner `owner` for a project of the same name using the same vcs, and the `version` attribute of the resulting derivation is set to `"dev"`, additionally if the owner is not provided (i.e. if the `owner:` prefix is missing), it defaults to the original owner of the package (see below),
* if it is a string of the form `"#N"`, and the domain is github, then it tries to download the current head of the pull request `#N` from github,
* `defaultVersion` (optional). Coq libraries may be compatible with some specific versions of Coq only. The `defaultVersion` attribute is used when no `version` is provided (or if `version = null`) to select the version of the library to use by default, depending on the context. This selection will mainly depend on a `coq` version number but also possibly on other packages versions (e.g. `mathcomp`). If its value ends up to be `null`, the package is marked for removal in end-user `coqPackages` attribute set.
* `release` (optional, defaults to `{}`), lists all the known releases of the library and for each of them provides an attribute set with at least a `hash` attribute (you may put the empty string `""` in order to automatically insert a fake hash, this will trigger an error which will allow you to find the correct hash), each attribute set of the list of releases also takes optional overloading arguments for the fetcher as below (i.e.`domain`, `owner`, `repo`, `rev`, `artifact` assuming the default fetcher is used) and optional overrides for the result of the fetcher (i.e. `version` and `src`).
* `fetcher` (optional, defaults to a generic fetching mechanism supporting github or gitlab based infrastructures), is a function that takes at least an `owner`, a `repo`, a `rev`, and a `hash` and returns an attribute set with a `version` and `src`.
* `repo` (optional, defaults to the value of `pname`),
* `owner` (optional, defaults to `"coq-community"`).
* `domain` (optional, defaults to `"github.com"`), domains including the strings `"github"` or `"gitlab"` in their names are automatically supported, otherwise, one must change the `fetcher` argument to support them (cf `pkgs/development/coq-modules/heq/default.nix` for an example),
* `releaseRev` (optional, defaults to `(v: v)`), provides a default mapping from release names to revision hashes/branch names/tags,
* `releaseArtifact` (optional, defaults to `(v: null)`), provides a default mapping from release names to artifact names (only works for github artifact for now),
* `displayVersion` (optional), provides a way to alter the computation of `name` from `pname`, by explaining how to display version numbers,
* `namePrefix` (optional, defaults to `[ "coq" ]`), provides a way to alter the computation of `name` from `pname`, by explaining which dependencies must occur in `name`,
* `nativeBuildInputs` (optional), is a list of executables that are required to build the current derivation, in addition to the default ones (namely `which`, `dune` and `ocaml` depending on whether `useDune`, `useDuneifVersion` and `mlPlugin` are set).
* `extraNativeBuildInputs` (optional, deprecated), an additional list of derivation to add to `nativeBuildInputs`,
* `overrideNativeBuildInputs` (optional) replaces the default list of derivation to which `nativeBuildInputs` and `extraNativeBuildInputs` adds extra elements,
* `buildInputs` (optional), is a list of libraries and dependencies that are required to build and run the current derivation, in addition to the default one `[ coq ]`,
* `extraBuildInputs` (optional, deprecated), an additional list of derivation to add to `buildInputs`,
* `overrideBuildInputs` (optional) replaces the default list of derivation to which `buildInputs` and `extraBuildInputs` adds extras elements,
* `propagatedBuildInputs` (optional) is passed as is to `mkDerivation`, we recommend to use this for Coq libraries and Coq plugin dependencies, as this makes sure the paths of the compiled libraries and plugins will always be added to the build environments of subsequent derivation, which is necessary for Coq packages to work correctly,
* `mlPlugin` (optional, defaults to `false`). Some extensions (plugins) might require OCaml and sometimes other OCaml packages. Standard dependencies can be added by setting the current option to `true`. For a finer grain control, the `coq.ocamlPackages` attribute can be used in `nativeBuildInputs`, `buildInputs`, and `propagatedBuildInputs` to depend on the same package set Coq was built against.
* `useDuneifVersion` (optional, default to `(x: false)` uses Dune to build the package if the provided predicate evaluates to true on the version, e.g. `useDuneifVersion = versions.isGe "1.1"` will use dune if the version of the package is greater or equal to `"1.1"`,
* `useDune` (optional, defaults to `false`) uses Dune to build the package if set to true, the presence of this attribute overrides the behavior of the previous one.
* `opam-name` (optional, defaults to concatenating with a dash separator the components of `namePrefix` and `pname`), name of the Dune package to build.
* `enableParallelBuilding` (optional, defaults to `true`), since it is activated by default, we provide a way to disable it.
* `extraInstallFlags` (optional), allows to extend `installFlags` which initializes the variable `COQMF_COQLIB` so as to install in the proper subdirectory. Indeed Coq libraries should be installed in `$(out)/lib/coq/${coq.coq-version}/user-contrib/`. Such directories are automatically added to the `$COQPATH` environment variable by the hook defined in the Coq derivation.
* `setCOQBIN` (optional, defaults to `true`), by default, the environment variable `$COQBIN` is set to the current Coq's binary, but one can disable this behavior by setting it to `false`,
* `useMelquiondRemake` (optional, default to `null`) is an attribute set, which, if given, overloads the `preConfigurePhases`, `configureFlags`, `buildPhase`, and `installPhase` attributes of the derivation for a specific use in libraries using `remake` as set up by Guillaume Melquiond for `flocq`, `gappalib`, `interval`, and `coquelicot` (see the corresponding derivation for concrete examples of use of this option). For backward compatibility, the attribute `useMelquiondRemake.logpath` must be set to the logical root of the library (otherwise, one can pass `useMelquiondRemake = {}` to activate this without backward compatibility).
* `dropAttrs`, `keepAttrs`, `dropDerivationAttrs` are all optional and allow to tune which attribute is added or removed from the final call to `mkDerivation`.
It also takes other standard `mkDerivation` attributes, they are added as such, except for `meta` which extends an automatically computed `meta` (where the `platform` is the same as `coq` and the homepage is automatically computed).
Here is a simple package example. It is a pure Coq library, thus it depends on Coq. It builds on the Mathematical Components library, thus it also takes some `mathcomp` derivations as `extraBuildInputs`.
```nix
{
lib,
mkCoqDerivation,
version ? null,
coq,
mathcomp,
mathcomp-finmap,
mathcomp-bigenough,
}:
mkCoqDerivation {
# namePrefix leads to e.g. `name = coq8.11-mathcomp1.11-multinomials-1.5.2`
namePrefix = [
"coq"
"mathcomp"
];
pname = "multinomials";
owner = "math-comp";
inherit version;
defaultVersion =
with lib.versions;
lib.switch
[ coq.version mathcomp.version ]
[
{
cases = [
(range "8.7" "8.12")
(isEq "1.11")
];
out = "1.5.2";
}
{
cases = [
(range "8.7" "8.11")
(range "1.8" "1.10")
];
out = "1.5.0";
}
{
cases = [
(range "8.7" "8.10")
(range "1.8" "1.10")
];
out = "1.4";
}
{
cases = [
(isEq "8.6")
(range "1.6" "1.7")
];
out = "1.1";
}
]
null;
release = {
"1.5.2".hash = "sha256-mjCx9XKa38Nz9E6wNK7YSqHdJ7YTua5fD3d6J4e7WpU=";
"1.5.1".hash = "sha256-Q8tm0y2FQAt2V1kZYkDlHWRia/lTvXAMVjdmzEV11I4=";
"1.5.0".hash = "sha256-HIK0f21G69oEW8JG46gSBde/Q2LR3GiBCv680gHbmRg=";
"1.5.0".rev = "1.5";
"1.4".hash = "sha256-F9g3MSIr3B6UZ3p8QWjz3/Jpw9sudJ+KRlvjiHSO024=";
"1.3".hash = "sha256-BPJTlAL0ETHvLMBslE0KFVt3DNoaGuMrHt2SBGyJe1A=";
"1.2".hash = "sha256-mHXBXSLYO4BN+jfN50y/+XCx0Qq5g4Ac2Y/qlsbgAdY=";
"1.1".hash = "sha256-ejAsMQbB/LtU9j+g160VdGXULrCe9s0gBWzyhKqmCuE=";
"1.0".hash = "sha256-tZTOltEBBKWciDxDMs/Ye4Jnq/33CANrHJ4FBMPtq+I=";
};
propagatedBuildInputs = [
mathcomp.ssreflect
mathcomp.algebra
mathcomp-finmap
mathcomp-bigenough
];
meta = {
description = "Coq/SSReflect Library for Monoidal Rings and Multinomials";
license = lib.licenses.cecill-c;
};
}
```
## Three ways of overriding Coq packages {#coq-overriding-packages}
There are three distinct ways of changing a Coq package by overriding one of its values: `.override`, `overrideCoqDerivation`, and `.overrideAttrs`. This section explains what sort of values can be overridden with each of these methods.
### `.override` {#coq-override}
`.override` lets you change arguments to a Coq derivation. In the case of the `multinomials` package above, `.override` would let you override arguments like `mkCoqDerivation`, `version`, `coq`, `mathcomp`, `mathcom-finmap`, etc.
For example, assuming you have a special `mathcomp` dependency you want to use, here is how you could override the `mathcomp` dependency:
```nix
multinomials.override { mathcomp = my-special-mathcomp; }
```
In Nixpkgs, all Coq derivations take a `version` argument. This can be overridden in order to easily use a different version:
```nix
coqPackages.multinomials.override { version = "1.5.1"; }
```
Refer to [](#coq-packages-attribute-sets-coqpackages) for all the different formats that you can potentially pass to `version`, as well as the restrictions.
### `overrideCoqDerivation` {#coq-overrideCoqDerivation}
The `overrideCoqDerivation` function lets you easily change arguments to `mkCoqDerivation`. These arguments are described in [](#coq-packages-attribute-sets-coqpackages).
For example, here is how you could locally add a new release of the `multinomials` library, and set the `defaultVersion` to use this release:
```nix
coqPackages.lib.overrideCoqDerivation {
defaultVersion = "2.0";
release."2.0".hash = "sha256-czoP11rtrIM7+OLdMisv2EF7n/IbGuwFxHiPtg3qCNM=";
} coqPackages.multinomials
```
### `.overrideAttrs` {#coq-overrideAttrs}
`.overrideAttrs` lets you override arguments to the underlying `stdenv.mkDerivation` call. Internally, `mkCoqDerivation` uses `stdenv.mkDerivation` to create derivations for Coq libraries. You can override arguments to `stdenv.mkDerivation` with `.overrideAttrs`.
For instance, here is how you could add some code to be performed in the derivation after installation is complete:
```nix
coqPackages.multinomials.overrideAttrs (oldAttrs: {
postInstall = oldAttrs.postInstall or "" + ''
echo "you can do anything you want here"
'';
})
```

View File

@@ -0,0 +1,152 @@
# COSMIC {#sec-language-cosmic}
## Packaging COSMIC applications {#ssec-cosmic-packaging}
COSMIC (Computer Operating System Main Interface Components) is a desktop environment developed by
System76, primarily for the Pop!_OS Linux distribution. Applications in the COSMIC ecosystem are
written in Rust and use libcosmic, which builds on the Iced GUI framework. This section explains
how to properly package and integrate COSMIC applications within Nix.
### libcosmicAppHook {#ssec-cosmic-libcosmic-app-hook}
The `libcosmicAppHook` is a setup hook that helps with this by automatically configuring
and wrapping applications based on libcosmic. It handles many common requirements like:
- Setting up proper linking for libraries that may be dlopen'd by libcosmic/iced apps
- Configuring XDG paths for settings schemas, icons, and other resources
- Managing Vergen environment variables for build-time information
- Setting up Rust linker flags for specific libraries
To use the hook, simply add it to your package's `nativeBuildInputs`:
```nix
{
lib,
rustPlatform,
libcosmicAppHook,
}:
rustPlatform.buildRustPackage {
# ...
nativeBuildInputs = [ libcosmicAppHook ];
# ...
}
```
### Settings fallback {#ssec-cosmic-settings-fallback}
COSMIC applications use libcosmic's UI components, which may need access to theme settings. The
`cosmic-settings` package provides default theme settings as a fallback in its `share` directory.
By default, `libcosmicAppHook` includes this fallback path in `XDG_DATA_DIRS`, ensuring that COSMIC
applications will have access to theme settings even if they aren't available elsewhere in the
system.
This fallback behavior can be disabled by setting `includeSettings = false` when including the hook:
```nix
{
lib,
rustPlatform,
libcosmicAppHook,
}:
let
# Get build-time version of libcosmicAppHook
libcosmicAppHook' = (libcosmicAppHook.__spliced.buildHost or libcosmicAppHook).override {
includeSettings = false;
};
in
rustPlatform.buildRustPackage {
# ...
nativeBuildInputs = [ libcosmicAppHook' ];
# ...
}
```
Note that `cosmic-settings` is a separate application and not a part of the libcosmic settings
system itself. It's included by default in `libcosmicAppHook` only to provide these fallback theme
settings.
### Icons {#ssec-cosmic-icons}
COSMIC applications can use icons from the COSMIC icon theme. While COSMIC applications can build
and run without these icons, they would be missing visual elements. The `libcosmicAppHook`
automatically includes `cosmic-icons` in the wrapped application's `XDG_DATA_DIRS` as a fallback,
ensuring that the application has access to its required icons even if the system doesn't have the
COSMIC icon theme installed globally.
Unlike the `cosmic-settings` fallback, the `cosmic-icons` fallback cannot be removed or disabled, as
it is essential for COSMIC applications to have access to these icons for proper visual rendering.
### Runtime Libraries {#ssec-cosmic-runtime-libraries}
COSMIC applications built on libcosmic and Iced require several runtime libraries that are dlopen'd
rather than linked directly. The `libcosmicAppHook` ensures that these libraries are correctly
linked by setting appropriate Rust linker flags. The libraries handled include:
- Graphics libraries (EGL, Vulkan)
- Input libraries (xkbcommon)
- Display server protocols (Wayland, X11)
This ensures that the applications will work correctly at runtime, even though they use dynamic
loading for these dependencies.
### Adding custom wrapper arguments {#ssec-cosmic-custom-wrapper-args}
You can pass additional arguments to the wrapper using `libcosmicAppWrapperArgs` in the `preFixup` hook:
```nix
{
lib,
rustPlatform,
libcosmicAppHook,
}:
rustPlatform.buildRustPackage {
# ...
preFixup = ''
libcosmicAppWrapperArgs+=(--set-default ENVIRONMENT_VARIABLE VALUE)
'';
# ...
}
```
## Frequently encountered issues {#ssec-cosmic-common-issues}
### Setting up Vergen environment variables {#ssec-cosmic-common-issues-vergen}
Many COSMIC applications use the Vergen Rust crate for build-time information. The `libcosmicAppHook`
automatically sets up the `VERGEN_GIT_COMMIT_DATE` environment variable based on `SOURCE_DATE_EPOCH`
to ensure reproducible builds.
However, some applications may explicitly require additional Vergen environment variables.
Without these properly set, you may encounter build failures with errors like:
```
> cargo:rerun-if-env-changed=VERGEN_GIT_COMMIT_DATE
> cargo:rerun-if-env-changed=VERGEN_GIT_SHA
>
> --- stderr
> Error: no suitable 'git' command found!
> warning: build failed, waiting for other jobs to finish...
```
While `libcosmicAppHook` handles `VERGEN_GIT_COMMIT_DATE`, you may need to explicitly set other
variables. For applications that require these variables, you should set them directly in the
package definition:
```nix
{
lib,
rustPlatform,
libcosmicAppHook,
}:
rustPlatform.buildRustPackage {
# ...
env = {
VERGEN_GIT_COMMIT_DATE = "2025-01-01";
VERGEN_GIT_SHA = "0000000000000000000000000000000000000000"; # SHA-1 hash of the commit
};
# ...
}
```
Not all COSMIC applications require these variables, but for those that do, setting them explicitly
will prevent build failures.

View File

@@ -0,0 +1,80 @@
# Crystal {#crystal}
## Building a Crystal package {#building-a-crystal-package}
This section uses [Mint](https://github.com/mint-lang/mint) as an example for how to build a Crystal package.
If the Crystal project has any dependencies, the first step is to get a `shards.nix` file encoding those. Get a copy of the project and go to its root directory such that its `shard.lock` file is in the current directory. Executable projects should usually commit the `shard.lock` file, but sometimes that's not the case, which means you need to generate it yourself. With an existing `shard.lock` file, `crystal2nix` can be run.
```bash
$ git clone https://github.com/mint-lang/mint
$ cd mint
$ git checkout 0.5.0
$ if [ ! -f shard.lock ]; then nix-shell -p shards --run "shards lock"; fi
$ nix-shell -p crystal2nix --run crystal2nix
```
This should have generated a `shards.nix` file.
Next create a Nix file for your derivation and use `pkgs.crystal.buildCrystalPackage` as follows:
```nix
with import <nixpkgs> { };
crystal.buildCrystalPackage rec {
pname = "mint";
version = "0.5.0";
src = fetchFromGitHub {
owner = "mint-lang";
repo = "mint";
rev = version;
hash = "sha256-dFN9l5fgrM/TtOPqlQvUYgixE4KPr629aBmkwdDoq28=";
};
# Insert the path to your shards.nix file here
shardsFile = ./shards.nix;
# ...
}
```
This won't build anything yet, because we haven't told it what files build. We can specify a mapping from binary names to source files with the `crystalBinaries` attribute. The project's compilation instructions should show this. For Mint, the binary is called "mint", which is compiled from the source file `src/mint.cr`, so we'll specify this as follows:
```nix
{
crystalBinaries.mint.src = "src/mint.cr";
# ...
}
```
Additionally you can override the default `crystal build` options (which are currently `--release --progress --no-debug --verbose`) with
```nix
{
crystalBinaries.mint.options = [
"--release"
"--verbose"
];
}
```
Depending on the project, you might need additional steps to get it to compile successfully. In Mint's case, we need to link against openssl, so in the end the Nix file looks as follows:
```nix
with import <nixpkgs> { };
crystal.buildCrystalPackage rec {
version = "0.5.0";
pname = "mint";
src = fetchFromGitHub {
owner = "mint-lang";
repo = "mint";
rev = version;
hash = "sha256-dFN9l5fgrM/TtOPqlQvUYgixE4KPr629aBmkwdDoq28=";
};
shardsFile = ./shards.nix;
crystalBinaries.mint.src = "src/mint.cr";
buildInputs = [ openssl ];
}
```

View File

@@ -0,0 +1,438 @@
# CUDA {#cuda}
Compute Unified Device Architecture (CUDA) is a parallel computing platform and application programming interface (API) model created by NVIDIA. It's commonly used to accelerate computationally intensive problems and has been widely adopted for high-performance computing (HPC) and machine learning (ML) applications.
## User Guide {#cuda-user-guide}
Packages provided by NVIDIA which require CUDA are typically stored in CUDA package sets.
Nixpkgs provides a number of CUDA package sets, each based on a different CUDA release. Top-level attributes that provide access to CUDA package sets follow these naming conventions:
- `cudaPackages_x_y`: A major-minor-versioned package set for a specific CUDA release, where `x` and `y` are the major and minor versions of the CUDA release.
- `cudaPackages_x`: A major-versioned alias to the major-minor-versioned CUDA package set with the latest widely supported major CUDA release.
- `cudaPackages`: An unversioned alias to the major-versioned alias for the latest widely supported CUDA release. The package set referenced by this alias is also referred to as the "default" CUDA package set.
It is recommended to use the unversioned `cudaPackages` attribute. While versioned package sets are available (e.g., `cudaPackages_12_8`), they are periodically removed.
Here are two examples to illustrate the naming conventions:
- If `cudaPackages_12_9` is the latest release in the 12.x series, but core libraries like OpenCV or ONNX Runtime fail to build with it, `cudaPackages_12` may alias `cudaPackages_12_8` instead of `cudaPackages_12_9`.
- If `cudaPackages_13_1` is the latest release, but core libraries like PyTorch or Torch Vision fail to build with it, `cudaPackages` may alias `cudaPackages_12` instead of `cudaPackages_13`.
All CUDA package sets include common CUDA packages like `libcublas`, `cudnn`, `tensorrt`, and `nccl`.
### Configuring Nixpkgs for CUDA {#cuda-configuring-nixpkgs-for-cuda}
CUDA support is not enabled by default in Nixpkgs. To enable CUDA support, make sure Nixpkgs is imported with a configuration similar to the following:
```nix
{
allowUnfreePredicate =
let
ensureList = x: if builtins.isList x then x else [ x ];
in
package:
builtins.all (
license:
license.free
|| builtins.elem license.shortName [
"CUDA EULA"
"cuDNN EULA"
"cuSPARSELt EULA"
"cuTENSOR EULA"
"NVidia OptiX EULA"
]
) (ensureList package.meta.license);
cudaCapabilities = [ <target-architectures> ];
cudaForwardCompat = true;
cudaSupport = true;
}
```
The majority of CUDA packages are unfree, so either `allowUnfreePredicate` or `allowUnfree` should be set.
The `cudaSupport` configuration option is used by packages to conditionally enable CUDA-specific functionality. This configuration option is commonly used by packages which can be built with or without CUDA support.
The `cudaCapabilities` configuration option specifies a list of CUDA capabilities. Packages may use this option to control device code generation to take advantage of architecture-specific functionality, speed up compile times by producing less device code, or slim package closures. For example, you can build for Ada Lovelace GPUs with `cudaCapabilities = [ "8.9" ];`. If `cudaCapabilities` is not provided, the default value is calculated per-package set, derived from a list of GPUs supported by that CUDA version. Please consult [supported GPUs](https://en.wikipedia.org/wiki/CUDA#GPUs_supported) for specific cards. Library maintainers should consult [NVCC Docs](https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/) and its release notes.
::: {.caution}
Certain CUDA capabilities are not targeted by default, including capabilities belonging to the Jetson family of devices (e.g. `8.7`, which corresponds to the Jetson Orin) or non-baseline feature-sets (e.g. `9.0a`, which corresponds to the Hopper exclusive feature set). If you need to target these capabilities, you must explicitly set `cudaCapabilities` to include them.
:::
The `cudaForwardCompat` boolean configuration option determines whether PTX support for future hardware is enabled.
### Modifying CUDA package sets {#cuda-modifying-cuda-package-sets}
CUDA package sets are created by using `callPackage` on `pkgs/top-level/cuda-packages.nix` with an explicit argument for `cudaMajorMinorVersion`, a string of the form `"<major>.<minor>"` (e.g., `"12.2"`), which informs the CUDA package set tooling which version of CUDA to use. The majority of the CUDA package set tooling is available through the top-level attribute set `_cuda`, a fixed-point defined outside the CUDA package sets.
::: {.caution}
The `cudaMajorMinorVersion` and `_cuda` attributes are not part of the CUDA package set fixed-point, but are instead provided by `callPackage` from the top-level in the construction of the package set. As such, they must be modified via the package set's `override` attribute.
:::
::: {.caution}
As indicated by the underscore prefix, `_cuda` is an implementation detail and no guarantees are provided with respect to its stability or API. The `_cuda` attribute set is exposed only to ease creation or modification of CUDA package sets by expert, out-of-tree users.
:::
::: {.note}
The `_cuda` attribute set fixed-point should be modified through its `extend` attribute.
:::
The `_cuda.fixups` attribute set is a mapping from package name (`pname`) to a `callPackage`-compatible expression which will be provided to `overrideAttrs` on the result of our generic builder.
::: {.caution}
Fixups are chosen from `_cuda.fixups` by `pname`. As a result, packages with multiple versions (e.g., `cudnn`, `cudnn_8_9`, etc.) all share a single fixup function (i.e., `_cuda.fixups.cudnn`, which is `pkgs/development/cuda-modules/fixups/cudnn.nix`).
:::
As an example, you can change the fixup function used for cuDNN for only the default CUDA package set with this overlay:
```nix
final: prev: {
cudaPackages = prev.cudaPackages.override (prevArgs: {
_cuda = prevArgs._cuda.extend (
_: prevAttrs: {
fixups = prevAttrs.fixups // {
cudnn = <your-fixup-function>;
};
}
);
});
}
```
### Extending CUDA package sets {#cuda-extending-cuda-package-sets}
CUDA package sets are scopes and provide the usual `overrideScope` attribute for overriding package attributes (see the note about `cudaMajorMinorVersion` and `_cuda` in [Configuring CUDA package sets](#cuda-modifying-cuda-package-sets)).
Inspired by `pythonPackagesExtensions`, the `_cuda.extensions` attribute is a list of extensions applied to every version of the CUDA package set, allowing modification of all versions of the CUDA package set without needing to know their names or explicitly enumerate and modify them. As an example, disabling `cuda_compat` across all CUDA package sets can be accomplished with this overlay:
```nix
final: prev: {
_cuda = prev._cuda.extend (
_: prevAttrs: {
extensions = prevAttrs.extensions ++ [ (_: _: { cuda_compat = null; }) ];
}
);
}
```
### Using `cudaPackages` {#cuda-using-cudapackages}
::: {.caution}
A non-trivial amount of CUDA package discoverability and usability relies on the various setup hooks used by a CUDA package set. As a result, users will likely encounter issues trying to perform builds within a `devShell` without manually invoking phases.
:::
To use one or more CUDA packages in an expression, give the expression a `cudaPackages` parameter, and in case CUDA support is optional, add a `config` and `cudaSupport` parameter:
```nix
{
config,
cudaSupport ? config.cudaSupport,
cudaPackages,
}:
<package-expression>
```
In your package's derivation arguments, it is _strongly_ recommended that the following are set:
```nix
{
__structuredAttrs = true;
strictDeps = true;
}
```
These settings ensure that the CUDA setup hooks function as intended.
When using `callPackage`, you can choose to pass in a different variant, e.g. when a package requires a specific version of CUDA:
```nix
{ mypkg = callPackage { cudaPackages = cudaPackages_12_6; }; }
```
::: {.caution}
Overriding the CUDA package set for a package may cause inconsistencies, because the override does not affect its direct or transitive dependencies. As a result, it is easy to end up with a package that use a different CUDA package set than its dependencies. If possible, it is recommended that you change the default CUDA package set globally, to ensure a consistent environment.
:::
### Nixpkgs CUDA variants {#cuda-nixpkgs-cuda-variants}
Nixpkgs CUDA variants are provided primarily for the convenience of selecting CUDA-enabled packages by attribute path. As an example, the `pkgsForCudaArch` collection of CUDA Nixpkgs variants allows you to access an instantiation of OpenCV with CUDA support for an Ada Lovelace GPU with the attribute path `pkgsForCudaArch.sm_89.opencv`, without needing to modify the `config` provided when importing Nixpkgs.
::: {.caution}
Nixpkgs variants are not free: they require re-evaluating Nixpkgs. Where possible, import Nixpkgs once, with the desired configuration.
:::
#### Using `cudaPackages.pkgs` {#cuda-using-cudapackages-pkgs}
Each CUDA package set has a `pkgs` attribute, which is a variant of Nixpkgs in which the enclosing CUDA package set becomes the default. This was done primarily to avoid package set leakage, wherein a member of a non-default CUDA package set has a (potentially transitive) dependency on a member of the default CUDA package set.
::: {.note}
Package set leakage is a common problem in Nixpkgs and is not limited to CUDA package sets.
:::
As an added benefit of `pkgs` being configured this way, building a package with a non-default version of CUDA is as simple as accessing an attribute. As an example, `cudaPackages_12_8.pkgs.opencv` provides OpenCV built against CUDA 12.8.
#### Using `pkgsCuda` {#cuda-using-pkgscuda}
The `pkgsCuda` attribute set is a variant of Nixpkgs configured with `cudaSupport = true;` and `rocmSupport = false`. It is a convenient way to access a variant of Nixpkgs configured with the default set of CUDA capabilities.
#### Using `pkgsForCudaArch` {#cuda-using-pkgsforcudaarch}
The `pkgsForCudaArch` attribute set maps CUDA architectures (e.g., `sm_89` for Ada Lovelace or `sm_90a` for architecture-specific Hopper) to Nixpkgs variants configured to support exactly that architecture. As an example, `pkgsForCudaArch.sm_89` is a Nixpkgs variant extending `pkgs` and setting the following values in `config`:
```nix
{
cudaSupport = true;
cudaCapabilities = [ "8.9" ];
cudaForwardCompat = false;
}
```
::: {.note}
In `pkgsForCudaArch`, the `cudaForwardCompat` option is set to `false` because exactly one CUDA architecture is supported by the corresponding Nixpkgs variant. Furthermore, some architectures, including architecture-specific feature sets like `sm_90a`, cannot be built with forward compatibility.
:::
::: {.caution}
Not every version of CUDA supports every architecture!
To illustrate: support for Blackwell (e.g., `sm_100`) was added in CUDA 12.8. Assume our Nixpkgs' default CUDA package set is to CUDA 12.6. Then the Nixpkgs variant available through `pkgsForCudaArch.sm_100` is useless, since packages like `pkgsForCudaArch.sm_100.opencv` and `pkgsForCudaArch.sm_100.python3Packages.torch` will try to generate code for `sm_100`, an architecture unknown to CUDA 12.6. In that case, you should use `pkgsForCudaArch.sm_100.cudaPackages_12_8.pkgs` instead (see [Using cudaPackages.pkgs](#cuda-using-cudapackages-pkgs) for more details).
:::
The `pkgsForCudaArch` attribute set makes it possible to access packages built for a specific architecture without needing to manually call `pkgs.extend` and supply a new `config`. As an example, `pkgsForCudaArch.sm_89.python3Packages.torch` provides PyTorch built for Ada Lovelace GPUs.
### Running Docker or Podman containers with CUDA support {#cuda-docker-podman}
It is possible to run Docker or Podman containers with CUDA support. The recommended mechanism to perform this task is to use the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/index.html).
The NVIDIA Container Toolkit can be enabled in NixOS like follows:
```nix
{ hardware.nvidia-container-toolkit.enable = true; }
```
This will automatically enable a service that generates a CDI specification (located at `/var/run/cdi/nvidia-container-toolkit.json`) based on the auto-detected hardware of your machine. You can check this service by running:
```ShellSession
$ systemctl status nvidia-container-toolkit-cdi-generator.service
```
::: {.note}
Depending on what settings you had already enabled in your system, you might need to restart your machine in order for the NVIDIA Container Toolkit to generate a valid CDI specification for your machine.
:::
Once that a valid CDI specification has been generated for your machine on boot time, both Podman and Docker (> 25) will use this spec if you provide them with the `--device` flag:
```ShellSession
$ podman run --rm -it --device=nvidia.com/gpu=all ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
GPU 1: NVIDIA GeForce RTX 2080 SUPER (UUID: <REDACTED>)
```
```ShellSession
$ docker run --rm -it --device=nvidia.com/gpu=all ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
GPU 1: NVIDIA GeForce RTX 2080 SUPER (UUID: <REDACTED>)
```
You can check all the identifiers that have been generated for your auto-detected hardware by checking the contents of the `/var/run/cdi/nvidia-container-toolkit.json` file:
```ShellSession
$ nix run nixpkgs#jq -- -r '.devices[].name' < /var/run/cdi/nvidia-container-toolkit.json
0
1
all
```
#### Specifying what devices to expose to the container {#cuda-specifying-what-devices-to-expose-to-the-container}
You can choose what devices are exposed to your containers by using the identifier on the generated CDI specification. Like follows:
```ShellSession
$ podman run --rm -it --device=nvidia.com/gpu=0 ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
```
You can repeat the `--device` argument as many times as necessary if you have multiple GPU's and you want to pick up which ones to expose to the container:
```ShellSession
$ podman run --rm -it --device=nvidia.com/gpu=0 --device=nvidia.com/gpu=1 ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
GPU 1: NVIDIA GeForce RTX 2080 SUPER (UUID: <REDACTED>)
```
::: {.note}
By default, the NVIDIA Container Toolkit will use the GPU index to identify specific devices. You can change the way to identify what devices to expose by using the `hardware.nvidia-container-toolkit.device-name-strategy` NixOS attribute.
:::
#### Using docker-compose {#cuda-using-docker-compose}
It's possible to expose GPUs to a `docker-compose` environment as well. With a `docker-compose.yaml` file like follows:
```yaml
services:
some-service:
image: ubuntu:latest
command: sleep infinity
deploy:
resources:
reservations:
devices:
- driver: cdi
device_ids:
- nvidia.com/gpu=all
```
In the same manner, you can pick specific devices that will be exposed to the container:
```yaml
services:
some-service:
image: ubuntu:latest
command: sleep infinity
deploy:
resources:
reservations:
devices:
- driver: cdi
device_ids:
- nvidia.com/gpu=0
- nvidia.com/gpu=1
```
## Contributing {#cuda-contributing}
::: {.warning}
This section of the docs is still very much in progress. Feedback is welcome in GitHub Issues tagging @NixOS/cuda-maintainers or on [Matrix](https://matrix.to/#/#cuda:nixos.org).
:::
### Package set maintenance {#cuda-package-set-maintenance}
The CUDA Toolkit is a suite of CUDA libraries and software meant to provide a development environment for CUDA-accelerated applications. Until the release of CUDA 11.4, NVIDIA had only made the CUDA Toolkit available as a multi-gigabyte runfile installer, which we provide through the [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit) attribute. From CUDA 11.4 and onwards, NVIDIA has also provided CUDA redistributables (“CUDA-redist”): individually packaged CUDA Toolkit components meant to facilitate redistribution and inclusion in downstream projects. These packages are available in the [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) package set.
All new projects should use the CUDA redistributables available in [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) in place of [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit), as they are much easier to maintain and update.
#### Updating redistributables {#cuda-updating-redistributables}
1. Go to NVIDIA's index of CUDA redistributables: <https://developer.download.nvidia.com/compute/cuda/redist/>
2. Make a note of the new version of CUDA available.
3. Run
```bash
nix run github:connorbaker/cuda-redist-find-features -- \
download-manifests \
--log-level DEBUG \
--version <newest CUDA version> \
https://developer.download.nvidia.com/compute/cuda/redist \
./pkgs/development/cuda-modules/cuda/manifests
```
This will download a copy of the manifest for the new version of CUDA.
4. Run
```bash
nix run github:connorbaker/cuda-redist-find-features -- \
process-manifests \
--log-level DEBUG \
--version <newest CUDA version> \
https://developer.download.nvidia.com/compute/cuda/redist \
./pkgs/development/cuda-modules/cuda/manifests
```
This will generate a `redistrib_features_<newest CUDA version>.json` file in the same directory as the manifest.
5. Update the `cudaVersionMap` attribute set in `pkgs/development/cuda-modules/cuda/extension.nix`.
#### Updating cuTensor {#cuda-updating-cutensor}
1. Repeat the steps present in [Updating CUDA redistributables](#cuda-updating-redistributables) with the following changes:
- Use the index of cuTensor redistributables: <https://developer.download.nvidia.com/compute/cutensor/redist>
- Use the newest version of cuTensor available instead of the newest version of CUDA.
- Use `pkgs/development/cuda-modules/cutensor/manifests` instead of `pkgs/development/cuda-modules/cuda/manifests`.
- Skip the step of updating `cudaVersionMap` in `pkgs/development/cuda-modules/cuda/extension.nix`.
#### Updating supported compilers and GPUs {#cuda-updating-supported-compilers-and-gpus}
1. Update `nvccCompatibilities` in `pkgs/development/cuda-modules/_cuda/data/nvcc.nix` to include the newest release of NVCC, as well as any newly supported host compilers.
2. Update `cudaCapabilityToInfo` in `pkgs/development/cuda-modules/_cuda/data/cuda.nix` to include any new GPUs supported by the new release of CUDA.
#### Updating the CUDA Toolkit runfile installer {#cuda-updating-the-cuda-toolkit}
::: {.warning}
While the CUDA Toolkit runfile installer is still available in Nixpkgs as the [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit) attribute, its use is not recommended, and it should be considered deprecated. Please migrate to the CUDA redistributables provided by the [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) package set.
To ensure packages relying on the CUDA Toolkit runfile installer continue to build, it will continue to be updated until a migration path is available.
:::
1. Go to NVIDIA's CUDA Toolkit runfile installer download page: <https://developer.nvidia.com/cuda-downloads>
2. Select the appropriate OS, architecture, distribution, and version, and installer type.
- For example: Linux, x86_64, Ubuntu, 22.04, runfile (local)
- NOTE: Typically, we use the Ubuntu runfile. It is unclear if the runfile for other distributions will work.
3. Take the link provided by the installer instructions on the webpage after selecting the installer type and get its hash by running:
```bash
nix store prefetch-file --hash-type sha256 <link>
```
4. Update `pkgs/development/cuda-modules/cudatoolkit/releases.nix` to include the release.
#### Updating the CUDA package set {#cuda-updating-the-cuda-package-set}
1. Include a new `cudaPackages_<major>_<minor>` package set in `pkgs/top-level/all-packages.nix`.
- NOTE: Changing the default CUDA package set should occur in a separate PR, allowing time for additional testing.
2. Successfully build the closure of the new package set, updating `pkgs/development/cuda-modules/cuda/overrides.nix` as needed. Below are some common failures:
| Unable to ... | During ... | Reason | Solution | Note |
| -------------- | -------------------------------- | ------------------------------------------------ | -------------------------- | ------------------------------------------------------------ |
| Find headers | `configurePhase` or `buildPhase` | Missing dependency on a `dev` output | Add the missing dependency | The `dev` output typically contains the headers |
| Find libraries | `configurePhase` | Missing dependency on a `dev` output | Add the missing dependency | The `dev` output typically contains CMake configuration files |
| Find libraries | `buildPhase` or `patchelf` | Missing dependency on a `lib` or `static` output | Add the missing dependency | The `lib` or `static` output typically contains the libraries |
Failure to run the resulting binary is typically the most challenging to diagnose, as it may involve a combination of the aforementioned issues. This type of failure typically occurs when a library attempts to load or open a library it depends on that it does not declare in its `DT_NEEDED` section. Try the following debugging steps:
1. First ensure that dependencies are patched with [`autoAddDriverRunpath`](https://search.nixos.org/packages?channel=unstable&type=packages&query=autoAddDriverRunpath).
2. Failing that, try running the application with [`nixGL`](https://github.com/guibou/nixGL) or a similar wrapper tool.
3. If that works, it likely means that the application is attempting to load a library that is not in the `RPATH` or `RUNPATH` of the binary.
### Writing tests {#cuda-writing-tests}
::: {.caution}
The existence of `passthru.testers` and `passthru.tests` should be considered an implementation detail -- they are not meant to be a public or stable interface.
:::
In general, there are two attribute sets in `passthru` that are used to build and run tests for CUDA packages: `passthru.testers` and `passthru.tests`. Each attribute set may contain an attribute set named `cuda`, which contains CUDA-specific derivations. The `cuda` attribute set is used to separate CUDA-specific derivations from those which support multiple implementations (e.g., OpenCL, ROCm, etc.) or have different licenses. For an example of such generic derivations, see the `magma` package.
::: {.note}
Derivations are nested under the `cuda` attribute due to an OfBorg quirk: if evaluation fails (e.g., because of unfree licenses), the entire enclosing attribute set is discarded. This prevents other attributes in the set from being discovered, evaluated, or built.
:::
#### `passthru.testers` {#cuda-passthru-testers}
Attributes added to `passthru.testers` are derivations which produce an executable which runs a test. The produced executable should:
- Take care to set up the environment, make temporary directories, and so on.
- Be registered as the derivation's `meta.mainProgram` so that it can be run directly.
::: {.note}
Testers which always require CUDA should be placed in `passthru.testers.cuda`, while those which are generic should be placed in `passthru.testers`.
:::
The `passthru.testers` attribute set allows running tests outside the Nix sandbox. There are a number of reasons why this is useful, since such a test:
- Can be run on non-NixOS systems, when wrapped with utilities like `nixGL` or `nix-gl-host`.
- Has network access patterns which are difficult or impossible to sandbox.
- Is free to produce output which is not deterministic, such as timing information.
#### `passthru.tests` {#cuda-passthru-tests}
Attributes added to `passthru.tests` are derivations which run tests inside the Nix sandbox. Tests should:
- Use the executables produced by `passthru.testers`, where possible, to avoid duplication of test logic.
- Include `requiredSystemFeatures = [ "cuda" ];`, possibly conditioned on the value of `cudaSupport` if they are generic, to ensure that they are only run on systems exposing a CUDA-capable GPU.
::: {.note}
Tests which always require CUDA should be placed in `passthru.tests.cuda`, while those which are generic should be placed in `passthru.tests`.
:::
This is useful for tests which are deterministic (e.g., checking exit codes) and which can be provided with all necessary resources in the sandbox.

View File

@@ -0,0 +1,91 @@
# Cue (Cuelang) {#cuelang}
[Cuelang](https://cuelang.org/) is a language to:
- describe schemas and validate backward-compatibility
- generate code and schemas in various formats (e.g. JSON Schema, OpenAPI)
- do configuration akin to [Dhall Lang](https://dhall-lang.org/)
- perform data validation
## Cuelang schema quick start {#cuelang-quickstart}
Cuelang schemas are similar to JSON, here is a quick cheatsheet:
- Default types includes: `null`, `string`, `bool`, `bytes`, `number`, `int`, `float`, lists as `[...T]` where `T` is a type.
- All structures, defined by: `myStructName: { <fields> }` are **open** -- they accept fields which are not specified.
- Closed structures can be built by doing `myStructName: close({ <fields> })` -- they are strict in what they accept.
- `#X` are **definitions**, referenced definitions are **recursively closed**, i.e. all its children structures are **closed**.
- `&` operator is the [unification operator](https://cuelang.org/docs/references/spec/#unification) (similar to a type-level merging operator), `|` is the [disjunction operator](https://cuelang.org/docs/references/spec/#disjunction) (similar to a type-level union operator).
- Values **are** types, i.e. `myStruct: { a: 3 }` is a valid type definition that only allows `3` as value.
- Read <https://cuelang.org/docs/concepts/logic/> to learn more about the semantics.
- Read <https://cuelang.org/docs/references/spec/> to learn about the language specification.
## `writeCueValidator` {#cuelang-writeCueValidator}
Nixpkgs provides a `pkgs.writeCueValidator` helper, which will write a validation script based on the provided Cuelang schema.
Here is an example:
```nix
pkgs.writeCueValidator (pkgs.writeText "schema.cue" ''
#Def1: {
field1: string
}
'') { document = "#Def1"; }
```
- The first parameter is the Cue schema file.
- The second parameter is an options parameter, currently, only: `document` can be passed.
`document` : match your input data against this fragment of structure or definition, e.g. you may use the same schema file but different documents based on the data you are validating.
Another example, given the following `validator.nix` :
```nix
{
pkgs ? import <nixpkgs> { },
}:
let
genericValidator =
version:
pkgs.writeCueValidator (pkgs.writeText "schema.cue" ''
#Version1: {
field1: string
}
#Version2: #Version1 & {
field1: "unused"
}'') { document = "#Version${toString version}"; };
in
{
validateV1 = genericValidator 1;
validateV2 = genericValidator 2;
}
```
The result is a script that will validate the file you pass as the first argument against the schema you provided `writeCueValidator`.
It can be any format that `cue vet` supports, i.e. YAML or JSON for example.
Here is an example, named `example.json`, given the following JSON:
```
{ "field1": "abc" }
```
You can run the result script (named `validate`) as the following:
```console
$ nix-build validator.nix
$ ./result example.json
$ ./result-2 example.json
field1: conflicting values "unused" and "abc":
./example.json:1:13
../../../../../../nix/store/v64dzx3vr3glpk0cq4hzmh450lrwh6sg-schema.cue:5:11
$ sed -i 's/"abc"/3/' example.json
$ ./result example.json
field1: conflicting values 3 and string (mismatched types int and string):
./example.json:1:13
../../../../../../nix/store/v64dzx3vr3glpk0cq4hzmh450lrwh6sg-schema.cue:5:11
```
**Known limitations**
* The script will enforce **concrete** values and will not accept lossy transformations (strictness). You can add these options if you need them.

View File

@@ -0,0 +1,142 @@
# Dart {#sec-language-dart}
## Dart applications {#ssec-dart-applications}
The function `buildDartApplication` builds Dart applications managed with pub.
It fetches its Dart dependencies automatically through `pub2nix`, and (through a series of hooks) builds and installs the executables specified in the pubspec file. The hooks can be used in other derivations, if needed. The phases can also be overridden to do something different from installing binaries.
If you are packaging a Flutter desktop application, use [`buildFlutterApplication`](#ssec-dart-flutter) instead.
`pubspecLock` is the parsed pubspec.lock file. pub2nix uses this to download required packages.
This can be converted to JSON from YAML with something like `yq . pubspec.lock`, and then read by Nix.
Alternatively, `autoPubspecLock` can be used instead, and set to a path to a regular `pubspec.lock` file. This relies on import-from-derivation, and is not permitted in Nixpkgs, but can be useful at other times.
::: {.warning}
When using `autoPubspecLock` with a local source directory, make sure to use a
concatenation operator (e.g. `autoPubspecLock = src + "/pubspec.lock";`), and
not string interpolation.
String interpolation will copy your entire source directory to the Nix store and
use its store path, meaning that unrelated changes to your source tree will
cause the generated `pubspec.lock` derivation to rebuild!
:::
If the package has Git package dependencies, the hashes must be provided in the `gitHashes` set. If a hash is missing, an error message prompting you to add it will be shown.
The `dart` commands run can be overridden through `pubGetScript` and `dartCompileCommand`; you can also add flags using `dartCompileFlags` or `dartJitFlags`.
Dart supports multiple [outputs types](https://dart.dev/tools/dart-compile#types-of-output); you can choose between them using `dartOutputType` (defaults to `exe`). If you want to override the binaries path or the source path they come from, you can use `dartEntryPoints`. Outputs that require a runtime will automatically be wrapped with the relevant runtime (`dartaotruntime` for `aot-snapshot`, `dart run` for `jit-snapshot` and `kernel`, `node` for `js`); this can be overridden through `dartRuntimeCommand`.
```nix
{
lib,
buildDartApplication,
fetchFromGitHub,
}:
buildDartApplication rec {
pname = "dart-sass";
version = "1.62.1";
src = fetchFromGitHub {
owner = "sass";
repo = "dart-sass";
tag = version;
hash = "sha256-U6enz8yJcc4Wf8m54eYIAnVg/jsGi247Wy8lp1r1wg4=";
};
pubspecLock = lib.importJSON ./pubspec.lock.json;
}
```
### Patching dependencies {#ssec-dart-applications-patching-dependencies}
Some Dart packages require patches or build environment changes. Package derivations can be customised with the `customSourceBuilders` argument.
A collection of such customisations can be found in Nixpkgs, in the `development/compilers/dart/package-source-builders` directory.
This allows fixes for packages to be shared between all applications that use them. It is strongly recommended to add to this collection instead of including fixes in your application derivation itself.
### Running executables from dev_dependencies {#ssec-dart-applications-build-tools}
Many Dart applications require executables from the `dev_dependencies` section in `pubspec.yaml` to be run before building them.
This can be done in `preBuild`, in one of two ways:
1. Packaging the tool with `buildDartApplication`, adding it to Nixpkgs, and running it like any other application
2. Running the tool from the package cache
Of these methods, the first is recommended when using a tool that does not need
to be of a specific version.
For the second method, the `packageRun` function from the `dartConfigHook` can be used.
This is an alternative to `dart run` that does not rely on Pub.
e.g., for `build_runner`:
```bash
packageRun build_runner build
```
Do _not_ use `dart run <package_name>`, as this will attempt to download dependencies with Pub.
### Usage with nix-shell {#ssec-dart-applications-nix-shell}
#### Using dependencies from the Nix store {#ssec-dart-applications-nix-shell-deps}
As `buildDartApplication` provides dependencies instead of `pub get`, Dart needs to be explicitly told where to find them.
Run the following commands in the source directory to configure Dart appropriately.
Do not use `pub` after doing so; it will download the dependencies itself and overwrite these changes.
```bash
cp --no-preserve=all "$pubspecLockFilePath" pubspec.lock
mkdir -p .dart_tool && cp --no-preserve=all "$packageConfig" .dart_tool/package_config.json
```
## Flutter applications {#ssec-dart-flutter}
The function `buildFlutterApplication` builds Flutter applications.
See the [Dart documentation](#ssec-dart-applications) for more details on required files and arguments.
`flutter` in Nixpkgs always points to `flutterPackages.stable`, which is the latest packaged version. To avoid unforeseen breakage during upgrade, packages in Nixpkgs should use a specific flutter version, such as `flutter319` and `flutter322`, instead of using `flutter` directly.
```nix
{ flutter322, fetchFromGitHub }:
flutter322.buildFlutterApplication {
pname = "firmware-updater";
version = "0-unstable-2023-04-30";
# To build for the Web, use the targetFlutterPlatform argument.
# targetFlutterPlatform = "web";
src = fetchFromGitHub {
owner = "canonical";
repo = "firmware-updater";
rev = "6e7dbdb64e344633ea62874b54ff3990bd3b8440";
hash = "sha256-s5mwtr5MSPqLMN+k851+pFIFFPa0N1hqz97ys050tFA=";
fetchSubmodules = true;
};
pubspecLock = lib.importJSON ./pubspec.lock.json;
}
```
### Usage with nix-shell {#ssec-dart-flutter-nix-shell}
Flutter-specific `nix-shell` usage notes are included here. See the [Dart documentation](#ssec-dart-applications-nix-shell) for general `nix-shell` instructions.
#### Entering the shell {#ssec-dart-flutter-nix-shell-enter}
By default, dependencies for only the `targetFlutterPlatform` are available in the
build environment. This is useful for keeping closures small but can be problematic
during development. It's common, for example, to build Web apps for Linux during
development to take advantage of native features such as stateful hot reload.
To enter a shell with all the usual target platforms available, use the `multiShell` attribute.
e.g. `nix-shell '<nixpkgs>' -A fluffychat-web.multiShell`.

View File

@@ -0,0 +1,471 @@
# Dhall {#sec-language-dhall}
The Nixpkgs support for Dhall assumes some familiarity with Dhall's language
support for importing Dhall expressions, which is documented here:
* [`dhall-lang.org` - Installing packages](https://docs.dhall-lang.org/tutorials/Language-Tour.html#installing-packages)
## Remote imports {#ssec-dhall-remote-imports}
Nixpkgs bypasses Dhall's support for remote imports using Dhall's
semantic integrity checks. Specifically, any Dhall import can be protected by
an integrity check like:
```dhall
https://prelude.dhall-lang.org/v20.1.0/package.dhall
sha256:26b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
```
… and if the import is cached, then the interpreter will load the import from
the cache instead of fetching the URL.
Nixpkgs uses this trick to add all of a Dhall expression's dependencies into the
cache so that the Dhall interpreter never needs to resolve any remote URLs. In
fact, Nixpkgs uses a Dhall interpreter with remote imports disabled when
packaging Dhall expressions to enforce that the interpreter never resolves a
remote import. This means that Nixpkgs only supports building Dhall expressions
if all of their remote imports are protected by semantic integrity checks.
Instead of remote imports, Nixpkgs uses Nix to fetch remote Dhall code. For
example, the Prelude Dhall package uses `pkgs.fetchFromGitHub` to fetch the
`dhall-lang` repository containing the Prelude. Relying exclusively on Nix
to fetch Dhall code ensures that Dhall packages built using Nix remain pure and
also behave well when built within a sandbox.
## Packaging a Dhall expression from scratch {#ssec-dhall-packaging-expression}
We can illustrate how Nixpkgs integrates Dhall by beginning from the following
trivial Dhall expression with one dependency (the Prelude):
```dhall
-- ./true.dhall
let Prelude = https://prelude.dhall-lang.org/v20.1.0/package.dhall
in Prelude.Bool.not False
```
As written, this expression cannot be built using Nixpkgs because the
expression does not protect the Prelude import with a semantic integrity
check, so the first step is to freeze the expression using `dhall freeze`,
like this:
```ShellSession
$ dhall freeze --inplace ./true.dhall
```
… which gives us:
```dhall
-- ./true.dhall
let Prelude =
https://prelude.dhall-lang.org/v20.1.0/package.dhall
sha256:26b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
in Prelude.Bool.not False
```
To package that expression, we create a `./true.nix` file containing the
following specification for the Dhall package:
```nix
# ./true.nix
{ buildDhallPackage, Prelude }:
buildDhallPackage {
name = "true";
code = ./true.dhall;
dependencies = [ Prelude ];
source = true;
}
```
… and we complete the build by incorporating that Dhall package into the
`pkgs.dhallPackages` hierarchy using an overlay, like this:
```nix
# ./example.nix
let
nixpkgs = fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/94b2848559b12a8ed1fe433084686b2a81123c99.tar.gz";
hash = "sha256-B4Q3c6IvTLg3Q92qYa8y+i4uTaphtFdjp+Ir3QQjdN0=";
};
dhallOverlay = self: super: { true = self.callPackage ./true.nix { }; };
overlay = self: super: {
dhallPackages = super.dhallPackages.override (old: {
overrides = self.lib.composeExtensions (old.overrides or (_: _: { })) dhallOverlay;
});
};
pkgs = import nixpkgs {
config = { };
overlays = [ overlay ];
};
in
pkgs
```
… which we can then build using this command:
```ShellSession
$ nix build --file ./example.nix dhallPackages.true
```
## Contents of a Dhall package {#ssec-dhall-package-contents}
The above package produces the following directory tree:
```ShellSession
$ tree -a ./result
result
├── .cache
│   └── dhall
│   └── 122027abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
├── binary.dhall
└── source.dhall
```
… where:
* `source.dhall` contains the result of interpreting our Dhall package:
```ShellSession
$ cat ./result/source.dhall
True
```
* The `.cache` subdirectory contains one binary cache product encoding the
same result as `source.dhall`:
```ShellSession
$ dhall decode < ./result/.cache/dhall/122027abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
True
```
* `binary.dhall` contains a Dhall expression which handles fetching and decoding
the same cache product:
```ShellSession
$ cat ./result/binary.dhall
missing sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
$ cp -r ./result/.cache .cache
$ chmod -R u+w .cache
$ XDG_CACHE_HOME=.cache dhall --file ./result/binary.dhall
True
```
The `source.dhall` file is only present for packages that specify
`source = true;`. By default, Dhall packages omit the `source.dhall` in order
to conserve disk space when they are used exclusively as dependencies. For
example, if we build the Prelude package it will only contain the binary
encoding of the expression:
```ShellSession
$ nix build --file ./example.nix dhallPackages.Prelude
$ tree -a result
result
├── .cache
│   └── dhall
│   └── 122026b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
└── binary.dhall
2 directories, 2 files
```
Typically, you only specify `source = true;` for the top-level Dhall expression
of interest (such as our example `true.nix` Dhall package). However, if you
wish to specify `source = true` for all Dhall packages, then you can amend the
Dhall overlay like this:
```nix
{
dhallOverrides = self: super: {
# Enable source for all Dhall packages
buildDhallPackage = args: super.buildDhallPackage (args // { source = true; });
true = self.callPackage ./true.nix { };
};
}
```
… and now the Prelude will contain the fully decoded result of interpreting
the Prelude:
```ShellSession
$ nix build --file ./example.nix dhallPackages.Prelude
$ tree -a result
result
├── .cache
│   └── dhall
│   └── 122026b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
├── binary.dhall
└── source.dhall
$ cat ./result/source.dhall
{ Bool =
{ and =
\(_ : List Bool) ->
List/fold Bool _ Bool (\(_ : Bool) -> \(_ : Bool) -> _@1 && _) True
, build = \(_ : Type -> _ -> _@1 -> _@2) -> _ Bool True False
, even =
\(_ : List Bool) ->
List/fold Bool _ Bool (\(_ : Bool) -> \(_ : Bool) -> _@1 == _) True
, fold =
\(_ : Bool) ->
```
## Packaging functions {#ssec-dhall-packaging-functions}
We already saw an example of using `buildDhallPackage` to create a Dhall
package from a single file, but most Dhall packages consist of more than one
file and there are two derived utilities that you may find more useful when
packaging multiple files:
* `buildDhallDirectoryPackage` - build a Dhall package from a local directory
* `buildDhallGitHubPackage` - build a Dhall package from a GitHub repository
The `buildDhallPackage` is the lowest-level function and accepts the following
arguments:
* `name`: The name of the derivation
* `dependencies`: Dhall dependencies to build and cache ahead of time
* `code`: The top-level expression to build for this package
Note that the `code` field accepts an arbitrary Dhall expression. You're
not limited to just a file.
* `source`: Set to `true` to include the decoded result as `source.dhall` in the
build product, at the expense of requiring more disk space
* `documentationRoot`: Set to the root directory of the package if you want
`dhall-docs` to generate documentation underneath the `docs` subdirectory of
the build product
The `buildDhallDirectoryPackage` is a higher-level function implemented in terms
of `buildDhallPackage` that accepts the following arguments:
* `name`: Same as `buildDhallPackage`
* `dependencies`: Same as `buildDhallPackage`
* `source`: Same as `buildDhallPackage`
* `src`: The directory containing Dhall code that you want to turn into a Dhall
package
* `file`: The top-level file (`package.dhall` by default) that is the entry point
to the rest of the package
* `document`: Set to `true` to generate documentation for the package
The `buildDhallGitHubPackage` is another higher-level function implemented in
terms of `buildDhallPackage` that accepts the following arguments:
* `name`: Same as `buildDhallPackage`
* `dependencies`: Same as `buildDhallPackage`
* `source`: Same as `buildDhallPackage`
* `owner`: The owner of the repository
* `repo`: The repository name
* `rev`: The desired revision (or branch, or tag)
* `directory`: The subdirectory of the Git repository to package (if a
directory other than the root of the repository)
* `file`: The top-level file (`${directory}/package.dhall` by default) that is
the entry point to the rest of the package
* `document`: Set to `true` to generate documentation for the package
Additionally, `buildDhallGitHubPackage` accepts the same arguments as
`fetchFromGitHub`, such as `hash` or `fetchSubmodules`.
## `dhall-to-nixpkgs` {#ssec-dhall-dhall-to-nixpkgs}
You can use the `dhall-to-nixpkgs` command-line utility to automate
packaging Dhall code. For example:
```ShellSession
$ nix-shell -p haskellPackages.dhall-nixpkgs nix-prefetch-git
[nix-shell]$ dhall-to-nixpkgs github https://github.com/Gabriella439/dhall-semver.git
{ buildDhallGitHubPackage, Prelude }:
buildDhallGitHubPackage {
name = "dhall-semver";
githubBase = "github.com";
owner = "Gabriella439";
repo = "dhall-semver";
rev = "2d44ae605302ce5dc6c657a1216887fbb96392a4";
fetchSubmodules = false;
hash = "sha256-n0nQtswVapWi/x7or0O3MEYmAkt/a1uvlOtnje6GGnk=";
directory = "";
file = "package.dhall";
source = false;
document = false;
dependencies = [ (Prelude.overridePackage { file = "package.dhall"; }) ];
}
```
:::{.note}
`nix-prefetch-git` is added to the `nix-shell -p` invocation above, because it has to be in `$PATH` for `dhall-to-nixpkgs` to work.
:::
The utility takes care of automatically detecting remote imports and converting
them to package dependencies. You can also use the utility on local
Dhall directories, too:
```ShellSession
$ dhall-to-nixpkgs directory ~/proj/dhall-semver
{ buildDhallDirectoryPackage, Prelude }:
buildDhallDirectoryPackage {
name = "proj";
src = ~/proj/dhall-semver;
file = "package.dhall";
source = false;
document = false;
dependencies = [ (Prelude.overridePackage { file = "package.dhall"; }) ];
}
```
### Remote imports as fixed-output derivations {#ssec-dhall-remote-imports-as-fod}
`dhall-to-nixpkgs` has the ability to fetch and build remote imports as
fixed-output derivations by using their Dhall integrity check. This is
sometimes easier than manually packaging all remote imports.
This can be used like the following:
```ShellSession
$ dhall-to-nixpkgs directory --fixed-output-derivations ~/proj/dhall-semver
{ buildDhallDirectoryPackage, buildDhallUrl }:
buildDhallDirectoryPackage {
name = "proj";
src = ~/proj/dhall-semver;
file = "package.dhall";
source = false;
document = false;
dependencies = [
(buildDhallUrl {
url = "https://prelude.dhall-lang.org/v17.0.0/package.dhall";
hash = "sha256-ENs8kZwl6QRoM9+Jeo/+JwHcOQ+giT2VjDQwUkvlpD4=";
dhallHash = "sha256:10db3c919c25e9046833df897a8ffe2701dc390fa0893d958c3430524be5a43e";
})
];
}
```
Here, `dhall-semver`'s `Prelude` dependency is fetched and built with the
`buildDhallUrl` helper function, instead of being passed in as a function
argument.
## Overriding dependency versions {#ssec-dhall-overriding-dependency-versions}
Suppose that we change our `true.dhall` example expression to depend on an older
version of the Prelude (19.0.0):
```dhall
-- ./true.dhall
let Prelude =
https://prelude.dhall-lang.org/v19.0.0/package.dhall
sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2
in Prelude.Bool.not False
```
If we try to rebuild that expression the build will fail:
```ShellSession
$ nix build --file ./example.nix dhallPackages.true
builder for '/nix/store/0f1hla7ff1wiaqyk1r2ky4wnhnw114fi-true.drv' failed with exit code 1; last 10 log lines:
Dhall was compiled without the 'with-http' flag.
The requested URL was: https://prelude.dhall-lang.org/v19.0.0/package.dhall
4│ https://prelude.dhall-lang.org/v19.0.0/package.dhall
5│ sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2
/nix/store/rsab4y99h14912h4zplqx2iizr5n4rc2-true.dhall:4:7
[1 built (1 failed), 0.0 MiB DL]
error: build of '/nix/store/0f1hla7ff1wiaqyk1r2ky4wnhnw114fi-true.drv' failed
```
… because the default Prelude selected by Nixpkgs revision
`94b2848559b12a8ed1fe433084686b2a81123c99` is version 20.1.0, which doesn't
have the same integrity check as version 19.0.0. This means that version
19.0.0 is not cached, and the interpreter is not allowed to fall back to
importing the URL.
However, we can override the default Prelude version by using `dhall-to-nixpkgs`
to create a Dhall package for our desired Prelude:
```ShellSession
$ dhall-to-nixpkgs github https://github.com/dhall-lang/dhall-lang.git \
--name Prelude \
--directory Prelude \
--rev v19.0.0 \
> Prelude.nix
```
… and then referencing that package in our Dhall overlay, by either overriding
the Prelude globally for all packages, like this:
```nix
{
dhallOverrides = self: super: {
true = self.callPackage ./true.nix { };
Prelude = self.callPackage ./Prelude.nix { };
};
}
```
… or selectively overriding the Prelude dependency for just the `true` package,
like this:
```nix
{
dhallOverrides = self: super: {
true = self.callPackage ./true.nix {
Prelude = self.callPackage ./Prelude.nix { };
};
};
}
```
## Overrides {#ssec-dhall-overrides}
You can override any of the arguments to `buildDhallGitHubPackage` or
`buildDhallDirectoryPackage` using the `overridePackage` attribute of a package.
For example, suppose we wanted to selectively enable `source = true` just for the Prelude. We can do that like this:
```nix
{
dhallOverrides = self: super: {
Prelude = super.Prelude.overridePackage { source = true; };
# ...
};
}
```
[semantic-integrity-checks]: https://docs.dhall-lang.org/tutorials/Language-Tour.html#installing-packages

View File

@@ -0,0 +1,69 @@
# D (Dlang) {#dlang}
Nixpkgs provides multiple D compilers such as `ldc` and `dmd`.
These can be used like any other package during build time.
However, Nixpkgs provides a build helper for compiling packages using the `dub` package manager.
Here's an example:
```nix
{
lib,
buildDubPackage,
fetchFromGitHub,
ncurses,
zlib,
}:
buildDubPackage rec {
pname = "btdu";
version = "0.5.1";
src = fetchFromGitHub {
owner = "CyberShadow";
repo = "btdu";
tag = "v${version}";
hash = "sha256-3sSZq+5UJH02IO0Y1yL3BLHDb4lk8k6awb5ZysBQciE=";
};
# generated by dub-to-nix, see below
dubLock = ./dub-lock.json;
buildInputs = [
ncurses
zlib
];
installPhase = ''
runHook preInstall
install -Dm755 btdu -t $out/bin
runHook postInstall
'';
}
```
Note that you need to define `installPhase` because `dub` doesn't know where files should go in `$out`.
Also note that running `dub test` is disabled by default. You can enable it by setting `doCheck = true`.
## Lockfiles {#dub-lockfiles}
Nixpkgs has its own lockfile format for `dub` dependencies, because `dub`'s official "lockfile" format (`dub.selections.json`) is not hash-based.
A lockfile can be generated using the `dub-to-nix` helper package.
* Firstly, install `dub-to-nix` into your shell session by running `nix-shell -p dub-to-nix`.
* Then navigate to the root of the source of the program you want to package.
* Finally, run `dub-to-nix`, and it will print the lockfile to stdout. You can pipe stdout into a text file or just copy the output manually into a file.
## `buildDubPackage` parameters {#builddubpackage-parameters}
The `buildDubPackage` function takes an attrset of parameters that are passed on to `stdenv.mkDerivation`.
The following parameters are specific to `buildDubPackage`:
* `dubLock`: A lockfile generated by `dub-to-nix` from the source of the package. Can be either a path to the file, or an attrset already parsed with `lib.importJSON`.
The latter useful if the package uses `dub` dependencies not already in the lockfile. (e.g. if the package calls `dub run some-dub-package` manually)
* `dubBuildType ? "release"`: The build type to pass to `dub build` as a value for the `--build=` flag.
* `dubFlags ? []`: The flags to pass to `dub build` and `dub test`.
* `dubBuildFlags ? []`: The flags to pass to `dub build`.
* `dubTestFlags ? []`: The flags to pass to `dub test`.
* `compiler ? ldc`: The D compiler to be used by `dub`.

View File

@@ -0,0 +1,303 @@
# Dotnet {#dotnet}
## Local Development Workflow {#local-development-workflow}
For local development, it's recommended to use nix-shell to create a dotnet environment:
```nix
# shell.nix
with import <nixpkgs> { };
mkShell {
name = "dotnet-env";
packages = [ dotnet-sdk ];
}
```
### Using many sdks in a workflow {#using-many-sdks-in-a-workflow}
It's very likely that more than one sdk will be needed on a given project. Dotnet provides several different frameworks (E.g dotnetcore, aspnetcore, etc.) as well as many versions for a given framework. Normally, dotnet is able to fetch a framework and install it relative to the executable. However, this would mean writing to the nix store in nixpkgs, which is read-only. To support the many-sdk use case, one can compose an environment using `dotnetCorePackages.combinePackages`:
```nix
with import <nixpkgs> { };
mkShell {
name = "dotnet-env";
packages = [
(
with dotnetCorePackages;
combinePackages [
sdk_8_0
sdk_9_0
]
)
];
}
```
This will produce a dotnet installation that has the dotnet 8.0 9.0 sdk. The first sdk listed will have its cli utility present in the resulting environment. Example info output:
```ShellSession
$ dotnet --info
.NET SDK:
Version: 9.0.100
Commit: 59db016f11
Workload version: 9.0.100-manifests.3068a692
MSBuild version: 17.12.7+5b8665660
Runtime Environment:
OS Name: nixos
OS Version: 25.05
OS Platform: Linux
RID: linux-x64
Base Path: /nix/store/a03c70i7x6rjdr6vikczsp5ck3v6rixh-dotnet-sdk-9.0.100/share/dotnet/sdk/9.0.100/
.NET workloads installed:
There are no installed workloads to display.
Configured to use loose manifests when installing new manifests.
Host:
Version: 9.0.0
Architecture: x64
Commit: 9d5a6a9aa4
.NET SDKs installed:
8.0.404 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/sdk]
9.0.100 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.11 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.0 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.11 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.0 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
```
## dotnet-sdk vs dotnetCorePackages.sdk {#dotnet-sdk-vs-dotnetcorepackages.sdk}
The `dotnetCorePackages.sdk_X_Y` is preferred over the old dotnet-sdk as both major and minor version are very important for a dotnet environment. If a given minor version isn't present (or was changed), then this will likely break your ability to build a project.
## dotnetCorePackages.sdk vs dotnetCorePackages.runtime vs dotnetCorePackages.aspnetcore {#dotnetcorepackages.sdk-vs-dotnetcorepackages.runtime-vs-dotnetcorepackages.aspnetcore}
The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given version. The `runtime` and `aspnetcore` packages are meant to serve as minimal runtimes to deploy alongside already built applications.
## Packaging a Dotnet Application {#packaging-a-dotnet-application}
To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions:
* `projectFile` is used for specifying the dotnet project file, relative to the source root. These have `.sln` (entire solution) or `.csproj` (single project) file extensions. This can be a list of multiple projects as well. When omitted, will attempt to find and build the solution (`.sln`). If running into problems, make sure to set it to a file (or a list of files) with the `.csproj` extension - building applications as entire solutions is not fully supported by the .NET CLI.
* `nugetDeps` should be a path to a JSON file, a path to a nix file (deprecated), a derivation, or a list of derivations. A `deps.json` file can be generated using the script attached to `passthru.fetch-deps`, which is the preferred method. All `nugetDeps` packages are added to `buildInputs`.
::: {.note}
For more detail about managing the `deps.json` file, see [Generating and updating NuGet dependencies](#generating-and-updating-nuget-dependencies)
:::
* `packNupkg` is used to pack project as a `nupkg`, and installs it to `$out/share`. If set to `true`, the derivation can be used as a dependency for another dotnet project by adding it to `buildInputs`.
* `buildInputs` can be used to resolve `ProjectReference` project items. Referenced projects can be packed with `buildDotnetModule` by setting the `packNupkg = true` attribute and passing a list of derivations to `buildInputs`. Since we are sharing referenced projects as NuGets they must be added to csproj/fsproj files as `PackageReference` as well.
For example, your project has a local dependency:
```xml
<ProjectReference Include="../foo/bar.fsproj" />
```
To enable discovery through `buildInputs` you would need to add:
```xml
<ProjectReference Include="../foo/bar.fsproj" />
<PackageReference Include="bar" Version="*" Condition=" '$(ContinuousIntegrationBuild)'=='true' "/>
```
* `executables` is used to specify which executables get wrapped to `$out/bin`, relative to `$out/lib/$pname`. If this is unset, all executables generated will get installed. If you do not want to install any, set this to `[]`. This gets done in the `preFixup` phase.
* `runtimeDeps` is used to wrap libraries into `LD_LIBRARY_PATH`. This is how dotnet usually handles runtime dependencies.
* `buildType` is used to change the type of build. Possible values are `Release`, `Debug`, etc. By default, this is set to `Release`.
* `selfContainedBuild` allows to enable the [self-contained](https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-self-contained) build flag. By default, it is set to false and generated applications have a dependency on the selected dotnet runtime. If enabled, the dotnet runtime is bundled into the executable and the built app has no dependency on .NET.
* `useAppHost` will enable creation of a binary executable that runs the .NET application using the specified root. More info in [Microsoft docs](https://learn.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent). Enabled by default.
* `useDotnetFromEnv` will change the binary wrapper so that it uses the .NET from the environment. The runtime specified by `dotnet-runtime` is given as a fallback in case no .NET is installed in the user's environment. This is most useful for .NET global tools and LSP servers, which often extend the .NET CLI and their runtime should match the user's .NET runtime.
* `dotnet-sdk` is useful in cases where you need to change what dotnet SDK is being used. You can also set this to the result of `dotnetSdkPackages.combinePackages`, if the project uses multiple SDKs to build.
* `dotnet-runtime` is useful in cases where you need to change what dotnet runtime is being used. This can be either a regular dotnet runtime, or an aspnetcore.
* `testProjectFile` is useful in cases where the regular project file does not contain the unit tests. It gets restored and build, but not installed. You may need to regenerate your nuget lockfile after setting this. Note that if set, only tests from this project are executed.
* `testFilters` is used to disable running unit tests based on various [filters](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test#filter-option-details). This gets passed as: `dotnet test --filter "{}"`, with each filter being concatenated using `"&"`.
* `disabledTests` is used to disable running specific unit tests. This gets passed as: `dotnet test --filter "FullyQualifiedName!={}"`, to ensure compatibility with all unit test frameworks.
* `dotnetRestoreFlags` can be used to pass flags to `dotnet restore`.
* `dotnetBuildFlags` can be used to pass flags to `dotnet build`.
* `dotnetTestFlags` can be used to pass flags to `dotnet test`. Used only if `doCheck` is set to `true`.
* `dotnetInstallFlags` can be used to pass flags to `dotnet install`.
* `dotnetPackFlags` can be used to pass flags to `dotnet pack`. Used only if `packNupkg` is set to `true`.
* `dotnetFlags` can be used to pass flags to all of the above phases.
When packaging a new application, you need to fetch its dependencies. Create an empty `deps.json`, set `nugetDeps = ./deps.json`, then run `nix-build -A package.fetch-deps` to generate a script that will build the lockfile for you.
Here is an example `default.nix`, using some of the previously discussed arguments:
```nix
{
lib,
buildDotnetModule,
dotnetCorePackages,
ffmpeg,
}:
let
referencedProject = import ../../bar {
# ...
};
in
buildDotnetModule rec {
pname = "someDotnetApplication";
version = "0.1";
src = ./.;
projectFile = "src/project.sln";
nugetDeps = ./deps.json; # see "Generating and updating NuGet dependencies" section for details
buildInputs = [
referencedProject
]; # `referencedProject` must contain `nupkg` in the folder structure.
dotnet-sdk = dotnetCorePackages.sdk_8_0;
dotnet-runtime = dotnetCorePackages.runtime_8_0;
executables = [ "foo" ]; # This wraps "$out/lib/$pname/foo" to `$out/bin/foo`.
executables = [ ]; # Don't install any executables.
packNupkg = true; # This packs the project as "foo-0.1.nupkg" at `$out/share`.
runtimeDeps = [ ffmpeg ]; # This will wrap ffmpeg's library path into `LD_LIBRARY_PATH`.
}
```
Keep in mind that you can tag the [`@NixOS/dotnet`](https://github.com/orgs/nixos/teams/dotnet) team for help and code review.
## Dotnet global tools {#dotnet-global-tools}
[.NET Global tools](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools) are a mechanism provided by the dotnet CLI to install .NET binaries from Nuget packages.
They can be installed either as a global tool for the entire system, or as a local tool specific to project.
The local installation is the easiest and works on NixOS in the same way as on other Linux distributions.
[See dotnet documentation](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-local-tool) to learn more.
[The global installation method](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-global-tool)
should also work most of the time. You have to remember to update the `PATH`
value to the location the tools are installed to (the CLI will inform you about it during installation) and also set
the `DOTNET_ROOT` value, so that the tool can find the .NET SDK package.
You can find the path to the SDK by running `nix eval --raw nixpkgs#dotnet-sdk` (substitute the `dotnet-sdk` package for
another if a different SDK version is needed).
This method is not recommended on NixOS, since it's not declarative and involves installing binaries not made for NixOS,
which will not always work.
The third, and preferred way, is packaging the tool into a Nix derivation.
### Packaging Dotnet global tools {#packaging-dotnet-global-tools}
Dotnet global tools are standard .NET binaries, just made available through a special
NuGet package. Therefore, they can be built and packaged like every .NET application,
using `buildDotnetModule`.
If however the source is not available or difficult to build, the
`buildDotnetGlobalTool` helper can be used, which will package the tool
straight from its NuGet package.
This helper has the same arguments as `buildDotnetModule`, with a few differences:
* `pname` and `version` are required, and will be used to find the NuGet package of the tool
* `nugetName` can be used to override the NuGet package name that will be downloaded, if it's different from `pname`
* `nugetHash` is the hash of the fetched NuGet package. `nugetSha256` is also supported, but not recommended. Set this to `lib.fakeHash` for the first build, and it will error out, giving you the proper hash. Also remember to update it during version updates (it will not error out if you just change the version while having a fetched package in `/nix/store`)
* `dotnet-runtime` is set to `dotnet-sdk` by default. When changing this, remember that .NET tools fetched from NuGet require an SDK.
Here is an example of packaging `pbm`, an unfree binary without source available:
```nix
{ buildDotnetGlobalTool, lib }:
buildDotnetGlobalTool {
pname = "pbm";
version = "1.3.1";
nugetHash = "sha256-ZG2HFyKYhVNVYd2kRlkbAjZJq88OADe3yjxmLuxXDUo=";
meta = {
homepage = "https://cmd.petabridge.com/index.html";
changelog = "https://cmd.petabridge.com/articles/RELEASE_NOTES.html";
license = lib.licenses.unfree;
platforms = lib.platforms.linux;
};
}
```
## Generating and updating NuGet dependencies {#generating-and-updating-nuget-dependencies}
When writing a new expression, you can use the generated `fetch-deps` script to initialise the lockfile.
After setting `nugetDeps` to the desired location of the lockfile (e.g. `./deps.json`),
build the script with `nix-build -A package.fetch-deps` and then run the result.
(When the root attr is your package, it's simply `nix-build -A fetch-deps`.)
There is also a manual method:
First, restore the packages to the `out` directory, ensure you have cloned
the upstream repository and you are inside it.
```bash
$ dotnet restore --packages out
Determining projects to restore...
Restored /home/ggg/git-credential-manager/src/shared/Git-Credential-Manager/Git-Credential-Manager.csproj (in 1.21 sec).
```
Next, use the `nuget-to-json` tool provided in Nixpkgs to generate a lockfile to `deps.json` from
the packages inside the `out` directory.
```bash
$ nuget-to-json out > deps.json
```
The `nuget-to-json` tool will generate an output similar to the one below
```json
[
{
"pname": "Avalonia",
"version": "11.1.3",
"hash": "sha256-kz+k/vkuWoL0XBvRT8SadMOmmRCFk9W/J4k/IM6oYX0="
},
{
"pname": "Avalonia.Angle.Windows.Natives",
"version": "2.1.22045.20230930",
"hash": "sha256-RxPcWUT3b/+R3Tu5E5ftpr5ppCLZrhm+OTsi0SwW3pc="
},
{
"pname": "Avalonia.BuildServices",
"version": "0.0.29",
"hash": "sha256-WPHRMNowRnYSCh88DWNBCltWsLPyOfzXGzBqLYE7tRY="
},
// ...
{
"pname": "System.Runtime.CompilerServices.Unsafe",
"version": "6.0.0",
"hash": "sha256-bEG1PnDp7uKYz/OgLOWs3RWwQSVYm+AnPwVmAmcgp2I="
},
{
"pname": "System.Security.Cryptography.ProtectedData",
"version": "4.5.0",
"hash": "sha256-Z+X1Z2lErLL7Ynt2jFszku6/IgrngO3V1bSfZTBiFIc="
},
{
"pname": "Tmds.DBus.Protocol",
"version": "0.16.0",
"hash": "sha256-vKYEaa1EszR7alHj48R8G3uYArhI+zh2ZgiBv955E98="
}
]
```
Finally, you move the `deps.json` file to the appropriate location to be used by `nugetDeps`, then you're all set!
If you ever need to update the dependencies of a package, you instead do
* `nix-build -A package.fetch-deps` to generate the update script for `package`
* Run `./result` to regenerate the lockfile to the path passed for `nugetDeps` (keep in mind if it can't be resolved to a local path, the script will write to `$1` or a temporary path instead)
* Finally, ensure the correct file was written and the derivation can be built.

View File

@@ -0,0 +1,216 @@
# Emscripten {#emscripten}
[Emscripten](https://github.com/kripken/emscripten): An LLVM-to-JavaScript Compiler
If you want to work with `emcc`, `emconfigure` and `emmake` as you are used to from Ubuntu and similar distributions,
```console
nix-shell -p emscripten
```
A few things to note:
* `export EMCC_DEBUG=2` is nice for debugging
* The build artifact cache in `~/.emscripten` sometimes creates issues and needs to be removed from time to time
## Examples {#declarative-usage}
Let's see two different examples from `pkgs/top-level/emscripten-packages.nix`:
* `pkgs.zlib.override`
* `pkgs.buildEmscriptenPackage`
A special requirement of the `pkgs.buildEmscriptenPackage` is the `doCheck = true`.
This means each Emscripten package requires that a [`checkPhase`](#ssec-check-phase) is implemented.
* Use `export EMCC_DEBUG=2` from within a phase to get more detailed debug output what is going wrong.
* The cache at `~/.emscripten` requires to set `HOME=$TMPDIR` in individual phases.
This makes compilation slower but also more deterministic.
::: {.example #usage-1-pkgs.zlib.override}
# Using `pkgs.zlib.override {}`
This example uses `zlib` from Nixpkgs, but instead of compiling **C** to **ELF** it compiles **C** to **JavaScript** since we were using `pkgs.zlib.override` and changed `stdenv` to `pkgs.emscriptenStdenv`.
A few adaptions and hacks were put in place to make it work.
One advantage is that when `pkgs.zlib` is updated, it will automatically update this package as well.
```nix
(pkgs.zlib.override { stdenv = pkgs.emscriptenStdenv; }).overrideAttrs (old: {
buildInputs = old.buildInputs ++ [ pkg-config ];
# we need to reset this setting!
env = (old.env or { }) // {
NIX_CFLAGS_COMPILE = "";
};
configurePhase = ''
# FIXME: Some tests require writing at $HOME
HOME=$TMPDIR
runHook preConfigure
#export EMCC_DEBUG=2
emconfigure ./configure --prefix=$out --shared
runHook postConfigure
'';
dontStrip = true;
outputs = [ "out" ];
buildPhase = ''
runHook preBuild
emmake make
runHook postBuild
'';
installPhase = ''
runHook preInstall
emmake make install
runHook postInstall
'';
checkPhase = ''
runHook preCheck
echo "================= testing zlib using node ================="
echo "Compiling a custom test"
set -x
emcc -O2 -s EMULATE_FUNCTION_POINTER_CASTS=1 test/example.c -DZ_SOLO \
libz.so.${old.version} -I . -o example.js
echo "Using node to execute the test"
${pkgs.nodejs}/bin/node ./example.js
set +x
if [ $? -ne 0 ]; then
echo "test failed for some reason"
exit 1;
else
echo "it seems to work! very good."
fi
echo "================= /testing zlib using node ================="
runHook postCheck
'';
postPatch = pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isDarwin ''
substituteInPlace configure \
--replace-fail '/usr/bin/libtool' 'ar' \
--replace-fail 'AR="libtool"' 'AR="ar"' \
--replace-fail 'ARFLAGS="-o"' 'ARFLAGS="-r"'
'';
})
```
:::{.example #usage-2-pkgs.buildemscriptenpackage}
# Using `pkgs.buildEmscriptenPackage {}`
This `xmlmirror` example features an Emscripten package that is defined completely from this context and no `pkgs.zlib.override` is used.
```nix
pkgs.buildEmscriptenPackage {
pname = "xmlmirror";
version = "1.2.3";
buildInputs = [
pkg-config
autoconf
automake
libtool
gnumake
libxml2
nodejs
openjdk
json_c
];
nativeBuildInputs = [
pkg-config
writableTmpDirAsHomeHook
zlib
];
src = pkgs.fetchgit {
url = "https://gitlab.com/odfplugfest/xmlmirror.git";
rev = "4fd7e86f7c9526b8f4c1733e5c8b45175860a8fd";
hash = "sha256-i+QgY+5PYVg5pwhzcDnkfXAznBg3e8sWH2jZtixuWsk=";
};
configurePhase = ''
runHook preConfigure
rm -f fastXmlLint.js*
# a fix for ERROR:root:For asm.js, TOTAL_MEMORY must be a multiple of 16MB, was 234217728
# https://gitlab.com/odfplugfest/xmlmirror/issues/8
sed -e "s/TOTAL_MEMORY=234217728/TOTAL_MEMORY=268435456/g" -i Makefile.emEnv
# https://github.com/kripken/emscripten/issues/6344
# https://gitlab.com/odfplugfest/xmlmirror/issues/9
sed -e "s/\$(JSONC_LDFLAGS) \$(ZLIB_LDFLAGS) \$(LIBXML20_LDFLAGS)/\$(JSONC_LDFLAGS) \$(LIBXML20_LDFLAGS) \$(ZLIB_LDFLAGS) /g" -i Makefile.emEnv
# https://gitlab.com/odfplugfest/xmlmirror/issues/11
sed -e "s/-o fastXmlLint.js/-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]' -o fastXmlLint.js/g" -i Makefile.emEnv
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
make -f Makefile.emEnv
runHook postBuild
'';
outputs = [
"out"
"doc"
];
installPhase = ''
runHook preInstall
mkdir -p $out/share
mkdir -p $doc/share/${name}
cp Demo* $out/share
cp -R codemirror-5.12 $out/share
cp fastXmlLint.js* $out/share
cp *.xsd $out/share
cp *.js $out/share
cp *.xhtml $out/share
cp *.html $out/share
cp *.json $out/share
cp *.rng $out/share
cp README.md $doc/share/${name}
runHook postInstall
'';
checkPhase = ''
runHook preCheck
runHook postCheck
'';
}
```
:::
## Debugging {#declarative-debugging}
Use `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz` and from there you can go trough the individual steps. This makes it easy to build a good `unit test` or list the files of the project.
1. `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz`
2. `cd /tmp/`
3. `unpackPhase`
4. cd libz-1.2.3
5. `configurePhase`
6. `buildPhase`
7. ... happy hacking...

View File

@@ -0,0 +1,228 @@
# Factor {#sec-language-factor}
## Development Environment {#ssec-factor-dev-env}
All Nix expressions for the Factor compiler and development environment can be found in `pkgs/top-level/factor-packages.nix`.
The default package `factor-lang` provides support for the built-in graphical user interface and a selected set of C library bindings, e.g., for sound and TLS connections.
It also comes with the Fuel library for Emacs that provides an integrated development environment for developing Factor programs including access to the Factor runtime and online documentation.
For using less frequently used libraries that need additional bindings, you can override the `factor-lang` package and add more library bindings and/or binaries to its PATH.
The package is defined in `pkgs/development/compilers/factor-lang/wrapper.nix` and provides several attributes for adding those:
- `extraLibs` adds the packages' `/lib` paths to the wrapper and adds all shared libraries to an ld.so cache such that they can be found dynamically by the Factor runtime.
- `binPackages` does the same as `extraLibs` and additionally adds the packages to Factor's PATH environment variable.
- `extraVocabs` adds Factor vocabularies to the tree that are not part of the standard library.
The packages must adhere to the default vocabulary root structure to be found.
- `guiSupport` draws in all necessary graphical libraries to enable the Factor GUI.
This should be set to `true` when considering building and running graphical applications with this Factor runtime (even if the Factor GUI is not used for programming).
This argument is `true` by default.
- `enableDefaults` can be deactivated to only wrap libraries that are named in `extraLibs` or `binPackages`.
This reduces the runtime dependencies especially when shipping Factor applications.
The package also passes through several attributes listing the wrapped libraries and binaries, namely, `extraLibs` and `binPackages` as well as `defaultLibs` and `defaultBins`.
Additionally, all `runtimeLibs` is the concatenation of all the above for the purpose of providing all necessary dynamic libraries as "`propagatedBuildInputs`".
`factorPackages` provides pre-configured Factor packages:
- `factorPackages.factor-lang` is the default package with GUI support and several default library bindings (e.g. openssl, openal etc.).
- `factorPackages.factor-no-gui` turns off GUI support while maintaining default library bindings.
- `factorPackages.factor-minimal` comes with practically no additional library bindings and binaries and no GUI support.
- `factorPackages.factor-minimal-gui` comes with no additional library bindings but includes GUI support.
### Scaffolding and the `work` vocabulary root {#ssec-factor-scaffolding}
Factor uses the concept of "scaffolding" to spin off a new vocabulary in a personal workspace rooted at the `work` vocabulary root.
This concept does not scale very well, because it makes many assumptions which all turn out to be wrong at some point.
In the current implementation, the `work` vocabulary root points to `/var/lib/factor` on the target machine.
This can be suitable for a single-user system.
Create the location and make it writable to your user.
Then, you can use the `scaffold-work` word as instructed by many tutorials.
If you don't like this approach, you can work around it by creating a `~/.factor-roots` file in your home directory which contains the locations you desire to represent additional Factor vocabulary roots, one directory per line.
Use `scaffold-vocab` to create your vocabularies in one of these additional roots.
The online Factor documentation is extensive on how to use the scaffolding framework.
## Packaging Factor Vocabularies {#ssec-factor-packaging}
All Factor vocabularies that shall be added to a Factor environment via the `extraVocabs` attribute must adhere to the following directory scheme.
Its top-level directory must be one (or multiple) of `basis`, `core` or `extra`.
`work` is routed to `/var/lib/factor` and is not shipped nor referenced in the nix store, see the section on [scaffolding](#ssec-factor-scaffolding).
You should usually use `extra`, but you can use the other roots to overwrite built-in vocabularies.
Be aware that vocabularies in `core` are part of the Factor image which the development environment is run from.
This means the code in those vocabularies is not loaded from the sources, such that you need to call `refresh-all` to recompile and load the changed definitions.
In these instances, it is advised to override the `factor-unwrapped` package directly, which compiles and packages the core Factor libraries into the default Factor
image.
As per Factor convention, your vocabulary `foo.factor` must be in a directory of the same name in addition to one of the previously mentioned vocabulary roots, e.g. `extra/foo/foo.factor`.
All extra Factor vocabularies are registered in `pkgs/top-level/factor-packages.nix` and their package definitions usually live in `development/compilers/factor-lang/vocabs/`.
Package a vocabulary using the `buildFactorVocab` function.
Its default `installPhase` takes care of installing it under `out/lib/factor`.
It also understands the following special attributes:
- `vocabName` is the path to the vocabulary to be installed.
Defaults to `pname`.
- `vocabRoot` is the vocabulary root to install the vocabulary under.
Defaults to `extra`.
Unless you know what you are doing, do not change it.
Other readily understood vocabulary roots are `core` and `basis`, which allow you to modify the default Factor runtime environment with an external package.
- `extraLibs`, `extraVocabs`, `extraPaths` have the same meaning as for [applications](#ssec-factor-applications).
They have no immediate effect and are just passed through.
When building factor-lang packages and Factor applications that use this respective vocabulary, these variables are evaluated and their paths added to the runtime environment.
The function understands several forms of source directory trees:
1. Simple single-vocab projects with their Factor and supplementary files directly in the project root.
All `.factor` and `.txt` files are copied to `out/lib/factor/<vocabRoot>/<vocabName>`.
2. More complex projects with several vocabularies next to each other, e.g. `./<vocabName>` and `./<otherVocab>`.
All directories except `bin`, `doc` and `lib` are copied to `out/lib/factor/<vocabRoot>`.
3. Even more complex projects that touch multiple vocabulary roots.
Vocabularies must reside under `lib/factor/<root>/<vocab>` with the name-giving vocabulary being in `lib/factor/<vocabRoot>/<vocabName>`.
All directories in `lib/factor` are copied to `out/`.
For instance, packaging the Bresenham algorithm for line interpolation looks like this, see `pkgs/development/compilers/factor-lang/vocabs/bresenham` for the complete file:
```nix
{ factorPackages, fetchFromGitHub }:
factorPackages.buildFactorVocab {
pname = "bresenham";
version = "dev";
src = fetchFromGitHub {
owner = "Capital-EX";
repo = "bresenham";
rev = "58d76b31a17f547e19597a09d02d46a742bf6808";
hash = "sha256-cfQOlB877sofxo29ahlRHVpN3wYTUc/rFr9CJ89dsME=";
};
}
```
The vocabulary goes to `lib/factor/extra`, extra files, like licenses etc. would go to `share/` as usual and could be added to the output via a `postInstall` phase.
In case the vocabulary binds to a shared library or calls a binary that needs to be present in the runtime environment of its users, add `extraPaths` and `extraLibs` attributes, respectively.
They are then picked up by the `buildFactorApplication` function and added as runtime dependencies.
## Building Applications {#ssec-factor-applications}
Factor applications are built using Factor's `deploy` facility with the help of the `buildFactorApplication` function.
### `buildFactorApplication` function {#ssec-factor-buildFactorApplication-func}
`factorPackages.buildFactorApplication` *`buildDesc`*
When packaging a Factor application with [`buildFactorApplication`](#ssec-factor-buildFactorApplication-func), its [`override`](#sec-pkg-override) interface should contain the `factorPackages` argument.
For example:
```nix
{
lib,
fetchurl,
factorPackages,
}:
factorPackages.buildFactorApplication (finalAttrs: {
pname = "foo";
version = "1.0";
src = fetchurl {
url = "https://some-forge.org/foo-${finalAttrs.version}.tar.gz";
};
})
```
The `buildFactorApplication` function expects the following source structure for a package `foo-1.0` and produces a `/bin/foo` application:
```
foo-1.0/
foo/
foo.factor
deploy.factor
<more files and directories>...
```
It provides the additional attributes `vocabName` and `binName` to cope with naming deviations.
The `deploy.factor` file controls how the application is deployed and is documented in the Factor online documentation on the `deploy` facility.
Use the `preInstall` or `postInstall` hooks to copy additional files and directories to `out/`.
The function itself only builds the application in `/lib/factor/` and a wrapper in `/bin/`.
A more complex example shows how to specify runtime dependencies and additional Factor vocabularies at the example of the `painter` Factor application:
```nix
{
lib,
fetchFromGitHub,
factorPackages,
curl,
}:
factorPackages.buildFactorApplication (finalAttrs: {
pname = "painter";
version = "1";
factor-lang = factorPackages.factor-minimal-gui;
src = fetchFromGitHub {
name = finalAttrs.vocabName;
owner = "Capital-EX";
repo = "painter";
rev = "365797be8c4f82440bec0ad0a50f5a858a06c1b6";
hash = "sha256-VdvnvKNGcFAtjWVDoxyYgRSyyyy0BEZ2MZGQ71O8nUI=";
};
sourceRoot = ".";
enableUI = true;
extraVocabs = [ factorPackages.bresenham ];
extraPaths = with finalAttrs.factor-lang; binPackages ++ defaultBins ++ [ curl ];
})
```
The use of the `src.name` and `sourceRoot` attributes conveniently establish the necessary `painter` vocabulary directory that is needed for the deployment to work.
It requires the packager to specify the full set of binaries to be made available at runtime.
This enables the standard pattern for application packages to specify all runtime dependencies explicitly without the Factor runtime interfering.
`buildFactorApplication` is a wrapper around `stdenv.mkDerivation` and takes all of its attributes.
Additional attributes that are understood by `buildFactorApplication`:
*`buildDesc`* (Function or attribute set)
: A build description similar to `stdenv.mkDerivation` with the following attributes:
`vocabName` (String; _optional_)
: is the path to the vocabulary to be deployed relative to the source root.
So, directory `foo/` from the example above could be `extra/deep/down/foo`.
This allows you to maintain Factor's vocabulary hierarchy and distribute the same source tree as a stand-alone application and as a library in the Factor development environment via the `extraVocabs` attribute.
`binName` (String; _optional_)
: is the name of the resulting binary in `/bin/`.
It defaults to the last directory component in `vocabName`.
It is also added as the `meta.mainProgram` attribute to facilitate `nix run`.
`enableUI` (Boolean; _optional_)
: is `false` by default.
Set this to `true` when you ship a graphical application.
`extraLibs` (List; _optional_)
: adds additional libraries as runtime dependencies.
Defaults to `[]` and is concatenated with `runtimeLibs` from the used factor-lang package.
Use `factor-minimal` to minimize the closure of runtime libraries.
`extraPaths` (List; _optional_)
: adds additional binaries to the runtime PATH environment variable (without adding their libraries, as well).
Defaults to `[]` and is concatenated with `defaultBins` and `binPackages` from the used factor-lang package.
Use `factor-minimal` to minimize the closure of runtime libraries.
`deployScriptText` (String; _optional_)
: is the actual deploy Factor file that is executed to deploy the application.
You can change it if you need to perform additional computation during deployment.
`factor-lang` (Package; _optional_)
: overrides the Factor package to use to deploy this application, which also affects the default library bindings and programs in the runtime PATH.
It defaults to `factor-lang` when `enableUI` is turned on and `factor-no-gui` when it is turned off.
Applications that use only Factor libraries without external bindings or programs may set this to `factor-minimal` or `factor-minimal-gui`.

View File

@@ -0,0 +1,229 @@
# GNOME {#sec-language-gnome}
## Packaging GNOME applications {#ssec-gnome-packaging}
Programs in the GNOME universe are written in various languages but they all use GObject-based libraries like GLib, GTK or GStreamer. These libraries are often modular, relying on looking into certain directories to find their modules. However, due to Nixs specific file system organization, this will fail without our intervention. Fortunately, the libraries usually allow overriding the directories through environment variables, either natively or thanks to a patch in nixpkgs. [Wrapping](#fun-wrapProgram) the executables to ensure correct paths are available to the application constitutes a significant part of packaging a modern desktop application. In this section, we will describe various modules needed by such applications, environment variables needed to make the modules load, and finally a script that will do the work for us.
### Settings {#ssec-gnome-settings}
[GSettings](https://developer.gnome.org/gio/stable/GSettings.html) API is often used for storing settings. GSettings schemas are required, to know the type and other metadata of the stored values. GLib looks for `glib-2.0/schemas/gschemas.compiled` files inside the directories of `XDG_DATA_DIRS`.
On Linux, GSettings API is implemented using [dconf](https://gitlab.gnome.org/GNOME/dconf) backend. You will need to add `dconf` [GIO module](#ssec-gnome-gio-modules) to `GIO_EXTRA_MODULES` variable, otherwise the `memory` backend will be used and the saved settings will not be persistent.
Last you will need the dconf database D-Bus service itself. You can enable it using `programs.dconf.enable`.
Some applications will also require `gsettings-desktop-schemas` for things like reading proxy configuration or user interface customization. This dependency is often not mentioned by upstream, you should grep for `org.gnome.desktop` and `org.gnome.system` to see if the schemas are needed.
### GIO modules {#ssec-gnome-gio-modules}
GLibs [GIO](https://developer.gnome.org/gio/stable/ch01.html) library supports several [extension points](https://developer.gnome.org/gio/stable/extending-gio.html). Notably, they allow:
* implementing settings backends (already [mentioned](#ssec-gnome-settings))
* adding TLS support
* proxy settings
* virtual file systems
The modules are typically installed to `lib/gio/modules/` directory of a package and you need to add them to `GIO_EXTRA_MODULES` if you need any of those features.
In particular, we recommend:
* adding `dconf.lib` for any software on Linux that reads [GSettings](#ssec-gnome-settings) (even transitively through e.g. GTKs file manager)
* adding `glib-networking` for any software that accesses network using GIO or libsoup glib-networking contains a module that implements TLS support and loads system-wide proxy settings
To allow software to use various virtual file systems, `gvfs` package can be also added. But that is usually an optional feature so we typically use `gvfs` from the system (e.g. installed globally using NixOS module).
### GdkPixbuf loaders {#ssec-gnome-gdk-pixbuf-loaders}
GTK applications typically use [GdkPixbuf](https://gitlab.gnome.org/GNOME/gdk-pixbuf/) to load images. But `gdk-pixbuf` package only supports basic bitmap formats like JPEG, PNG or TIFF, requiring to use third-party loader modules for other formats. This is especially painful since GTK itself includes SVG icons, which cannot be rendered without a loader provided by `librsvg`.
Unlike other libraries mentioned in this section, GdkPixbuf only supports a single value in its controlling environment variable `GDK_PIXBUF_MODULE_FILE`. It is supposed to point to a cache file containing information about the available loaders. Each loader package will contain a `lib/gdk-pixbuf-2.0/2.10.0/loaders.cache` file describing the default loaders in `gdk-pixbuf` package plus the loader contained in the package itself. If you want to use multiple third-party loaders, you will need to create your own cache file manually. Fortunately, this is pretty rare as [not many loaders exist](https://gitlab.gnome.org/federico/gdk-pixbuf-survey/blob/master/src/modules.md).
`gdk-pixbuf` contains [a setup hook](#ssec-gnome-hooks-gdk-pixbuf) that sets `GDK_PIXBUF_MODULE_FILE` from dependencies but as mentioned in further section, it is pretty limited. Loaders should propagate this setup hook.
### Icons {#ssec-gnome-icons}
When an application uses icons, an icon theme should be available in `XDG_DATA_DIRS` during runtime. The package for the default, icon-less [hicolor-icon-theme](https://www.freedesktop.org/wiki/Software/icon-theme/) (should be propagated by every icon theme) contains [a setup hook](#ssec-gnome-hooks-hicolor-icon-theme) that will pick up icon themes from `buildInputs` and add their datadirs to `XDG_ICON_DIRS` environment variable (this is Nixpkgs specific, not actually a XDG standard variable). Unfortunately, relying on that would mean every user has to download the theme included in the package expression no matter their preference. For that reason, we leave the installation of icon theme on the user. If you use one of the desktop environments, you probably already have an icon theme installed.
In the rare case you need to use icons from dependencies (e.g. when an app forces an icon theme), you can use the following to pick them up:
```nix
{
buildInputs = [ pantheon.elementary-icon-theme ];
preFixup = ''
gappsWrapperArgs+=(
# The icon theme is hardcoded.
--prefix XDG_DATA_DIRS : "$XDG_ICON_DIRS"
)
'';
}
```
To avoid costly file system access when locating icons, GTK, [as well as Qt](https://woboq.com/blog/qicon-reads-gtk-icon-cache-in-qt57.html), can rely on `icon-theme.cache` files from the themes' top-level directories. These files are generated using `gtk-update-icon-cache`, which is expected to be run whenever an icon is added or removed to an icon theme (typically an application icon into `hicolor` theme) and some programs do indeed run this after icon installation. However, since packages are installed into their own prefix by Nix, this would lead to conflicts. For that reason, `gtk3` provides a [setup hook](#ssec-gnome-hooks-gtk-drop-icon-theme-cache) that will clean the file from installation. Since most applications only ship their own icon that will be loaded on start-up, it should not affect them too much. On the other hand, icon themes are much larger and more widely used so we need to cache them. Because we recommend installing icon themes globally, we will generate the cache files from all packages in a profile using a NixOS module. You can enable the cache generation using `gtk.iconCache.enable` option if your desktop environment does not already do that.
### Packaging icon themes {#ssec-icon-theme-packaging}
Icon themes may inherit from other icon themes. The inheritance is specified using the `Inherits` key in the `index.theme` file distributed with the icon theme. According to the [icon theme specification](https://specifications.freedesktop.org/icon-theme-spec/latest), icons not provided by the theme are looked for in its parent icon themes. Therefore the parent themes should be installed as dependencies for a more complete experience regarding the icon sets used.
The package `hicolor-icon-theme` provides a setup hook which makes symbolic links for the parent themes into the directory `share/icons` of the current theme directory in the nix store, making sure they can be found at runtime. For that to work the packages providing parent icon themes should be listed as propagated build dependencies, together with `hicolor-icon-theme`.
Also make sure that `icon-theme.cache` is installed for each theme provided by the package, and set `dontDropIconThemeCache` to `true` so that the cache file is not removed by the `gtk3` setup hook.
### GTK Themes {#ssec-gnome-themes}
Previously, a GTK theme needed to be in `XDG_DATA_DIRS`. This is no longer necessary for most programs since GTK incorporated Adwaita theme. Some programs (for example, those designed for [elementary HIG](https://docs.elementary.io/hig)) might require a special theme like `pantheon.elementary-gtk-theme`.
### GObject introspection typelibs {#ssec-gnome-typelibs}
[GObject introspection](https://gitlab.gnome.org/GNOME/gobject-introspection) allows applications to use C libraries in other languages easily. It does this through `typelib` files searched in `GI_TYPELIB_PATH`.
### Various plug-ins {#ssec-gnome-plugins}
If your application uses [GStreamer](https://gstreamer.freedesktop.org/) or [Grilo](https://gitlab.gnome.org/GNOME/grilo), you should set `GST_PLUGIN_SYSTEM_PATH_1_0` and `GRL_PLUGIN_PATH`, respectively.
## Onto `wrapGApps*` hooks {#ssec-gnome-hooks}
Given the requirements above, the package expression would become messy quickly:
```nix
{
preFixup = ''
for f in $(find $out/bin/ $out/libexec/ -type f -executable); do
wrapProgram "$f" \
--prefix GIO_EXTRA_MODULES : "${getLib dconf}/lib/gio/modules" \
--prefix XDG_DATA_DIRS : "$out/share" \
--prefix XDG_DATA_DIRS : "$out/share/gsettings-schemas/${name}" \
--prefix XDG_DATA_DIRS : "${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}" \
--prefix XDG_DATA_DIRS : "${hicolor-icon-theme}/share" \
--prefix GI_TYPELIB_PATH : "${
lib.makeSearchPath "lib/girepository-1.0" [
pango
json-glib
]
}"
done
'';
}
```
Fortunately, we have a [family of hooks]{#ssec-gnome-hooks-wrapgappshook} that automate this. They work in conjunction with other setup hooks that populate environment variables, and will then wrap all executables in `bin` and `libexec` directories using said variables.
- [`wrapGAppsHook3`]{#ssec-gnome-hooks-wrapgappshook3} for GTK 3 apps. For convenience, it also adds `dconf.lib` for a GIO module implementing a GSettings backend using `dconf`, `gtk3` for GSettings schemas, and `librsvg` for GdkPixbuf loader to the closure.
- [`wrapGAppsHook4`]{#ssec-gnome-hooks-wrapgappshook4} for GTK 4 apps. Same as `wrapGAppsHook3` but replaces `gtk3` with `gtk4`.
- [`wrapGAppsNoGuiHook`]{#ssec-gnome-hooks-wrapgappsnoguihook} for programs without a graphical interface. Same as the above but does not bring `gtk3` and `librsvg` into the closure.
The hooks do the following:
- `wrapGApps*` hook itself will add the packages `share` directory to `XDG_DATA_DIRS`.
- []{#ssec-gnome-hooks-glib} `glib` setup hook will populate `GSETTINGS_SCHEMAS_PATH` and then `wrapGApps*` hook will prepend it to `XDG_DATA_DIRS`.
- []{#ssec-gnome-hooks-gdk-pixbuf} `gdk-pixbuf` setup hook will populate `GDK_PIXBUF_MODULE_FILE` with the path to biggest `loaders.cache` file from the dependencies containing [GdkPixbuf loaders](#ssec-gnome-gdk-pixbuf-loaders). This works fine when there are only two packages containing loaders (`gdk-pixbuf` and e.g. `librsvg`) it will choose the second one, reasonably expecting that it will be bigger since it describes extra loader in addition to the default ones. But when there are more than two loader packages, this logic will break. One possible solution would be constructing a custom cache file for each package containing a program like `services/x11/gdk-pixbuf.nix` NixOS module does. `wrapGApps*` hook copies the `GDK_PIXBUF_MODULE_FILE` environment variable into the produced wrapper.
- []{#ssec-gnome-hooks-gtk-drop-icon-theme-cache} One of `gtk3`s setup hooks will remove `icon-theme.cache` files from packages icon theme directories to avoid conflicts. Icon theme packages should prevent this with `dontDropIconThemeCache = true;`.
- []{#ssec-gnome-hooks-dconf} `dconf.lib` is a dependency of `wrapGApps*` hook, which then also adds it to the `GIO_EXTRA_MODULES` variable.
- []{#ssec-gnome-hooks-hicolor-icon-theme} `hicolor-icon-theme`s setup hook will add icon themes to `XDG_ICON_DIRS`.
- []{#ssec-gnome-hooks-gobject-introspection} `gobject-introspection` setup hook populates `GI_TYPELIB_PATH` variable with `lib/girepository-1.0` directories of dependencies, which is then added to wrapper by `wrapGApps*` hook. It also adds `share` directories of dependencies to `XDG_DATA_DIRS`, which is intended to promote GIR files but it also [pollutes the closures](https://github.com/NixOS/nixpkgs/issues/32790) of packages using `wrapGApps*` hook.
- []{#ssec-gnome-hooks-gst-grl-plugins} Setup hooks of `gst_all_1.gstreamer` and `grilo` will populate the `GST_PLUGIN_SYSTEM_PATH_1_0` and `GRL_PLUGIN_PATH` variables, respectively, which will then be added to the wrapper by `wrapGApps*` hook.
You can also pass additional arguments to `makeWrapper` using `gappsWrapperArgs` in `preFixup` hook:
```nix
{
preFixup = ''
gappsWrapperArgs+=(
# Thumbnailers
--prefix XDG_DATA_DIRS : "${gdk-pixbuf}/share"
--prefix XDG_DATA_DIRS : "${librsvg}/share"
--prefix XDG_DATA_DIRS : "${shared-mime-info}/share"
)
'';
}
```
## Updating GNOME packages {#ssec-gnome-updating}
Most GNOME package offer [`updateScript`](#var-passthru-updateScript), it is therefore possible to update to latest source tarball by running `nix-shell maintainers/scripts/update.nix --argstr package nautilus` or even en masse with `nix-shell maintainers/scripts/update.nix --argstr path gnome`. Read the packages `NEWS` file to see what changed.
## Frequently encountered issues {#ssec-gnome-common-issues}
### `GLib-GIO-ERROR **: 06:04:50.903: No GSettings schemas are installed on the system` {#ssec-gnome-common-issues-no-schemas}
There are no schemas available in `XDG_DATA_DIRS`. Temporarily add a random package containing schemas like `gsettings-desktop-schemas` to `buildInputs`. [`glib`](#ssec-gnome-hooks-glib) and [`wrapGApps*`](#ssec-gnome-hooks-wrapgappshook) setup hooks will take care of making the schemas available to application and you will see the actual missing schemas with the [next error](#ssec-gnome-common-issues-missing-schema). Or you can try looking through the source code for the actual schemas used.
### `GLib-GIO-ERROR **: 06:04:50.903: Settings schema org.gnome.foo is not installed` {#ssec-gnome-common-issues-missing-schema}
Package is missing some GSettings schemas. You can find out the package containing the schema with `nix-locate org.gnome.foo.gschema.xml` and let the hooks handle the wrapping as [above](#ssec-gnome-common-issues-no-schemas).
### When using `wrapGApps*` hook with special derivers or hooks you can end up with double wrapped binaries. {#ssec-gnome-common-issues-double-wrapped}
This is because some setup hooks like `qt6.wrapQtAppsHook` also wrap programs using `makeWrapper`. Likewise, some derivers (e.g. `python.pkgs.buildPythonApplication`) automatically pull in their own setup hooks that produce wrappers.
The simplest workaround is to disable the `wrapGApps*` hook's automatic wrapping using `dontWrapGApps = true;` while passing its `makeWrapper` arguments to another wrapper.
In the case of a Python application it could look like:
```nix
python3.pkgs.buildPythonApplication {
pname = "gnome-music";
version = "3.32.2";
nativeBuildInputs = [
wrapGAppsHook3
gobject-introspection
# ...
];
dontWrapGApps = true;
# Arguments to be passed to `makeWrapper`, only used by buildPython*
preFixup = ''
makeWrapperArgs+=("''${gappsWrapperArgs[@]}")
'';
}
```
And for a QT app like:
```nix
stdenv.mkDerivation {
pname = "calibre";
version = "3.47.0";
nativeBuildInputs = [
wrapGAppsHook3
qt6.wrapQtAppsHook
qmake
# ...
];
dontWrapGApps = true;
preFixup = ''
qtWrapperArgs+=("''${gappsWrapperArgs[@]}")
'';
}
```
### I am packaging a project that cannot be wrapped, like a library or GNOME Shell extension. {#ssec-gnome-common-issues-unwrappable-package}
You can rely on applications depending on the library setting the necessary environment variables but that is often easy to miss. Instead we recommend to patch the paths in the source code whenever possible. Here are some examples:
- []{#ssec-gnome-common-issues-unwrappable-package-gnome-shell-ext} [Replacing a `GI_TYPELIB_PATH` in GNOME Shell extension](https://github.com/NixOS/nixpkgs/blob/e981466fbb08e6231a1377539ff17fbba3270fda/pkgs/by-name/gn/gnome-shell-extensions/package.nix#L25-L32) we are using `replaceVars` to include the path to a typelib into a patch.
- []{#ssec-gnome-common-issues-unwrappable-package-gsettings} The following examples are hardcoding GSettings schema paths. To get the schema paths we use the functions
* `glib.getSchemaPath` Takes a nix package attribute as an argument.
* `glib.makeSchemaPath` Takes a package output like `$out` and a derivation name. You should use this if the schemas you need to hardcode are in the same derivation.
[]{#ssec-gnome-common-issues-unwrappable-package-gsettings-vala} [Hard-coding GSettings schema path in Vala plug-in (dynamically loaded library)](https://github.com/NixOS/nixpkgs/blob/7bb8f05f12ca3cff9da72b56caa2f7472d5732bc/pkgs/desktops/pantheon/apps/elementary-files/default.nix#L78-L86) here, `replaceVars` cannot be used since the schema comes from the same package preventing us from pass its path to the function, probably due to a [Nix bug](https://github.com/NixOS/nix/issues/1846).
[]{#ssec-gnome-common-issues-unwrappable-package-gsettings-c} [Hard-coding GSettings schema path in C library](https://github.com/NixOS/nixpkgs/blob/29c120c065d03b000224872251bed93932d42412/pkgs/development/libraries/glib-networking/default.nix#L31-L34) nothing special other than using [Coccinelle patch](https://github.com/NixOS/nixpkgs/pull/67957#issuecomment-527717467) to generate the patch itself.
### I need to wrap a binary outside `bin` and `libexec` directories. {#ssec-gnome-common-issues-weird-location}
You can manually trigger the wrapping with `wrapGApp` in `preFixup` phase. It takes a path to a program as a first argument; the remaining arguments are passed directly to [`wrapProgram`](#fun-wrapProgram) function.

View File

@@ -0,0 +1,331 @@
# Go {#sec-language-go}
## Building Go modules with `buildGoModule` {#ssec-language-go}
The function `buildGoModule` builds Go programs managed with Go modules. It builds [Go Modules](https://go.dev/wiki/Modules) through a two phase build:
- An intermediate fetcher derivation called `goModules`. This derivation will be used to fetch all the dependencies of the Go module.
- A final derivation will use the output of the intermediate derivation to build the binaries and produce the final output.
### Example for `buildGoModule` {#ex-buildGoModule}
The following is an example expression using `buildGoModule`:
```nix
{
pet = buildGoModule (finalAttrs: {
pname = "pet";
version = "0.3.4";
src = fetchFromGitHub {
owner = "knqyf263";
repo = "pet";
tag = "v${finalAttrs.version}";
hash = "sha256-Gjw1dRrgM8D3G7v6WIM2+50r4HmTXvx0Xxme2fH9TlQ=";
};
vendorHash = "sha256-ciBIR+a1oaYH+H1PcC8cD8ncfJczk1IiJ8iYNM+R6aA=";
meta = {
description = "Simple command-line snippet manager, written in Go";
homepage = "https://github.com/knqyf263/pet";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ kalbasit ];
};
});
}
```
## Attributes of `buildGoModule` {#buildgomodule-parameters}
Many attributes [controlling the build phase](#variables-controlling-the-build-phase) are respected by `buildGoModule`. Note that `buildGoModule` reads the following attributes also when building the `vendor/` goModules fixed output derivation as well:
- [`sourceRoot`](#var-stdenv-sourceRoot)
- [`prePatch`](#var-stdenv-prePatch)
- [`patches`](#var-stdenv-patches)
- [`patchFlags`](#var-stdenv-patchFlags)
- [`postPatch`](#var-stdenv-postPatch)
- [`preBuild`](#var-stdenv-preBuild)
- `env`: useful for passing down variables such as `GOWORK`.
To control test execution of the build derivation, the following attributes are of interest:
- [`checkInputs`](#var-stdenv-checkInputs)
- [`preCheck`](#var-stdenv-preCheck)
- [`checkFlags`](#var-stdenv-checkFlags)
In addition to the above attributes, and the many more variables respected also by `stdenv.mkDerivation`, `buildGoModule` respects Go-specific attributes that tweak them to behave slightly differently:
### `vendorHash` {#var-go-vendorHash}
Hash of the output of the intermediate fetcher derivation (the dependencies of the Go modules).
`vendorHash` can be set to `null`.
In that case, rather than fetching the dependencies, the dependencies already vendored in the `vendor` directory of the source repo will be used.
To avoid updating this field when dependencies change, run `go mod vendor` in your source repo and set `vendorHash = null;`.
You can read more about [vendoring in the Go documentation](https://go.dev/ref/mod#vendoring).
To obtain the hash, set `vendorHash = lib.fakeHash;` and run the build. ([more details here](#sec-source-hashes)).
Another way is to use `nix-prefetch` to obtain the hash. The following command gets the value of `vendorHash` for package `pet`:
```sh
cd path/to/nixpkgs
nix-prefetch -E "{ sha256 }: ((import ./. { }).my-package.overrideAttrs { vendorHash = sha256; }).goModules"
```
`vendorHash` can be overridden with `overrideAttrs`. Override the above example like this:
```nix
{
pet_0_4_0 = pet.overrideAttrs (
finalAttrs: previousAttrs: {
version = "0.4.0";
src = fetchFromGitHub {
inherit (previousAttrs.src) owner repo;
rev = "v${finalAttrs.version}";
hash = "sha256-gVTpzmXekQxGMucDKskGi+e+34nJwwsXwvQTjRO6Gdg=";
};
vendorHash = "sha256-dUvp7FEW09V0xMuhewPGw3TuAic/sD7xyXEYviZ2Ivs=";
}
);
}
```
### `proxyVendor` {#var-go-proxyVendor}
If `true`, the intermediate fetcher downloads dependencies from the
[Go module proxy](https://go.dev/ref/mod#module-proxy) (using `go mod download`) instead of vendoring them. The resulting
[module cache](https://go.dev/ref/mod#module-cache) is then passed to the final derivation.
This is useful if your code depends on C code and `go mod tidy` does not include the needed sources to build or
if any dependency has case-insensitive conflicts which will produce platform-dependent `vendorHash` checksums.
Defaults to `false`.
### `modPostBuild` {#var-go-modPostBuild}
Shell commands to run after the build of the goModules executes `go mod vendor`, and before calculating fixed output derivation's `vendorHash`.
Note that if you change this attribute, you need to update the `vendorHash` attribute.
### `modRoot` {#var-go-modRoot}
The root directory of the Go module that contains the `go.mod` file.
Defaults to `./`, which is the root of `src`.
### `ldflags` {#var-go-ldflags}
A string list of flags to pass to the Go linker tool via the `-ldflags` argument of `go build`. Possible values can be retrieved by running `go tool link --help`.
The most common use case for this argument is to make the resulting executable aware of its own version by injecting the value of string variable using the `-X` flag. For example:
```nix
{
ldflags = [
"-X main.Version=${version}"
"-X main.Commit=${version}"
];
}
```
### `tags` {#var-go-tags}
A string list of [Go build tags (also called build constraints)](https://pkg.go.dev/cmd/go#hdr-Build_constraints) that are passed via the `-tags` argument of `go build`. These constraints control whether Go files from the source should be included in the build. For example:
```nix
{
tags = [
"production"
"sqlite"
];
}
```
Tags can also be set conditionally:
```nix
{ tags = [ "production" ] ++ lib.optionals withSqlite [ "sqlite" ]; }
```
### `deleteVendor` {#var-go-deleteVendor}
If set to `true`, removes the pre-existing vendor directory. This should only be used if the dependencies included in the vendor folder are broken or incomplete.
### `subPackages` {#var-go-subPackages}
Specified as a string or list of strings. Limits the builder from building child packages that have not been listed. If `subPackages` is not specified, all child packages will be built.
Many Go projects keep the main package in a `cmd` directory.
Following example could be used to only build the example-cli and example-server binaries:
```nix
{
subPackages = [
"cmd/example-cli"
"cmd/example-server"
];
}
```
### `excludedPackages` {#var-go-excludedPackages}
Specified as a string or list of strings. Causes the builder to skip building child packages that match any of the provided values.
### `enableParallelBuilding` {#var-go-enableParallelBuilding}
Whether builds and tests should run in parallel.
Defaults to `true`.
### `allowGoReference` {#var-go-allowGoReference}
Whether the build result should be allowed to contain references to the Go tool chain. This might be needed for programs that are coupled with the compiler, but shouldn't be set without a good reason.
Defaults to `false`
### `goSum` {#var-go-goSum}
Specifies the contents of the `go.sum` file and triggers rebuilds when it changes. This helps combat inconsistent dependency errors on `go.sum` changes.
Defaults to `null`
### `buildTestBinaries` {#var-go-buildTestBinaries}
This option allows to compile test binaries instead of the usual binaries produced by a package.
Go can [compile test into binaries](https://pkg.go.dev/cmd/go#hdr-Test_packages) using the `go test -c` command.
These binaries can then be executed at a later point (outside the Nix sandbox) to run the tests.
This is mostly useful for downstream consumers to run integration or end-to-end tests that won't work in the Nix sandbox, for example because they require network access.
## Versioned toolchains and builders {#ssec-go-toolchain-versions}
Beside `buildGoModule`, there are also versioned builders available that pin a specific Go version, like `buildGo124Module` for Go 1.24.
Similar, versioned toolchains are available, like `go_1_24` for Go 1.24.
Both builder and toolchain of a certain version will be removed as soon as the Go version reaches its end of life.
As toolchain updates in nixpkgs cause mass rebuilds and must go through the staging cycle, it can take a while until a new Go minor version is available to consumers of nixpkgs.
If you want quicker access to the latest minor, use `go_latest` toolchain and `buildGoLatestModule` builder.
To learn more about the Go maintenance and upgrade procedure in nixpkgs, check out the [Go toolchain/builder upgrade policy](https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/go/README.md#go-toolchainbuilder-upgrade-policy).
::: {.warning}
The use of `go_latest` and `buildGoLatestModule` is restricted within nixpkgs.
The [Go toolchain/builder upgrade policy](https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/go/README.md#go-toolchainbuilder-upgrade-policy) must be followed.
:::
## Overriding `goModules` {#buildGoModule-goModules-override}
Overriding `<pkg>.goModules` by calling `goModules.overrideAttrs` is unsupported. Still, it is possible to override the `vendorHash` (`goModules`'s `outputHash`) and the `pre`/`post` hooks for both the build and patch phases of the primary and `goModules` derivation.
Alternatively, the primary derivation provides an overridable `passthru.overrideModAttrs` function to store the attribute overlay implicitly taken by `goModules.overrideAttrs`. Here's an example usage of `overrideModAttrs`:
```nix
{
pet-overridden = pet.overrideAttrs (
finalAttrs: previousAttrs: {
passthru = previousAttrs.passthru // {
# If the original package has an `overrideModAttrs` attribute set, you'd
# want to extend it, and not replace it. Hence we use
# `lib.composeExtensions`. If you are sure the `overrideModAttrs` of the
# original package trivially does nothing, you can safely replace it
# with your own by not using `lib.composeExtensions`.
overrideModAttrs = lib.composeExtensions previousAttrs.passthru.overrideModAttrs (
finalModAttrs: previousModAttrs: {
# goModules-specific overriding goes here
postBuild = ''
# Here you have access to the `vendor` directory.
substituteInPlace vendor/github.com/example/repo/file.go \
--replace-fail "panic(err)" ""
'';
}
);
};
}
);
}
```
## Controlling the Go environment {#ssec-go-environment}
The Go build can be further tweaked by setting environment variables via the `env` attribute. In most cases, this isn't needed. Possible values can be found in the [Go documentation of accepted environment variables](https://pkg.go.dev/cmd/go#hdr-Environment_variables). Notice that some of these flags are set by the build helper itself and should not be set explicitly. If in doubt, grep the implementation of the build helper.
`buildGoModule` officially supports the following environment variables:
### `env.CGO_ENABLED` {#var-go-CGO_ENABLED}
When set to `0`, the [cgo](https://pkg.go.dev/cmd/cgo) command is disabled. As a consequence, the build
program can't link against C libraries anymore, and the resulting binary is statically linked.
When building with CGO enabled, Go will likely link some packages from the Go standard library against C libraries,
even when the target code does not explicitly call into C dependencies. With `env.CGO_ENABLED = 0;`, Go
will always use the Go native implementation of these internal packages. For reference see
[net](https://pkg.go.dev/net#hdr-Name_Resolution) and [os/user](https://pkg.go.dev/os/user#pkg-overview) packages.
Notice that the decision whether these packages should use native Go implementation or not can also be controlled
on a per package level using build tags (`tags`). In case CGO is disabled, these tags have no additional effect.
When a Go program depends on C libraries, place those dependencies in `buildInputs`:
```nix
{
buildInputs = [
libvirt
libxml2
];
}
```
`env.CGO_ENABLED` defaults to `1`.
## Skipping tests {#ssec-skip-go-tests}
`buildGoModule` runs tests by default. Failing tests can be disabled using the `checkFlags` parameter.
This is done with the [`-skip` or `-run`](https://pkg.go.dev/cmd/go#hdr-Testing_flags) flags of the `go test` command.
For example, only a selection of tests could be run with:
```nix
{
# -run and -skip accept regular expressions
checkFlags = [ "-run=^Test(Simple|Fast)$" ];
}
```
If a larger amount of tests should be skipped, the following pattern can be used:
```nix
{
checkFlags =
let
# Skip tests that require network access
skippedTests = [
"TestNetwork"
"TestDatabase/with_mysql" # exclude only the subtest
"TestIntegration"
];
in
[ "-skip=^${builtins.concatStringsSep "$|^" skippedTests}$" ];
}
```
To disable tests altogether, set `doCheck = false;`.
## Migrating from `buildGoPackage` to `buildGoModule` {#buildGoPackage-migration}
::: {.warning}
`buildGoPackage` was removed for the 25.05 release. It was used to build legacy Go programs
that do not support Go modules.
:::
Go modules, released 6y ago, are now widely adopted in the ecosystem.
Most upstream projects are using Go modules, and the tooling previously used for dependency management in Go is mostly deprecated, archived or at least unmaintained at this point.
In case a project doesn't have external dependencies or dependencies are vendored in a way understood by `go mod init`, migration can be done with a few changes in the package.
- Switch the builder from `buildGoPackage` to `buildGoModule`
- Remove `goPackagePath` and other attributes specific to `buildGoPackage`
- Set `vendorHash = null;`
- Run `go mod init <module name>` in `postPatch`
In case the package has external dependencies that aren't vendored or the build setup is more complex the upstream source might need to be patched.
Examples for the migration can be found in the [issue tracking migration within nixpkgs](https://github.com/NixOS/nixpkgs/issues/318069).

View File

@@ -0,0 +1,186 @@
# Gradle {#gradle}
Gradle is a popular build tool for Java/Kotlin. Gradle itself doesn't
currently provide tools to make dependency resolution reproducible, so
nixpkgs has a proxy designed for intercepting Gradle web requests to
record dependencies so they can be restored in a reproducible fashion.
## Building a Gradle package {#building-a-gradle-package}
Here's how a typical derivation will look:
```nix
stdenv.mkDerivation (finalAttrs: {
pname = "pdftk";
version = "3.3.3";
src = fetchFromGitLab {
owner = "pdftk-java";
repo = "pdftk";
tag = "v${finalAttrs.version}";
hash = "sha256-ciKotTHSEcITfQYKFZ6sY2LZnXGChBJy0+eno8B3YHY=";
};
nativeBuildInputs = [
gradle
makeWrapper
];
# if the package has dependencies, mitmCache must be set
mitmCache = gradle.fetchDeps {
inherit (finalAttrs) pname;
data = ./deps.json;
};
# this is required for using mitm-cache on Darwin
__darwinAllowLocalNetworking = true;
gradleFlags = [ "-Dfile.encoding=utf-8" ];
# defaults to "assemble"
gradleBuildTask = "shadowJar";
# will run the gradleCheckTask (defaults to "test")
doCheck = true;
installPhase = ''
mkdir -p $out/{bin,share/pdftk}
cp build/libs/pdftk-all.jar $out/share/pdftk
makeWrapper ${lib.getExe jre} $out/bin/pdftk \
--add-flags "-jar $out/share/pdftk/pdftk-all.jar"
cp ${finalAttrs.src}/pdftk.1 $out/share/man/man1
'';
meta.sourceProvenance = with lib.sourceTypes; [
fromSource
binaryBytecode # mitm cache
];
})
```
To update (or initialize) dependencies, run the update script via
something like `$(nix-build -A <pname>.mitmCache.updateScript)`
(`nix-build` builds the `updateScript`, `$(...)` runs the script at the
path printed by `nix-build`).
If your package can't be evaluated using a simple `pkgs.<pname>`
expression (for example, if your package isn't located in nixpkgs, or if
you want to override some of its attributes), you will usually have to
pass `pkg` instead of `pname` to `gradle.fetchDeps`. There are two ways
of doing so.
The first is to add the derivation arguments required for getting the
package. Using the pdftk example above:
```nix
{
lib,
stdenv,
gradle,
# ...
pdftk,
}:
stdenv.mkDerivation (finalAttrs: {
# ...
mitmCache = gradle.fetchDeps {
pkg = pdftk;
data = ./deps.json;
};
})
```
This allows you to `override` any arguments of the `pkg` used for the update script (for example, `pkg = pdftk.override { enableSomeFlag = true };)`.
The second is to use `finalAttrs.finalPackage` like this:
```nix
stdenv.mkDerivation (finalAttrs: {
# ...
mitmCache = gradle.fetchDeps {
pkg = finalAttrs.finalPackage;
data = ./deps.json;
};
})
```
The limitation of this method is that you cannot override the `pkg` derivations's arguments.
In the former case, the update script will stay the same even if the derivation is called with different arguments. In the latter case, the update script will change depending on the derivation arguments. It's up to you to decide which one would work best for your derivation.
## Update Script {#gradle-update-script}
The update script does the following:
- Build the derivation's source via `pkgs.srcOnly`
- Enter a `nix-shell` for the derivation in a `bwrap` sandbox (the
sandbox is only used on Linux)
- Set the `IN_GRADLE_UPDATE_DEPS` environment variable to `1`
- Run the derivation's `unpackPhase`, `patchPhase`, `configurePhase`
- Run the derivation's `gradleUpdateScript` (the Gradle setup hook sets
a default value for it, which runs `preBuild`, `preGradleUpdate`
hooks, fetches the dependencies using `gradleUpdateTask`, and finally
runs the `postGradleUpdate` hook)
- Finally, store all of the fetched files' hashes in the lockfile. They
may be `.jar`/`.pom` files from Maven repositories, or they may be
files otherwise used for building the package.
`fetchDeps` takes the following arguments:
- `attrPath` - the path to the package in nixpkgs (for example,
`"javaPackages.openjfx22"`). Used for update script metadata.
- `pname` - an alias for `attrPath` for convenience. This is what you
will generally use instead of `pkg` or `attrPath`.
- `pkg` - the package to be used for fetching the dependencies. Defaults
to `getAttrFromPath (splitString "." attrPath) pkgs`.
- `bwrapFlags` - allows you to override bwrap flags (only relevant for
downstream, non-nixpkgs projects)
- `data` - path to the dependencies lockfile (can be relative to the
package, can be absolute). In nixpkgs, it's discouraged to have the
lockfiles be named anything other `deps.json`, consider creating
subdirectories if your package requires multiple `deps.json` files.
## Environment {#gradle-environment}
The Gradle setup hook accepts the following environment variables:
- `mitmCache` - the MITM proxy cache imported using `gradle.fetchDeps`
- `gradleFlags` - command-line flags to be used for every Gradle
invocation (this simply registers a function that uses the necessary
flags).
- You can't use `gradleFlags` for flags that contain spaces, in that
case you must add `gradleFlagsArray+=("-flag with spaces")` to the
derivation's bash code instead.
- If you want to build the package using a specific Java version, you
can pass `"-Dorg.gradle.java.home=${jdk}"` as one of the flags.
- `gradleBuildTask` - the Gradle task (or tasks) to be used for building
the package. Defaults to `assemble`.
- `gradleCheckTask` - the Gradle task (or tasks) to be used for checking
the package if `doCheck` is set to `true`. Defaults to `test`.
- `gradleUpdateTask` - the Gradle task (or tasks) to be used for
fetching all of the package's dependencies in
`mitmCache.updateScript`. Defaults to `nixDownloadDeps`.
- `gradleUpdateScript` - the code to run for fetching all of the
package's dependencies in `mitmCache.updateScript`. Defaults to
running the `preBuild` and `preGradleUpdate` hooks, running the
`gradleUpdateTask`, and finally running the `postGradleUpdate` hook.
- `gradleInitScript` - path to the `--init-script` to pass to Gradle. By
default, a simple init script that enables reproducible archive
creation is used.
- Note that reproducible archives might break some builds. One example
of an error caused by it is `Could not create task ':jar'. Replacing
an existing task that may have already been used by other plugins is
not supported`. If you get such an error, the easiest "fix" is
disabling reproducible archives altogether by setting
`gradleInitScript` to something like `writeText
"empty-init-script.gradle" ""`
- `enableParallelBuilding` / `enableParallelChecking` /
`enableParallelUpdating` - pass `--parallel` to Gradle in the
build/check phase or in the update script. Defaults to true. If the
build fails for mysterious reasons, consider setting this to false.
- `dontUseGradleConfigure` / `dontUseGradleBuild` / `dontUseGradleCheck`
\- force disable the Gradle setup hook for certain phases.
- Note that if you disable the configure hook, you may face issues
such as `Failed to load native library 'libnative-platform.so'`,
because the configure hook is responsible for initializing Gradle.

View File

@@ -0,0 +1,54 @@
# Hare {#sec-language-hare}
## Building Hare programs with `hareHook` {#ssec-language-hare}
The `hareHook` package sets up the environment for building Hare programs by
doing the following:
1. Setting the `HARECACHE`, `HAREPATH` and `NIX_HAREFLAGS` environment variables;
1. Propagating `harec`, `qbe` and two wrapper scripts for the hare binary.
It is not a function as is the case for some other languages --- *e. g.*, Go or
Rust ---, but a package to be added to `nativeBuildInputs`.
## Attributes of `hareHook` {#hareHook-attributes}
The following attributes are accepted by `hareHook`:
1. `hareBuildType`: Either `release` (default) or `debug`. It controls if the
`-R` flag is added to `NIX_HAREFLAGS`.
## Example for `hareHook` {#ex-hareHook}
```nix
{
hareHook,
lib,
stdenv,
}:
stdenv.mkDerivation {
pname = "<name>";
version = "<version>";
src = "<src>";
nativeBuildInputs = [ hareHook ];
meta = {
description = "<description>";
inherit (hareHook) badPlatforms platforms;
};
}
```
## Cross Compilation {#hareHook-cross-compilation}
`hareHook` should handle cross compilation out of the box. This is the main
purpose of `NIX_HAREFLAGS`: In it, the `-a` flag is passed with the architecture
of the `hostPlatform`.
However, manual intervention may be needed when a binary compiled by the build
process must be run for the build to complete --- *e. g.*, when using Hare's
`hare` module for code generation.
In those cases, `hareHook` provides the `hare-native` script, which is a wrapper
around the hare binary for using the native (`buildPlatform`) toolchain.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
# Hy {#sec-language-hy}
## Installation {#ssec-hy-installation}
### Installation without packages {#installation-without-packages}
You can install `hy` via nix-env or by adding it to `configuration.nix` by referring to it as a `hy` attribute. This kind of installation adds `hy` to your environment and it successfully works with `python3`.
::: {.caution}
Packages that are installed with your python derivation, are not accessible by `hy` this way.
:::
### Installation with packages {#installation-with-packages}
Creating a `hy` derivation with custom `python` packages is really simple and similar to the way that python does it. The attribute `hy` provides the function `withPackages` that creates a custom `hy` derivation with specified packages.
For example, if you want to create a shell with `matplotlib` and `numpy`, you can do it like so:
```ShellSession
$ nix-shell -p "hy.withPackages (ps: with ps; [ numpy matplotlib ])"
```
Or if you want to extend your `configuration.nix`:
```nix
{
# ...
environment.systemPackages = with pkgs; [
(hy.withPackages (
py-packages: with py-packages; [
numpy
matplotlib
]
))
];
}
```

View File

@@ -0,0 +1,156 @@
# Idris {#idris}
## Installing Idris {#installing-idris}
The easiest way to get a working idris version is to install the `idris` attribute:
```ShellSession
$ nix-env -f "<nixpkgs>" -iA idris
```
This however only provides the `prelude` and `base` libraries. To install idris with additional libraries, you can use the `idrisPackages.with-packages` function, e.g. in an overlay in `~/.config/nixpkgs/overlays/my-idris.nix`:
```nix
self: super: {
myIdris =
with self.idrisPackages;
with-packages [
contrib
pruviloj
];
}
```
And then:
```ShellSession
$ # On NixOS
$ nix-env -iA nixos.myIdris
$ # On non-NixOS
$ nix-env -iA nixpkgs.myIdris
```
To see all available Idris packages:
```ShellSession
$ # On NixOS
$ nix-env -qaPA nixos.idrisPackages
$ # On non-NixOS
$ nix-env -qaPA nixpkgs.idrisPackages
```
Similarly, entering a `nix-shell`:
```ShellSession
$ nix-shell -p 'idrisPackages.with-packages (with idrisPackages; [ contrib pruviloj ])'
```
## Starting Idris with library support {#starting-idris-with-library-support}
To have access to these libraries in idris, call it with an argument `-p <library name>` for each library:
```ShellSession
$ nix-shell -p 'idrisPackages.with-packages (with idrisPackages; [ contrib pruviloj ])'
[nix-shell:~]$ idris -p contrib -p pruviloj
```
A listing of all available packages the Idris binary has access to is available via `--listlibs`:
```ShellSession
$ idris --listlibs
00prelude-idx.ibc
pruviloj
base
contrib
prelude
00pruviloj-idx.ibc
00base-idx.ibc
00contrib-idx.ibc
```
## Building an Idris project with Nix {#building-an-idris-project-with-nix}
As an example of how a Nix expression for an Idris package can be created, here is the one for `idrisPackages.yaml`:
```nix
{
lib,
build-idris-package,
fetchFromGitHub,
contrib,
lightyear,
}:
build-idris-package {
name = "yaml";
version = "2018-01-25";
# This is the .ipkg file that should be built, defaults to the package name
# In this case it should build `Yaml.ipkg` instead of `yaml.ipkg`
# This is only necessary because the yaml packages ipkg file is
# different from its package name here.
ipkgName = "Yaml";
# Idris dependencies to provide for the build
idrisDeps = [
contrib
lightyear
];
src = fetchFromGitHub {
owner = "Heather";
repo = "Idris.Yaml";
rev = "5afa51ffc839844862b8316faba3bafa15656db4";
hash = "sha256-h28F9EEPuvab6zrfeE+0k1XGQJGwINnsJEG8yjWIl7w=";
};
meta = {
description = "Idris YAML lib";
homepage = "https://github.com/Heather/Idris.Yaml";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.brainrape ];
};
}
```
Assuming this file is saved as `yaml.nix`, it's buildable using
```ShellSession
$ nix-build -E '(import <nixpkgs> {}).idrisPackages.callPackage ./yaml.nix {}'
```
Or it's possible to use
```nix
with import <nixpkgs> { };
{
yaml = idrisPackages.callPackage ./yaml.nix { };
}
```
in another file (say `default.nix`) to be able to build it with
```ShellSession
$ nix-build -A yaml
```
## Passing options to `idris` commands {#passing-options-to-idris-commands}
The `build-idris-package` function provides also optional input values to set additional options for the used `idris` commands.
Specifically, you can set `idrisBuildOptions`, `idrisTestOptions`, `idrisInstallOptions` and `idrisDocOptions` to provide additional options to the `idris` command respectively when building, testing, installing and generating docs for your package.
For example you could set
```nix
build-idris-package {
idrisBuildOptions = [
"--log"
"1"
"--verbose"
];
# ...
}
```
to require verbose output during `idris` build phase.

View File

@@ -0,0 +1,58 @@
# Idris2 {#sec-idris2}
In addition to exposing the Idris2 compiler itself, Nixpkgs exposes an `idris2Packages.buildIdris` helper to make it a bit more ergonomic to build Idris2 executables or libraries.
The `buildIdris` function takes an attribute set that defines at a minimum the `src` and `ipkgName` of the package to be built and any `idrisLibraries` required to build it. The `src` is the same source you're familiar with and the `ipkgName` must be the name of the `ipkg` file for the project (omitting the `.ipkg` extension). The `idrisLibraries` is a list of other library derivations created with `buildIdris`. You can optionally specify other derivation properties as needed but sensible defaults for `configurePhase`, `buildPhase`, and `installPhase` are provided.
Importantly, `buildIdris` does not create a single derivation but rather an attribute set with two properties: `executable` and `library`. The `executable` property is a derivation and the `library` property is a function that will return a derivation for the library with or without source code included. Source code need not be included unless you are aiming to use IDE or LSP features that are able to jump to definitions within an editor.
A simple example of a fully packaged library would be the [`LSP-lib`](https://github.com/idris-community/LSP-lib) found in the `idris-community` GitHub organization.
```nix
{ fetchFromGitHub, idris2Packages }:
let
lspLibPkg = idris2Packages.buildIdris {
ipkgName = "lsp-lib";
src = fetchFromGitHub {
owner = "idris-community";
repo = "LSP-lib";
rev = "main";
hash = "sha256-EvSyMCVyiy9jDZMkXQmtwwMoLaem1GsKVFqSGNNHHmY=";
};
idrisLibraries = [ ];
};
in
lspLibPkg.library { withSource = true; }
```
The above results in a derivation with the installed library results (with source code).
A slightly more involved example of a fully packaged executable would be the [`idris2-lsp`](https://github.com/idris-community/idris2-lsp) which is an Idris2 language server that uses the `LSP-lib` found above.
```nix
{
callPackage,
fetchFromGitHub,
idris2Packages,
}:
# Assuming the previous example lives in `lsp-lib.nix`:
let
lspLib = callPackage ./lsp-lib.nix { };
inherit (idris2Packages) idris2Api;
lspPkg = idris2Packages.buildIdris {
ipkgName = "idris2-lsp";
src = fetchFromGitHub {
owner = "idris-community";
repo = "idris2-lsp";
rev = "main";
hash = "sha256-vQTzEltkx7uelDtXOHc6QRWZ4cSlhhm5ziOqWA+aujk=";
};
idrisLibraries = [
idris2Api
lspLib
];
};
in
lspPkg.executable
```
The above uses the default value of `withSource = false` for the `idris2Api` but could be modified to include that library's source by passing `(idris2Api { withSource = true; })` to `idrisLibraries` instead. `idris2Api` in the above derivation comes built in with `idris2Packages`. This library exposes many of the otherwise internal APIs of the Idris2 compiler.

View File

@@ -0,0 +1,103 @@
# Languages and frameworks {#chap-language-support}
The [standard build environment](#chap-stdenv) makes it easy to build typical Autotools-based packages with very little code. Any other kind of package can be accommodated by overriding the appropriate phases of `stdenv`. However, there are specialised functions in Nixpkgs to easily build packages for other programming languages, such as Perl or Haskell. These are described in this chapter.
Each supported language or software ecosystem has its own package set named `<language or ecosystem>Packages`, which can be explored in various ways:
- Search on [search.nixos.org](https://search.nixos.org/packages)
For example, search for [`haskellPackages`](https://search.nixos.org/packages?query=haskellPackages) or [`rubyPackages`](https://search.nixos.org/packages?query=rubyPackages).
- Navigate attribute sets with [`nix repl`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-repl).
This technique is generally useful to inspect Nix language data structures.
:::{.example #example-navigte-nix-repl}
# Navigate Java compiler variants in `javaPackages` with `nix repl`
```shell-session
$ nix repl '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable
nix-repl> javaPackages.<tab>
javaPackages.compiler javaPackages.openjfx15 javaPackages.openjfx21 javaPackages.recurseForDerivations
javaPackages.jogl_2_4_0 javaPackages.openjfx17 javaPackages.openjfx22
javaPackages.mavenfod javaPackages.openjfx19 javaPackages.override
javaPackages.openjfx11 javaPackages.openjfx20 javaPackages.overrideDerivation
```
:::
- List all derivations on the command line with [`nix-env --query`](https://nixos.org/manual/nix/stable/command-ref/nix-env/query).
`nix-env` is the only convenient way to do that, as it will skip attributes that fail [assertions](https://nixos.org/manual/nix/stable/language/constructs#assertions), such as when a package is [marked as broken](#var-meta-broken), rather than failing the entire evaluation.
:::{.example #example-list-haskellPackages}
# List all Python packages in Nixpkgs
The following command lists all [derivations names](https://nixos.org/manual/nix/stable/language/derivations#attr-name) with their attribute path from the latest Nixpkgs rolling release (`nixpkgs-unstable`).
```shell-session
$ nix-env -qaP -f '<nixpkgs>' -A pythonPackages -I nixpkgs=channel:nixpkgs-unstable
```
```console
pythonPackages.avahi avahi-0.8
pythonPackages.boost boost-1.81.0
pythonPackages.caffe caffe-1.0
pythonPackages.caffeWithCuda caffe-1.0
pythonPackages.cbeams cbeams-1.0.3
```
:::
```{=include=} sections
agda.section.md
android.section.md
astal.section.md
beam.section.md
chicken.section.md
coq.section.md
cosmic.section.md
crystal.section.md
cuda.section.md
cuelang.section.md
dart.section.md
dhall.section.md
dlang.section.md
dotnet.section.md
emscripten.section.md
factor.section.md
gnome.section.md
go.section.md
gradle.section.md
hare.section.md
haskell.section.md
hy.section.md
idris.section.md
idris2.section.md
ios.section.md
java.section.md
javascript.section.md
julia.section.md
lisp.section.md
lua.section.md
maven.section.md
nim.section.md
ocaml.section.md
octave.section.md
perl.section.md
php.section.md
pkg-config.section.md
python.section.md
qt.section.md
r.section.md
ruby.section.md
rust.section.md
scheme.section.md
swift.section.md
tcl.section.md
texlive.section.md
typst.section.md
vim.section.md
neovim.section.md
```

View File

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

View File

@@ -0,0 +1,135 @@
# Java {#sec-language-java}
Ant-based Java packages are typically built from source as follows:
```nix
stdenv.mkDerivation {
pname = "...";
version = "...";
src = fetchurl {
# ...
};
nativeBuildInputs = [
ant
jdk
stripJavaArchivesHook # removes timestamp metadata from jar files
];
buildPhase = ''
runHook preBuild
ant # build the project using ant
runHook postBuild
'';
installPhase = ''
runHook preInstall
# copy generated jar file(s) to an appropriate location in $out
install -Dm644 build/foo.jar $out/share/java/foo.jar
runHook postInstall
'';
}
```
Note that `jdk` is an alias for the OpenJDK (self-built where available,
or pre-built via Zulu).
Also note that not using `stripJavaArchivesHook` will likely cause the
generated `.jar` files to be non-deterministic, which is not optimal.
Using it, however, does not always guarantee reproducibility.
JAR files that are intended to be used by other packages should be
installed in `$out/share/java`. JDKs have a `stdenv` setup hook that adds
any JARs in the `share/java` directories of the build inputs to the
`CLASSPATH` environment variable. For instance, if the package `libfoo`
installs a JAR named `foo.jar` in its `share/java` directory, and
another package declares the attribute
```nix
{
buildInputs = [ libfoo ];
nativeBuildInputs = [ jdk ];
}
```
then `CLASSPATH` will be set to
`/nix/store/...-libfoo/share/java/foo.jar`.
Private JARs should be installed in a location like
`$out/share/package-name`.
If your Java package provides a program, you need to generate a wrapper
script to run it using a JRE. You can use `makeWrapper` for this:
```nix
{
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
runHook preInstall
mkdir -p $out/bin
makeWrapper ${jre}/bin/java $out/bin/foo \
--add-flags "-cp $out/share/java/foo.jar org.foo.Main"
runHook postInstall
'';
}
```
Since the introduction of the Java Platform Module System in Java 9,
Java distributions typically no longer ship with a general-purpose JRE:
instead, they allow generating a JRE with only the modules required for
your application(s). Because we can't predict what modules will be
needed on a general-purpose system, the default `jre` package is the full
JDK. When building a minimal system/image, you can override the
`modules` parameter on `jre_minimal` to build a JRE with only the
modules relevant for you:
```nix
let
my_jre = pkgs.jre_minimal.override {
modules = [
# The modules used by 'something' and 'other' combined:
"java.base"
"java.logging"
];
};
something = (pkgs.something.override { jre = my_jre; });
other = (pkgs.other.override { jre = my_jre; });
in
<...>
```
You can also specify what JDK your JRE should be based on, for example
selecting a 'headless' build to avoid including a link to GTK+:
```nix
{ my_jre = pkgs.jre_minimal.override { jdk = jdk11_headless; }; }
```
Note all JDKs passthru `home`, so if your application requires
environment variables like `JAVA_HOME` being set, that can be done in a
generic fashion with the `--set` argument of `makeWrapper`:
```bash
--set JAVA_HOME ${jdk.home}
```
It is possible to use a different Java compiler than `javac` from the
OpenJDK. For instance, to use the GNU Java Compiler:
```nix
{
nativeBuildInputs = [
gcj
ant
];
}
```
Here, Ant will automatically use `gij` (the GNU Java Runtime) instead of
the OpenJRE.

View File

@@ -0,0 +1,933 @@
# Javascript {#language-javascript}
## Introduction {#javascript-introduction}
This contains instructions on how to package JavaScript applications.
The various tools available will be listed in the [tools-overview](#javascript-tools-overview).
Some general principles for packaging will follow.
Finally, some tool-specific instructions will be given.
## Getting unstuck / finding code examples {#javascript-finding-examples}
If you find you are lacking inspiration for packaging JavaScript applications, the links below might prove useful.
Searching online for prior art can be helpful if you are running into solved problems.
### Github {#javascript-finding-examples-github}
- Searching Nix files for `yarnConfigHook`: <https://github.com/search?q=yarnConfigHook+language%3ANix&type=code>
- Searching just `flake.nix` files for `yarnConfigHook`: <https://github.com/search?q=yarnConfigHook+path%3A**%2Fflake.nix&type=code>
### Gitlab {#javascript-finding-examples-gitlab}
- Searching Nix files for `yarnConfigHook`: <https://gitlab.com/search?scope=blobs&search=yarnConfigHook+extension%3Anix>
- Searching just `flake.nix` files for `yarnConfigHook`: <https://gitlab.com/search?scope=blobs&search=yarnConfigHook+filename%3Aflake.nix>
## Tools overview {#javascript-tools-overview}
## General principles {#javascript-general-principles}
The following principles are given in order of importance with potential exceptions.
### Try to use the same node version used upstream {#javascript-upstream-node-version}
It is often not documented which node version is used upstream, but if it is, try to use the same version when packaging.
This can be a problem if upstream is using the latest and greatest and you are trying to use an earlier version of node.
Some cryptic errors regarding V8 may appear.
### Try to respect the package manager originally used by upstream (and use the upstream lock file) {#javascript-upstream-package-manager}
A lock file (package-lock.json, yarn.lock...) is supposed to make reproducible installations of `node_modules` for each tool.
Guidelines of package managers, recommend to commit those lock files to the repos.
If a particular lock file is present, it is a strong indication of which package manager is used upstream.
It's better to try to use a Nix tool that understands the lock file.
Using a different tool might give you a hard-to-understand error because different packages have been installed.
An example of problems that could arise can be found [here](https://github.com/NixOS/nixpkgs/pull/126629).
Upstream use npm, but this is an attempt to package it with `yarn2nix` (that uses yarn.lock).
Using a different tool forces you to commit a lock file to the repository.
These files are fairly large, so when packaging for nixpkgs, this approach does not scale well.
Exceptions to this rule are:
- When you encounter one of the bugs from a Nix tool. In each of the tool-specific instructions, known problems will be detailed. If you have a problem with a particular tool, then it's best to try another tool, even if this means you will have to re-create a lock file and commit it to Nixpkgs. In general `yarn2nix` has fewer known problems, and so a simple search in Nixpkgs will reveal many `yarn.lock` files committed.
- Some lock files contain particular version of a package that has been pulled off npm for some reason. In that case, you can recreate upstream lock (by removing the original and `npm install`, `yarn`, ...) and commit this to nixpkgs.
- The only tool that supports workspaces (a feature of npm that helps manage sub-directories with different package.json from a single top level package.json) is `yarn2nix`. If upstream has workspaces you should try `yarn2nix`.
### Try to use upstream package.json {#javascript-upstream-package-json}
Exceptions to this rule are:
- Sometimes the upstream repo assumes some dependencies should be installed globally. In that case, you can add them manually to the upstream `package.json` (`yarn add xxx` or `npm install xxx`, ...). Dependencies that are installed locally can be executed with `npx` for CLI tools (e.g. `npx postcss ...`, this is how you can call those dependencies in the phases).
- Sometimes there is a version conflict between some dependency requirements. In that case you can fix a version by removing the `^`.
- Sometimes the script defined in the package.json does not work as is. Some scripts for example use CLI tools that might not be available, or cd in directory with a different package.json (for workspaces notably). In that case, it's perfectly fine to look at what the particular script is doing and break this down in the phases. In the build script you can see `build:*` calling in turns several other build scripts like `build:ui` or `build:server`. If one of those fails, you can try to separate those into,
```sh
yarn build:ui
yarn build:server
# OR
npm run build:ui
npm run build:server
```
when you need to override a package.json. It's nice to use the one from the upstream source and do some explicit override. Here is an example:
```nix
{
patchedPackageJSON = final.runCommand "package.json" { } ''
${jq}/bin/jq '.version = "0.4.0" |
.devDependencies."@jsdoc/cli" = "^0.2.5"
${sonar-src}/package.json > $out
'';
}
```
You will still need to commit the modified version of the lock files, but at least the overrides are explicit for everyone to see.
### Using node_modules directly {#javascript-using-node_modules}
Each tool has an abstraction to just build the node_modules (dependencies) directory.
You can always use the `stdenv.mkDerivation` with the node_modules to build the package (symlink the node_modules directory and then use the package build command).
The node_modules abstraction can be also used to build some web framework frontends.
For an example of this see how [plausible](https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/web-apps/plausible/default.nix) is built. `mkYarnModules` to make the derivation containing node_modules.
Then when building the frontend you can just symlink the node_modules directory.
## Javascript packages inside nixpkgs {#javascript-packages-nixpkgs}
The [pkgs/development/node-packages](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/node-packages) folder contains a generated collection of [npm packages](https://npmjs.com/) that can be installed with the Nix package manager.
As a rule of thumb, the package set should only provide _end-user_ software packages, such as command-line utilities.
Libraries should only be added to the package set if there is a non-npm package that requires it.
When it is desired to use npm libraries in a development project, use the `node2nix` generator directly on the `package.json` configuration file of the project.
The package set provides support for the official stable Node.js versions.
The latest stable LTS release in `nodePackages`, as well as the latest stable current release in `nodePackages_latest`.
If your package uses native addons, you need to examine what kind of native build system it uses. Here are some examples:
- `node-gyp`
- `node-gyp-builder`
- `node-pre-gyp`
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 [pkgs/development/node-packages/overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/node-packages/overrides.nix):
```nix
{
dat = prev.dat.override (oldAttrs: {
buildInputs = [
final.node-gyp-build
pkgs.libtool
pkgs.autoconf
pkgs.automake
];
meta = oldAttrs.meta // {
broken = since "12";
};
});
}
```
### Adding and updating JavaScript packages in Nixpkgs {#javascript-adding-or-updating-packages}
To add a package from npm to Nixpkgs:
1. Modify [pkgs/development/node-packages/node-packages.json](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/node-packages/node-packages.json) to add, update or remove package entries to have it included in `nodePackages` and `nodePackages_latest`.
2. Run the script:
```sh
./pkgs/development/node-packages/generate.sh
```
3. Build your new package to test your changes:
```sh
nix-build -A nodePackages.<new-or-updated-package>
```
To build against the latest stable Current Node.js version (e.g. 18.x):
```sh
nix-build -A nodePackages_latest.<new-or-updated-package>
```
If the package doesn't build, you may need to add an override as explained above.
4. If the package's name doesn't match any of the executables it provides, add an entry in [pkgs/development/node-packages/main-programs.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/node-packages/main-programs.nix). This will be the case for all scoped packages, e.g., `@angular/cli`.
5. Add and commit all modified and generated files.
For more information about the generation process, consult the [README.md](https://github.com/svanderburg/node2nix) file of the `node2nix` tool.
To update npm packages in Nixpkgs, run the same `generate.sh` script:
```sh
./pkgs/development/node-packages/generate.sh
```
#### Git protocol error {#javascript-git-error}
Some packages may have Git dependencies from GitHub specified with `git://`.
GitHub has [disabled unencrypted Git connections](https://github.blog/2021-09-01-improving-git-protocol-security-github/#no-more-unauthenticated-git), so you may see the following error when running the generate script:
```
The unauthenticated git protocol on port 9418 is no longer supported
```
Use the following Git configuration to resolve the issue:
```sh
git config --global url."https://github.com/".insteadOf git://github.com/
```
## Tool-specific instructions {#javascript-tool-specific}
### buildNpmPackage {#javascript-buildNpmPackage}
`buildNpmPackage` allows you to package npm-based projects in Nixpkgs without the use of an auto-generated dependencies file (as used in [node2nix](#javascript-node2nix)).
It works by utilizing npm's cache functionality -- creating a reproducible cache that contains the dependencies of a project, and pointing npm to it.
Here's an example:
```nix
{
lib,
buildNpmPackage,
fetchFromGitHub,
}:
buildNpmPackage (finalAttrs: {
pname = "flood";
version = "4.7.0";
src = fetchFromGitHub {
owner = "jesec";
repo = "flood";
tag = "v${finalAttrs.version}";
hash = "sha256-BR+ZGkBBfd0dSQqAvujsbgsEPFYw/ThrylxUbOksYxM=";
};
npmDepsHash = "sha256-tuEfyePwlOy2/mOPdXbqJskO6IowvAP4DWg8xSZwbJw=";
# The prepack script runs the build script, which we'd rather do in the build phase.
npmPackFlags = [ "--ignore-scripts" ];
NODE_OPTIONS = "--openssl-legacy-provider";
meta = {
description = "Modern web UI for various torrent clients with a Node.js backend and React frontend";
homepage = "https://flood.js.org";
license = lib.licenses.gpl3Only;
maintainers = with lib.maintainers; [ winter ];
};
})
```
In the default `installPhase` set by `buildNpmPackage`, it uses `npm pack --json --dry-run` to decide what files to install in `$out/lib/node_modules/$name/`, where `$name` is the `name` string defined in the package's `package.json`.
Additionally, the `bin` and `man` keys in the source's `package.json` are used to decide what binaries and manpages are supposed to be installed.
If these are not defined, `npm pack` may miss some files, and no binaries will be produced.
#### Arguments {#javascript-buildNpmPackage-arguments}
* `npmDepsHash`: The output hash of the dependencies for this project. Can be calculated in advance with [`prefetch-npm-deps`](#javascript-buildNpmPackage-prefetch-npm-deps).
* `makeCacheWritable`: Whether to make the cache writable prior to installing dependencies. Don't set this unless npm tries to write to the cache directory, as it can slow down the build.
* `npmBuildScript`: The script to run to build the project. Defaults to `"build"`.
* `npmWorkspace`: The workspace directory within the project to build and install.
* `dontNpmBuild`: Option to disable running the build script. Set to `true` if the package does not have a build script. Defaults to `false`. Alternatively, setting `buildPhase` explicitly also disables this.
* `dontNpmInstall`: Option to disable running `npm install`. Defaults to `false`. Alternatively, setting `installPhase` explicitly also disables this.
* `npmFlags`: Flags to pass to all npm commands.
* `npmInstallFlags`: Flags to pass to `npm ci`.
* `npmBuildFlags`: Flags to pass to `npm run ${npmBuildScript}`.
* `npmPackFlags`: Flags to pass to `npm pack`.
* `npmPruneFlags`: Flags to pass to `npm prune`. Defaults to the value of `npmInstallFlags`.
* `makeWrapperArgs`: Flags to pass to `makeWrapper`, added to executable calling the generated `.js` with `node` as an interpreter. These scripts are defined in `package.json`.
* `nodejs`: The `nodejs` package to build against, using the corresponding `npm` shipped with that version of `node`. Defaults to `pkgs.nodejs`.
* `npmDeps`: The dependencies used to build the npm package. Especially useful to not have to recompute workspace dependencies.
#### prefetch-npm-deps {#javascript-buildNpmPackage-prefetch-npm-deps}
`prefetch-npm-deps` is a Nixpkgs package that calculates the hash of the dependencies of an npm project ahead of time.
```console
$ ls
package.json package-lock.json index.js
$ prefetch-npm-deps package-lock.json
...
sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
```
#### fetchNpmDeps {#javascript-buildNpmPackage-fetchNpmDeps}
`fetchNpmDeps` is a Nix function that requires the following mandatory arguments:
- `src`: A directory / tarball with `package-lock.json` file
- `hash`: The output hash of the node dependencies defined in `package-lock.json`.
It returns a derivation with all `package-lock.json` dependencies downloaded into `$out/`, usable as an npm cache.
#### importNpmLock {#javascript-buildNpmPackage-importNpmLock}
This function replaces the npm dependency references in `package.json` and `package-lock.json` with paths to the Nix store.
How each dependency is fetched can be customized with the `fetcherOpts` argument.
This is a simpler and more convenient alternative to [`fetchNpmDeps`](#javascript-buildNpmPackage-fetchNpmDeps) for managing npm dependencies in Nixpkgs.
There is no need to specify a `hash`, since it relies entirely on the integrity hashes already present in the `package-lock.json` file.
##### Inputs {#javascript-buildNpmPackage-inputs}
- `npmRoot`: Path to package directory containing the source tree.
If this is omitted, the `package` and `packageLock` arguments must be specified instead.
- `package`: Parsed contents of `package.json`
- `packageLock`: Parsed contents of `package-lock.json`
- `pname`: Package name
- `version`: Package version
- `fetcherOpts`: An attribute set of arguments forwarded to the underlying fetcher.
It returns a derivation with a patched `package.json` & `package-lock.json` with all dependencies resolved to Nix store paths.
:::{.note}
`npmHooks.npmConfigHook` cannot be used with `importNpmLock`.
Use `importNpmLock.npmConfigHook` instead.
:::
:::{.example}
##### `pkgs.importNpmLock` usage example {#javascript-buildNpmPackage-example}
```nix
{ buildNpmPackage, importNpmLock }:
buildNpmPackage {
pname = "hello";
version = "0.1.0";
src = ./.;
npmDeps = importNpmLock { npmRoot = ./.; };
npmConfigHook = importNpmLock.npmConfigHook;
}
```
:::
:::{.example}
##### `pkgs.importNpmLock` usage example with `fetcherOpts` {#javascript-buildNpmPackage-example-fetcherOpts}
`importNpmLock` uses the following fetchers:
- `pkgs.fetchurl` for `http(s)` dependencies
- `fetchGit` for `git` dependencies
It is possible to provide additional arguments to individual fetchers as needed:
```nix
{ buildNpmPackage, importNpmLock }:
buildNpmPackage {
pname = "hello";
version = "0.1.0";
src = ./.;
npmDeps = importNpmLock {
npmRoot = ./.;
fetcherOpts = {
# Pass 'curlOptsList' to 'pkgs.fetchurl' while fetching 'axios'
"node_modules/axios" = {
curlOptsList = [ "--verbose" ];
};
};
};
npmConfigHook = importNpmLock.npmConfigHook;
}
```
:::
#### importNpmLock.buildNodeModules {#javascript-buildNpmPackage-importNpmLock.buildNodeModules}
`importNpmLock.buildNodeModules` returns a derivation with a pre-built `node_modules` directory, as imported by `importNpmLock`.
This is to be used together with `importNpmLock.hooks.linkNodeModulesHook` to facilitate `nix-shell`/`nix develop` based development workflows.
It accepts an argument with the following attributes:
`npmRoot` (Path; optional)
: Path to package directory containing the source tree. If not specified, the `package` and `packageLock` arguments must both be specified.
`package` (Attrset; optional)
: Parsed contents of `package.json`, as returned by `lib.importJSON ./my-package.json`. If not specified, the `package.json` in `npmRoot` is used.
`packageLock` (Attrset; optional)
: Parsed contents of `package-lock.json`, as returned `lib.importJSON ./my-package-lock.json`. If not specified, the `package-lock.json` in `npmRoot` is used.
`derivationArgs` (`mkDerivation` attrset; optional)
: Arguments passed to `stdenv.mkDerivation`
For example:
```nix
pkgs.mkShell {
packages = [
importNpmLock.hooks.linkNodeModulesHook
nodejs
];
npmDeps = importNpmLock.buildNodeModules {
npmRoot = ./.;
inherit nodejs;
};
}
```
will create a development shell where a `node_modules` directory is created & packages symlinked to the Nix store when activated.
:::{.note}
Commands like `npm install` & `npm add` that write packages & executables need to be used with `--package-lock-only`.
This means `npm` installs dependencies by writing into `package-lock.json` without modifying the `node_modules` folder. Installation happens through reloading the devShell.
This might be best practice since it gives the `nix shell` virtually exclusive ownership over your `node_modules` folder.
It's recommended to set `package-lock-only = true` in your project-local [`.npmrc`](https://docs.npmjs.com/cli/v11/configuring-npm/npmrc).
:::
### corepack {#javascript-corepack}
This package puts the corepack wrappers for pnpm and yarn in your PATH, and they will honor the `packageManager` setting in the `package.json`.
### node2nix {#javascript-node2nix}
#### Preparation {#javascript-node2nix-preparation}
You will need to generate a Nix expression for the dependencies. Don't forget the `-l package-lock.json` if there is a lock file. Most probably you will need the `--development` to include the `devDependencies`
So the command will most likely be:
```sh
node2nix --development -l package-lock.json
```
See `node2nix` [docs](https://github.com/svanderburg/node2nix) for more info.
#### Pitfalls {#javascript-node2nix-pitfalls}
- If upstream package.json does not have a "version" attribute, `node2nix` will crash. You will need to add it like shown in [the package.json section](#javascript-upstream-package-json).
- `node2nix` has some [bugs](https://github.com/svanderburg/node2nix/issues/238) related to working with lock files from npm distributed with `nodejs_16`.
- `node2nix` does not like missing packages from npm. If you see something like `Cannot resolve version: vue-loader-v16@undefined` then you might want to try another tool. The package might have been pulled off of npm.
### pnpm {#javascript-pnpm}
Pnpm is available as the top-level package `pnpm`. Additionally, there are variants pinned to certain major versions, like `pnpm_8` and `pnpm_9`, which support different sets of lock file versions.
When packaging an application that includes a `pnpm-lock.yaml`, you need to fetch the pnpm store for that project using a fixed-output-derivation. The functions `pnpm_8.fetchDeps` and `pnpm_9.fetchDeps` can create this pnpm store derivation. In conjunction, the setup hooks `pnpm_8.configHook` and `pnpm_9.configHook` will prepare the build environment to install the pre-fetched dependencies store. Here is an example for a package that contains `package.json` and a `pnpm-lock.yaml` files using the above `pnpm_` attributes:
```nix
{
stdenv,
nodejs,
# This is pinned as { pnpm = pnpm_9; }
pnpm,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "foo";
version = "0-unstable-1980-01-01";
src = {
#...
};
nativeBuildInputs = [
nodejs
pnpm.configHook
];
pnpmDeps = pnpm.fetchDeps {
inherit (finalAttrs) pname version src;
fetcherVersion = 2;
hash = "...";
};
})
```
NOTE: It is highly recommended to use a pinned version of pnpm (i.e., `pnpm_8` or `pnpm_9`), to increase future reproducibility. It might also be required to use an older version if the package needs support for a certain lock file version.
In case you are patching `package.json` or `pnpm-lock.yaml`, make sure to pass `finalAttrs.patches` to the function as well (i.e., `inherit (finalAttrs) patches`.
`pnpm.configHook` supports adding additional `pnpm install` flags via `pnpmInstallFlags` which can be set to a Nix string array:
```nix
{ pnpm }:
stdenv.mkDerivation (finalAttrs: {
pname = "foo";
version = "0-unstable-1980-01-01";
src = {
# ...
};
pnpmInstallFlags = [ "--shamefully-hoist" ];
pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pnpmInstallFlags; };
})
```
#### Dealing with `sourceRoot` {#javascript-pnpm-sourceRoot}
If the pnpm project is in a subdirectory, you can just define `sourceRoot` or `setSourceRoot` for `fetchDeps`.
If `sourceRoot` is different between the parent derivation and `fetchDeps`, you will have to set `pnpmRoot` to effectively be the same location as it is in `fetchDeps`.
Assuming the following directory structure, we can define `sourceRoot` and `pnpmRoot` as follows:
```
.
├── frontend
│   ├── ...
│   ├── package.json
│   └── pnpm-lock.yaml
└── ...
```
```nix
{
# ...
pnpmDeps = pnpm.fetchDeps {
# ...
sourceRoot = "${finalAttrs.src.name}/frontend";
};
# by default the working directory is the extracted source
pnpmRoot = "frontend";
}
```
#### PNPM Workspaces {#javascript-pnpm-workspaces}
If you need to use a PNPM workspace for your project, then set `pnpmWorkspaces = [ "<workspace project name 1>" "<workspace project name 2>" ]`, etc, in your `pnpm.fetchDeps` call,
which will make PNPM only install dependencies for those workspace packages.
For example:
```nix
{
# ...
pnpmWorkspaces = [ "@astrojs/language-server" ];
pnpmDeps = pnpm.fetchDeps {
inherit (finalAttrs) pnpmWorkspaces;
#...
};
}
```
The above would make `pnpm.fetchDeps` call only install dependencies for the `@astrojs/language-server` workspace package.
Note that you do not need to set `sourceRoot` to make this work.
Usually, in such cases, you'd want to use `pnpm --filter=<pnpm workspace name> build` to build your project, as `npmHooks.npmBuildHook` probably won't work. A `buildPhase` based on the following example will probably fit most workspace projects:
```nix
{
buildPhase = ''
runHook preBuild
pnpm --filter=@astrojs/language-server build
runHook postBuild
'';
}
```
#### Additional PNPM Commands and settings {#javascript-pnpm-extraCommands}
If you require setting an additional PNPM configuration setting (such as `dedupe-peer-dependents` or similar),
set `prePnpmInstall` to the right commands to run. For example:
```nix
{
prePnpmInstall = ''
pnpm config set dedupe-peer-dependents false
'';
pnpmDeps = pnpm.fetchDeps {
inherit (finalAttrs) prePnpmInstall;
# ...
};
}
```
In this example, `prePnpmInstall` will be run by both `pnpm.configHook` and by the `pnpm.fetchDeps` builder.
#### PNPM `fetcherVersion` {#javascript-pnpm-fetcherVersion}
This is the version of the output of `pnpm.fetchDeps`, if you haven't set it already, you can use `1` with your current hash:
```nix
{
# ...
pnpmDeps = pnpm.fetchDeps {
# ...
fetcherVersion = 1;
hash = "..."; # you can use your already set hash here
};
}
```
After upgrading to a newer `fetcherVersion`, you need to regenerate the hash:
```nix
{
# ...
pnpmDeps = pnpm.fetchDeps {
# ...
fetcherVersion = 2;
hash = "..."; # clear this hash and generate a new one
};
}
```
This variable ensures that we can make changes to the output of `pnpm.fetchDeps` without breaking existing hashes.
Changes can include workarounds or bug fixes to existing PNPM issues.
##### Version history {#javascript-pnpm-fetcherVersion-versionHistory}
- 1: Initial version, nothing special
- 2: [Ensure consistent permissions](https://github.com/NixOS/nixpkgs/pull/422975)
### Yarn {#javascript-yarn}
Yarn based projects use a `yarn.lock` file instead of a `package-lock.json` to pin dependencies.
To package yarn-based applications, you need to distinguish by the version pointers in the `yarn.lock` file. See the following sections.
#### Yarn v1 {#javascript-yarn-v1}
Yarn v1 lockfiles contain a comment `# yarn lockfile v1` at the beginning of the file.
Nixpkgs provides the Nix function `fetchYarnDeps` which fetches an offline cache suitable for running `yarn install` before building the project. In addition, Nixpkgs provides the hooks:
- `yarnConfigHook`: Fetches the dependencies from the offline cache and installs them into `node_modules`.
- `yarnBuildHook`: Runs `yarn build` or a specified `yarn` command that builds the project.
- `yarnInstallHook`: Runs `yarn install --production` to prune dependencies and installs the project into `$out`.
An example usage of the above attributes is:
```nix
{
lib,
stdenv,
fetchFromGitHub,
fetchYarnDeps,
yarnConfigHook,
yarnBuildHook,
yarnInstallHook,
nodejs,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "...";
version = "...";
src = fetchFromGitHub {
owner = "...";
repo = "...";
rev = "v${finalAttrs.version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
yarnOfflineCache = fetchYarnDeps {
yarnLock = finalAttrs.src + "/yarn.lock";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
nativeBuildInputs = [
yarnConfigHook
yarnBuildHook
yarnInstallHook
# Needed for executing package.json scripts
nodejs
];
meta = {
# ...
};
})
```
##### `yarnConfigHook` arguments {#javascript-yarnconfighook}
By default, `yarnConfigHook` relies upon the attribute `${yarnOfflineCache}` (or `${offlineCache}` if the former is not set) to find the location of the offline cache produced by `fetchYarnDeps`. To disable this phase, you can set `dontYarnInstallDeps = true` or override the `configurePhase`.
##### `yarnBuildHook` arguments {#javascript-yarnbuildhook}
This script by default runs `yarn --offline build`, and it relies upon the project's dependencies installed at `node_modules`. Below is a list of additional `mkDerivation` arguments read by this hook:
- `yarnBuildScript`: Sets a different `yarn --offline` subcommand (defaults to `build`).
- `yarnBuildFlags`: Single string list of additional flags to pass the above command, or a Nix list of such additional flags.
##### `yarnInstallHook` arguments {#javascript-yarninstallhook}
To install the package `yarnInstallHook` uses both `npm` and `yarn` to cleanup project files and dependencies. To disable this phase, you can set `dontYarnInstall = true` or override the `installPhase`. Below is a list of additional `mkDerivation` arguments read by this hook:
- `yarnKeepDevDeps`: Disables the removal of devDependencies from `node_modules` before installation.
#### yarn2nix {#javascript-yarn2nix}
> [!WARNING]
> The `yarn2nix` functions have been deprecated in favor of `yarnConfigHook`, `yarnBuildHook` and `yarnInstallHook` (for Yarn v1) and `yarn-berry_*.*` tooling (Yarn v3 and v4). Documentation for `yarn2nix` functions still appears here for the sake of the packages that still use them. See also a tracking issue [#324246](https://github.com/NixOS/nixpkgs/issues/324246).
##### Preparation {#javascript-yarn2nix-preparation}
You will need at least a `yarn.lock` file. If upstream does not have one you need to generate it and reference it in your package definition.
If the downloaded files contain the `package.json` and `yarn.lock` files they can be used like this:
```nix
{
offlineCache = fetchYarnDeps {
yarnLock = src + "/yarn.lock";
hash = "....";
};
}
```
##### mkYarnPackage {#javascript-yarn2nix-mkYarnPackage}
> [!WARNING]
> The `mkYarnPackage` functions have been deprecated in favor of `yarnConfigHook`, `yarnBuildHook` and `yarnInstallHook` (for Yarn v1) and `yarn-berry_*.*` tooling (Yarn v3 and v4). Documentation for `mkYarnPackage` functions still appears here for the sake of the packages that still use them. See also a tracking issue [#324246](https://github.com/NixOS/nixpkgs/issues/324246).
`mkYarnPackage` will by default try to generate a binary. For packages only generating static assets (Svelte, Vue, React, Webpack, ...), you will need to explicitly override the build step with your instructions.
It's important to use the `--offline` flag. For example if you script is `"build": "something"` in `package.json` use:
```nix
{
nativeBuildInputs = [ writableTmpDirAsHomeHook ];
buildPhase = ''
runHook preBuild
yarn --offline build
runHook postBuild
'';
}
```
The `distPhase` is packing the package's dependencies in a tarball using `yarn pack`. You can disable it using:
```nix
{ doDist = false; }
```
The configure phase can sometimes fail because it makes many assumptions that may not always apply. One common override is:
```nix
{
configurePhase = ''
runHook preConfigure
ln -s $node_modules node_modules
runHook postConfigure
'';
}
```
or if you need a writeable node_modules directory:
```nix
{
configurePhase = ''
runHook preConfigure
cp -r $node_modules node_modules
chmod +w node_modules
runHook postConfigure
'';
}
```
##### mkYarnModules {#javascript-yarn2nix-mkYarnModules}
This will generate a derivation including the `node_modules` directory.
If you have to build a derivation for an integrated web framework (Rails, Phoenix, etc.), this is probably the easiest way.
#### Overriding dependency behavior {#javascript-mkYarnPackage-overriding-dependencies}
In the `mkYarnPackage` record the property `pkgConfig` can be used to override packages when you encounter problems building.
For instance, say your package is throwing errors when trying to invoke node-sass:
```
ENOENT: no such file or directory, scandir '/build/source/node_modules/node-sass/vendor'
```
To fix this we will specify different versions of build inputs to use, as well as some post install steps to get the software built the way we want:
```nix
mkYarnPackage rec {
pkgConfig = {
node-sass = {
buildInputs = with final; [
python
libsass
pkg-config
];
postInstall = ''
LIBSASS_EXT=auto yarn --offline run build
rm build/config.gypi
'';
};
};
}
```
##### Pitfalls {#javascript-yarn2nix-pitfalls}
- If version is missing from upstream package.json, yarn will silently install nothing. In that case, you will need to override package.json as shown in the [package.json section](#javascript-upstream-package-json)
- Having trouble with `node-gyp`? Try adding these lines to the `yarnPreBuild` steps:
```nix
{
yarnPreBuild = ''
mkdir -p $HOME/.node-gyp/${nodejs.version}
echo 9 > $HOME/.node-gyp/${nodejs.version}/installVersion
ln -sfv ${nodejs}/include $HOME/.node-gyp/${nodejs.version}
export npm_config_nodedir=${nodejs}
'';
}
```
- The `echo 9` steps comes from this answer: <https://stackoverflow.com/a/49139496>
- Exporting the headers in `npm_config_nodedir` comes from this issue: <https://github.com/nodejs/node-gyp/issues/1191#issuecomment-301243919>
- `offlineCache` (described [above](#javascript-yarn2nix-preparation)) must be specified to avoid [Import From Derivation](#ssec-import-from-derivation) (IFD) when used inside Nixpkgs.
#### Yarn Berry v3/v4 {#javascript-yarn-v3-v4}
Yarn Berry (v3 / v4) have similar formats, they start with blocks like these:
```yaml
__metadata:
version: 6
cacheKey: 8[cX]
```
```yaml
__metadata:
version: 8
cacheKey: 10[cX]
```
For these packages, we have some helpers exposed under the respective `yarn-berry_3` and `yarn-berry_4` packages:
- `yarn-berry-fetcher`
- `fetchYarnBerryDeps`
- `yarnBerryConfigHook`
It's recommended to ensure you're explicitly pinning the major version used, for example by capturing the `yarn-berry_Xn` argument and then re-defining it as a `yarn-berry` `let` binding.
```nix
{
stdenv,
nodejs,
yarn-berry_4,
}:
let
yarn-berry = yarn-berry_4;
in
stdenv.mkDerivation (finalAttrs: {
pname = "foo";
version = "0-unstable-1980-01-01";
src = {
#...
};
nativeBuildInputs = [
nodejs
yarn-berry.yarnBerryConfigHook
];
offlineCache = yarn-berry.fetchYarnBerryDeps {
inherit (finalAttrs) src;
hash = "...";
};
})
```
##### `yarn-berry_X.fetchYarnBerryDeps` {#javascript-fetchYarnBerryDeps}
`fetchYarnBerryDeps` runs `yarn-berry-fetcher fetch` in a fixed-output-derivation. It is a custom fetcher designed to reproducibly download all files in the `yarn.lock` file, validating their hashes in the process. For git dependencies, it creates a checkout at `${offlineCache}/checkouts/<40-character-commit-hash>` (relying on the git commit hash to describe the contents of the checkout).
To produce the `hash` argument for `fetchYarnBerryDeps` function call, the `yarn-berry-fetcher prefetch` command can be used:
```console
$ yarn-berry-fetcher prefetch </path/to/yarn.lock> [/path/to/missing-hashes.json]
```
This prints the hash to stdout and can be used in update scripts to recalculate the hash for a new version of `yarn.lock`.
##### `yarn-berry_X.yarnBerryConfigHook` {#javascript-yarnBerryConfigHook}
`yarnBerryConfigHook` uses the store path `offlineCache` points to, to run a `yarn install` during the build, producing a usable `node_modules` directory from the downloaded dependencies.
Internally, this uses a patched version of Yarn to ensure git dependencies are re-packed and any attempted downloads fail immediately.
##### Patching upstream `package.json` or `yarn.lock` files {#javascript-yarnBerry-patching}
In case patching the upstream `package.json` or `yarn.lock` is needed, it's important to pass `finalAttrs.patches` to `fetchYarnBerryDeps` as well, so the patched variants are picked up (i.e., `inherit (finalAttrs) patches`.
##### Missing hashes in the `yarn.lock` file {#javascript-yarnBerry-missing-hashes}
Unfortunately, `yarn.lock` files do not include hashes for optional/platform-specific dependencies. This is [by design](https://github.com/yarnpkg/berry/issues/6759).
To compensate for this, the `yarn-berry-fetcher missing-hashes` subcommand can be used to produce all missing hashes. These are usually stored in a `missing-hashes.json` file, which needs to be passed to both the build itself, as well as the `fetchYarnBerryDeps` helper:
```nix
{
stdenv,
nodejs,
yarn-berry_4,
}:
let
yarn-berry = yarn-berry_4;
in
stdenv.mkDerivation (finalAttrs: {
pname = "foo";
version = "0-unstable-1980-01-01";
src = {
#...
};
nativeBuildInputs = [
nodejs
yarn-berry.yarnBerryConfigHook
];
missingHashes = ./missing-hashes.json;
offlineCache = yarn-berry.fetchYarnBerryDeps {
inherit (finalAttrs) src missingHashes;
hash = "...";
};
})
```
## Outside Nixpkgs {#javascript-outside-nixpkgs}
There are some other tools available, which are written in the Nix language.
These can't be used inside Nixpkgs because they require [Import From Derivation](#ssec-import-from-derivation), which is not allowed in Nixpkgs.
If you are packaging something outside Nixpkgs, consider the following:
### npmlock2nix {#javascript-npmlock2nix}
[npmlock2nix](https://github.com/nix-community/npmlock2nix) aims at building `node_modules` without code generation. It hasn't reached v1 yet, the API might be subject to change.
#### Pitfalls {#javascript-npmlock2nix-pitfalls}
There are some [problems with npm v7](https://github.com/tweag/npmlock2nix/issues/45).
### nix-npm-buildpackage {#javascript-nix-npm-buildpackage}
[nix-npm-buildpackage](https://github.com/serokell/nix-npm-buildpackage) aims at building `node_modules` without code generation. It hasn't reached v1 yet, the API might change. It supports both `package-lock.json` and yarn.lock.
#### Pitfalls {#javascript-nix-npm-buildpackage-pitfalls}
There are some [problems with npm v7](https://github.com/serokell/nix-npm-buildpackage/issues/33).

View File

@@ -0,0 +1,81 @@
# Julia {#language-julia}
## Introduction {#julia-introduction}
Nixpkgs includes Julia as the `julia` derivation.
You can get specific versions by looking at the other `julia*` top-level derivations available.
For example, `julia_19` corresponds to Julia 1.9.
We also provide the current stable version as `julia-stable`, and an LTS version as `julia-lts`.
Occasionally, a Julia version has been too difficult to build from source in Nixpkgs and has been fetched prebuilt instead.
These Julia versions are differentiated with the `*-bin` suffix; for example, `julia-stable-bin`.
## julia.withPackages {#julia-withpackage}
The basic Julia derivations only provide the built-in packages that come with the distribution.
You can build Julia environments with additional packages using the `julia.withPackages` command.
This function accepts a list of strings representing Julia package names.
For example, you can build a Julia environment with the `Plots` package as follows.
```nix
julia.withPackages [ "Plots" ]
```
Arguments can be passed using `.override`.
For example:
```nix
(julia.withPackages.override {
precompile = false; # Turn off precompilation
})
[ "Plots" ]
```
Here's a nice way to run a Julia environment with a shell one-liner:
```sh
nix-shell -p 'julia.withPackages ["Plots"]' --run julia
```
### Arguments {#julia-withpackage-arguments}
* `precompile`: Whether to run `Pkg.precompile()` on the generated environment.
This will make package imports faster, but may fail in some cases.
For example, there is an upstream issue with `Gtk.jl` that prevents precompilation from working in the Nix build sandbox, because the precompiled code tries to access a display.
Packages like this will work fine if you build with `precompile=false`, and then precompile as needed once your environment starts.
Defaults: `true`
* `extraLibs`: Extra library dependencies that will be placed on the `LD_LIBRARY_PATH` for Julia.
Should not be needed as we try to obtain library dependencies automatically using Julia's artifacts system.
* `makeWrapperArgs`: Extra arguments to pass to the `makeWrapper` call which we use to wrap the Julia binary.
* `setDefaultDepot`: Whether to automatically prepend `$HOME/.julia` to the `JULIA_DEPOT_PATH`.
This is useful because Julia expects a writable depot path as the first entry, which the one we build in Nixpkgs is not.
If there's no writable depot, then Julia will show a warning and be unable to save command history logs etc.
Default: `true`
* `packageOverrides`: Allows you to override packages by name by passing an alternative source.
For example, you can use a custom version of the `LanguageServer` package by passing `packageOverrides = { "LanguageServer" = fetchFromGitHub {...}; }`.
* `augmentedRegistry`: Allows you to change the registry from which Julia packages are drawn.
This normally points at a special augmented version of the Julia [General packages registry](https://github.com/JuliaRegistries/General).
If you want to use a bleeding-edge version to pick up the latest package updates, you can plug in a later revision than the one in Nixpkgs.
* `juliaCpuTarget`: Allows you to set `JULIA_CPU_TARGET` when precompiling. Has no effect if `precompile=false`.
You may want to use this if you're building a Julia depot that will end up in a Nix cache and used on machines with
different CPUs.
Why? Julia will detect the CPU microarchitecture of the build machine and include this information in the precompiled
`*.ji` files. Starting in 1.10, Julia became more strict about checking the CPU target compatibility, so it may reject
your precompiled files if they were compiled on a different machine.
A good option to provide wide compatibility is to set this to `"generic"`, although this may reduce performance.
You can also set a semicolon-separated list of multiple different targets. See the Julia documentation for details.

View File

@@ -0,0 +1,305 @@
# lisp-modules {#lisp}
This document describes the Nixpkgs infrastructure for building Common Lisp
systems that use [ASDF](https://asdf.common-lisp.dev/) (Another System
Definition Facility). It lives in `pkgs/development/lisp-modules`.
## Overview {#lisp-overview}
The main entry point of the API are the Common Lisp implementation packages
themselves (e.g. `abcl`, `ccl`, `clasp-common-lisp`, `clisp`, `ecl`,
`sbcl`). They have the `pkgs` and `withPackages` attributes, which can be used
to discover available packages and to build wrappers, respectively.
The `pkgs` attribute set contains packages that were automatically
[imported](#lisp-importing-packages-from-quicklisp) from Quicklisp, and any
other [manually defined](#lisp-defining-packages-inside) ones. Not every package
works for all the CL implementations (e.g. `nyxt` only makes sense for `sbcl`).
The `withPackages` function is of primary utility. It is used to build
[runnable wrappers](#lisp-building-wrappers), with a pinned and pre-built
[ASDF FASL](#lisp-loading-asdf) available in the `ASDF` environment variable,
and `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` configured to
[find the desired systems at runtime](#lisp-loading-systems).
In addition, Lisps have the `withOverrides` function, which can be used to
[substitute](#lisp-including-external-pkg-in-scope) any package in the scope of
their `pkgs`. This will also be useful together with `overrideLispAttrs` when
[dealing with slashy systems](#lisp-dealing-with-slashy-systems), because they
should stay in the main package and be built by specifying the `systems`
argument to `build-asdf-system`.
## The 90% use case example {#lisp-use-case-example}
The most common way to use the library is to run ad-hoc wrappers like this:
`nix-shell -p 'sbcl.withPackages (ps: with ps; [ alexandria ])'`
Then, in a shell:
```
$ sbcl
* (load (sb-ext:posix-getenv "ASDF"))
* (asdf:load-system 'alexandria)
```
Also one can create a `pkgs.mkShell` environment in `shell.nix`/`flake.nix`:
```nix
let
sbcl' = sbcl.withPackages (ps: [ ps.alexandria ]);
in
mkShell { packages = [ sbcl' ]; }
```
Such a Lisp can be now used e.g. to compile your sources:
```nix
{
buildPhase = ''
runHook preBuild
${sbcl'}/bin/sbcl --load my-build-file.lisp
runHook postBuild
'';
}
```
## Importing packages from Quicklisp {#lisp-importing-packages-from-quicklisp}
To save some work of writing Nix expressions, there is a script that imports all
the packages distributed by Quicklisp into `imported.nix`. This works by parsing
its `releases.txt` and `systems.txt` files, which are published every couple of
months on [quicklisp.org](https://beta.quicklisp.org/dist/quicklisp.txt).
The import process is implemented in the `import` directory as Common Lisp
code in the `org.lispbuilds.nix` ASDF system. To run the script, one can
execute `ql-import.lisp`:
```
cd pkgs/development/lisp-modules
nix-shell --run 'sbcl --script ql-import.lisp'
```
The script will:
1. Download the latest Quicklisp `systems.txt` and `releases.txt` files
2. Generate a temporary SQLite database of all QL systems in `packages.sqlite`
3. Generate an `imported.nix` file from the database
(The `packages.sqlite` file can be deleted at will, because it is regenerated
each time the script runs.)
The maintainer's job is to:
1. Re-run the `ql-import.lisp` script when there is a new Quicklisp release
2. [Add any missing native dependencies](#lisp-quicklisp-adding-native-dependencies) in `ql.nix`
3. For packages that still don't build, [package them manually](#lisp-defining-packages-inside) in `packages.nix`
Also, the `imported.nix` file **must not be edited manually**! It should only be
generated as described in this section (by running `ql-import.lisp`).
### Adding native dependencies {#lisp-quicklisp-adding-native-dependencies}
The Quicklisp files contain ASDF dependency data, but don't include native
library (CFFI) dependencies, and, in the case of ABCL, Java dependencies.
The `ql.nix` file contains a long list of overrides, where these dependencies
can be added.
Packages defined in `packages.nix` contain these dependencies naturally.
### Trusting `systems.txt` and `releases.txt` {#lisp-quicklisp-trusting}
The previous implementation of `lisp-modules` didn't fully trust the Quicklisp
data, because there were times where the dependencies specified were not
complete and caused broken builds. It instead used a `nix-shell` environment to
discover real dependencies by using the ASDF APIs.
The current implementation has chosen to trust this data, because it's faster to
parse a text file than to build each system to generate its Nix file, and
because that way packages can be mass-imported. Because of that, there may come
a day where some packages will break, due to bugs in Quicklisp. In that case,
the fix could be a manual override in `packages.nix` and `ql.nix`.
A known fact is that Quicklisp doesn't include dependencies on slashy systems in
its data. This is an example of a situation where such fixes were used, e.g. to
replace the `systems` attribute of the affected packages. (See the definition of
`iolib`).
### Quirks {#lisp-quicklisp-quirks}
During Quicklisp import:
- `+` in names is converted to `_plus{_,}`: `cl+ssl`->`cl_plus_ssl`, `alexandria+`->`alexandria_plus`
- `.` in names is converted to `_dot_`: `iolib.base`->`iolib_dot_base`
- names starting with a number have a `_` prepended (`3d-vectors`->`_3d-vectors`)
- `_` in names is converted to `__` for reversibility
## Defining packages manually inside Nixpkgs {#lisp-defining-packages-inside}
Packages that for some reason are not in Quicklisp, and so cannot be
auto-imported, or don't work straight from the import, are defined in the
`packages.nix` file.
In that file, use the `build-asdf-system` function, which is a wrapper around
`mkDerivation` for building ASDF systems. Various other hacks are present, such
as `build-with-compile-into-pwd` for systems which create files during
compilation (such as cl-unicode).
The `build-asdf-system` function is documented
[here](#lisp-defining-packages-outside). Also, `packages.nix` is full of
examples of how to use it.
## Defining packages manually outside Nixpkgs {#lisp-defining-packages-outside}
Lisp derivations (`abcl`, `sbcl` etc.) also export the `buildASDFSystem`
function, which is similar to `build-asdf-system` from `packages.nix`, but is
part of the public API.
It takes the following arguments:
- `pname`: the package name
- `version`: the package version
- `src`: the package source
- `patches`: patches to apply to the source before build
- `nativeLibs`: native libraries used by CFFI and grovelling
- `javaLibs`: Java libraries for ABCL
- `lispLibs`: dependencies on other packages build with `buildASDFSystem`
- `systems`: list of systems to build
It can be used to define packages outside Nixpkgs, and, for example, add them
into the package scope with `withOverrides`.
### Including an external package in scope {#lisp-including-external-pkg-in-scope}
A package defined outside Nixpkgs using `buildASDFSystem` can be woven into the
Nixpkgs-provided scope like this:
```nix
let
alexandria = sbcl.buildASDFSystem rec {
pname = "alexandria";
version = "1.4";
src = fetchFromGitLab {
domain = "gitlab.common-lisp.net";
owner = "alexandria";
repo = "alexandria";
tag = "v${version}";
hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
};
};
sbcl' = sbcl.withOverrides (self: super: { inherit alexandria; });
in
sbcl'.pkgs.alexandria
```
## Overriding package attributes {#lisp-overriding-package-attributes}
Packages export the `overrideLispAttrs` function, which can be used to build a
new package with different parameters.
Example of overriding `alexandria`:
```nix
sbcl.pkgs.alexandria.overrideLispAttrs (oldAttrs: rec {
version = "1.4";
src = fetchFromGitLab {
domain = "gitlab.common-lisp.net";
owner = "alexandria";
repo = "alexandria";
tag = "v${version}";
hash = "sha256-1Hzxt65dZvgOFIljjjlSGgKYkj+YBLwJCACi5DZsKmQ=";
};
})
```
### Dealing with slashy systems {#lisp-dealing-with-slashy-systems}
Slashy (secondary) systems should not exist in their own packages! Instead, they
should be included in the parent package as an extra entry in the `systems`
argument to the `build-asdf-system`/`buildASDFSystem` functions.
The reason is that ASDF searches for a secondary system in the `.asd` of the
parent package. Thus, having them separate would cause either one of them not to
load cleanly, because one will contain FASLs of itself but not the other, and
vice versa.
To package slashy systems, use `overrideLispAttrs`, like so:
```nix
ecl.pkgs.alexandria.overrideLispAttrs (oldAttrs: {
systems = oldAttrs.systems ++ [ "alexandria/tests" ];
lispLibs = oldAttrs.lispLibs ++ [ ecl.pkgs.rt ];
})
```
See the [respective section](#lisp-including-external-pkg-in-scope) on using
`withOverrides` for how to weave it back into `ecl.pkgs`.
Note that sometimes the slashy systems might not only have more dependencies
than the main one, but create a circular dependency between `.asd`
files. Unfortunately, in this case an ad-hoc solution becomes necessary.
## Building Wrappers {#lisp-building-wrappers}
Wrappers can be built using the `withPackages` function of Common Lisp
implementations (`abcl`, `ecl`, `sbcl` etc.):
```
nix-shell -p 'sbcl.withPackages (ps: [ ps.alexandria ps.bordeaux-threads ])'
```
Such a wrapper can then be used like this:
```
$ sbcl
* (load (sb-ext:posix-getenv "ASDF"))
* (asdf:load-system 'alexandria)
* (asdf:load-system 'bordeaux-threads)
```
### Loading ASDF {#lisp-loading-asdf}
For best results, avoid calling `(require 'asdf)` when using the
library-generated wrappers.
Use `(load (ext:getenv "ASDF"))` instead, supplying your implementation's way of
getting an environment variable for `ext:getenv`. This will load the
(pre-compiled to FASL) Nixpkgs-provided version of ASDF.
### Loading systems {#lisp-loading-systems}
There, you can use `asdf:load-system`. This works by setting the right
values for the `CL_SOURCE_REGISTRY`/`ASDF_OUTPUT_TRANSLATIONS` environment
variables, so that systems are found in the Nix store and pre-compiled FASLs are
loaded.
## Adding a new Lisp {#lisp-adding-a-new-lisp}
The function `wrapLisp` is used to wrap Common Lisp implementations. It adds the
`pkgs`, `withPackages`, `withOverrides` and `buildASDFSystem` attributes to the
derivation.
`wrapLisp` takes these arguments:
- `pkg`: the Lisp package
- `faslExt`: Implementation-specific extension for FASL files
- `program`: The name of executable file in `${pkg}/bin/` (Default: `pkg.pname`)
- `flags`: A list of flags to always pass to `program` (Default: `[]`)
- `asdf`: The ASDF version to use (Default: `pkgs.asdf_3_3`)
- `packageOverrides`: Package overrides config (Default: `(self: super: {})`)
This example wraps CLISP:
```nix
wrapLisp {
pkg = clisp;
faslExt = "fas";
flags = [
"-E"
"UTF8"
];
}
```

View File

@@ -0,0 +1,289 @@
# Lua {#lua}
## Using Lua {#lua-userguide}
### Overview of Lua {#lua-overview}
Several versions of the Lua interpreter are available: luajit, lua 5.1, 5.2, 5.3.
The attribute `lua` refers to the default interpreter, it is also possible to refer to specific versions, e.g. `lua5_2` refers to Lua 5.2.
Lua libraries are in separate sets, with one set per interpreter version.
The interpreters have several common attributes. One of these attributes is
`pkgs`, which is a package set of Lua libraries for this specific
interpreter. E.g., the `busted` package corresponding to the default interpreter
is `lua.pkgs.busted`, and the lua 5.2 version is `lua5_2.pkgs.busted`.
The main package set contains aliases to these package sets, e.g.
`luaPackages` refers to `lua5_1.pkgs` and `lua52Packages` to
`lua5_2.pkgs`.
Note that nixpkgs patches the non-luajit interpreters to avoid referring to
`/usr` and have `;;` (a [placeholder](https://www.lua.org/manual/5.1/manual.html#pdf-package.path) replaced with the default LUA_PATH) work correctly.
### Installing Lua and packages {#installing-lua-and-packages}
#### Lua environment defined in separate `.nix` file {#lua-environment-defined-in-separate-.nix-file}
Create a file, e.g. `build.nix`, with the following expression
```nix
with import <nixpkgs> { };
lua5_2.withPackages (
ps: with ps; [
busted
luafilesystem
]
)
```
and install it in your profile with
```shell
nix-env -if build.nix
```
Now you can use the Lua interpreter, as well as the extra packages (`busted`,
`luafilesystem`) that you added to the environment.
#### Lua environment defined in `~/.config/nixpkgs/config.nix` {#lua-environment-defined-in-.confignixpkgsconfig.nix}
If you prefer to, you could also add the environment as a package override to the Nixpkgs set, e.g.
using `config.nix`,
```nix
{
# ...
packageOverrides =
pkgs: with pkgs; {
myLuaEnv = lua5_2.withPackages (
ps: with ps; [
busted
luafilesystem
]
);
};
}
```
and install it in your profile with
```shell
nix-env -iA nixpkgs.myLuaEnv
```
The environment is installed by referring to the attribute, and considering
the `nixpkgs` channel was used.
#### Lua environment defined in `/etc/nixos/configuration.nix` {#lua-environment-defined-in-etcnixosconfiguration.nix}
For the sake of completeness, here's another example how to install the environment system-wide.
```nix
{
# ...
environment.systemPackages = with pkgs; [
(lua.withPackages (
ps: with ps; [
busted
luafilesystem
]
))
];
}
```
### How to override a Lua package using overlays? {#how-to-override-a-lua-package-using-overlays}
Use the following overlay template:
```nix
final: prev: {
lua = prev.lua.override {
packageOverrides = luaself: luaprev: {
luarocks-nix = luaprev.luarocks-nix.overrideAttrs (oa: {
pname = "luarocks-nix";
src = /home/my_luarocks/repository;
});
};
};
luaPackages = lua.pkgs;
}
```
### Temporary Lua environment with `nix-shell` {#temporary-lua-environment-with-nix-shell}
There are two methods for loading a shell with Lua packages. The first and recommended method
is to create an environment with `lua.buildEnv` or `lua.withPackages` and load that. E.g.
```sh
$ nix-shell -p 'lua.withPackages(ps: with ps; [ busted luafilesystem ])'
```
opens a shell from which you can launch the interpreter
```sh
[nix-shell:~] lua
```
The other method, which is not recommended, does not create an environment and requires you to list the packages directly,
```sh
$ nix-shell -p lua.pkgs.busted lua.pkgs.luafilesystem
```
Again, it is possible to launch the interpreter from the shell.
The Lua interpreter has the attribute `pkgs` which contains all Lua libraries for that specific interpreter.
## Developing with lua {#lua-developing}
Now that you know how to get a working Lua environment with Nix, it is time
to go forward and start actually developing with Lua. There are two ways to
package lua software, either it is on luarocks and most of it can be taken care
of by the luarocks2nix converter or the packaging has to be done manually.
Let's present the luarocks way first and the manual one in a second time.
### Packaging a library on luarocks {#packaging-a-library-on-luarocks}
[Luarocks.org](https://luarocks.org/) is the main repository of lua packages.
The site proposes two types of packages, the `rockspec` and the `src.rock`
(equivalent of a [rockspec](https://github.com/luarocks/luarocks/wiki/Rockspec-format) but with the source).
Luarocks-based packages are generated in [pkgs/development/lua-modules/generated-packages.nix](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/lua-modules/generated-packages.nix) from
the whitelist maintainers/scripts/luarocks-packages.csv and updated by running
the package `luarocks-packages-updater`:
```sh
nix-shell -p luarocks-packages-updater --run luarocks-packages-updater
```
[luarocks2nix](https://github.com/nix-community/luarocks) is a tool capable of generating nix derivations from both rockspec and src.rock (and favors the src.rock).
The automation only goes so far though and some packages need to be customized.
These customizations go in [pkgs/development/lua-modules/overrides.nix](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/lua-modules/overrides.nix).
For instance if the rockspec defines `external_dependencies`, these need to be manually added to the overrides.nix.
You can try converting luarocks packages to nix packages with the command `nix-shell -p luarocks-nix` and then `luarocks nix PKG_NAME`.
#### Packaging a library manually {#packaging-a-library-manually}
You can develop your package as you usually would, just don't forget to wrap it
within a `toLuaModule` call, for instance
```nix
{
mynewlib = toLuaModule (
stdenv.mkDerivation {
# ...
}
);
}
```
There is also the `buildLuaPackage` function that can be used when lua modules
are not packaged for luarocks. You can see a few examples at `pkgs/top-level/lua-packages.nix`.
## Lua Reference {#lua-reference}
### Lua interpreters {#lua-interpreters}
Versions 5.1, 5.2, 5.3 and 5.4 of the lua interpreter are available as
respectively `lua5_1`, `lua5_2`, `lua5_3` and `lua5_4`. Luajit is available too.
The Nix expressions for the interpreters can be found in `pkgs/development/interpreters/lua-5`.
#### Attributes on lua interpreters packages {#attributes-on-lua-interpreters-packages}
Each interpreter has the following attributes:
- `interpreter`. Alias for `${pkgs.lua}/bin/lua`.
- `buildEnv`. Function to build lua interpreter environments with extra packages bundled together. See section *lua.buildEnv function* for usage and documentation.
- `withPackages`. Simpler interface to `buildEnv`.
- `pkgs`. Set of Lua packages for that specific interpreter. The package set can be modified by overriding the interpreter and passing `packageOverrides`.
#### `buildLuarocksPackage` function {#buildluarockspackage-function}
The `buildLuarocksPackage` function is implemented in `pkgs/development/interpreters/lua-5/build-luarocks-package.nix`
The following is an example:
```nix
{
luaposix = buildLuarocksPackage {
pname = "luaposix";
version = "34.0.4-1";
src = fetchurl {
url = "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/luaposix-34.0.4-1.src.rock";
hash = "sha256-4mLJG8n4m6y4Fqd0meUDfsOb9RHSR0qa/KD5KCwrNXs=";
};
disabled = (luaOlder "5.1") || (luaAtLeast "5.4");
propagatedBuildInputs = [
bit32
lua
std_normalize
];
meta = {
homepage = "https://github.com/luaposix/luaposix/";
description = "Lua bindings for POSIX";
maintainers = with lib.maintainers; [
vyp
lblasc
];
license.fullName = "MIT/X11";
};
};
}
```
The `buildLuarocksPackage` delegates most tasks to luarocks:
* it adds `luarocks` as an unpacker for `src.rock` files (zip files really).
* `configurePhase` writes a temporary luarocks configuration file which location
is exported via the environment variable `LUAROCKS_CONFIG`.
* the `buildPhase` does nothing.
* `installPhase` calls `luarocks make --deps-mode=none --tree $out` to build and
install the package
* In the `postFixup` phase, the `wrapLuaPrograms` bash function is called to
wrap all programs in the `$out/bin/*` directory to include `$PATH`
environment variable and add dependent libraries to script's `LUA_PATH` and
`LUA_CPATH`.
It accepts as arguments:
* 'luarocksConfig': a nix value that directly maps to the luarocks config used during
the installation
By default `meta.platforms` is set to the same value as the interpreter unless overridden otherwise.
#### `buildLuaApplication` function {#buildluaapplication-function}
The `buildLuaApplication` function is practically the same as `buildLuaPackage`.
The difference is that `buildLuaPackage` by default prefixes the names of the packages with the version of the interpreter.
Because with an application we're not interested in multiple version the prefix is dropped.
#### lua.withPackages function {#lua.withpackages-function}
The `lua.withPackages` takes a function as an argument that is passed the set of lua packages and returns the list of packages to be included in the environment.
Using the `withPackages` function, the previous example for the luafilesystem environment can be written like this:
```nix
lua.withPackages (ps: [ ps.luafilesystem ])
```
`withPackages` passes the correct package set for the specific interpreter version as an argument to the function. In the above example, `ps` equals `luaPackages`.
But you can also easily switch to using `lua5_1`:
```nix
lua5_1.withPackages (ps: [ ps.lua ])
```
Now, `ps` is set to `lua5_1.pkgs`, matching the version of the interpreter.
### Lua Contributing guidelines {#lua-contributing}
Following rules should be respected:
* Commit names of Lua libraries should reflect that they are Lua libraries, so write for example `luaPackages.luafilesystem: 1.11 -> 1.12`.

View File

@@ -0,0 +1,590 @@
# Maven {#maven}
Maven is a well-known build tool for the Java ecosystem; however, it has some challenges when integrating into the Nix build system.
The following provides a list of common patterns with how to package a Maven project (or any JVM language that can export to Maven) as a Nix package.
## Building a package using `maven.buildMavenPackage` {#maven-buildmavenpackage}
Consider the following package:
```nix
{
lib,
fetchFromGitHub,
jre,
makeWrapper,
maven,
}:
maven.buildMavenPackage rec {
pname = "jd-cli";
version = "1.2.1";
src = fetchFromGitHub {
owner = "intoolswetrust";
repo = "jd-cli";
tag = "jd-cli-${version}";
hash = "sha256-rRttA5H0A0c44loBzbKH7Waoted3IsOgxGCD2VM0U/Q=";
};
mvnHash = "sha256-kLpjMj05uC94/5vGMwMlFzLKNFOKeyNvq/vmB6pHTAo=";
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
runHook preInstall
mkdir -p $out/bin $out/share/jd-cli
install -Dm644 jd-cli/target/jd-cli.jar $out/share/jd-cli
makeWrapper ${jre}/bin/java $out/bin/jd-cli \
--add-flags "-jar $out/share/jd-cli/jd-cli.jar"
runHook postInstall
'';
meta = {
description = "Simple command line wrapper around JD Core Java Decompiler project";
homepage = "https://github.com/intoolswetrust/jd-cli";
license = lib.licenses.gpl3Plus;
maintainers = with lib.maintainers; [ majiir ];
};
}
```
This package calls `maven.buildMavenPackage` to do its work. The primary difference from `stdenv.mkDerivation` is the `mvnHash` variable, which is a hash of all of the Maven dependencies.
::: {.tip}
After setting `maven.buildMavenPackage`, we then do standard Java `.jar` installation by saving the `.jar` to `$out/share/java` and then making a wrapper which allows executing that file; see [](#sec-language-java) for additional generic information about packaging Java applications.
:::
### Overriding Maven package attributes {#maven-overriding-package-attributes}
```
overrideMavenAttrs :: (AttrSet -> Derivation) | ((AttrSet -> Attrset) -> Derivation) -> Derivation
```
The output of `buildMavenPackage` has an `overrideMavenAttrs` attribute, which is a function that takes either
- any subset of the attributes that can be passed to `buildMavenPackage`
or
- a function that takes the argument passed to the previous invocation of `buildMavenPackage` (conventionally called `old`) and returns an attribute set that can be passed to `buildMavenPackage`
and returns a derivation that builds a Maven package based on the old and new arguments merged.
This is similar to [](#sec-pkg-overrideAttrs), but notably does not allow accessing the final value of the argument to `buildMavenPackage`.
:::{.example}
### `overrideMavenAttrs` Example
Use `overrideMavenAttrs` to build `jd-cli` version 1.2.0 and disable some flaky test:
```nix
jd-cli.overrideMavenAttrs (old: rec {
version = "1.2.0";
src = fetchFromGitHub {
owner = old.src.owner;
repo = old.src.repo;
rev = "${old.pname}-${version}";
# old source hash of 1.2.0 version
hash = "sha256-US7j6tQ6mh1libeHnQdFxPGoxHzbZHqehWSgCYynKx8=";
};
# tests can be disabled by prefixing it with `!`
# see Maven documentation for more details:
# https://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One
mvnParameters = lib.escapeShellArgs [
"-Dsurefire.failIfNoSpecifiedTests=false"
"-Dtest=!JavaDecompilerTest#basicTest,!JavaDecompilerTest#patternMatchingTest"
];
# old mvnHash of 1.2.0 maven dependencies
mvnHash = "sha256-N9XC1pg6Y4sUiBWIQUf16QSXCuiAPpXEHGlgApviF4I=";
})
```
:::
### Offline build {#maven-offline-build}
By default, `buildMavenPackage` does the following:
1. Run `mvn package -Dmaven.repo.local=$out/.m2 ${mvnParameters}` in the
`fetchedMavenDeps` [fixed-output derivation](https://nixos.org/manual/nix/stable/glossary.html#gloss-fixed-output-derivation).
2. Run `mvn package -o -nsu "-Dmaven.repo.local=$mvnDeps/.m2"
${mvnParameters}` again in the main derivation.
As a result, tests are run twice.
This also means that a failing test will trigger a new attempt to realise the fixed-output derivation, which in turn downloads all dependencies again.
For bigger Maven projects, this might lead to a long feedback cycle.
Use `buildOffline = true` to change the behaviour of `buildMavenPackage to the following:
1. Run `mvn de.qaware.maven:go-offline-maven-plugin:1.2.8:resolve-dependencies
-Dmaven.repo.local=$out/.m2 ${mvnDepsParameters}` in the fixed-output derivation.
2. Run `mvn package -o -nsu "-Dmaven.repo.local=$mvnDeps/.m2"
${mvnParameters}` in the main derivation.
As a result, all dependencies are downloaded in step 1 and the tests are executed in step 2.
A failing test only triggers a rebuild of step 2 as it can reuse the dependencies of step 1 because they have not changed.
::: {.warning}
Test dependencies are not downloaded in step 1 and are therefore missing in
step 2 which will most probably fail the build. The `go-offline` plugin cannot
handle these so-called [dynamic dependencies](https://github.com/qaware/go-offline-maven-plugin?tab=readme-ov-file#dynamic-dependencies).
In that case you must add these dynamic dependencies manually with:
```nix
maven.buildMavenPackage rec {
manualMvnArtifacts = [
# add dynamic test dependencies here
"org.apache.maven.surefire:surefire-junit-platform:3.1.2"
"org.junit.platform:junit-platform-launcher:1.10.0"
];
}
```
:::
### Stable Maven plugins {#stable-maven-plugins}
Maven defines default versions for its core plugins, e.g. `maven-compiler-plugin`. If your project does not override these versions, an upgrade of Maven will change the version of the used plugins, and therefore the derivation and hash.
When `maven` is upgraded, `mvnHash` for the derivation must be updated as well: otherwise, the project will be built on the derivation of old plugins, and fail because the requested plugins are missing.
This clearly prevents automatic upgrades of Maven: a manual effort must be made throughout nixpkgs by any maintainer wishing to push the upgrades.
To make sure that your package does not add extra manual effort when upgrading Maven, explicitly define versions for all plugins. You can check if this is the case by adding the following plugin to your (parent) POM:
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>enforce-plugin-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requirePluginVersions />
</rules>
</configuration>
</execution>
</executions>
</plugin>
```
## Manually using `mvn2nix` {#maven-mvn2nix}
::: {.warning}
This way is no longer recommended; see [](#maven-buildmavenpackage) for the simpler and preferred way.
:::
For the purposes of this example let's consider a very basic Maven project with the following `pom.xml` with a single dependency on [emoji-java](https://github.com/vdurmont/emoji-java).
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.fzakaria</groupId>
<artifactId>maven-demo</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>NixOS Maven Demo</name>
<dependencies>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>5.1.1</version>
</dependency>
</dependencies>
</project>
```
Our main class file will be very simple:
```java
import com.vdurmont.emoji.EmojiParser;
public class Main {
public static void main(String[] args) {
String str = "NixOS :grinning: is super cool :smiley:!";
String result = EmojiParser.parseToUnicode(str);
System.out.println(result);
}
}
```
You find this demo project at [https://github.com/fzakaria/nixos-maven-example](https://github.com/fzakaria/nixos-maven-example).
### Solving for dependencies {#solving-for-dependencies}
#### buildMaven with NixOS/mvn2nix-maven-plugin {#buildmaven-with-nixosmvn2nix-maven-plugin}
`buildMaven` is an alternative method that tries to follow similar patterns of other programming languages by generating a lock file. It relies on the maven plugin [mvn2nix-maven-plugin](https://github.com/NixOS/mvn2nix-maven-plugin).
First you generate a `project-info.json` file using the maven plugin.
> This should be executed in the project's source repository or be told which `pom.xml` to execute with.
```bash
# run this step within the project's source repository
mvn org.nixos.mvn2nix:mvn2nix-maven-plugin:mvn2nix
cat project-info.json | jq | head
{
"project": {
"artifactId": "maven-demo",
"groupId": "org.nixos",
"version": "1.0",
"classifier": "",
"extension": "jar",
"dependencies": [
{
"artifactId": "maven-resources-plugin",
```
This file is then given to the `buildMaven` function, and it returns 2 attributes.
**`repo`**:
A Maven repository that is a symlink farm of all the dependencies found in the `project-info.json`
**`build`**:
A simple derivation that runs through `mvn compile` & `mvn package` to build the JAR. You may use this as inspiration for more complicated derivations.
Here is an [example](https://github.com/fzakaria/nixos-maven-example/blob/main/build-maven-repository.nix) of building the Maven repository
```nix
{
pkgs ? import <nixpkgs> { },
}:
with pkgs;
(buildMaven ./project-info.json).repo
```
The benefit over the _double invocation_ as we will see below, is that the _/nix/store_ entry is a _linkFarm_ of every package, so that changes to your dependency set doesn't involve downloading everything from scratch.
```bash
tree $(nix-build --no-out-link build-maven-repository.nix) | head
/nix/store/g87va52nkc8jzbmi1aqdcf2f109r4dvn-maven-repository
├── antlr
│   └── antlr
│   └── 2.7.2
│   ├── antlr-2.7.2.jar -> /nix/store/d027c8f2cnmj5yrynpbq2s6wmc9cb559-antlr-2.7.2.jar
│   └── antlr-2.7.2.pom -> /nix/store/mv42fc5gizl8h5g5vpywz1nfiynmzgp2-antlr-2.7.2.pom
├── avalon-framework
│   └── avalon-framework
│   └── 4.1.3
│   ├── avalon-framework-4.1.3.jar -> /nix/store/iv5fp3955w3nq28ff9xfz86wvxbiw6n9-avalon-framework-4.1.3.jar
```
#### Double Invocation {#double-invocation}
::: {.note}
This pattern is the simplest but may cause unnecessary rebuilds due to the output hash changing.
:::
The double invocation is a _simple_ way to get around the problem that `nix-build` may be sandboxed and have no Internet connectivity.
It treats the entire Maven repository as a single source to be downloaded, relying on Maven's dependency resolution to satisfy the output hash. This is similar to fetchers like `fetchgit`, except it has to run a Maven build to determine what to download.
The first step will be to build the Maven project as a fixed-output derivation in order to collect the Maven repository -- below is an [example](https://github.com/fzakaria/nixos-maven-example/blob/main/double-invocation-repository.nix).
::: {.note}
Traditionally the Maven repository is at `~/.m2/repository`. We will override this to be the `$out` directory.
:::
```nix
{
lib,
stdenv,
maven,
}:
stdenv.mkDerivation {
name = "maven-repository";
buildInputs = [ maven ];
src = ./.; # or fetchFromGitHub, cleanSourceWith, etc
buildPhase = ''
runHook preBuild
mvn package -Dmaven.repo.local=$out
runHook postBuild
'';
# keep only *.{pom,jar,sha1,nbm} and delete all ephemeral files with lastModified timestamps inside
installPhase = ''
runHook preInstall
find $out -type f \
-name \*.lastUpdated -or \
-name resolver-status.properties -or \
-name _remote.repositories \
-delete
runHook postInstall
'';
# don't do any fixup
dontFixup = true;
outputHashAlgo = null;
outputHashMode = "recursive";
# replace this with the correct SHA256
outputHash = lib.fakeHash;
}
```
The build will fail, and tell you the expected `outputHash` to place. When you've set the hash, the build will return with a `/nix/store` entry whose contents are the full Maven repository.
::: {.warning}
Some additional files are deleted that would cause the output hash to change potentially on subsequent runs.
:::
```bash
tree $(nix-build --no-out-link double-invocation-repository.nix) | head
/nix/store/8kicxzp98j68xyi9gl6jda67hp3c54fq-maven-repository
├── backport-util-concurrent
│   └── backport-util-concurrent
│   └── 3.1
│   ├── backport-util-concurrent-3.1.pom
│   └── backport-util-concurrent-3.1.pom.sha1
├── classworlds
│   └── classworlds
│   ├── 1.1
│   │   ├── classworlds-1.1.jar
```
If your package uses _SNAPSHOT_ dependencies or _version ranges_; there is a strong likelihood that over time, your output hash will change since the resolved dependencies may change. Hence this method is less recommended than using `buildMaven`.
### Building a JAR {#building-a-jar}
Regardless of which strategy is chosen above, the step to build the derivation is the same.
```nix
{
stdenv,
maven,
callPackage,
}:
let
# pick a repository derivation, here we will use buildMaven
repository = callPackage ./build-maven-repository.nix { };
in
stdenv.mkDerivation (finalAttrs: {
pname = "maven-demo";
version = "1.0";
src = fetchTarball "https://github.com/fzakaria/nixos-maven-example/archive/main.tar.gz";
buildInputs = [ maven ];
buildPhase = ''
runHook preBuild
echo "Using repository ${repository}"
mvn --offline -Dmaven.repo.local=${repository} package;
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm644 target/${finalAttrs.pname}-${finalAttrs.version}.jar $out/share/java
runHook postInstall
'';
})
```
::: {.tip}
We place the library in `$out/share/java` since JDK package has a _stdenv setup hook_ that adds any JARs in the `share/java` directories of the build inputs to the CLASSPATH environment.
:::
```bash
tree $(nix-build --no-out-link build-jar.nix)
/nix/store/7jw3xdfagkc2vw8wrsdv68qpsnrxgvky-maven-demo-1.0
└── share
└── java
└── maven-demo-1.0.jar
2 directories, 1 file
```
### Runnable JAR {#runnable-jar}
The previous example builds a `jar` file but that's not a file one can run.
You need to use it with `java -jar $out/share/java/output.jar` and make sure to provide the required dependencies on the classpath.
The following explains how to use `makeWrapper` in order to make the derivation produce an executable that will run the JAR file you created.
We will use the same repository we built above (either _double invocation_ or _buildMaven_) to setup a CLASSPATH for our JAR.
The following two methods are more suited to Nix then building an [UberJar](https://imagej.net/Uber-JAR) which may be the more traditional approach.
#### CLASSPATH {#classpath}
This method is ideal if you are providing a derivation for _nixpkgs_ and don't want to patch the project's `pom.xml`.
We will read the Maven repository and flatten it to a single list. This list will then be concatenated with the _CLASSPATH_ separator to create the full classpath.
We make sure to provide this classpath to the `makeWrapper`.
```nix
{
stdenv,
maven,
callPackage,
makeWrapper,
jre,
}:
let
repository = callPackage ./build-maven-repository.nix { };
in
stdenv.mkDerivation (finalAttrs: {
pname = "maven-demo";
version = "1.0";
src = fetchTarball "https://github.com/fzakaria/nixos-maven-example/archive/main.tar.gz";
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ maven ];
buildPhase = ''
runHook preBuild
echo "Using repository ${repository}"
mvn --offline -Dmaven.repo.local=${repository} package;
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
classpath=$(find ${repository} -name "*.jar" -printf ':%h/%f');
install -Dm644 target/maven-demo-${finalAttrs.version}.jar $out/share/java
# create a wrapper that will automatically set the classpath
# this should be the paths from the dependency derivation
makeWrapper ${jre}/bin/java $out/bin/maven-demo \
--add-flags "-classpath $out/share/java/maven-demo-${finalAttrs.version}.jar:''${classpath#:}" \
--add-flags "Main"
runHook postInstall
'';
})
```
#### MANIFEST file via Maven Plugin {#manifest-file-via-maven-plugin}
This method is ideal if you are the project owner and want to change your `pom.xml` to set the CLASSPATH within it.
Augment the `pom.xml` to create a JAR with the following manifest:
```xml
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>../../repository/</classpathPrefix>
<classpathLayoutType>repository</classpathLayoutType>
<mainClass>Main</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
```
The above plugin instructs the JAR to look for the necessary dependencies in the `lib/` relative folder. The layout of the folder is also in the _maven repository_ style.
```bash
unzip -q -c $(nix-build --no-out-link runnable-jar.nix)/share/java/maven-demo-1.0.jar META-INF/MANIFEST.MF
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: nixbld
Class-Path: . ../../repository/com/vdurmont/emoji-java/5.1.1/emoji-jav
a-5.1.1.jar ../../repository/org/json/json/20170516/json-20170516.jar
Created-By: Apache Maven 3.6.3
Build-Jdk: 1.8.0_265
Main-Class: Main
```
We will modify the derivation above to add a symlink to our repository so that it's accessible to our JAR during the `installPhase`.
```nix
{
stdenv,
maven,
callPackage,
makeWrapper,
jre,
}:
let
# pick a repository derivation, here we will use buildMaven
repository = callPackage ./build-maven-repository.nix { };
in
stdenv.mkDerivation (finalAttrs: {
pname = "maven-demo";
version = "1.0";
src = fetchTarball "https://github.com/fzakaria/nixos-maven-example/archive/main.tar.gz";
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ maven ];
buildPhase = ''
runHook preBuild
echo "Using repository ${repository}"
mvn --offline -Dmaven.repo.local=${repository} package;
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
# create a symbolic link for the repository directory
ln -s ${repository} $out/repository
install -Dm644 target/maven-demo-${finalAttrs.version}.jar $out/share/java
# create a wrapper that will automatically set the classpath
# this should be the paths from the dependency derivation
makeWrapper ${jre}/bin/java $out/bin/maven-demo \
--add-flags "-jar $out/share/java/maven-demo-${finalAttrs.version}.jar"
runHook postInstall
'';
})
```
::: {.note}
Our script produces a dependency on `jre` rather than `jdk` to restrict the runtime closure necessary to run the application.
:::
This will give you an executable shell-script that launches your JAR with all the dependencies available.
```bash
tree $(nix-build --no-out-link runnable-jar.nix)
/nix/store/8d4c3ibw8ynsn01ibhyqmc1zhzz75s26-maven-demo-1.0
├── bin
│   └── maven-demo
├── repository -> /nix/store/g87va52nkc8jzbmi1aqdcf2f109r4dvn-maven-repository
└── share
└── java
└── maven-demo-1.0.jar
$(nix-build --no-out-link --option tarball-ttl 1 runnable-jar.nix)/bin/maven-demo
NixOS 😀 is super cool 😃!
```

View File

@@ -0,0 +1,200 @@
# Neovim {#neovim}
Install `neovim-unwrapped` to get a bare-bones Neovim to configure imperatively.
This is the closest to what you encounter on other distributions.
`neovim` is a wrapper around Neovim with some extra configuration, for
instance, to set the various language providers like Python.
The wrapper can be further configured to include your favorite plugins and
configurations for a reproducible neovim across machines.
See the next section for more details.
## Custom configuration {#neovim-custom-configuration}
There are two wrappers available to provide additional configuration around the vanilla package `pkgs.neovim-unwrapped`:
1. `wrapNeovim`: the historical one you should use
2. `wrapNeovimUnstable` intended to replace the former. It has more features but
the interface is not stable yet.
You can configure the former via:
```nix
neovim.override {
configure = {
customRC = ''
# here your custom configuration goes!
'';
packages.myVimPackage = with pkgs.vimPlugins; {
# See examples below on how to use custom packages.
start = [ ];
# If a Vim plugin has a dependency that is not explicitly listed in
# `opt`, that dependency will always be added to `start` to avoid confusion.
opt = [ ];
};
};
}
```
`myVimPackage` is an arbitrary name for the generated package. You can choose any name you like.
If you want to use `neovim-qt` as a graphical editor, you can configure it by overriding Neovim in an overlay
or passing it an overridden Neovim:
```nix
neovim-qt.override {
neovim = neovim.override {
configure = {
customRC = ''
# your custom configuration
'';
};
};
}
```
You can use the new unstable wrapper but the interface may change:
- `autoconfigure`: certain plugins need a custom configuration to work with Nix.
For instance, `sqlite-lua` needs `g:sqlite_clib_path` to be set to work. Nixpkgs historically patched these in the plugins with several drawbacks: harder maintenance and making upstream work harder. Per convention, these mandatory bits of configuration are bookmarked in nixpkgs in `passthru.initLua`. Enabling `autoconfigure` automatically adds the snippets required for the plugins to work.
- `autowrapRuntimeDeps`: Appends plugin's runtime dependencies to `PATH`. For instance, `rest.nvim` requires `curl` to work. Enabling `autowrapRuntimeDeps` adds it to the `PATH` visible by your Neovim wrapper (but not your global `PATH`).
- `luaRcContent`: Extra lua code to add to the generated `init.lua`.
- `neovimRcContent`: Extra vimL code sourced by the generated `init.lua`.
- `wrapperArgs`: Extra arguments forwarded to the `makeWrapper` call.
- `wrapRc`: Nix, not being able to write in your `$HOME`, loads the
generated Neovim configuration via the `$VIMINIT` environment variable, i.e. : `export VIMINIT='lua dofile("/nix/store/…-init.lua")'`. This has side effects like preventing Neovim from sourcing your `init.lua` in `$XDG_CONFIG_HOME/nvim` (see bullet 7 of [`:help startup`](https://neovim.io/doc/user/starting.html#startup) in Neovim). Disable it if you want to generate your own wrapper. You can still reuse the generated vimscript init code via `neovim.passthru.initRc`.
- `plugins`: A list of plugins to add to the wrapper.
```
wrapNeovimUnstable neovim-unwrapped {
autoconfigure = true;
autowrapRuntimeDeps = true;
luaRcContent = ''
vim.o.sessionoptions = 'buffers,curdir,help,tabpages,winsize,winpos,localoptions'
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
vim.opt.smoothscroll = true
vim.opt.colorcolumn = { 100 }
vim.opt.termguicolors = true
'';
# plugins accepts a list of either plugins or { plugin = ...; config = ..vimscript.. };
plugins = with vimPlugins; [
{
plugin = vim-obsession;
config = ''
map <Leader>$ <Cmd>Obsession<CR>
'';
}
(nvim-treesitter.withPlugins (p: [ p.nix p.python ]))
hex-nvim
];
}
```
You can explore the configuration with`nix repl` to discover these options and
override them. For instance:
```nix
neovim.overrideAttrs (oldAttrs: {
autowrapRuntimeDeps = false;
})
```
### Specificities for some plugins {#neovim-plugin-specificities}
### Plugin optional configuration {#neovim-plugin-required-snippet}
Some plugins require specific configuration to work. We choose not to
patch those plugins but expose the necessary configuration under
`PLUGIN.passthru.initLua` for neovim plugins. For instance, the `unicode-vim` plugin
needs the path towards a unicode database so we expose the following snippet `vim.g.Unicode_data_directory="${self.unicode-vim}/autoload/unicode"` under `vimPlugins.unicode-vim.passthru.initLua`.
#### LuaRocks based plugins {#neovim-luarocks-based-plugins}
In order to automatically handle plugin dependencies, several Neovim plugins
upload their package to [LuaRocks](https://www.luarocks.org). This means less work for nixpkgs maintainers in the long term as dependencies get updated automatically.
This means several Neovim plugins are first packaged as nixpkgs [lua
packages](#packaging-a-library-on-luarocks), and converted via `buildNeovimPlugin` in
a vim plugin. This conversion is necessary because Neovim expects lua folders to be
top-level while LuaRocks installs them in various subfolders by default.
For instance:
```nix
{
rtp-nvim = neovimUtils.buildNeovimPlugin { luaAttr = luaPackages.rtp-nvim; };
}
```
To update these packages, you should use the lua updater rather than vim's.
#### Treesitter {#neovim-plugin-treesitter}
By default `nvim-treesitter` encourages you to download, compile and install
the required Treesitter grammars at run time with `:TSInstall`. This works
poorly on NixOS. Instead, to install the `nvim-treesitter` plugins with a set
of precompiled grammars, you can use the `nvim-treesitter.withPlugins` function:
```nix
(pkgs.neovim.override {
configure = {
packages.myPlugins = with pkgs.vimPlugins; {
start = [
(nvim-treesitter.withPlugins (
plugins: with plugins; [
nix
python
]
))
];
};
};
})
```
To enable all grammars packaged in nixpkgs, use `pkgs.vimPlugins.nvim-treesitter.withAllGrammars`.
### Testing Neovim plugins {#testing-neovim-plugins}
#### neovimRequireCheck {#testing-neovim-plugins-neovim-require-check}
`neovimRequireCheck` is a simple test which checks if Neovim can require lua modules without errors. This is often enough to catch missing dependencies.
It accepts a single string for a module, or a list of module strings to test.
- `nvimRequireCheck = MODULE;`
- `nvimRequireCheck = [ MODULE1 MODULE2 ];`
When `nvimRequireCheck` is not specified, we will search the plugin's directory for lua modules to attempt loading. This quick smoke test can catch obvious dependency errors that might be missed.
The check hook will fail the build if any modules cannot be loaded. This encourages inspecting the logs to identify potential issues.
To only check a specific module, add it manually to the plugin definition [overrides](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix).
```nix
{
gitsigns-nvim = super.gitsigns-nvim.overrideAttrs {
dependencies = [ self.plenary-nvim ];
nvimRequireCheck = "gitsigns";
};
}
```
Some plugins will have lua modules that require a user configuration to function properly or can contain optional lua modules that we don't want to test by requiring.
We can skip specific modules using `nvimSkipModules`. Similar to `nvimRequireCheck`, it accepts a list of strings.
- `nvimSkipModules = [ MODULE1 MODULE2 ];`
```nix
{
asyncrun-vim = super.asyncrun-vim.overrideAttrs {
nvimSkipModules = [
# vim plugin with optional toggleterm integration
"asyncrun.toggleterm"
"asyncrun.toggleterm2"
];
};
}
```
In rare cases, we might not want to actually test loading lua modules for a plugin. In those cases, we can disable `neovimRequireCheck` with `doCheck = false;`.
This can be manually added through plugin definition overrides in the [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix).
```nix
{
vim-test = super.vim-test.overrideAttrs {
# Vim plugin with a test lua file
doCheck = false;
};
}
```

View File

@@ -0,0 +1,171 @@
# Nim {#sec-language-nim}
The Nim compiler and a builder function is available.
Nim programs are built using a lockfile and either `buildNimPackage` or `buildNimSbom`.
## buildNimPackage {#buildNimPackage}
The following example shows a Nim program that depends only on Nim libraries:
```nix
{
lib,
buildNimPackage,
fetchFromGitHub,
}:
buildNimPackage (finalAttrs: {
pname = "ttop";
version = "1.2.7";
src = fetchFromGitHub {
owner = "inv2004";
repo = "ttop";
rev = "v${finalAttrs.version}";
hash = lib.fakeHash;
};
lockFile = ./lock.json;
nimFlags = [ "-d:NimblePkgVersion=${finalAttrs.version}" ];
})
```
### `buildNimPackage` parameters {#buildnimpackage-parameters}
The `buildNimPackage` function takes an attrset of parameters that are passed on to `stdenv.mkDerivation`.
The following parameters are specific to `buildNimPackage`:
* `lockFile`: JSON formatted lockfile.
* `nimbleFile`: Specify the Nimble file location of the package being built
rather than discover the file at build-time.
* `nimRelease ? true`: Build the package in *release* mode.
* `nimDefines ? []`: A list of Nim defines. Key-value tuples are not supported.
* `nimFlags ? []`: A list of command line arguments to pass to the Nim compiler.
Use this to specify defines with arguments in the form of `-d:${name}=${value}`.
* `nimDoc` ? false`: Build and install HTML documentation.
### Lockfiles {#nim-lockfiles}
Nim lockfiles are created with the `nim_lk` utility.
Run `nim_lk` with the source directory as an argument and it will print a lockfile to stdout.
```sh
$ cd nixpkgs
$ nix build -f . ttop.src
$ nix run -f . nim_lk ./result | jq --sort-keys > pkgs/by-name/tt/ttop/lock.json
```
## buildNimSbom {#buildNimSbom}
An alternative to `buildNimPackage` is `buildNimSbom` which builds packages from [CycloneDX SBOM](https://cyclonedx.org/) files.
`buildNimSbom` resolves Nim dependencies to [fixed-output derivations](https://nixos.org/manual/nix/stable/glossary#gloss-fixed-output-derivation) using the [nix:fod namespace](#sec-interop.cylonedx-fod).
In the following minimal example only the source code checkout and a `buildInput` are specified.
The SBOM file provides metadata such as `pname` and `version` as well as the sources to Nim dependencies.
```nix
# pkgs/by-name/ni/nim_lk/package.nix
{
lib,
buildNimSbom,
fetchFromSourcehut,
openssl,
}:
buildNimSbom (finalAttrs: {
src = fetchFromSourcehut {
owner = "~ehmry";
repo = "nim_lk";
rev = finalAttrs.version;
hash = lib.fakeHash;
};
buildInputs = [ openssl ];
}) ./sbom.json
```
### Generating SBOMs {#generating-nim-sboms}
The [nim_lk](https://git.sr.ht/~ehmry/nim_lk) utility can generate SBOMs from [Nimble](https://github.com/nim-lang/nimble) package metadata.
See the [nim_lk documentation](https://git.sr.ht/~ehmry/nim_lk#nimble-to-cyclonedx-sbom) for more information.
## Overriding Nim packages {#nim-overrides}
The `buildNimPackage` and `buildNimSbom` functions generate flags and additional build dependencies from the `lockFile` parameter passed to `buildNimPackage`. Using [`overrideAttrs`](#sec-pkg-overrideAttrs) on the final package will apply after this has already been generated, so this can't be used to override the `lockFile` in a package built with `buildNimPackage`. To be able to override parameters before flags and build dependencies are generated from the `lockFile`, use `overrideNimAttrs` instead with the same syntax as `overrideAttrs`:
```nix
pkgs.nitter.overrideNimAttrs {
# using a different source which has different dependencies from the standard package
src = pkgs.fetchFromGithub {
# …
};
# new lock file generated from the source
lockFile = ./custom-lock.json;
}
```
## Lockfile dependency overrides {#nim-lock-overrides}
The `buildNimPackage` function matches the libraries specified by `lockFile` to attrset of override functions that are then applied to the package derivation.
The default overrides are maintained as the top-level `nimOverrides` attrset at `pkgs/top-level/nim-overrides.nix`.
For example, to propagate a dependency on SDL2 for lockfiles that select the Nim `sdl2` library, an overlay is added to the set in the `nim-overrides.nix` file:
```nix
{
lib,
# …
SDL2,
# …
}:
{
# …
sdl2 =
lockAttrs:
{
buildInputs ? [ ],
...
}:
{
buildInputs = buildInputs ++ [ SDL2 ];
};
# …
}
```
The annotations in the `nim-overrides.nix` set are functions that take two arguments and return a new attrset to be overlaid on the package being built.
- lockAttrs: the attrset for this library from within a lockfile. This can be used to implement library version constraints, such as marking libraries as broken or insecure.
- prevAttrs: the attrset produced by initial arguments to `buildNimPackage` and any preceding lockfile overlays.
### Overriding an Nim library override {#nim-lock-overrides-overrides}
The `nimOverrides` attrset makes it possible to modify overrides in a few different ways.
Override a package internal to its definition:
```nix
{
lib,
buildNimPackage,
nimOverrides,
libressl,
}:
let
buildNimPackage' = buildNimPackage.override {
nimOverrides = nimOverrides.override { openssl = libressl; };
};
in
buildNimPackage' (finalAttrs: {
pname = "foo";
# …
})
```
Override a package externally:
```nix
{ pkgs }:
{
foo = pkgs.foo.override {
buildNimPackage = pkgs.buildNimPackage.override {
nimOverrides = pkgs.nimOverrides.override { openssl = libressl; };
};
};
}
```

View File

@@ -0,0 +1,145 @@
# OCaml {#sec-language-ocaml}
## User guide {#sec-language-ocaml-user-guide}
OCaml libraries are available in attribute sets of the form `ocaml-ng.ocamlPackages_X_XX` where X is to be replaced with the desired compiler version. For example, ocamlgraph compiled with OCaml 4.12 can be found in `ocaml-ng.ocamlPackages_4_12.ocamlgraph`. The compiler itself is also located in this set, under the name `ocaml`.
If you don't care about the exact compiler version, `ocamlPackages` is a top-level alias pointing to a recent version of OCaml.
OCaml applications are usually available top-level, and not inside `ocamlPackages`. Notable exceptions are build tools that must be built with the same compiler version as the compiler you intend to use like `dune` or `ocaml-lsp`.
To open a shell able to build a typical OCaml project, put the dependencies in `buildInputs` and add `ocamlPackages.ocaml` and `ocamlPackages.findlib` to `nativeBuildInputs` at least.
For example:
```nix
let
pkgs = import <nixpkgs> { };
# choose the ocaml version you want to use
ocamlPackages = pkgs.ocaml-ng.ocamlPackages_4_12;
in
pkgs.mkShell {
# build tools
nativeBuildInputs = with ocamlPackages; [
ocaml
findlib
dune_2
ocaml-lsp
];
# dependencies
buildInputs = with ocamlPackages; [ ocamlgraph ];
}
```
## Packaging guide {#sec-language-ocaml-packaging}
OCaml libraries should be installed in `$(out)/lib/ocaml/${ocaml.version}/site-lib/`. Such directories are automatically added to the `$OCAMLPATH` environment variable when building another package that depends on them or when opening a `nix-shell`.
Given that most of the OCaml ecosystem is now built with dune, nixpkgs includes a convenience build support function called `buildDunePackage` that will build an OCaml package using dune, OCaml and findlib and any additional dependencies provided as `buildInputs` or `propagatedBuildInputs`.
Here is a simple package example.
- It defines an (optional) attribute `minimalOCamlVersion` (see note below)
that will be used to throw a descriptive evaluation error if building with
an older OCaml is attempted.
- It uses the `fetchFromGitHub` fetcher to get its source.
- It also accepts a `duneVersion` parameter (valid values are `"1"`, `"2"`, and
`"3"`). The recommended practice is to set it only if you don't want the default
value and/or it depends on something else like package version. You might see
a not-supported argument `useDune2`. The behavior was `useDune2 = true;` =>
`duneVersion = "2";` and `useDune2 = false;` => `duneVersion = "1";`. It was
used at the time when dune3 didn't exist.
- It sets the optional `doCheck` attribute such that tests will be run with
`dune runtest -p angstrom` after the build (`dune build -p angstrom`) is
complete, but only if the OCaml version is at least `"4.05"`.
- It uses the package `ocaml-syntax-shims` as a build input, `alcotest` and
`ppx_let` as check inputs (because they are needed to run the tests), and
`bigstringaf` and `result` as propagated build inputs (thus they will also be
available to libraries depending on this library).
- The library will be installed using the `angstrom.install` file that dune
generates.
```nix
{
lib,
fetchFromGitHub,
buildDunePackage,
ocaml,
ocaml-syntax-shims,
alcotest,
result,
bigstringaf,
ppx_let,
}:
buildDunePackage (finalAttrs: {
pname = "angstrom";
version = "0.15.0";
minimalOCamlVersion = "4.04";
src = fetchFromGitHub {
owner = "inhabitedtype";
repo = "angstrom";
tag = finalAttrs.version;
hash = "sha256-MK8o+iPGANEhrrTc1Kz9LBilx2bDPQt7Pp5P2libucI=";
};
buildInputs = [ ocaml-syntax-shims ];
propagatedBuildInputs = [
bigstringaf
result
];
doCheck = lib.versionAtLeast ocaml.version "4.05";
checkInputs = [
alcotest
ppx_let
];
meta = {
homepage = "https://github.com/inhabitedtype/angstrom";
description = "OCaml parser combinators built for speed and memory efficiency";
license = lib.licenses.bsd3;
maintainers = with lib.maintainers; [ sternenseemann ];
};
})
```
Here is a second example, this time using a source archive generated with `dune-release`. It is a good idea to use this archive when it is available as it will usually contain substituted variables such as a `%%VERSION%%` field. This library does not depend on any other OCaml library and no tests are run after building it.
```nix
{
lib,
fetchurl,
buildDunePackage,
}:
buildDunePackage (finalAtts: {
pname = "wtf8";
version = "1.0.2";
minimalOCamlVersion = "4.02";
src = fetchurl {
url = "https://github.com/flowtype/ocaml-wtf8/releases/download/v${finalAtts.version}/wtf8-v${finalAtts.version}.tbz";
hash = "sha256-d5/3KUBAWRj8tntr4RkJ74KWW7wvn/B/m1nx0npnzyc=";
};
meta = {
homepage = "https://github.com/flowtype/ocaml-wtf8";
description = "WTF-8 is a superset of UTF-8 that allows unpaired surrogates";
license = lib.licenses.mit;
maintainers = [ lib.maintainers.eqyiel ];
};
})
```
The build will automatically fail if two distinct versions of the same library
are added to `buildInputs` (which usually happens transitively because of
`propagatedBuildInputs`). Set `dontDetectOcamlConflicts` to true to disable this
behavior.

View File

@@ -0,0 +1,92 @@
# Octave {#sec-octave}
## Introduction {#ssec-octave-introduction}
Octave is a modular scientific programming language and environment.
A majority of the packages supported by Octave from their [website](https://gnu-octave.github.io/packages/) are packaged in nixpkgs.
## Structure {#ssec-octave-structure}
All Octave add-on packages are available in two ways:
1. Under the top-level `Octave` attribute, `octave.pkgs`.
2. As a top-level attribute, `octavePackages`.
## Packaging Octave Packages {#ssec-octave-packaging}
Nixpkgs provides a function `buildOctavePackage`, a generic package builder function for any Octave package that complies with the Octave's current packaging format.
All Octave packages are defined in [pkgs/top-level/octave-packages.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/octave-packages.nix) rather than `pkgs/all-packages.nix`.
Each package is defined in its own file in the [pkgs/development/octave-modules](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/octave-modules) directory.
Octave packages are made available through `all-packages.nix` through both the attribute `octavePackages` and `octave.pkgs`.
You can test building an Octave package as follows:
```ShellSession
$ nix-build -A octavePackages.symbolic
```
To install it into your user profile, run this command from the root of the repository:
```ShellSession
$ nix-env -f. -iA octavePackages.symbolic
```
You can build Octave with packages by using the `withPackages` passed-through function.
```ShellSession
$ nix-shell -p 'octave.withPackages (ps: with ps; [ symbolic ])'
```
This will also work in a `shell.nix` file.
```nix
{
pkgs ? import <nixpkgs> { },
}:
pkgs.mkShell {
nativeBuildInputs = with pkgs; [ (octave.withPackages (opkgs: with opkgs; [ symbolic ])) ];
}
```
### `buildOctavePackage` Steps {#sssec-buildOctavePackage-steps}
The `buildOctavePackage` does several things to make sure things work properly.
1. Sets the environment variable `OCTAVE_HISTFILE` to `/dev/null` during package compilation so that the commands run through the Octave interpreter directly are not logged.
2. Skips the configuration step, because the packages are stored as gzipped tarballs, which Octave itself handles directly.
3. Changes the hierarchy of the tarball so that only a single directory is at the top-most level of the tarball.
4. Use Octave itself to run the `pkg build` command, which unzips the tarball, extracts the necessary files written in Octave, and compiles any code written in C++ or Fortran, and places the fully compiled artifact in `$out`.
`buildOctavePackage` is built on top of `stdenv` in a standard way, allowing most things to be customized.
### Handling Dependencies {#sssec-octave-handling-dependencies}
In Octave packages, there are four sets of dependencies that can be specified:
`nativeBuildInputs`
: Just like other packages, `nativeBuildInputs` is intended for architecture-dependent build-time-only dependencies.
`buildInputs`
: Like other packages, `buildInputs` is intended for architecture-independent build-time-only dependencies.
`propagatedBuildInputs`
: Similar to other packages, `propagatedBuildInputs` is intended for packages that are required for both building and running of the package.
See [Symbolic](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/octave-modules/symbolic/default.nix) for how this works and why it is needed.
`requiredOctavePackages`
: This is a special dependency that ensures the specified Octave packages are dependent on others, and are made available simultaneously when loading them in Octave.
### Installing Octave Packages {#sssec-installing-octave-packages}
By default, the `buildOctavePackage` function does _not_ install the requested package into Octave for use.
The function will only build the requested package.
This is due to Octave maintaining a text-based database about which packages are installed where.
To this end, when all the requested packages have been built, the Octave package and all its add-on packages are put together into an environment, similar to Python.
1. First, all the Octave binaries are wrapped with the environment variable `OCTAVE_SITE_INITFILE` set to a file in `$out`, which is required for Octave to be able to find the non-standard package database location.
2. Because of the way `buildEnv` works, all tarballs that are present (which should be all Octave packages to install) should be removed.
3. The path down to the default install location of Octave packages is recreated so that Nix-operated Octave can install the packages.
4. Install the packages into the `$out` environment while writing package entries to the database file.
This database file is unique for each different (according to Nix) environment invocation.
5. Rewrites the Octave-wide startup file to read from the list of packages installed in that particular environment.
6. Wrap any programs that are required by the Octave packages so that they work with all the paths defined within the environment.

View File

@@ -0,0 +1,187 @@
# Perl {#sec-language-perl}
## Running Perl programs on the shell {#ssec-perl-running}
When executing a Perl script, it is possible you get an error such as `./myscript.pl: bad interpreter: /usr/bin/perl: no such file or directory`. This happens when the script expects Perl to be installed at `/usr/bin/perl`, which is not the case when using Perl from nixpkgs. You can fix the script by changing the first line to:
```perl
#!/usr/bin/env perl
```
to take the Perl installation from the `PATH` environment variable, or invoke Perl directly with:
```ShellSession
$ perl ./myscript.pl
```
When the script is using a Perl library that is not installed globally, you might get an error such as `Can't locate DB_File.pm in @INC (you may need to install the DB_File module)`. In that case, you can use `nix-shell` to start an ad-hoc shell with that library installed, for instance:
```ShellSession
$ nix-shell -p perl perlPackages.DBFile --run ./myscript.pl
```
If you are always using the script in places where `nix-shell` is available, you can embed the `nix-shell` invocation in the shebang like this:
```perl
#!/usr/bin/env nix-shell
#! nix-shell -i perl -p perl perlPackages.DBFile
```
## Packaging Perl programs {#ssec-perl-packaging}
Nixpkgs provides a function `buildPerlPackage`, a generic package builder function for any Perl package that has a standard `Makefile.PL`. Its implemented in [pkgs/development/perl-modules/generic](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/perl-modules/generic).
Perl packages from CPAN are defined in [pkgs/top-level/perl-packages.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix) rather than `pkgs/all-packages.nix`. 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 `perl-packages.nix`. However, more complicated packages should be put in a separate file, typically in `pkgs/development/perl-modules`. Here is an example of the former:
```nix
{
ClassC3 = buildPerlPackage rec {
pname = "Class-C3";
version = "0.21";
src = fetchurl {
url = "mirror://cpan/authors/id/F/FL/FLORA/Class-C3-${version}.tar.gz";
hash = "sha256-/5GE5xHT0uYGOQxroqj6LMU7CtKn2s6vMVoSXxL4iK4=";
};
};
}
```
Note the use of `mirror://cpan/`, and the `pname` and `version` in the URL definition to ensure that the `pname` attribute is consistent with the source that were actually downloading. Perl packages are made available in `all-packages.nix` through the variable `perlPackages`. For instance, if you have a package that needs `ClassC3`, you would typically write
```nix
{
foo = import ../path/to/foo.nix {
inherit
stdenv
fetchurl # ...
;
inherit (perlPackages) ClassC3;
};
}
```
in `all-packages.nix`. You can test building a Perl package as follows:
```ShellSession
$ nix-build -A perlPackages.ClassC3
```
To install it with `nix-env` instead: `nix-env -f. -iA perlPackages.ClassC3`.
So what does `buildPerlPackage` do? It does the following:
1. In the configure phase, it calls `perl Makefile.PL` to generate a Makefile. You can set the variable `makeMakerFlags` to pass flags to `Makefile.PL`
2. It adds the contents of the `PERL5LIB` environment variable to `#! .../bin/perl` line of Perl scripts as `-Idir` 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.)
3. In the fixup phase, it writes the propagated build inputs (`propagatedBuildInputs`) to the file `$out/nix-support/propagated-user-env-packages`. `nix-env` 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.
`buildPerlPackage` is built on top of `stdenv`, so everything can be customised in the usual way. For instance, the `BerkeleyDB` module has a `preConfigure` hook to generate a configuration file used by `Makefile.PL`:
```nix
{
buildPerlPackage,
fetchurl,
db,
}:
buildPerlPackage rec {
pname = "BerkeleyDB";
version = "0.36";
src = fetchurl {
url = "mirror://cpan/authors/id/P/PM/PMQS/BerkeleyDB-${version}.tar.gz";
hash = "sha256-4Y+HGgGQqcOfdiKcFIyMrWBEccVNVAMDBWZlFTMorh8=";
};
preConfigure = ''
echo "LIB = ${db.out}/lib" > config.in
echo "INCLUDE = ${db.dev}/include" >> config.in
'';
}
```
Dependencies on other Perl packages can be specified in the `buildInputs` and `propagatedBuildInputs` attributes. If something is exclusively a build-time dependency, use `buildInputs`; if its (also) a runtime dependency, use `propagatedBuildInputs`. For instance, this builds a Perl module that has runtime dependencies on a bunch of other modules:
```nix
{
ClassC3Componentised = buildPerlPackage rec {
pname = "Class-C3-Componentised";
version = "1.0004";
src = fetchurl {
url = "mirror://cpan/authors/id/A/AS/ASH/Class-C3-Componentised-${version}.tar.gz";
hash = "sha256-ASO9rV/FzJYZ0BH572Fxm2ZrFLMZLFATJng1NuU4FHc=";
};
propagatedBuildInputs = [
ClassC3
ClassInspector
TestException
MROCompat
];
};
}
```
On Darwin, if a script has too many `-Idir` flags in its first line (its “shebang line”), it will not run. This can be worked around by calling the `shortenPerlShebang` function from the `postInstall` phase:
```nix
{
lib,
stdenv,
buildPerlPackage,
fetchurl,
shortenPerlShebang,
}:
{
ImageExifTool = buildPerlPackage {
pname = "Image-ExifTool";
version = "12.50";
src = fetchurl {
url = "https://exiftool.org/Image-ExifTool-${version}.tar.gz";
hash = "sha256-vOhB/FwQMC8PPvdnjDvxRpU6jAZcC6GMQfc0AH4uwKg=";
};
nativeBuildInputs = lib.optional stdenv.hostPlatform.isDarwin shortenPerlShebang;
postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
shortenPerlShebang $out/bin/exiftool
'';
};
}
```
This will remove the `-I` flags from the shebang line, rewrite them in the `use lib` 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.
### Generation from CPAN {#ssec-generation-from-CPAN}
Nix expressions for Perl packages can be generated (almost) automatically from CPAN. This is done by the program `nix-generate-from-cpan`, which can be installed as follows:
```ShellSession
$ nix-env -f "<nixpkgs>" -iA nix-generate-from-cpan
```
Substitute `<nixpkgs>` by the path of a nixpkgs clone to use the latest version.
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:
```ShellSession
$ nix-generate-from-cpan XML::Simple
XMLSimple = buildPerlPackage rec {
pname = "XML-Simple";
version = "2.22";
src = fetchurl {
url = "mirror://cpan/authors/id/G/GR/GRANTM/XML-Simple-2.22.tar.gz";
hash = "sha256-uUUO8i6pZErl1q2ghtxDAPoQW+BQogMOvU79KMGY60k=";
};
propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ];
meta = {
description = "API for simple XML files";
license = with lib.licenses; [ artistic1 gpl1Plus ];
};
};
```
The output can be pasted into `pkgs/top-level/perl-packages.nix` or wherever else you need it.
### Cross-compiling modules {#ssec-perl-cross-compilation}
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 `lib/perl5/site_perl/cross_perl/${perl.version}`. See the `postInstall` for `DBI` for an example.

View File

@@ -0,0 +1,333 @@
# PHP {#sec-php}
## User Guide {#ssec-php-user-guide}
### Overview {#ssec-php-user-guide-overview}
Several versions of PHP are available on Nix, each of which having a
wide variety of extensions and libraries available.
The different versions of PHP that nixpkgs provides are located under
attributes named based on major and minor version number; e.g.,
`php84` is PHP 8.4.
Only versions of PHP that are supported by upstream for the entirety
of a given NixOS release will be included in that release of
NixOS. See [PHP Supported
Versions](https://www.php.net/supported-versions.php).
The attribute `php` refers to the version of PHP considered most
stable and thoroughly tested in nixpkgs for any given release of
NixOS - not necessarily the latest major release from upstream.
All available PHP attributes are wrappers around their respective
binary PHP package and provide commonly used extensions this way. The
real PHP 8.4 package, i.e. the unwrapped one, is available as
`php84.unwrapped`; see the next section for more details.
Interactive tools built on PHP are put in `php.packages`; composer is
for example available at `php.packages.composer`.
Most extensions that come with PHP, as well as some popular
third-party ones, are available in `php.extensions`; for example, the
opcache extension shipped with PHP is available at
`php.extensions.opcache` and the third-party ImageMagick extension at
`php.extensions.imagick`.
### Installing PHP with extensions {#ssec-php-user-guide-installing-with-extensions}
A PHP package with specific extensions enabled can be built using
`php.withExtensions`. This is a function which accepts an anonymous
function as its only argument; the function should accept two named
parameters: `enabled` - a list of currently enabled extensions and
`all` - the set of all extensions, and return a list of wanted
extensions. For example, a PHP package with all default extensions and
ImageMagick enabled:
```nix
php.withExtensions ({ enabled, all }: enabled ++ [ all.imagick ])
```
To exclude some, but not all, of the default extensions, you can
filter the `enabled` list like this:
```nix
php.withExtensions (
{ enabled, all }: (lib.filter (e: e != php.extensions.opcache) enabled) ++ [ all.imagick ]
)
```
To build your list of extensions from the ground up, you can
ignore `enabled`:
```nix
php.withExtensions (
{ all, ... }:
with all;
[
imagick
opcache
]
)
```
`php.withExtensions` provides extensions by wrapping a minimal php
base package, providing a `php.ini` file listing all extensions to be
loaded. You can access this package through the `php.unwrapped`
attribute; useful if you, for example, need access to the `dev`
output. The generated `php.ini` file can be accessed through the
`php.phpIni` attribute.
If you want a PHP build with extra configuration in the `php.ini`
file, you can use `php.buildEnv`. This function takes two named and
optional parameters: `extensions` and `extraConfig`. `extensions`
takes an extension specification equivalent to that of
`php.withExtensions`, `extraConfig` a string of additional `php.ini`
configuration parameters. For example, a PHP package with the opcache
and ImageMagick extensions enabled, and `memory_limit` set to `256M`:
```nix
php.buildEnv {
extensions =
{ all, ... }:
with all;
[
imagick
opcache
];
extraConfig = "memory_limit=256M";
}
```
#### Example setup for `phpfpm` {#ssec-php-user-guide-installing-with-extensions-phpfpm}
You can use the previous examples in a `phpfpm` pool called `foo` as
follows:
```nix
let
myPhp = php.withExtensions (
{ all, ... }:
with all;
[
imagick
opcache
]
);
in
{
services.phpfpm.pools."foo".phpPackage = myPhp;
}
```
```nix
let
myPhp = php.buildEnv {
extensions =
{ all, ... }:
with all;
[
imagick
opcache
];
extraConfig = "memory_limit=256M";
};
in
{
services.phpfpm.pools."foo".phpPackage = myPhp;
}
```
#### Example usage with `nix-shell` {#ssec-php-user-guide-installing-with-extensions-nix-shell}
This brings up a temporary environment that contains a PHP interpreter
with the extensions `imagick` and `opcache` enabled:
```sh
nix-shell -p 'php.withExtensions ({ all, ... }: with all; [ imagick opcache ])'
```
### Installing PHP packages with extensions {#ssec-php-user-guide-installing-packages-with-extensions}
All interactive tools use the PHP package you get them from, so all
packages at `php.packages.*` use the `php` package with its default
extensions. Sometimes this default set of extensions isn't enough and
you may want to extend it. A common case of this is the `composer`
package: a project may depend on certain extensions and `composer`
won't work with that project unless those extensions are loaded.
Example of building `composer` with additional extensions:
```nix
(php.withExtensions (
{ all, enabled }:
enabled
++ (with all; [
imagick
redis
])
)).packages.composer
```
### Overriding PHP packages {#ssec-php-user-guide-overriding-packages}
`php-packages.nix` form a scope, allowing us to override the packages defined
within. For example, to apply a patch to a `mysqlnd` extension, you can
pass an overlay-style function to `php`s `packageOverrides` argument:
```nix
php.override {
packageOverrides = final: prev: {
extensions = prev.extensions // {
mysqlnd = prev.extensions.mysqlnd.overrideAttrs (attrs: {
patches = attrs.patches or [ ] ++ [
# ...
];
});
};
};
}
```
### Building PHP projects {#ssec-building-php-projects}
With [Composer](https://getcomposer.org/), you can effectively build PHP
projects by streamlining dependency management. As the de-facto standard
dependency manager for PHP, Composer enables you to declare and manage the
libraries your project relies on, ensuring a more organized and efficient
development process.
Composer is not a package manager in the same sense as `Yum` or `Apt` are. Yes,
it deals with "packages" or libraries, but it manages them on a per-project
basis, installing them in a directory (e.g. `vendor`) inside your project. By
default, it does not install anything globally. This idea is not new and
Composer is strongly inspired by Node's `npm` and Ruby's `bundler`.
Currently, there is no other PHP tool that offers the same functionality as
Composer. Consequently, incorporating a helper in Nix to facilitate building
such applications is a logical choice.
In a Composer project, dependencies are defined in a `composer.json` file,
while their specific versions are locked in a `composer.lock` file. Some
Composer-based projects opt to include this `composer.lock` file in their source
code, while others choose not to.
In Nix, there are multiple approaches to building a Composer-based project.
One such method is the `php.buildComposerProject2` helper function, which serves
as a wrapper around `mkDerivation`.
Using this function, you can build a PHP project that includes both a
`composer.json` and `composer.lock` file. If the project specifies binaries
using the `bin` attribute in `composer.json`, these binaries will be
automatically linked and made accessible in the derivation. In this context,
"binaries" refer to PHP scripts that are intended to be executable.
To use the helper effectively, add the `vendorHash` attribute, which
enables the wrapper to handle the heavy lifting.
Internally, the helper operates in three stages:
1. It constructs a `composerRepository` attribute derivation by creating a
composer repository on the filesystem containing dependencies specified in
`composer.json`. This process uses the function
`php.mkComposerRepository` which in turn uses the
`php.composerHooks.composerRepositoryHook` hook. Internally this function uses
a custom
[Composer plugin](https://github.com/nix-community/composer-local-repo-plugin) to
generate the repository.
2. The resulting `composerRepository` derivation is then used by the
`php.composerHooks.composerInstallHook` hook, which is responsible for
creating the final `vendor` directory.
3. Any "binary" specified in the `composer.json` are linked and made accessible
in the derivation.
As the autoloader optimization can be activated directly within the
`composer.json` file, we do not enable any autoloader optimization flags.
To customize the PHP version, you can specify the `php` attribute. Similarly, if
you wish to modify the Composer version, use the `composer` attribute. It is
important to note that both attributes should be of the `derivation` type.
Here's an example of working code example using `php.buildComposerProject2`:
```nix
{ php, fetchFromGitHub }:
php.buildComposerProject2 (finalAttrs: {
pname = "php-app";
version = "1.0.0";
src = fetchFromGitHub {
owner = "git-owner";
repo = "git-repo";
tag = finalAttrs.version;
hash = "sha256-VcQRSss2dssfkJ+iUb5qT+FJ10GHiFDzySigcmuVI+8=";
};
# PHP version containing the `ast` extension enabled
php = php.buildEnv {
extensions = ({ enabled, all }: enabled ++ (with all; [ ast ]));
};
# The composer vendor hash
vendorHash = "sha256-86s/F+/5cBAwBqZ2yaGRM5rTGLmou5//aLRK5SA0WiQ=";
# If the composer.lock file is missing from the repository, add it:
# composerLock = ./path/to/composer.lock;
})
```
In case the file `composer.lock` is missing from the repository, it is possible
to specify it using the `composerLock` attribute.
The other method is to use all these methods and hooks individually. This has
the advantage of building a PHP library within another derivation very easily
when necessary.
Here's a working code example to build a PHP library using `mkDerivation` and
separate functions and hooks:
```nix
{
stdenvNoCC,
fetchFromGitHub,
php,
}:
stdenvNoCC.mkDerivation (
finalAttrs:
let
src = fetchFromGitHub {
owner = "git-owner";
repo = "git-repo";
rev = finalAttrs.version;
hash = "sha256-VcQRSss2dssfkJ+iUb5qT+FJ10GHiFDzySigcmuVI+8=";
};
in
{
inherit src;
pname = "php-app";
version = "1.0.0";
buildInputs = [ php ];
nativeBuildInputs = [
php.packages.composer
# This hook will use the attribute `composerRepository`
php.composerHooks.composerInstallHook
];
composerRepository = php.mkComposerRepository {
inherit (finalAttrs) pname version src;
composerNoDev = true;
composerNoPlugins = true;
composerNoScripts = true;
# Specifying a custom composer.lock since it is not present in the sources.
composerLock = ./composer.lock;
# The composer vendor hash
vendorHash = "sha256-86s/F+/5cBAwBqZ2yaGRM5rTGLmou5//aLRK5SA0WiQ=";
};
}
)
```

View File

@@ -0,0 +1,58 @@
# pkg-config {#sec-pkg-config}
*pkg-config* is a unified interface for declaring and querying built C/C++ libraries.
Nixpkgs provides a couple of facilities for working with this tool.
## Writing packages providing pkg-config modules {#pkg-config-writing-packages}
Packages should set `meta.pkgConfigModules` with the list of package config modules they provide.
They should also use `testers.hasPkgConfigModules` to check that the final built package matches that list,
and optionally check that the pkgconf modules' version metadata matches the derivation's.
Additionally, the [`validatePkgConfig` setup hook](https://nixos.org/manual/nixpkgs/stable/#validatepkgconfig) will do extra checks on to-be-installed pkg-config modules.
A good example of all these things is miniz:
```nix
{ pkg-config, testers, ... }:
stdenv.mkDerivation (finalAttrs: {
# ...
nativeBuildInputs = [
pkg-config
validatePkgConfig
];
passthru.tests.pkg-config = testers.hasPkgConfigModules {
package = finalAttrs.finalPackage;
versionCheck = true;
};
meta = {
# ...
pkgConfigModules = [ "miniz" ];
};
})
```
## Accessing packages via pkg-config module name {#sec-pkg-config-usage}
### Within Nixpkgs {#sec-pkg-config-usage-internal}
A [setup hook](#setup-hook-pkg-config) is bundled in the `pkg-config` package to bring a derivation's declared build inputs into the environment.
This will populate environment variables like `PKG_CONFIG_PATH`, `PKG_CONFIG_PATH_FOR_BUILD`, and `PKG_CONFIG_PATH_HOST` based on:
- how `pkg-config` itself is depended upon
- how other dependencies are depended upon
For more details see the section on [specifying dependencies in general](#ssec-stdenv-dependencies).
Normal pkg-config commands to look up dependencies by name will then work with those environment variables defined by the hook.
### Externally {#sec-pkg-config-usage-external}
The `defaultPkgConfigPackages` package set is a set of aliases, named after the modules they provide.
This is meant to be used by language-to-nix integrations.
Hand-written packages should use the normal Nixpkgs attribute name instead.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
# Qt {#sec-language-qt}
Writing Nix expressions for Qt libraries and applications is largely similar to that for other C++ software.
This section assumes some knowledge of the latter.
The major caveat with Qt applications is that Qt uses a plugin system to load additional modules at runtime.
In Nixpkgs, we wrap Qt applications to inject environment variables telling Qt where to discover the required plugins and QML modules.
This effectively makes the runtime dependencies pure and explicit at build-time, at the cost of introducing
an extra indirection.
## Nix expression for a Qt package (default.nix) {#qt-default-nix}
```nix
{ stdenv, qt6 }:
stdenv.mkDerivation {
pname = "myapp";
version = "1.0";
buildInputs = [ qt6.qtbase ];
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
}
```
The same goes for Qt 5 where libraries and tools are under `libsForQt5`.
Any Qt package should include `wrapQtAppsHook` or `wrapQtAppsNoGuiHook` in `nativeBuildInputs`, or explicitly set `dontWrapQtApps` to bypass generating the wrappers.
::: {.note}
`wrapQtAppsHook` propagates plugins and QML components from `qtwayland` on platforms that support it, to allow applications to act as native Wayland clients. It should be used for all graphical applications.
`wrapQtAppsNoGuiHook` does not propagate `qtwayland` to reduce closure size for purely command-line applications.
:::
## Packages supporting multiple Qt versions {#qt-versions}
If your package is a library that can be built with multiple Qt versions, you may want to take Qt modules as separate arguments (`qtbase`, `qtdeclarative` etc.), and invoke the package from `pkgs/top-level/qt5-packages.nix` or `pkgs/top-level/qt6-packages.nix` using the respective `callPackage` functions.
Applications should generally be built with upstream's preferred Qt version.
## Locating additional runtime dependencies {#qt-runtime-dependencies}
Add entries to `qtWrapperArgs` to modify the wrappers created by
`wrapQtAppsHook`:
```nix
{ stdenv, qt6 }:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
qtWrapperArgs = [ "--prefix PATH : /path/to/bin" ];
}
```
The entries are passed as arguments to [wrapProgram](#fun-wrapProgram).
If you need more control over the wrapping process, set `dontWrapQtApps` to disable automatic wrapper generation,
and then create wrappers manually in `fixupPhase`, using `wrapQtApp`, which itself is a small wrapper over [wrapProgram](#fun-wrapProgram):
The `makeWrapper` arguments required for Qt are also exposed in the environment as `$qtWrapperArgs`.
```nix
{
stdenv,
lib,
wrapQtAppsHook,
}:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ wrapQtAppsHook ];
dontWrapQtApps = true;
preFixup = ''
wrapQtApp "$out/bin/myapp" --prefix PATH : /path/to/bin
'';
}
```
::: {.note}
`wrapQtAppsHook` ignores files that are non-ELF executables.
This means that scripts won't be automatically wrapped so you'll need to manually wrap them as previously mentioned.
An example of when you'd always need to do this is with Python applications that use PyQt.
:::

View File

@@ -0,0 +1,142 @@
# R {#r}
## Installation {#installation}
Define an environment for R that contains all the libraries that you'd like to
use by adding the following snippet to your $HOME/.config/nixpkgs/config.nix file:
```nix
{
packageOverrides =
super:
let
self = super.pkgs;
in
{
rEnv = super.rWrapper.override {
packages = with self.rPackages; [
devtools
ggplot2
reshape2
yaml
optparse
];
};
};
}
```
Then you can use `nix-env -f "<nixpkgs>" -iA rEnv` to install it into your user
profile. The set of available libraries can be discovered by running the
command `nix-env -f "<nixpkgs>" -qaP -A rPackages`. The first column from that
output is the name that has to be passed to rWrapper in the code snipped above.
However, if you'd like to add a file to your project source to make the
environment available for other contributors, you can create a `default.nix`
file like so:
```nix
with import <nixpkgs> { };
{
myProject = stdenv.mkDerivation {
name = "myProject";
version = "1";
src = if lib.inNixShell then null else nix;
buildInputs = with rPackages; [
R
ggplot2
knitr
];
};
}
```
and then run `nix-shell .` to be dropped into a shell with those packages
available.
## RStudio {#rstudio}
RStudio uses a standard set of packages and ignores any custom R
environments or installed packages you may have. To create a custom
environment, see `rstudioWrapper`, which functions similarly to
`rWrapper`:
```nix
{
packageOverrides =
super:
let
self = super.pkgs;
in
{
rstudioEnv = super.rstudioWrapper.override {
packages = with self.rPackages; [
dplyr
ggplot2
reshape2
];
};
};
}
```
Then like above, `nix-env -f "<nixpkgs>" -iA rstudioEnv` will install
this into your user profile.
Alternatively, you can create a self-contained `shell.nix` without the need to
modify any configuration files:
```nix
{
pkgs ? import <nixpkgs> { },
}:
pkgs.rstudioWrapper.override {
packages = with pkgs.rPackages; [
dplyr
ggplot2
reshape2
];
}
```
Executing `nix-shell` will then drop you into an environment equivalent to the
one above. If you need additional packages just add them to the list and
re-enter the shell.
## Updating the package set {#updating-the-package-set}
There is a script and associated environment for regenerating the package
sets and synchronising the rPackages tree to the current CRAN and matching
BIOC release. These scripts are found in the `pkgs/development/r-modules`
directory and executed as follows:
```bash
nix-shell generate-shell.nix
Rscript generate-r-packages.R cran > cran-packages.json.new
mv cran-packages.json.new cran-packages.json
Rscript generate-r-packages.R bioc > bioc-packages.json.new
mv bioc-packages.json.new bioc-packages.json
Rscript generate-r-packages.R bioc-annotation > bioc-annotation-packages.json.new
mv bioc-annotation-packages.json.new bioc-annotation-packages.json
Rscript generate-r-packages.R bioc-experiment > bioc-experiment-packages.json.new
mv bioc-experiment-packages.json.new bioc-experiment-packages.json
```
`generate-r-packages.R <repo>` reads `<repo>-packages.json`, therefore
the renaming.
The contents of a generated `*-packages.json` file will be used to
create a package derivation for each R package listed in the file.
Some packages require overrides to specify external dependencies or other
patches and special requirements. These overrides are specified in the
`pkgs/development/r-modules/default.nix` file. As the `*-packages.json`
contents are automatically generated it should not be edited and broken
builds should be addressed using overrides.

View File

@@ -0,0 +1,341 @@
# Ruby {#sec-language-ruby}
## Using Ruby {#using-ruby}
Several versions of Ruby interpreters are available on Nix, as well as over 250 gems and many applications written in Ruby. The attribute `ruby` refers to the default Ruby interpreter, which is currently MRI 3.3. It's also possible to refer to specific versions, e.g. `ruby_3_y`, `jruby`, or `mruby`.
In the Nixpkgs tree, Ruby packages can be found throughout, depending on what they do, and are called from the main package set. Ruby gems, however are separate sets, and there's one default set for each interpreter (currently MRI only).
There are two main approaches for using Ruby with gems. One is to use a specifically locked `Gemfile` for an application that has very strict dependencies. The other is to depend on the common gems, which we'll explain further down, and rely on them being updated regularly.
The interpreters have common attributes, namely `gems`, and `withPackages`. So you can refer to `ruby.gems.nokogiri`, or `ruby_3_2.gems.nokogiri` to get the Nokogiri gem already compiled and ready to use.
Since not all gems have executables like `nokogiri`, it's usually more convenient to use the `withPackages` function like this: `ruby.withPackages (p: with p; [ nokogiri ])`. This will also make sure that the Ruby in your environment will be able to find the gem and it can be used in your Ruby code (for example via `ruby` or `irb` executables) via `require "nokogiri"` as usual.
### Temporary Ruby environment with `nix-shell` {#temporary-ruby-environment-with-nix-shell}
Rather than having a single Ruby environment shared by all Ruby development projects on a system, Nix allows you to create separate environments per project. `nix-shell` gives you the possibility to temporarily load another environment akin to a combined `chruby` or `rvm` and `bundle exec`.
There are two methods for loading a shell with Ruby packages. The first and recommended method is to create an environment with `ruby.withPackages` and load that.
```ShellSession
$ nix-shell -p "ruby.withPackages (ps: with ps; [ nokogiri pry ])"
```
The other method, which is not recommended, is to create an environment and list all the packages directly.
```ShellSession
$ nix-shell -p ruby.gems.nokogiri ruby.gems.pry
```
Again, it's possible to launch the interpreter from the shell. The Ruby interpreter has the attribute `gems` which contains all Ruby gems for that specific interpreter.
#### Load Ruby environment from `.nix` expression {#load-ruby-environment-from-.nix-expression}
As explained [in the `nix-shell` section](https://nixos.org/manual/nix/stable/command-ref/nix-shell) of the Nix manual, `nix-shell` can also load an expression from a `.nix` file.
Say we want to have Ruby, `nokogori`, and `pry`. Consider a `shell.nix` file with:
```nix
with import <nixpkgs> { };
ruby.withPackages (
ps: with ps; [
nokogiri
pry
]
)
```
What's happening here?
1. We begin with importing the Nix Packages collections. `import <nixpkgs>` imports the `<nixpkgs>` function, `{}` calls it and the `with` statement brings all attributes of `nixpkgs` in the local scope. These attributes form the main package set.
2. Then we create a Ruby environment with the `withPackages` function.
3. The `withPackages` function expects us to provide a function as an argument that takes the set of all ruby gems and returns a list of packages to include in the environment. Here, we select the packages `nokogiri` and `pry` from the package set.
#### Execute command with `--run` {#execute-command-with---run}
A convenient flag for `nix-shell` is `--run`. It executes a command in the `nix-shell`. We can e.g. directly open a `pry` REPL:
```ShellSession
$ nix-shell -p "ruby.withPackages (ps: with ps; [ nokogiri pry ])" --run "pry"
```
Or immediately require `nokogiri` in pry:
```ShellSession
$ nix-shell -p "ruby.withPackages (ps: with ps; [ nokogiri pry ])" --run "pry -rnokogiri"
```
Or run a script using this environment:
```ShellSession
$ nix-shell -p "ruby.withPackages (ps: with ps; [ nokogiri pry ])" --run "ruby example.rb"
```
#### Using `nix-shell` as shebang {#using-nix-shell-as-shebang}
In fact, for the last case, there is a more convenient method. You can add a [shebang](<https://en.wikipedia.org/wiki/Shebang_(Unix)>) to your script specifying which dependencies `nix-shell` needs. With the following shebang, you can just execute `./example.rb`, and it will run with all dependencies.
```ruby
#! /usr/bin/env nix-shell
#! nix-shell -i ruby -p "ruby.withPackages (ps: with ps; [ nokogiri rest-client ])"
require 'nokogiri'
require 'rest-client'
body = RestClient.get('http://example.com').body
puts Nokogiri::HTML(body).at('h1').text
```
## Developing with Ruby {#developing-with-ruby}
### Using an existing Gemfile {#using-an-existing-gemfile}
In most cases, you'll already have a `Gemfile.lock` listing all your dependencies. This can be used to generate a `gemset.nix` which is used to fetch the gems and combine them into a single environment. The reason why you need to have a separate file for this, is that Nix requires you to have a checksum for each input to your build. Since the `Gemfile.lock` that `bundler` generates doesn't provide us with checksums, we have to first download each gem, calculate its SHA256, and store it in this separate file.
So the steps from having just a `Gemfile` to a `gemset.nix` are:
```ShellSession
$ bundle lock
$ bundix
```
If you already have a `Gemfile.lock`, you can run `bundix` and it will work the same.
To update the gems in your `Gemfile.lock`, you may use the `bundix -l` flag, which will create a new `Gemfile.lock` in case the `Gemfile` has a more recent time of modification.
Once the `gemset.nix` is generated, it can be used in a `bundlerEnv` derivation. Here is an example you could use for your `shell.nix`:
```nix
# ...
let
gems = bundlerEnv {
name = "gems-for-some-project";
gemdir = ./.;
};
in
mkShell {
packages = [
gems
gems.wrappedRuby
];
}
```
With this file in your directory, you can run `nix-shell` to build and use the gems. The important parts here are `bundlerEnv` and `wrappedRuby`.
The `bundlerEnv` is a wrapper over all the gems in your gemset. This means that all the `/lib` and `/bin` directories will be available, and the executables of all gems (even of indirect dependencies) will end up in your `$PATH`. The `wrappedRuby` provides you with all executables that come with Ruby itself, but wrapped so they can easily find the gems in your gemset.
One common issue that you might have is that you have Ruby, but also `bundler` in your gemset. That leads to a conflict for `/bin/bundle` and `/bin/bundler`. You can resolve this by wrapping either your Ruby or your gems in a `lowPrio` call. So in order to give the `bundler` from your gemset priority, it would be used like this:
```nix
# ...
mkShell {
buildInputs = [
gems
(lowPrio gems.wrappedRuby)
];
}
```
Sometimes a Gemfile references other files. Such as `.ruby-version` or vendored gems. When copying the Gemfile to the nix store we need to copy those files alongside. This can be done using `extraConfigPaths`. For example:
```nix
{
gems = bundlerEnv {
name = "gems-for-some-project";
gemdir = ./.;
extraConfigPaths = [ "${./.}/.ruby-version" ];
};
}
```
### Gem-specific configurations and workarounds {#gem-specific-configurations-and-workarounds}
In some cases, especially if the gem has native extensions, you might need to modify the way the gem is built.
This is done via a common configuration file that includes all of the workarounds for each gem.
This file lives at `/pkgs/development/ruby-modules/gem-config/default.nix`, since it already contains a lot of entries, it should be pretty easy to add the modifications you need for your needs.
In the meanwhile, or if the modification is for a private gem, you can also add the configuration to only your own environment.
Two places that allow this modification are the `ruby` derivation, or `bundlerEnv`.
Here's the `ruby` one:
```nix
{
pg_version ? "10",
pkgs ? import <nixpkgs> { },
}:
let
myRuby = pkgs.ruby.override {
defaultGemConfig = pkgs.defaultGemConfig // {
pg = attrs: {
buildFlags = [
"--with-pg-config=${pkgs."postgresql_${pg_version}".pg_config}/bin/pg_config"
];
};
};
};
in
myRuby.withPackages (ps: with ps; [ pg ])
```
And an example with `bundlerEnv`:
```nix
{
pg_version ? "10",
pkgs ? import <nixpkgs> { },
}:
let
gems = pkgs.bundlerEnv {
name = "gems-for-some-project";
gemdir = ./.;
gemConfig = pkgs.defaultGemConfig // {
pg = attrs: {
buildFlags = [
"--with-pg-config=${pkgs."postgresql_${pg_version}".pg_config}/bin/pg_config"
];
};
};
};
in
mkShell {
buildInputs = [
gems
gems.wrappedRuby
];
}
```
And finally via overlays:
```nix
{
pg_version ? "10",
}:
let
pkgs = import <nixpkgs> {
overlays = [
(self: super: {
defaultGemConfig = super.defaultGemConfig // {
pg = attrs: {
buildFlags = [
"--with-pg-config=${pkgs."postgresql_${pg_version}".pg_config}/bin/pg_config"
];
};
};
})
];
};
in
pkgs.ruby.withPackages (ps: with ps; [ pg ])
```
Then we can get whichever postgresql version we desire and the `pg` gem will always reference it correctly:
```ShellSession
$ nix-shell --argstr pg_version 9_4 --run 'ruby -rpg -e "puts PG.library_version"'
90421
$ nix-shell --run 'ruby -rpg -e "puts PG.library_version"'
100007
```
Of course for this use-case one could also use overlays since the configuration for `pg` depends on the `postgresql` alias, but for demonstration purposes this has to suffice.
### Platform-specific gems {#ruby-platform-specif-gems}
Right now, bundix has some issues with pre-built, platform-specific gems: [bundix PR #68](https://github.com/nix-community/bundix/pull/68).
Until this is solved, you can tell bundler to not use platform-specific gems and instead build them from source each time:
- globally (will be set in `~/.config/.bundle/config`):
```shell
$ bundle config set force_ruby_platform true
```
- locally (will be set in `<project-root>/.bundle/config`):
```shell
$ bundle config set --local force_ruby_platform true
```
### Adding a gem to the default gemset {#adding-a-gem-to-the-default-gemset}
Now that you know how to get a working Ruby environment with Nix, it's time to go forward and start actually developing with Ruby. We will first have a look at how Ruby gems are packaged on Nix. Then, we will look at how you can use development mode with your code.
All gems in the standard set are automatically generated from a single `Gemfile`. The dependency resolution is done with `bundler` and makes it more likely that all gems are compatible with each other.
In order to add a new gem to nixpkgs, you can put it into the `/pkgs/development/ruby-modules/with-packages/Gemfile` and run `./maintainers/scripts/update-ruby-packages`.
To test that it works, you can then try using the gem with:
```shell
NIX_PATH=nixpkgs=$PWD nix-shell -p "ruby.withPackages (ps: with ps; [ name-of-your-gem ])"
```
### Packaging applications {#packaging-applications}
A common task is to add a Ruby executable to Nixpkgs; popular examples would be `chef`, `jekyll`, or `sass`. A good way to do that is to use the `bundlerApp` function, that allows you to make a package that only exposes the listed executables. Otherwise, the package may cause conflicts through common paths like `bin/rake` or `bin/bundler` that aren't meant to be used.
The absolute easiest way to do that is to write a `Gemfile` along these lines:
```ruby
source 'https://rubygems.org' do
gem 'mdl'
end
```
If you want to package a specific version, you can use the standard Gemfile syntax for that, e.g. `gem 'mdl', '0.5.0'`, but if you want the latest stable version anyway, it's easier to update by running the `bundle lock` and `bundix` steps again.
Now you can also make a `default.nix` that looks like this:
```nix
{ bundlerApp }:
bundlerApp {
pname = "mdl";
gemdir = ./.;
exes = [ "mdl" ];
}
```
All that's left to do is to generate the corresponding `Gemfile.lock` and `gemset.nix` as described above in the `Using an existing Gemfile` section.
#### Packaging executables that require wrapping {#packaging-executables-that-require-wrapping}
Sometimes your app will depend on other executables at runtime and try to find them through the `PATH` environment variable.
In this case, you can provide a `postBuild` hook to `bundlerApp` that wraps the gem in another script that prefixes the `PATH`.
Of course you could also make a custom `gemConfig` if you know exactly how to patch it, but it's usually much easier to maintain with a simple wrapper so the patch doesn't have to be adjusted for each version.
Here's another example:
```nix
{
lib,
bundlerApp,
makeWrapper,
git,
gnutar,
gzip,
}:
bundlerApp {
pname = "r10k";
gemdir = ./.;
exes = [ "r10k" ];
nativeBuildInputs = [ makeWrapper ];
postBuild = ''
wrapProgram $out/bin/r10k --prefix PATH : ${
lib.makeBinPath [
git
gnutar
gzip
]
}
'';
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
# Scheme {#sec-scheme}
## Package Management {#sec-scheme-package-management}
### Akku {#sec-scheme-package-management-akku}
About two hundred R6RS & R7RS libraries from [Akku](https://akkuscm.org/)
(which also mirrors [snow-fort](https://snow-fort.org/pkg))
are available inside the `akkuPackages` attrset, and the Akku executable
itself is at the top level as `akku`. The packages could be used
in a derivation's `buildInputs`, work inside of `nix-shell`, and
are tested using [Chez](https://www.scheme.com/) &
[Chibi](https://synthcode.com/wiki/chibi-scheme)
Scheme at build time.
Including a package as a build input is done in the typical Nix fashion.
For example, to include
[a bunch of SRFIs](https://akkuscm.org/packages/chez-srfi/)
primarily for Chez Scheme in a derivation, one might write:
```nix
{
buildInputs = [
chez
akkuPackages.chez-srfi
];
}
```
The package index is located in `pkgs/tools/package-management/akku`
as `deps.toml`, and should be updated occasionally by running `./update.sh`
in the directory. Doing so will pull the source URLs for new packages and
more recent versions, then write them to the TOML.

View File

@@ -0,0 +1,203 @@
# Swift {#swift}
The Swift compiler is provided by the `swift` package:
```sh
# Compile and link a simple executable.
nix-shell -p swift --run 'swiftc -' <<< 'print("Hello world!")'
# Run it!
./main
```
The `swift` package also provides the `swift` command, with some caveats:
- Swift Package Manager (SwiftPM) is packaged separately as `swiftpm`. If you
need functionality like `swift build`, `swift run`, `swift test`, you must
also add the `swiftpm` package to your closure.
- On Darwin, the `swift repl` command requires an Xcode installation. This is
because it uses the system LLDB debugserver, which has special entitlements.
## Module search paths {#ssec-swift-module-search-paths}
Like other toolchains in Nixpkgs, the Swift compiler executables are wrapped
to help Swift find your application's dependencies in the Nix store. These
wrappers scan the `buildInputs` of your package derivation for specific
directories where Swift modules are placed by convention, and automatically
add those directories to the Swift compiler search paths.
Swift follows different conventions depending on the platform. The wrappers
look for the following directories:
- On Darwin platforms: `lib/swift/macosx`
(If not targeting macOS, replace `macosx` with the Xcode platform name.)
- On other platforms: `lib/swift/linux/x86_64`
(Where `linux` and `x86_64` are from lowercase `uname -sm`.)
- For convenience, Nixpkgs also adds `lib/swift` to the search path.
This can save a bit of work packaging Swift modules, because many Nix builds
will produce output for just one target anyway.
## Core libraries {#ssec-swift-core-libraries}
In addition to the standard library, the Swift toolchain contains some
additional 'core libraries' that, on Apple platforms, are normally distributed
as part of the OS or Xcode. These are packaged separately in Nixpkgs and can
be found (for use in `buildInputs`) as:
- `swiftPackages.Dispatch`
- `swiftPackages.Foundation`
- `swiftPackages.XCTest`
## Packaging with SwiftPM {#ssec-swift-packaging-with-swiftpm}
Nixpkgs includes a small helper `swiftpm2nix` that can fetch your SwiftPM
dependencies for you, when you need to write a Nix expression to package your
application.
The first step is to run the generator:
```sh
cd /path/to/my/project
# Enter a Nix shell with the required tools.
nix-shell -p swift swiftpm swiftpm2nix
# First, make sure the workspace is up-to-date.
swift package resolve
# Now generate the Nix code.
swiftpm2nix
```
This produces some files in a directory `nix`, which will be part of your Nix
expression. The next step is to write that expression:
```nix
{
stdenv,
swift,
swiftpm,
swiftpm2nix,
fetchFromGitHub,
}:
let
# Pass the generated files to the helper.
generated = swiftpm2nix.helpers ./nix;
in
stdenv.mkDerivation (finalAttrs: {
pname = "myproject";
version = "0.0.0";
src = fetchFromGitHub {
owner = "nixos";
repo = "myproject";
tag = finalAttrs.version;
hash = "";
};
# Including SwiftPM as a nativeBuildInput provides a buildPhase for you.
# This by default performs a release build using SwiftPM, essentially:
# swift build -c release
nativeBuildInputs = [
swift
swiftpm
];
# The helper provides a configure snippet that will prepare all dependencies
# in the correct place, where SwiftPM expects them.
configurePhase = ''
runHook preConfigure
${generated.configure}
runHook postConfigure
'';
installPhase = ''
runHook preInstall
# This is a special function that invokes swiftpm to find the location
# of the binaries it produced.
binPath="$(swiftpmBinPath)"
# Now perform any installation steps.
mkdir -p $out/bin
cp $binPath/myproject $out/bin/
runHook postInstall
'';
})
```
### Custom build flags {#ssec-swiftpm-custom-build-flags}
If you'd like to build a different configuration than `release`:
```nix
{ swiftpmBuildConfig = "debug"; }
```
It is also possible to provide additional flags to `swift build`:
```nix
{ swiftpmFlags = [ "--disable-dead-strip" ]; }
```
The default `buildPhase` already passes `-j` for parallel building.
If these two customization options are insufficient, provide your own
`buildPhase` that invokes `swift build`.
### Running tests {#ssec-swiftpm-running-tests}
Including `swiftpm` in your `nativeBuildInputs` also provides a default
`checkPhase`, but it must be enabled with:
```nix
{ doCheck = true; }
```
This essentially runs: `swift test -c release`
### Patching dependencies {#ssec-swiftpm-patching-dependencies}
In some cases, it may be necessary to patch a SwiftPM dependency. SwiftPM
dependencies are located in `.build/checkouts`, but the `swiftpm2nix` helper
provides these as symlinks to read-only `/nix/store` paths. In order to patch
them, we need to make them writable.
A special function `swiftpmMakeMutable` is available to replace the symlink
with a writable copy:
```nix
{
configurePhase = ''
runHook preConfigure
${generated.configure}
# Replace the dependency symlink with a writable copy.
swiftpmMakeMutable swift-crypto
# Now apply a patch.
patch -p1 -d .build/checkouts/swift-crypto -i ${./some-fix.patch}
runHook postConfigure
'';
}
```
## Considerations for custom build tools {#ssec-swift-considerations-for-custom-build-tools}
### Linking the standard library {#ssec-swift-linking-the-standard-library}
The `swift` package has a separate `lib` output containing just the Swift
standard library, to prevent Swift applications needing a dependency on the
full Swift compiler at runtime. Linking with the Nixpkgs Swift toolchain
already ensures binaries correctly reference the `lib` output.
Sometimes, Swift is used only to compile part of a mixed codebase, and the
link step is manual. Custom build tools often locate the standard library
relative to the `swift` compiler executable, and while the result will work,
when this path ends up in the binary, it will have the Swift compiler as an
unintended dependency.
In this case, you should investigate how your build process discovers the
standard library, and override the path. The correct path will be something
like: `"${swift.swift.lib}/${swift.swiftModuleSubdir}"`

View File

@@ -0,0 +1,54 @@
# Tcl {#sec-language-tcl}
## User guide {#sec-language-tcl-user-guide}
Tcl interpreters are available under the `tcl` and `tcl-X_Y` attributes, where `X_Y` is the Tcl version.
Tcl libraries are available in the `tclPackages` attribute set.
They are only guaranteed to work with the default Tcl version, but will probably also work with others thanks to the [stubs mechanism](https://wiki.tcl-lang.org/page/Stubs).
## Packaging guide {#sec-language-tcl-packaging}
Tcl packages are typically built with `tclPackages.mkTclDerivation`.
Tcl dependencies go in `buildInputs`/`nativeBuildInputs`/... like other packages.
For more complex package definitions, such as packages with mixed languages, use `tcl.tclPackageHook`.
Where possible, make sure to enable stubs for maximum compatibility, usually with the `--enable-stubs` configure flag.
Here is a simple package example to be called with `tclPackages.callPackage`.
```
{ lib, fetchzip, mkTclDerivation, openssl }:
mkTclDerivation rec {
pname = "tcltls";
version = "1.7.22";
src = fetchzip {
url = "https://core.tcl-lang.org/tcltls/uv/tcltls-${version}.tar.gz";
hash = "sha256-TOouWcQc3MNyJtaAGUGbaQoaCWVe6g3BPERct/V65vk=";
};
buildInputs = [ openssl ];
configureFlags = [
"--with-ssl-dir=${openssl.dev}"
"--enable-stubs"
];
meta = {
homepage = "https://core.tcl-lang.org/tcltls/index";
description = "OpenSSL / RSA-bsafe Tcl extension";
maintainers = [ lib.maintainers.agbrooks ];
license = lib.licenses.tcltk;
platforms = lib.platforms.unix;
};
}
```
All Tcl libraries are declared in `pkgs/top-level/tcl-packages.nix` and are defined in `pkgs/development/tcl-modules/`.
If possible, prefer the by-name hierarchy in `pkgs/development/tcl-modules/by-name/`.
Its use is documented in `pkgs/development/tcl-modules/by-name/README.md`.
All Tcl applications reside elsewhere.
In case a package is used as both a library and an application (for example `expect`), it should be defined in `tcl-packages.nix`, with an alias elsewhere.

View File

@@ -0,0 +1,249 @@
# TeX Live {#sec-language-texlive}
There is a TeX Live packaging that lives entirely under attribute `texlive`.
## User's guide (experimental new interface) {#sec-language-texlive-user-guide-experimental}
Release 23.11 ships with a new interface that will eventually replace `texlive.combine`.
- For basic usage, use some of the prebuilt environments available at the top level, such as `texliveBasic`, `texliveSmall`. For the full list of prebuilt environments, inspect `texlive.schemes`.
- Packages cannot be used directly but must be assembled in an environment. To create or add packages to an environment, use
```nix
texliveSmall.withPackages (
ps: with ps; [
collection-langkorean
algorithms
cm-super
]
)
```
The function `withPackages` can be called multiple times to add more packages.
- **Note.** Within Nixpkgs, packages should only use prebuilt environments as inputs, such as `texliveSmall` or `texliveInfraOnly`, and should not depend directly on `texlive`. Further dependencies should be added by calling `withPackages`. This is to ensure that there is a consistent and simple way to override the inputs.
- `texlive.withPackages` uses the same logic as `buildEnv`. Only parts of a package are installed in an environment: its 'runtime' files (`tex` output), binaries (`out` output), and support files (`tlpkg` output). Moreover, man and info pages are assembled into separate `man` and `info` outputs. To add only the TeX files of a package, or its documentation (`texdoc` output), just specify the outputs:
```nix
texlive.withPackages (
ps: with ps; [
texdoc # recommended package to navigate the documentation
perlPackages.LaTeXML.tex # tex files of LaTeXML, omit binaries
cm-super
cm-super.texdoc # documentation of cm-super
]
)
```
- All packages distributed by TeX Live, which contains most of CTAN, are available and can be found under `texlive.pkgs`:
```ShellSession
$ nix repl
nix-repl> :l <nixpkgs>
nix-repl> texlive.pkgs.[TAB]
```
Note that the packages in `texlive.pkgs` are only provided for search purposes and must not be used directly.
- **Experimental and subject to change without notice:** to add the documentation for all packages in the environment, use
```nix
texliveSmall.__overrideTeXConfig { withDocs = true; }
```
This can be applied before or after calling `withPackages`.
The function currently supports the parameters `withDocs`, `withSources`, and `requireTeXPackages`.
## User's guide {#sec-language-texlive-user-guide}
- For basic usage just pull `texlive.combined.scheme-basic` for an environment with basic LaTeX support.
- It typically won't work to use separately installed packages together. Instead, you can build a custom set of packages like this. Most CTAN packages should be available:
```nix
texlive.combine {
inherit (texlive)
scheme-small
collection-langkorean
algorithms
cm-super
;
}
```
- There are all the schemes, collections and a few thousand packages, as defined upstream (perhaps with tiny differences).
- By default you only get executables and files needed during runtime, and a little documentation for the core packages. To change that, you need to add `pkgFilter` function to `combine`.
```nix
texlive.combine {
# inherit (texlive) whatever-you-want;
pkgFilter =
pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.hasManpages || pkg.pname == "cm-super";
# elem tlType [ "run" "bin" "doc" "source" ]
# there are also other attributes: version, name
}
```
- You can list packages e.g. by `nix repl`.
```ShellSession
$ nix repl
nix-repl> :l <nixpkgs>
nix-repl> texlive.collection-[TAB]
```
- Note that the wrapper assumes that the result has a chance to be useful. For example, the core executables should be present, as well as some core data files. The supported way of ensuring this is by including some scheme, for example, `scheme-basic`, into the combination.
- TeX Live packages are also available under `texlive.pkgs` as derivations with outputs `out`, `tex`, `texdoc`, `texsource`, `tlpkg`, `man`, `info`. They cannot be installed outside of `texlive.combine` but are available for other uses. To repackage a font, for instance, use
```nix
stdenvNoCC.mkDerivation (finalAttrs: {
src = texlive.pkgs.iwona;
dontUnpack = true;
inherit (finalAttrs.src) pname version;
installPhase = ''
runHook preInstall
install -Dm644 $src/fonts/opentype/nowacki/iwona/*.otf -t $out/share/fonts/opentype
runHook postInstall
'';
})
```
See `biber`, `iwona` for complete examples.
## Custom packages {#sec-language-texlive-custom-packages}
You may find that you need to use an external TeX package. A derivation for such package has to provide the contents of the "texmf" directory in its `"tex"` output, according to the [TeX Directory Structure](https://tug.ctan.org/tds/tds.html). Dependencies on other TeX packages can be listed in the attribute `tlDeps`.
The functions `texlive.combine` and `texlive.withPackages` recognise the following outputs:
- `"out"`: contents are linked in the TeX Live environment, and binaries in the `$out/bin` folder are wrapped;
- `"tex"`: linked in `$TEXMFDIST`; files should follow the TDS (for instance `$tex/tex/latex/foiltex/foiltex.cls`);
- `"texdoc"`, `"texsource"`: ignored by default, treated as `"tex"`;
- `"tlpkg"`: linked in `$TEXMFROOT/tlpkg`;
- `"man"`, `"info"`, ...: the other outputs are combined into separate outputs.
When using `pkgFilter`, `texlive.combine` will assign `tlType` respectively `"bin"`, `"run"`, `"doc"`, `"source"`, `"tlpkg"` to the above outputs.
Here is a (very verbose) example. See also the packages `auctex`, `eukleides`, `mftrace` for more examples.
```nix
with import <nixpkgs> { };
let
foiltex = stdenvNoCC.mkDerivation {
pname = "latex-foiltex";
version = "2.1.4b";
outputs = [
"tex"
"texdoc"
];
passthru.tlDeps = with texlive; [ latex ];
srcs = [
(fetchurl {
url = "http://mirrors.ctan.org/macros/latex/contrib/foiltex/foiltex.dtx";
hash = "sha256-/2I2xHXpZi0S988uFsGuPV6hhMw8e0U5m/P8myf42R0=";
})
(fetchurl {
url = "http://mirrors.ctan.org/macros/latex/contrib/foiltex/foiltex.ins";
hash = "sha256-KTm3pkd+Cpu0nSE2WfsNEa56PeXBaNfx/sOO2Vv0kyc=";
})
];
unpackPhase = ''
runHook preUnpack
for _src in $srcs; do
cp "$_src" $(stripHash "$_src")
done
runHook postUnpack
'';
nativeBuildInputs = [
(texliveSmall.withPackages (
ps: with ps; [
cm-super
hypdoc
latexmk
]
))
# multiple-outputs.sh fails if $out is not defined
(writeShellScript "force-tex-output.sh" ''
out="''${tex-}"
'')
writableTmpDirAsHomeHook # Need a writable $HOME for latexmk
];
dontConfigure = true;
buildPhase = ''
runHook preBuild
# Generate the style files
latex foiltex.ins
# Generate the documentation
latexmk -pdf foiltex.dtx
runHook postBuild
'';
installPhase = ''
runHook preInstall
path="$tex/tex/latex/foiltex"
mkdir -p "$path"
cp *.{cls,def,clo,sty} "$path/"
path="$texdoc/doc/tex/latex/foiltex"
mkdir -p "$path"
cp *.pdf "$path/"
runHook postInstall
'';
meta = {
description = "LaTeX2e class for overhead transparencies";
license = lib.licenses.unfreeRedistributable;
maintainers = with lib.maintainers; [ veprbl ];
platforms = lib.platforms.all;
};
};
latex_with_foiltex = texliveSmall.withPackages (_: [ foiltex ]);
in
runCommand "test.pdf" { nativeBuildInputs = [ latex_with_foiltex ]; } ''
cat >test.tex <<EOF
\documentclass{foils}
\title{Presentation title}
\date{}
\begin{document}
\maketitle
\end{document}
EOF
pdflatex test.tex
cp test.pdf $out
''
```
## LuaLaTeX font cache {#sec-language-texlive-lualatex-font-cache}
The font cache for LuaLaTeX is written to `$HOME`.
Therefore, it is necessary to set `$HOME` to a writable path, e.g. [before using LuaLaTeX in nix derivations](https://github.com/NixOS/nixpkgs/issues/180639):
```nix
runCommandNoCC "lualatex-hello-world" { buildInputs = [ texliveFull ]; } ''
mkdir $out
echo '\documentclass{article} \begin{document} Hello world \end{document}' > main.tex
env HOME=$(mktemp -d) lualatex -interaction=nonstopmode -output-format=pdf -output-directory=$out ./main.tex
''
```
Additionally, [the cache of a user can diverge from the nix store](https://github.com/NixOS/nixpkgs/issues/278718).
To resolve font issues that might follow, the cache can be removed by the user:
```ShellSession
luaotfload-tool --cache=erase --flush-lookups --force
```

View File

@@ -0,0 +1,68 @@
# Typst {#typst}
Typst can be configured to include packages from [Typst Universe](https://typst.app/universe/) or custom packages.
## Custom Environment {#typst-custom-environment}
You can create a custom Typst environment with a selected set of packages from **Typst Universe** using the following code. It is also possible to specify a Typst package with a specific version (e.g., `cetz_0_3_0`). A package without a version number will always refer to its latest version.
```nix
typst.withPackages (
p: with p; [
polylux_0_4_0
cetz_0_3_0
]
)
```
### Handling Outdated Package Hashes {#typst-handling-outdated-package-hashes}
Since **Typst Universe** does not provide a way to fetch a package with a specific hash, the package hashes in `nixpkgs` can sometimes be outdated. To resolve this issue, you can manually override the package source using the following approach:
```nix
typst.withPackages.override
(old: {
typstPackages = old.typstPackages.extend (
_: previous: {
polylux_0_4_0 = previous.polylux_0_4_0.overrideAttrs (oldPolylux: {
src = oldPolylux.src.overrideAttrs { outputHash = YourUpToDatePolyluxHash; };
});
}
);
})
(
p: with p; [
polylux_0_4_0
cetz_0_3_0
]
)
```
## Custom Packages {#typst-custom-packages}
`Nixpkgs` provides a helper function, `buildTypstPackage`, to build custom Typst packages that can be used within the Typst environment. However, all dependencies of the custom package must be explicitly specified in `typstDeps`.
Here's how to define a custom Typst package:
```nix
{ buildTypstPackage, typstPackages }:
buildTypstPackage (finalAttrs: {
pname = "my-typst-package";
version = "0.0.1";
src = ./.;
typstDeps = with typstPackages; [ cetz_0_3_0 ];
})
```
### Package Scope and Usage {#typst-package-scope-and-usage}
By default, every custom package is scoped under `@preview`, as shown below:
```typst
#import "@preview/my-typst-package:0.0.1": *
```
Since `@preview` is intended for packages from **Typst Universe**, it is recommended to use this approach **only for temporary or experimental modifications over existing packages** from **Typst Universe**.
On the other hand, **local packages**, packages scoped under `@local`, are **not** considered part of the Typst environment. This means that local packages must be manually linked to the Typst compiler if needed.

View File

@@ -0,0 +1,223 @@
# Vim {#vim}
Vim can be configured to include your favorite plugins and additional libraries.
Loading can be deferred; see examples.
At the moment we support two different methods for managing plugins:
- Vim packages (*recommended*)
- vim-plug (vim only)
Right now two Vim packages are available: `vim` which has most features that require extra
dependencies disabled and `vim-full` which has them configurable and enabled by default.
::: {.note}
`vim_configurable` is a deprecated alias for `vim-full` and refers to the fact that its
build-time features are configurable. It has nothing to do with user configuration,
and both the `vim` and `vim-full` packages can be customized as explained in the next section.
:::
## Custom configuration {#vim-custom-configuration}
Adding custom .vimrc lines can be done using the following code:
```nix
vim-full.customize {
# `name` optionally specifies the name of the executable and package
name = "vim-with-plugins";
vimrcConfig.customRC = ''
set hidden
'';
}
```
This configuration is used when Vim is invoked with the command specified as name, in this case `vim-with-plugins`.
You can also omit `name` to customize Vim itself. See the
[definition of `vimUtils.makeCustomizable`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/vim-utils.nix#L408)
for all supported options.
## Managing plugins with Vim packages {#managing-plugins-with-vim-packages}
To store your plugins in Vim packages (the native Vim plugin manager, see `:help packages`) the following example can be used:
```nix
vim-full.customize {
vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
# loaded on launch
start = [
youcompleteme
fugitive
];
# manually loadable by calling `:packadd $plugin-name`
# however, if a Vim plugin has a dependency that is not explicitly listed in
# opt that dependency will always be added to start to avoid confusion.
opt = [
phpCompletion
elm-vim
];
# To automatically load a plugin when opening a filetype, add vimrc lines like:
# autocmd FileType php :packadd phpCompletion
};
}
```
The resulting package can be added to `packageOverrides` in `~/.nixpkgs/config.nix` to make it installable:
```nix
{
packageOverrides =
pkgs: with pkgs; {
myVim = vim-full.customize {
# `name` specifies the name of the executable and package
name = "vim-with-plugins";
# add here code from the example section
};
myNeovim = neovim.override {
configure = {
# add code from the example section here
};
};
};
}
```
After that you can install your special grafted `myVim` or `myNeovim` packages.
### What if your favourite Vim plugin isnt already packaged? {#what-if-your-favourite-vim-plugin-isnt-already-packaged}
If one of your favourite plugins isn't packaged, you can package it yourself:
```nix
{ config, pkgs, ... }:
let
easygrep = pkgs.vimUtils.buildVimPlugin {
name = "vim-easygrep";
src = pkgs.fetchFromGitHub {
owner = "dkprice";
repo = "vim-easygrep";
rev = "d0c36a77cc63c22648e792796b1815b44164653a";
hash = "sha256-bL33/S+caNmEYGcMLNCanFZyEYUOUmSsedCVBn4tV3g=";
};
};
in
{
environment.systemPackages = [
(pkgs.neovim.override {
configure = {
packages.myPlugins = with pkgs.vimPlugins; {
start = [
vim-go # already packaged plugin
easygrep # custom package
];
opt = [ ];
};
# ...
};
})
];
}
```
If your package requires building specific parts, use instead `pkgs.vimUtils.buildVimPlugin`.
## Managing plugins with vim-plug {#managing-plugins-with-vim-plug}
To use [vim-plug](https://github.com/junegunn/vim-plug) to manage your Vim
plugins the following example can be used:
```nix
vim-full.customize {
vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
# loaded on launch
plug.plugins = [
youcompleteme
fugitive
phpCompletion
elm-vim
];
};
}
```
Note: this is not possible anymore for Neovim.
## Adding new plugins to nixpkgs {#adding-new-plugins-to-nixpkgs}
Nix expressions for Vim plugins are stored in [pkgs/applications/editors/vim/plugins](https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/editors/vim/plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`nix-shell -p vimPluginsUpdater --run vim-plugins-updater`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/utils/updater.nix). This creates a [generated.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/vim-plugin-names).
When the vim updater detects an nvim-treesitter update, it also runs [`nvim-treesitter/update.py $(nix-build -A vimPlugins.nvim-treesitter)`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/utils/update.py) to update the tree sitter grammars for `nvim-treesitter`.
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:
```nix
{
deoplete-fish = super.deoplete-fish.overrideAttrs (old: {
dependencies = with super; [
deoplete-nvim
vim-fish
];
});
}
```
Sometimes plugins require an override that must be changed when the plugin is updated. This can cause issues when Vim plugins are auto-updated but the associated override isn't updated. For these plugins, the override should be written so that it specifies all information required to install the plugin, and running `nix-shell -p vimPluginsUpdater --run vim-plugins-updater` doesn't change the derivation for the plugin. Manually updating the override is required to update these types of plugins. An example of such a plugin is `LanguageClient-neovim`.
To add a new plugin, run `nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater 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 `vimPluginsUpdater` at all, and are included separately in `overrides.nix`. Currently, all these plugins are related to the `coc.nvim` ecosystem of the Language Server Protocol integration with Vim/Neovim.
## Updating plugins in nixpkgs {#updating-plugins-in-nixpkgs}
Run the update script with a GitHub API token that has at least `public_repo` access. Running the script without the token is likely to result in rate-limiting (429 errors). For steps on creating an API token, please refer to [GitHub's token documentation](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token).
```sh
nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater --github-token=mytoken' # or set GITHUB_TOKEN environment variable
```
Alternatively, set the number of processes to a lower count to avoid rate-limiting.
```sh
nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater --proc 1'
```
To update only specific plugins, list them after the `update` command:
```sh
nix-shell -p vimPluginsUpdater --run 'vim-plugins-updater update "nvim-treesitter" "mini.nvim" "mini-nvim"'
```
The updater script accepts plugin arguments in different formats:
- `"mini.nvim"` := The GitHub repository name, the raw plugin name, or the alias defined in `vim-plugin-names`.
- `"mini-nvim"` := The normalized plugin name, which matches the attribute name generated in `generated.nix`
## How to maintain an out-of-tree overlay of vim plugins? {#vim-out-of-tree-overlays}
You can use the updater script to generate basic packages out of a custom vim
plugin list:
```
nix-shell -p vimPluginsUpdater --run vim-plugins-updater -i vim-plugin-names -o generated.nix --no-commit
```
with the contents of `vim-plugin-names` being for example:
```
repo,branch,alias
pwntester/octo.nvim,,
```
You can then reference the generated vim plugins via:
```nix
{
myVimPlugins = pkgs.vimPlugins.extend ((pkgs.callPackage ./generated.nix { }));
}
```