2023-06-03 21:05:54 +02:00
# Trivial build helpers {#chap-trivial-builders}
2020-12-13 19:44:53 +01:00
2024-01-13 03:58:13 +01:00
Nixpkgs provides a variety of wrapper functions that help build commonly useful derivations. Like [`stdenv.mkDerivation` ](#sec-using-stdenv ), each of these builders creates a derivation, but the arguments passed are different (usually simpler) from those required by `stdenv.mkDerivation` .
2020-12-13 19:44:53 +01:00
## `runCommand` {#trivial-builder-runCommand}
2023-09-18 17:47:47 +02:00
`runCommand :: String -> AttrSet -> String -> Derivation`
2020-12-13 19:44:53 +01:00
2023-09-18 17:47:47 +02:00
`runCommand name drvAttrs buildCommand` returns a derivation that is built by running the specified shell commands.
`name :: String`
: The name that Nix will append to the store path in the same way that `stdenv.mkDerivation` uses its `name` attribute.
`drvAttr :: AttrSet`
: Attributes to pass to the underlying call to [`stdenv.mkDerivation` ](#chap-stdenv ).
`buildCommand :: String`
: Shell commands to run in the derivation builder.
::: {.note}
You have to create a file or directory `$out` for Nix to be able to run the builder successfully.
:::
::: {.example #ex -runcommand-simple}
# Invocation of `runCommand`
2020-12-13 19:44:53 +01:00
```nix
(import < nixpkgs > {}).runCommand "my-example" {} ''
echo My example command is running
mkdir $out
echo I can write data to the Nix store > $out/message
echo I can also run basic commands like:
echo ls
ls
echo whoami
whoami
echo date
date
''
```
2023-09-18 17:47:47 +02:00
:::
2020-12-13 19:44:53 +01:00
## `runCommandCC` {#trivial-builder-runCommandCC}
This works just like `runCommand` . The only difference is that it also provides a C compiler in `buildCommand` 's environment. To minimize your dependencies, you should only use this if you are sure you will need a C compiler as part of running your command.
## `runCommandLocal` {#trivial-builder-runCommandLocal}
2022-03-10 20:43:29 +01:00
Variant of `runCommand` that forces the derivation to be built locally, it is not substituted. This is intended for very cheap commands (< 1s execution time ). It saves on the network round-trip and can speed up a build .
2020-12-13 19:44:53 +01:00
2021-06-05 21:22:45 +02:00
::: {.note}
2022-03-10 20:43:29 +01:00
This sets [`allowSubstitutes` to `false` ](https://nixos.org/nix/manual/#adv-attr-allowSubstitutes ), so only use `runCommandLocal` if you are certain the user will always have a builder for the `system` of the derivation. This should be true for most trivial use cases (e.g., just copying some files to a different location or adding symlinks) because there the `system` is usually the same as `builtins.currentSystem` .
2020-12-13 19:44:53 +01:00
:::
2024-01-15 09:02:45 +01:00
## `writeTextFile`, `writeText`, `writeTextDir`, `writeScript`, `writeScriptBin`, `writeShellScript`, `writeShellScriptBin` {#trivial-builder-text-writing}
2020-12-13 19:44:53 +01:00
2024-01-13 03:58:13 +01:00
Nixpkgs provides the following functions for producing derivations which write text into the Nix store: `writeTextFile` , `writeText` , `writeTextDir` , `writeScript` , `writeScriptBin` , `writeShellScript` , and `writeShellScriptBin` .
2020-12-13 19:44:53 +01:00
2024-01-13 04:15:43 +01:00
`writeText` , `writeTextDir` , `writeScript` , `writeScriptBin` , `writeShellScript` , and `writeShellScriptBin` are convenience functions over `writeTextFile` .
2024-01-13 03:58:13 +01:00
These are useful for creating files from Nix expressions, which may be scripts or non-executable text files.
2023-12-29 13:52:10 +01:00
2024-01-13 04:49:04 +01:00
Each of these functions will cause a derivation to be produced. When you coerce the result of each of these functions to a string, it will evaluate to the *store path* of this derivation.
2023-12-29 13:52:10 +01:00
2024-01-15 17:29:35 +01:00
:::: {.note}
Some of these functions will put the resulting files within a directory inside the derivation output. If you need to refer to the resulting files somewhere else in Nix code, remember to append the path to the file. For example, if the derivation destination is a directory:
2023-12-29 13:52:10 +01:00
2024-01-15 16:49:36 +01:00
```nix
2024-01-13 04:59:49 +01:00
2023-12-29 13:52:10 +01:00
my-file = writeTextFile {
name = "my-file";
text = ''
Contents of File
'';
destination = "/share/my-file";
}
2024-01-15 17:29:35 +01:00
```
2023-12-29 13:52:10 +01:00
2024-01-15 17:29:35 +01:00
Remember to append "/share/my-file" to the derivation path when using it elsewhere:
```nix
2023-12-29 13:52:10 +01:00
writeShellScript "evaluate-my-file.sh" ''
cat ${my-file}/share/my-file
'';
```
2024-01-15 17:29:35 +01:00
2024-01-13 04:15:43 +01:00
::::
2023-12-29 13:52:10 +01:00
### `writeTextFile` {#trivial-builder-writeTextFile}
2024-01-12 17:24:26 +01:00
Writes a text file to the store
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`writeTextFile` takes an attribute set with the following possible attributes:
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`name`
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: Corresponds to the name used in the Nix store path identifier.
`text`
: The contents of the file.
`executable` _optional_
: Make this file have the executable bit set. Defaults to `false`
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`destination` _optional_
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: Supplies a subpath under the derivation's Nix store ouput path into which to create the file. It may contain directory path elements, these are created automatically when the derivation is realized. Defaults to `""` , which indicates that the store path itself will be a file containing the text contents.
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`checkPhase` _optional_
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: Commands to run after generating the file, e.g. lints. It defaults to `""` (no checking).
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`meta` _optional_
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: Additional metadata for the derivation. It defaults to `{}` .
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`allowSubstitutes` _optional_
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: Whether to allow substituting from a binary cache. It defaults to `false` , as the operation is assumed to be faster performed locally. You may want to set this to true if the `checkPhase` step is expensive.
`preferLocalBuild` _optional_
: Whether to prefer building locally, even if faster remote builders are available. It defaults to `true` for the same reason `allowSubstitutes` defaults to `false` .
2024-01-15 17:29:35 +01:00
The resulting store path will include some variation of the name, and it will be a file unless `destination` is used, in which case it will be a directory.
2023-12-29 13:52:10 +01:00
::: {.example #ex -writeTextFile}
2024-01-15 17:29:35 +01:00
# Usage 1 of `writeTextFile`
Writes my-file to `/nix/store/<store path>/some/subpath/my-cool-script` , making it executable. It also runs a check on the resulting file in a `checkPhase` , and supplies values for the less-used options.
2023-12-29 13:52:10 +01:00
```nix
2024-01-15 17:29:35 +01:00
writeTextFile {
2023-12-29 13:52:10 +01:00
name = "my-cool-script";
text = ''
#!/bin/sh
echo "This is my cool script!"
'';
executable = true;
2024-01-15 17:29:35 +01:00
destination = "/some/subpath/my-cool-script";
2023-12-29 13:52:10 +01:00
checkPhase = ''
2024-01-15 17:29:35 +01:00
${pkgs.shellcheck}/bin/shellcheck $out/some/subpath/my-cool-script
2023-12-29 13:52:10 +01:00
'';
meta = {
license = pkgs.lib.licenses.cc0;
};
allowSubstitutes = true;
preferLocalBuild = false;
2024-01-15 17:29:35 +01:00
};
```
:::
::: {.example #ex2 -writeTextFile}
# Usage 2 of `writeTextFile`
2023-12-29 13:52:10 +01:00
2024-01-15 17:29:35 +01:00
Writes `Contents of File` to `/nix/store/<store path>` . See also the `writeText` helper function below.
```nix
2021-12-11 19:50:03 +01:00
writeTextFile {
name = "my-file";
text = ''
Contents of File
'';
}
2024-01-15 17:29:35 +01:00
```
:::
2021-12-11 19:50:03 +01:00
2024-01-15 17:29:35 +01:00
::: {.example #ex3 -writeTextFile}
# Usage 3 of `writeTextFile`
Writes an executable `my-file` to `/nix/store/<store path>/bin/my-file` . See also the `writeScriptBin` helper function below.
```nix
2021-12-11 19:50:03 +01:00
writeTextFile {
name = "my-file";
text = ''
2024-01-15 17:29:35 +01:00
echo "hi"
2021-12-11 19:50:03 +01:00
'';
executable = true;
destination = "/bin/my-file";
}
2023-12-29 13:52:10 +01:00
```
:::
### `writeText` {#trivial-builder-writeText}
2024-01-12 17:24:26 +01:00
Writes a text file to the store
`writeText` takes two arguments: `name` and `text` , each of which should be
a string.
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
`name`
2024-01-12 18:17:24 +01:00
: the name used in the Nix store path.
2024-01-12 17:24:26 +01:00
`text`
: will be the contents of the file.
2023-12-29 13:52:10 +01:00
2024-01-13 04:53:50 +01:00
The store path will include the the name, and it will be a file.
2023-12-29 13:52:10 +01:00
Here is an example.
::: {.example #ex -writeText}
# Usage of `writeText`
2024-01-15 17:29:35 +01:00
Writes `Contents of File` to `/nix/store/<store path>`
2023-12-29 13:52:10 +01:00
```nix
2021-12-11 19:50:03 +01:00
writeText "my-file"
''
Contents of File
'';
2023-12-29 13:52:10 +01:00
```
:::
2024-01-13 03:58:13 +01:00
This example is equivalent to:
2023-12-29 13:52:10 +01:00
```nix
writeTextFile {
name = "my-file";
text = ''
Contents of File
'';
}
```
### `writeTextDir` {#trivial-builder-writeTextDir}
2024-01-12 17:24:26 +01:00
Writes a text file within a subdirectory of the store.
`writeTextDir` takes two arguments: `path` and `text` , each of which should be a string.
`path`
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: the destination within the Nix store path under which to create the file.
`text`
: the contents of the file.
2023-12-29 13:52:10 +01:00
2024-01-13 04:17:39 +01:00
The store path will be a directory.
2023-12-29 13:52:10 +01:00
::: {.example #ex -writeTextDir}
# Usage of `writeTextDir`
2024-01-15 17:29:35 +01:00
Writes `Contents of File` to `/nix/store/<store path>/share/my-file` .
2023-12-29 13:52:10 +01:00
```nix
2021-12-11 19:50:03 +01:00
writeTextDir "share/my-file"
''
Contents of File
'';
2023-12-29 13:52:10 +01:00
```
:::
2024-01-13 03:58:13 +01:00
This example is equivalent to:
2023-12-29 13:52:10 +01:00
```nix
writeTextFile {
name = "my-file";
text = ''
Contents of File
'';
destination = "share/my-file";
}
```
### `writeScript` {#trivial-builder-writeScript}
2024-01-12 17:24:26 +01:00
Writes a script within the store.
`writeScript` takes two arguments: `name` and `text` , each of which should be a string.
`name`
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: the name used in the Nix store path.
`text`
: the contents of the file.
The created file is marked as executable.
2023-12-29 13:52:10 +01:00
2024-01-13 04:53:50 +01:00
The store path will include the the name, and it will be a file.
2023-12-29 13:52:10 +01:00
Here is an example.
::: {.example #ex -writeScript}
# Usage of `writeScript`
2024-01-15 17:29:35 +01:00
Writes `Contents of File` to `/nix/store/<store path>` and makes the store path executable.
2023-12-29 13:52:10 +01:00
```nix
2021-12-11 19:50:03 +01:00
writeScript "my-file"
''
Contents of File
'';
2023-12-29 13:52:10 +01:00
```
:::
2024-01-13 03:58:13 +01:00
This example is equivalent to:
2023-12-29 13:52:10 +01:00
```nix
writeTextFile {
name = "my-file";
text = ''
Contents of File
'';
executable = true;
}
```
### `writeScriptBin` {#trivial-builder-writeScriptBin}
2024-01-12 17:24:26 +01:00
Writes a script within a "bin" subirectory of a subdirectory of the store.
`writeScriptBin` takes two arguments: `name` and `text` , each of which should be a string.
`name`
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: the name used in the Nix store path and within the file generated under the store path.
`text`
: the contents of the file.
The created file is marked as executable.
2023-12-29 13:52:10 +01:00
The file's contents will be put into `/nix/store/<store path>/bin/<name>` .
2024-01-13 04:53:50 +01:00
The store path will include the the name, and it will be a directory.
2023-12-29 13:52:10 +01:00
::: {.example #ex -writeScriptBin}
# Usage of `writeScriptBin`
```nix
writeScriptBin "my-script"
2021-12-11 19:50:03 +01:00
''
2023-12-29 13:52:10 +01:00
echo "hi"
'';
```
:::
2024-01-13 03:58:13 +01:00
This example is equivalent to:
2023-12-29 13:52:10 +01:00
```nix
writeTextFile {
name = "my-script";
text = ''
echo "hi"
2021-12-11 19:50:03 +01:00
'';
2023-12-29 13:52:10 +01:00
executable = true;
destination = "bin/my-script"
}
```
### `writeShellScript` {#trivial-builder-writeShellScript}
2024-01-12 17:24:26 +01:00
Writes a shell script to the store.
`writeShellScript` takes two arguments: `name` and `text` , each of which should be a string.
`name`
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
: the name used in the Nix store path.
`text`
: the contents of the file.
The created file is marked as executable.
This function is almost exactly like `writeScript` , but it prepends a shebang line that points to the runtime shell (usually bash) at the top of the file contents.
2023-12-29 13:52:10 +01:00
2024-01-13 04:53:50 +01:00
The store path will include the the name, and it will be a file.
2023-12-29 13:52:10 +01:00
Here is an example.
::: {.example #ex -writeShellScript}
# Usage of `writeShellScript`
```nix
writeShellScript "my-script"
2021-12-11 19:50:03 +01:00
''
2023-12-29 13:52:10 +01:00
echo "hi"
'';
```
:::
2024-01-13 03:58:13 +01:00
This example is equivalent to:
2023-12-29 13:52:10 +01:00
```nix
writeTextFile {
name = "my-script";
text = ''
#! ${pkgs.runtimeShell}
echo "hi"
2021-12-11 19:50:03 +01:00
'';
2023-12-29 13:52:10 +01:00
executable = true;
}
```
### `writeShellScriptBin` {#trivial-builder-writeShellScriptBin}
2024-01-12 17:24:26 +01:00
Writes a shell script to a "bin" subdirectory of subdirectory of the store.
`writeShellScriptBin` takes two arguments: `name` and `text` , each of which should be a string.
`name`
: the name used in the Nix store path and within the file generated under the store path.
`text`
: the contents of the file.
2023-12-29 13:52:10 +01:00
2024-01-12 17:24:26 +01:00
This function is almost exactly like `writeScriptBin` , but it prepends a shebang line that points to the runtime shell (usually bash) at the top of the file contents.
2023-12-29 13:52:10 +01:00
The file's contents will be put into `/nix/store/<store path>/bin/<name>` .
2024-01-13 04:53:50 +01:00
The store path will include the the name, and it will be a directory.
2023-12-29 13:52:10 +01:00
::: {.example #ex -writeShellScriptBin}
# Usage of `writeShellScriptBin`
```nix
writeShellScriptBin "my-script"
2021-12-11 19:50:03 +01:00
''
2023-12-29 13:52:10 +01:00
echo "hi"
2021-12-11 19:50:03 +01:00
'';
2023-12-29 13:52:10 +01:00
```
:::
2024-01-13 03:58:13 +01:00
This example is equivalent to:
2021-12-11 19:50:03 +01:00
2023-12-29 13:52:10 +01:00
```nix
writeTextFile {
name = "my-script";
text = ''
#! ${pkgs.runtimeShell}
echo "hi"
'';
executable = true;
destination = "bin/my-script"
}
2021-12-11 19:50:03 +01:00
```
2021-11-29 18:59:33 +01:00
## `concatTextFile`, `concatText`, `concatScript` {#trivial-builder-concatText}
These functions concatenate `files` to the Nix store in a single file. This is useful for configuration files structured in lines of text. `concatTextFile` takes an attribute set and expects two arguments, `name` and `files` . `name` corresponds to the name used in the Nix store path. `files` will be the files to be concatenated. You can also set `executable` to true to make this file have the executable bit set.
`concatText` and`concatScript` are simple wrappers over `concatTextFile` .
2021-12-11 19:50:03 +01:00
Here are a few examples:
```nix
# Writes my-file to /nix/store/<store path>
concatTextFile {
name = "my-file";
files = [ drv1 "${drv2}/path/to/file" ];
}
# See also the `concatText` helper function below.
# Writes executable my-file to /nix/store/<store path>/bin/my-file
concatTextFile {
name = "my-file";
files = [ drv1 "${drv2}/path/to/file" ];
executable = true;
destination = "/bin/my-file";
}
# Writes contents of files to /nix/store/<store path>
concatText "my-file" [ file1 file2 ]
# Writes contents of files to /nix/store/<store path>
concatScript "my-file" [ file1 file2 ]
```
2021-10-12 21:31:02 +02:00
## `writeShellApplication` {#trivial-builder-writeShellApplication}
2021-10-12 21:48:27 +02:00
This can be used to easily produce a shell script that has some dependencies (`runtimeInputs`). It automatically sets the `PATH` of the script to contain all of the listed inputs, sets some sanity shellopts (`errexit`, `nounset` , `pipefail` ), and checks the resulting script with [`shellcheck` ](https://github.com/koalaman/shellcheck ).
2021-10-12 21:31:02 +02:00
For example, look at the following code:
```nix
writeShellApplication {
name = "show-nixos-org";
2021-10-12 21:48:27 +02:00
runtimeInputs = [ curl w3m ];
2021-10-12 21:31:02 +02:00
text = ''
curl -s 'https://nixos.org' | w3m -dump -T text/html
'';
}
```
Unlike with normal `writeShellScriptBin` , there is no need to manually write out `${curl}/bin/curl` , setting the PATH
was handled by `writeShellApplication` . Moreover, the script is being checked with `shellcheck` for more strict
validation.
2020-12-13 19:44:53 +01:00
## `symlinkJoin` {#trivial-builder-symlinkJoin}
This can be used to put many derivations into the same directory structure. It works by creating a new derivation and adding symlinks to each of the paths listed. It expects two arguments, `name` , and `paths` . `name` is the name used in the Nix store path for the created derivation. `paths` is a list of paths that will be symlinked. These paths can be to Nix store derivations or any other subdirectory contained within.
2021-12-11 19:50:03 +01:00
Here is an example:
```nix
# adds symlinks of hello and stack to current build and prints "links added"
symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; }
```
This creates a derivation with a directory structure like the following:
```
/nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample
|-- bin
| |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello
| `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack
`-- share
|-- bash-completion
| `-- completions
| `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack
|-- fish
| `-- vendor_completions.d
| `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish
...
```
2021-05-14 17:27:25 +02:00
2021-05-15 15:10:55 +02:00
## `writeReferencesToFile` {#trivial-builder-writeReferencesToFile}
Writes the closure of transitive dependencies to a file.
This produces the equivalent of `nix-store -q --requisites` .
For example,
```nix
writeReferencesToFile (writeScriptBin "hi" ''${hello}/bin/hello'')
```
produces an output path `/nix/store/<hash>-runtime-deps` containing
```nix
/nix/store/< hash > -hello-2.10
/nix/store/< hash > -hi
/nix/store/< hash > -libidn2-2.3.0
/nix/store/< hash > -libunistring-0.9.10
/nix/store/< hash > -glibc-2.32-40
```
You can see that this includes `hi` , the original input path,
`hello` , which is a direct reference, but also
the other paths that are indirectly required to run `hello` .
2021-05-14 17:27:25 +02:00
## `writeDirectReferencesToFile` {#trivial-builder-writeDirectReferencesToFile}
Writes the set of references to the output file, that is, their immediate dependencies.
This produces the equivalent of `nix-store -q --references` .
For example,
```nix
writeDirectReferencesToFile (writeScriptBin "hi" ''${hello}/bin/hello'')
```
produces an output path `/nix/store/<hash>-runtime-references` containing
```nix
/nix/store/< hash > -hello-2.10
```
2022-03-10 20:43:29 +01:00
but none of `hello` 's dependencies because those are not referenced directly
2021-05-14 17:27:25 +02:00
by `hi` 's output.