From a654cc2a72e1a2b10d70c5a3544a5588d7325e6c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Thu, 16 Nov 2023 11:04:19 -0500 Subject: [PATCH 01/21] WIP document derivations and deriving paths And get rid of "store derivation" nonsense. --- doc/manual/source/SUMMARY.md.in | 1 + doc/manual/source/command-ref/nix-build.md | 6 +- .../source/command-ref/nix-copy-closure.md | 4 +- .../source/command-ref/nix-env/install.md | 8 +- .../source/command-ref/nix-env/query.md | 5 +- .../source/command-ref/nix-instantiate.md | 14 +- .../source/command-ref/nix-store/query.md | 14 +- .../source/command-ref/nix-store/realise.md | 12 +- doc/manual/source/glossary.md | 31 ++-- doc/manual/source/language/derivations.md | 10 +- .../source/language/import-from-derivation.md | 7 +- .../source/language/string-interpolation.md | 4 +- .../source/protocols/derivation-aterm.md | 2 +- doc/manual/source/release-notes/rl-0.8.md | 50 ++--- doc/manual/source/release-notes/rl-2.0.md | 146 +++++++-------- doc/manual/source/release-notes/rl-2.13.md | 2 +- doc/manual/source/release-notes/rl-2.15.md | 2 +- doc/manual/source/store/drv.md | 172 ++++++++++++++++++ src/libcmd/command.cc | 2 +- src/libcmd/installables.hh | 2 +- src/libexpr/eval-cache.cc | 2 +- src/libexpr/primops.cc | 4 +- src/libexpr/primops/context.cc | 2 +- src/nix/derivation-add.cc | 2 +- src/nix/derivation-add.md | 7 +- src/nix/derivation-show.cc | 5 +- src/nix/derivation-show.md | 6 +- src/nix/nix.md | 8 +- src/nix/path-info.md | 4 +- src/nix/search.md | 7 +- src/nix/store-copy-log.md | 4 +- 31 files changed, 359 insertions(+), 186 deletions(-) create mode 100644 doc/manual/source/store/drv.md diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index 244bf582d09..7b6d3fe42d5 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -22,6 +22,7 @@ - [Store Object](store/store-object.md) - [Content-Addressing Store Objects](store/store-object/content-address.md) - [Store Path](store/store-path.md) + - [Derivation and Deriving Path](store/drv.md) - [Store Types](store/types/index.md) {{#include ./store/types/SUMMARY.md}} - [Nix Language](language/index.md) diff --git a/doc/manual/source/command-ref/nix-build.md b/doc/manual/source/command-ref/nix-build.md index 3bb59cbed12..df8572ca4df 100644 --- a/doc/manual/source/command-ref/nix-build.md +++ b/doc/manual/source/command-ref/nix-build.md @@ -37,11 +37,11 @@ directory containing at least a file named `default.nix`. `nix-build` is essentially a wrapper around [`nix-instantiate`](nix-instantiate.md) (to translate a high-level Nix -expression to a low-level [store derivation]) and [`nix-store +expression to a low-level [derivation]) and [`nix-store --realise`](@docroot@/command-ref/nix-store/realise.md) (to build the store derivation). -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: @docroot@/glossary.md#gloss-derivation > **Warning** > @@ -80,7 +80,7 @@ except for `--arg` and `--attr` / `-A` which are passed to [`nix-instantiate`](n ```console $ nix-build '' --attr firefox -store derivation is /nix/store/qybprl8sz2lc...-firefox-1.5.0.7.drv +derivation is /nix/store/qybprl8sz2lc...-firefox-1.5.0.7.drv /nix/store/d18hyl92g30l...-firefox-1.5.0.7 $ ls -l result diff --git a/doc/manual/source/command-ref/nix-copy-closure.md b/doc/manual/source/command-ref/nix-copy-closure.md index 8cfd6ebad56..5d1307ca694 100644 --- a/doc/manual/source/command-ref/nix-copy-closure.md +++ b/doc/manual/source/command-ref/nix-copy-closure.md @@ -42,9 +42,9 @@ When using public key authentication, you can avoid typing the passphrase with ` - `--include-outputs` - Also copy the outputs of [store derivation]s included in the closure. + Also copy the outputs of [derivation]s included in the closure. - [store derivation]: @docroot@/glossary.md#gloss-store-derivation + [derivation]: @docroot@/glossary.md#gloss-store-derivation - `--use-substitutes` / `-s` diff --git a/doc/manual/source/command-ref/nix-env/install.md b/doc/manual/source/command-ref/nix-env/install.md index 748dd1e7a39..db9c312f615 100644 --- a/doc/manual/source/command-ref/nix-env/install.md +++ b/doc/manual/source/command-ref/nix-env/install.md @@ -25,7 +25,7 @@ The arguments *args* map to store paths in a number of possible ways: These are [realised], and the resulting output paths are installed. Currently installed derivations with a name equal to the name of a derivation being added are removed unless the option `--preserve-installed` is specified. - [derivation]: @docroot@/glossary.md#gloss-derivation + [derivation expression]: @docroot@/glossary.md#gloss-derivation-expression [default Nix expression]: @docroot@/command-ref/files/default-nix-expression.md [realised]: @docroot@/glossary.md#gloss-realise @@ -61,9 +61,9 @@ The arguments *args* map to store paths in a number of possible ways: The derivations returned by those function calls are installed. This allows derivations to be specified in an unambiguous way, which is necessary if there are multiple derivations with the same name. -- If *args* are [store derivations](@docroot@/glossary.md#gloss-store-derivation), then these are [realised], and the resulting output paths are installed. +- If *args* are [store paths] to [derivations](@docroot@/glossary.md#gloss-derivation), then those derivations are [realised], and the resulting output paths are installed. -- If *args* are [store paths] that are not store derivations, then these are [realised] and installed. +- If *args* are [store paths] not to derivations, then these are [realised] and installed. - By default all [outputs](@docroot@/language/derivations.md#attr-outputs) are installed for each [derivation]. This can be overridden by adding a `meta.outputsToInstall` attribute on the derivation listing a subset of the output names. @@ -193,7 +193,7 @@ To copy the store path with symbolic name `gcc` from another profile: $ nix-env --install --from-profile /nix/var/nix/profiles/foo gcc ``` -To install a specific [store derivation] (typically created by +To install a specific [derivation] (typically created by `nix-instantiate`): ```console diff --git a/doc/manual/source/command-ref/nix-env/query.md b/doc/manual/source/command-ref/nix-env/query.md index c67794ed58e..bb27bae4217 100644 --- a/doc/manual/source/command-ref/nix-env/query.md +++ b/doc/manual/source/command-ref/nix-env/query.md @@ -125,7 +125,10 @@ derivation is shown unless `--no-name` is specified. - `--drv-path` - Print the path of the [store derivation](@docroot@/glossary.md#gloss-store-derivation). + Print the [store path] to the [derivation]. + + [store path]: @docroot@/glossary.md#gloss-store-path + [derivation]: @docroot@/glossary.md#gloss-derivation - `--out-path` diff --git a/doc/manual/source/command-ref/nix-instantiate.md b/doc/manual/source/command-ref/nix-instantiate.md index 6f6fcdc1f66..974ba32eb6f 100644 --- a/doc/manual/source/command-ref/nix-instantiate.md +++ b/doc/manual/source/command-ref/nix-instantiate.md @@ -1,6 +1,6 @@ # Name -`nix-instantiate` - instantiate store derivations from Nix expressions +`nix-instantiate` - instantiate derivations from Nix expressions # Synopsis @@ -17,13 +17,13 @@ # Description -The command `nix-instantiate` produces [store derivation]s from (high-level) Nix expressions. +The command `nix-instantiate` produces [derivation]s from (high-level) Nix expressions. It evaluates the Nix expressions in each of *files* (which defaults to *./default.nix*). Each top-level expression should evaluate to a derivation, a list of derivations, or a set of derivations. The paths -of the resulting store derivations are printed on standard output. +of the resulting derivations are printed on standard output. -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: @docroot@/glossary.md#gloss-derivation If *files* is the character `-`, then a Nix expression will be read from standard input. @@ -42,8 +42,8 @@ standard input. - `--eval` Just parse and evaluate the input files, and print the resulting - values on standard output. No instantiation of store derivations - takes place. + values on standard output. + Derivations are not serialized and written to the store, but instead just discarded. > **Warning** > @@ -128,7 +128,7 @@ standard input. # Examples -Instantiate [store derivation]s from a Nix expression, and build them using `nix-store`: +Instantiate [derivation]s from a Nix expression, and build them using `nix-store`: ```console $ nix-instantiate test.nix (instantiate) diff --git a/doc/manual/source/command-ref/nix-store/query.md b/doc/manual/source/command-ref/nix-store/query.md index 601f46af6b2..f02b8ca3da2 100644 --- a/doc/manual/source/command-ref/nix-store/query.md +++ b/doc/manual/source/command-ref/nix-store/query.md @@ -26,14 +26,14 @@ symlink. - `--use-output` / `-u` - For each argument to the query that is a [store derivation], apply the + For each argument to the query that is a [derivation], apply the query to the output path of the derivation instead. - `--force-realise` / `-f` Realise each argument to the query first (see [`nix-store --realise`](./realise.md)). -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: @docroot@/glossary.md#gloss-derivation # Queries @@ -54,12 +54,12 @@ symlink. This query has one option: - `--include-outputs` - Also include the existing output paths of [store derivation]s, + Also include the existing output paths of [derivation]s, and their closures. This query can be used to implement various kinds of deployment. A *source deployment* is obtained by distributing the closure of a - store derivation. A *binary deployment* is obtained by distributing + derivation. A *binary deployment* is obtained by distributing the closure of an output path. A *cache deployment* (combined source/binary deployment, including binaries of build-time-only dependencies) is obtained by distributing the closure of a store @@ -112,7 +112,7 @@ symlink. of the `dot` tool of AT\&T's [Graphviz package](http://www.graphviz.org/). This can be used to visualise dependency graphs. To obtain a build-time dependency graph, apply - this to a store derivation. To obtain a runtime dependency graph, + this to a derivation. To obtain a runtime dependency graph, apply it to an output path. - `--tree` @@ -128,13 +128,13 @@ symlink. Prints the references graph of the store paths *paths* in the [GraphML](http://graphml.graphdrawing.org/) file format. This can be used to visualise dependency graphs. To obtain a build-time - dependency graph, apply this to a [store derivation]. To obtain a + dependency graph, apply this to a [derivation]. To obtain a runtime dependency graph, apply it to an output path. - `--binding` *name* / `-b` *name* Prints the value of the attribute *name* (i.e., environment - variable) of the [store derivation]s *paths*. It is an error for a + variable) of the [derivation]s *paths*. It is an error for a derivation to not have the specified attribute. - `--hash` diff --git a/doc/manual/source/command-ref/nix-store/realise.md b/doc/manual/source/command-ref/nix-store/realise.md index a899758dfab..674a9548613 100644 --- a/doc/manual/source/command-ref/nix-store/realise.md +++ b/doc/manual/source/command-ref/nix-store/realise.md @@ -11,10 +11,10 @@ Each of *paths* is processed as follows: -- If the path leads to a [store derivation]: - 1. If it is not [valid], substitute the store derivation file itself. +- If the path leads to a [derivation]: + 1. If it is not [valid], substitute the derivation file itself. 2. Realise its [output paths]: - - Try to fetch from [substituters] the [store objects] associated with the output paths in the store derivation's [closure]. + - Try to fetch from [substituters] the [store objects] associated with the output paths in the derivation's [closure]. - With [content-addressed derivations] (experimental): Determine the output paths to realise by querying content-addressed realisation entries in the [Nix database]. - For any store paths that cannot be substituted, produce the required store objects: @@ -23,11 +23,11 @@ Each of *paths* is processed as follows: - Otherwise, and if the path is not already valid: Try to fetch the associated [store objects] in the path's [closure] from [substituters]. -If no substitutes are available and no store derivation is given, realisation fails. +If no substitutes are available and no derivation is given, realisation fails. [store paths]: @docroot@/store/store-path.md [valid]: @docroot@/glossary.md#gloss-validity -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: @docroot@/glossary.md#gloss-derivation [output paths]: @docroot@/glossary.md#gloss-output-path [store objects]: @docroot@/store/store-object.md [closure]: @docroot@/glossary.md#gloss-closure @@ -71,7 +71,7 @@ For non-derivation arguments, the argument itself is printed. # Examples -This operation is typically used to build [store derivation]s produced by +This operation is typically used to build [derivation]s produced by [`nix-instantiate`](@docroot@/command-ref/nix-instantiate.md): ```console diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index fa357ece3d6..cd7d9e2cc6b 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -21,31 +21,26 @@ - [derivation]{#gloss-derivation} - A description of a build task. The result of a derivation is a - store object. Derivations declared in Nix expressions are specified - using the [`derivation` primitive](./language/derivations.md). These are - translated into low-level *store derivations* (implicitly by - `nix-build`, or explicitly by `nix-instantiate`). + A single build task. + See [Derivation](@docroot@/doc/manual/src/store/drv.md#Derivation) for details. [derivation]: #gloss-derivation -- [store derivation]{#gloss-store-derivation} +- [derivation expression]{#gloss-derivation} - A [derivation] represented as a `.drv` file in the [store]. - It has a [store path], like any [store object]. - It is the [instantiated][instantiate] form of a derivation. + A description of a [derivation] in the Nix language. + The result of a derivation is a store object. + Derivations are typically specified in Nix expressions using the [`derivation` primitive](./language/derivations.md). + These are translated into low-level *derivations* (implicitly by + `nix-env` and `nix-build`, or explicitly by `nix-instantiate`). - Example: `/nix/store/g946hcz4c8mdvq2g8vxx42z51qb71rvp-git-2.38.1.drv` - - See [`nix derivation show`](./command-ref/new-cli/nix3-derivation-show.md) (experimental) for displaying the contents of store derivations. - - [store derivation]: #gloss-store-derivation + [derivation expression]: #gloss-derivation-expression - [instantiate]{#gloss-instantiate}, instantiation - Save an evaluated [derivation] as a [store derivation] in the Nix [store]. + Translate a [derivation expression] into a [derivation]. - See [`nix-instantiate`](./command-ref/nix-instantiate.md), which produces a store derivation from a Nix expression that evaluates to a derivation. + See [`nix-instantiate`](./command-ref/nix-instantiate.md), which produces a derivation from a Nix expression that evaluates to a derivation. [instantiate]: #gloss-instantiate @@ -188,7 +183,7 @@ > > The contents of a `.nix` file form a Nix expression. - Nix expressions specify [derivations][derivation], which are [instantiated][instantiate] into the Nix store as [store derivations][store derivation]. + Nix expressions specify [derivation expressions][derivation expression], which are [instantiated][instantiate] into the Nix store as [derivations][derivation]. These derivations can then be [realised][realise] to produce [outputs][output]. > **Example** @@ -257,7 +252,7 @@ - [deriver]{#gloss-deriver} - The [store derivation] that produced an [output path]. + The [derivation] that produced an [output path]. The deriver for an output path can be queried with the `--deriver` option to [`nix-store --query`](@docroot@/command-ref/nix-store/query.md). diff --git a/doc/manual/source/language/derivations.md b/doc/manual/source/language/derivations.md index 771b2bd9130..58fc8e7065b 100644 --- a/doc/manual/source/language/derivations.md +++ b/doc/manual/source/language/derivations.md @@ -4,9 +4,9 @@ The most important built-in function is `derivation`, which is used to describe a specification for running an executable on precisely defined input files to repeatably produce output files at uniquely determined file system paths. It takes as input an attribute set, the attributes of which specify the inputs to the process. -It outputs an attribute set, and produces a [store derivation] as a side effect of evaluation. +It outputs an attribute set, and produces a [derivation] as a side effect of evaluation. -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: @docroot@/glossary.md#gloss-derivation ## Input attributes @@ -15,7 +15,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect - [`name`]{#attr-name} ([String](@docroot@/language/types.md#type-string)) A symbolic name for the derivation. - It is added to the [store path] of the corresponding [store derivation] as well as to its [output paths](@docroot@/glossary.md#gloss-output-path). + It is added to the [store path] of the corresponding [derivation] as well as to its [output paths](@docroot@/glossary.md#gloss-output-path). [store path]: @docroot@/store/store-path.md @@ -28,7 +28,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect > } > ``` > - > The store derivation's path will be `/nix/store/-hello.drv`. + > The derivation's path will be `/nix/store/-hello.drv`. > The [output](#attr-outputs) paths will be of the form `/nix/store/-hello[-]` - [`system`]{#attr-system} ([String](@docroot@/language/types.md#type-string)) @@ -182,7 +182,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect > } > ``` > - > The store derivation path will be `/nix/store/-example.drv`. + > The derivation path will be `/nix/store/-example.drv`. > The output paths will be > - `/nix/store/-example-lib` > - `/nix/store/-example-dev` diff --git a/doc/manual/source/language/import-from-derivation.md b/doc/manual/source/language/import-from-derivation.md index e901f5bcf5b..bb2ee62de9b 100644 --- a/doc/manual/source/language/import-from-derivation.md +++ b/doc/manual/source/language/import-from-derivation.md @@ -71,9 +71,10 @@ Boxes are data structures, arrow labels are transformations. | evaluate | | | | | | | | | V | | | -| .------------. | | .------------------. | -| | derivation |----|-instantiate-|->| store derivation | | -| '------------' | | '------------------' | +| .------------. | | | +| | derivation | | | .------------. | +| | expression |----|-instantiate-|---->| derivation | | +| '------------' | | '------------' | | | | | | | | | realise | | | | | | diff --git a/doc/manual/source/language/string-interpolation.md b/doc/manual/source/language/string-interpolation.md index 27780dcbb39..562d705f829 100644 --- a/doc/manual/source/language/string-interpolation.md +++ b/doc/manual/source/language/string-interpolation.md @@ -22,7 +22,7 @@ Rather than writing "--with-freetype2-library=" + freetype + "/lib" ``` -(where `freetype` is a [derivation]), you can instead write +(where `freetype` is an [output path]), you can instead write [derivation]: @docroot@/glossary.md#gloss-derivation @@ -148,7 +148,7 @@ An expression that is interpolated must evaluate to one of the following: - `__toString` must be a function that takes the attribute set itself and returns a string - `outPath` must be a string - This includes [derivations](./derivations.md) or [flake inputs](@docroot@/command-ref/new-cli/nix3-flake.md#flake-inputs) (experimental). + This includes [derivation expressions](./derivations.md) or [flake inputs](@docroot@/command-ref/new-cli/nix3-flake.md#flake-inputs) (experimental). A string interpolates to itself. diff --git a/doc/manual/source/protocols/derivation-aterm.md b/doc/manual/source/protocols/derivation-aterm.md index 1ba757ae024..5b2e130dc97 100644 --- a/doc/manual/source/protocols/derivation-aterm.md +++ b/doc/manual/source/protocols/derivation-aterm.md @@ -1,6 +1,6 @@ # Derivation "ATerm" file format -For historical reasons, [derivations](@docroot@/glossary.md#gloss-store-derivation) are stored on-disk in [ATerm](https://homepages.cwi.nl/~daybuild/daily-books/technology/aterm-guide/aterm-guide.html) format. +For historical reasons, [derivations](@docroot@/glossary.md#gloss-derivation) are stored on-disk in [ATerm](https://homepages.cwi.nl/~daybuild/daily-books/technology/aterm-guide/aterm-guide.html) format. Derivations are serialised in one of the following formats: diff --git a/doc/manual/source/release-notes/rl-0.8.md b/doc/manual/source/release-notes/rl-0.8.md index 626c0c92b79..b2b5855682d 100644 --- a/doc/manual/source/release-notes/rl-0.8.md +++ b/doc/manual/source/release-notes/rl-0.8.md @@ -39,29 +39,29 @@ Nix 0.8 has the following improvements: notion of “closure store expressions” is gone (and so is the notion of “successors”); the file system references of a store path are now just stored in the database. - + For instance, given any store path, you can query its closure: - + $ nix-store -qR $(which firefox) ... lots of paths ... - + Also, Nix now remembers for each store path the derivation that built it (the “deriver”): - + $ nix-store -qR $(which firefox) /nix/store/4b0jx7vq80l9aqcnkszxhymsf1ffa5jd-firefox-1.0.1.drv - + So to see the build-time dependencies, you can do - + $ nix-store -qR $(nix-store -qd $(which firefox)) - + or, in a nicer format: - + $ nix-store -q --tree $(nix-store -qd $(which firefox)) - + File system references are also stored in reverse. For instance, you can query all paths that directly or indirectly use a certain Glibc: - + $ nix-store -q --referrers-closure \ /nix/store/8lz9yc6zgmc0vlqmn2ipcpkjlmbi51vv-glibc-2.3.4 @@ -92,28 +92,28 @@ Nix 0.8 has the following improvements: - `nix-channel` has new operations `--list` and `--remove`. - New ways of installing components into user environments: - + - Copy from another user environment: - + $ nix-env -i --from-profile .../other-profile firefox - - - Install a store derivation directly (bypassing the Nix + + - Install a derivation directly (bypassing the Nix expression language entirely): - + $ nix-env -i /nix/store/z58v41v21xd3...-aterm-2.3.1.drv - + (This is used to implement `nix-install-package`, which is therefore immune to evolution in the Nix expression language.) - + - Install an already built store path directly: - + $ nix-env -i /nix/store/hsyj5pbn0d9i...-aterm-2.3.1 - + - Install the result of a Nix expression specified as a command-line argument: - + $ nix-env -f .../i686-linux.nix -i -E 'x: x.firefoxWrapper' - + The difference with the normal installation mode is that `-E` does not use the `name` attributes of derivations. Therefore, this can be used to disambiguate multiple derivations with the @@ -127,7 +127,7 @@ Nix 0.8 has the following improvements: - Implemented a concurrent garbage collector. It is now always safe to run the garbage collector, even if other Nix operations are happening simultaneously. - + However, there can still be GC races if you use `nix-instantiate` and `nix-store --realise` directly to build things. To prevent races, use the @@ -147,13 +147,13 @@ Nix 0.8 has the following improvements: - The behaviour of the garbage collector can be changed globally by setting options in `/nix/etc/nix/nix.conf`. - + - `gc-keep-derivations` specifies whether deriver links should be followed when searching for live paths. - + - `gc-keep-outputs` specifies whether outputs of derivations should be followed when searching for live paths. - + - `env-keep-derivations` specifies whether user environments should store the paths of derivations when they are added (thus keeping the derivations alive). diff --git a/doc/manual/source/release-notes/rl-2.0.md b/doc/manual/source/release-notes/rl-2.0.md index 9f6d4aa8323..40c1874c4cb 100644 --- a/doc/manual/source/release-notes/rl-2.0.md +++ b/doc/manual/source/release-notes/rl-2.0.md @@ -8,13 +8,13 @@ The following incompatible changes have been made: It has been superseded by the binary cache substituter mechanism since several years. As a result, the following programs have been removed: - + - `nix-pull` - + - `nix-generate-patches` - + - `bsdiff` - + - `bspatch` - The “copy from other stores” substituter mechanism @@ -58,26 +58,26 @@ This release has the following new features: `nix-build`, `nix-shell -p`, `nix-env -qa`, `nix-instantiate --eval`, `nix-push` and `nix-copy-closure`. It has the following major features: - + - Unlike the legacy commands, it has a consistent way to refer to packages and package-like arguments (like store paths). For example, the following commands all copy the GNU Hello package to a remote machine: - + nix copy --to ssh://machine nixpkgs.hello - + nix copy --to ssh://machine /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10 - + nix copy --to ssh://machine '(with import {}; hello)' - + By contrast, `nix-copy-closure` only accepted store paths as arguments. - + - It is self-documenting: `--help` shows all available command-line arguments. If `--help` is given after a subcommand, it shows examples for that subcommand. `nix --help-config` shows all configuration options. - + - It is much less verbose. By default, it displays a single-line progress indicator that shows how many packages are left to be built or downloaded, and (if there are running builds) the most @@ -85,7 +85,7 @@ This release has the following new features: last few lines of builder output. The full build log can be retrieved using `nix log`. - + - It [provides](https://github.com/NixOS/nix/commit/b8283773bd64d7da6859ed520ee19867742a03ba) all `nix.conf` configuration options as command line flags. For @@ -93,122 +93,122 @@ This release has the following new features: http-connections 100` you can write `--http-connections 100`. Boolean options can be written as `--foo` or `--no-foo` (e.g. `--no-auto-optimise-store`). - + - Many subcommands have a `--json` flag to write results to stdout in JSON format. - + > **Warning** - > + > > Please note that the `nix` command is a work in progress and the > interface is subject to change. - + It provides the following high-level (“porcelain”) subcommands: - + - `nix build` is a replacement for `nix-build`. - + - `nix run` executes a command in an environment in which the specified packages are available. It is (roughly) a replacement for `nix-shell -p`. Unlike that command, it does not execute the command in a shell, and has a flag (`-c`) that specifies the unquoted command line to be executed. - + It is particularly useful in conjunction with chroot stores, allowing Linux users who do not have permission to install Nix in `/nix/store` to still use binary substitutes that assume `/nix/store`. For example, - + nix run --store ~/my-nix nixpkgs.hello -c hello --greeting 'Hi everybody!' - + downloads (or if not substitutes are available, builds) the GNU Hello package into `~/my-nix/nix/store`, then runs `hello` in a mount namespace where `~/my-nix/nix/store` is mounted onto `/nix/store`. - + - `nix search` replaces `nix-env -qa`. It searches the available packages for occurrences of a search string in the attribute name, package name or description. Unlike `nix-env -qa`, it has a cache to speed up subsequent searches. - + - `nix copy` copies paths between arbitrary Nix stores, generalising `nix-copy-closure` and `nix-push`. - + - `nix repl` replaces the external program `nix-repl`. It provides an interactive environment for evaluating and building Nix expressions. Note that it uses `linenoise-ng` instead of GNU Readline. - + - `nix upgrade-nix` upgrades Nix to the latest stable version. This requires that Nix is installed in a profile. (Thus it won’t work on NixOS, or if it’s installed outside of the Nix store.) - + - `nix verify` checks whether store paths are unmodified and/or “trusted” (see below). It replaces `nix-store --verify` and `nix-store --verify-path`. - + - `nix log` shows the build log of a package or path. If the build log is not available locally, it will try to obtain it from the configured substituters (such as [cache.nixos.org](https://cache.nixos.org/), which now provides build logs). - + - `nix edit` opens the source code of a package in your editor. - + - `nix eval` replaces `nix-instantiate --eval`. - + - `nix why-depends` shows why one store path has another in its closure. This is primarily useful to finding the causes of closure bloat. For example, - + nix why-depends nixpkgs.vlc nixpkgs.libdrm.dev - + shows a chain of files and fragments of file contents that cause the VLC package to have the “dev” output of `libdrm` in its closure — an undesirable situation. - + - `nix path-info` shows information about store paths, replacing `nix-store -q`. A useful feature is the option `--closure-size` (`-S`). For example, the following command show the closure sizes of every path in the current NixOS system closure, sorted by size: - + nix path-info -rS /run/current-system | sort -nk2 - + - `nix optimise-store` replaces `nix-store --optimise`. The main difference is that it has a progress indicator. - + A number of low-level (“plumbing”) commands are also available: - + - `nix ls-store` and `nix ls-nar` list the contents of a store path or NAR file. The former is primarily useful in conjunction with remote stores, e.g. - + nix ls-store --store https://cache.nixos.org/ -lR /nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10 - + lists the contents of path in a binary cache. - + - `nix cat-store` and `nix cat-nar` allow extracting a file from a store path or NAR file. - + - `nix dump-path` writes the contents of a store path to stdout in NAR format. This replaces `nix-store --dump`. - + - `nix - show-derivation` displays a store derivation in JSON format. + show-derivation` displays a derivation in JSON format. This is an alternative to `pp-aterm`. - + - `nix add-to-store` replaces `nix-store --add`. - + - `nix sign-paths` signs store paths. - + - `nix copy-sigs` copies signatures from one store to another. - + - `nix show-config` shows all configuration options and their current values. @@ -224,11 +224,11 @@ This release has the following new features: `nix-copy-closure`, `nix-push` and substitution are all instances of the general notion of copying paths between different kinds of Nix stores. - + Stores are specified using an URI-like syntax, e.g. or . The following store types are supported: - + - `LocalStore` (stori URI `local` or an absolute path) and the misnamed `RemoteStore` (`daemon`) provide access to a local Nix store, the latter via the Nix daemon. You can use `auto` or the @@ -236,63 +236,63 @@ This release has the following new features: whether you have write permission to the Nix store. It is no longer necessary to set the `NIX_REMOTE` environment variable to use the Nix daemon. - + As noted above, `LocalStore` now supports chroot builds, allowing the “physical” location of the Nix store (e.g. `/home/alice/nix/store`) to differ from its “logical” location (typically `/nix/store`). This allows non-root users to use Nix while still getting the benefits from prebuilt binaries from [cache.nixos.org](https://cache.nixos.org/). - + - `BinaryCacheStore` is the abstract superclass of all binary cache stores. It supports writing build logs and NAR content listings in JSON format. - + - `HttpBinaryCacheStore` (`http://`, `https://`) supports binary caches via HTTP or HTTPS. If the server supports `PUT` requests, it supports uploading store paths via commands such as `nix copy`. - + - `LocalBinaryCacheStore` (`file://`) supports binary caches in the local filesystem. - + - `S3BinaryCacheStore` (`s3://`) supports binary caches stored in Amazon S3, if enabled at compile time. - + - `LegacySSHStore` (`ssh://`) is used to implement remote builds and `nix-copy-closure`. - + - `SSHStore` (`ssh-ng://`) supports arbitrary Nix operations on a remote machine via the same protocol used by `nix-daemon`. - Security has been improved in various ways: - + - Nix now stores signatures for local store paths. When paths are copied between stores (e.g., copied from a binary cache to a local store), signatures are propagated. - + Locally-built paths are signed automatically using the secret keys specified by the `secret-key-files` store option. Secret/public key pairs can be generated using `nix-store --generate-binary-cache-key`. - + In addition, locally-built store paths are marked as “ultimately trusted”, but this bit is not propagated when paths are copied between stores. - + - Content-addressable store paths no longer require signatures — they can be imported into a store by unprivileged users even if they lack signatures. - + - The command `nix verify` checks whether the specified paths are trusted, i.e., have a certain number of trusted signatures, are ultimately trusted, or are content-addressed. - + - Substitutions from binary caches [now](https://github.com/NixOS/nix/commit/ecbc3fedd3d5bdc5a0e1a0a51b29062f2874ac8b) require signatures by default. This was already the case on NixOS. - + - In Linux sandbox builds, we [now](https://github.com/NixOS/nix/commit/eba840c8a13b465ace90172ff76a0db2899ab11b) use `/build` instead of `/tmp` as the temporary build directory. @@ -309,7 +309,7 @@ This release has the following new features: hash or commit hash is specified. For example, calls to `builtins.fetchGit` are only allowed if a `rev` attribute is specified. - + The goal of this feature is to enable true reproducibility and traceability of builds (including NixOS system configurations) at the evaluation level. For example, in the future, `nixos-rebuild` @@ -367,21 +367,21 @@ This release has the following new features: log will be shown if a build fails. - Networking has been improved: - + - HTTP/2 is now supported. This makes binary cache lookups [much more efficient](https://github.com/NixOS/nix/commit/90ad02bf626b885a5dd8967894e2eafc953bdf92). - + - We now retry downloads on many HTTP errors, making binary caches substituters more resilient to temporary failures. - + - HTTP credentials can now be configured via the standard `netrc` mechanism. - + - If S3 support is enabled at compile time, URIs are [supported](https://github.com/NixOS/nix/commit/9ff9c3f2f80ba4108e9c945bbfda2c64735f987b) in all places where Nix allows URIs. - + - Brotli compression is now supported. In particular, [cache.nixos.org](https://cache.nixos.org/) build logs are now compressed using Brotli. @@ -431,9 +431,9 @@ The Nix language has the following new features: - Derivation attributes can now reference the outputs of the derivation using the `placeholder` builtin function. For example, the attribute - + configureFlags = "--prefix=${placeholder "out"} --includedir=${placeholder "dev"}"; - + will cause the `configureFlags` environment variable to contain the actual store paths corresponding to the `out` and `dev` outputs. @@ -444,7 +444,7 @@ The following builtin functions are new or extended: Nixpkgs, which fetches at build time and cannot be used to fetch Nix expressions during evaluation. A typical use case is to import external NixOS modules from your configuration, e.g. - + imports = [ (builtins.fetchGit https://github.com/edolstra/dwarffs + "/module.nix") ]; - Similarly, `builtins.fetchMercurial` allows you to fetch Mercurial @@ -485,7 +485,7 @@ The Nix build environment has the following changes: builder via the file `.attrs.json` in the builder’s temporary directory. This obviates the need for `passAsFile` since JSON files have no size restrictions, unlike process environments. - + [As a convenience to Bash builders](https://github.com/NixOS/nix/commit/2d5b1b24bf70a498e4c0b378704cfdb6471cc699), Nix writes a script named `.attrs.sh` to the builder’s directory diff --git a/doc/manual/source/release-notes/rl-2.13.md b/doc/manual/source/release-notes/rl-2.13.md index 168708113ea..4822803989b 100644 --- a/doc/manual/source/release-notes/rl-2.13.md +++ b/doc/manual/source/release-notes/rl-2.13.md @@ -22,7 +22,7 @@ accurate error locations. A short excerpt of the trace is now shown by default when an error occurs. -* Allow explicitly selecting outputs in a store derivation installable, just like we can do with other sorts of installables. +* Allow explicitly selecting outputs in a derivation installable, just like we can do with other sorts of installables. For example, ```shell-session # nix build /nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^dev diff --git a/doc/manual/source/release-notes/rl-2.15.md b/doc/manual/source/release-notes/rl-2.15.md index e7e52631ba4..428b1823fe4 100644 --- a/doc/manual/source/release-notes/rl-2.15.md +++ b/doc/manual/source/release-notes/rl-2.15.md @@ -11,7 +11,7 @@ As the choice of hash formats is no longer binary, the `--base16` flag is also added to explicitly specify the Base16 format, which is still the default. -* The special handling of an [installable](../command-ref/new-cli/nix.md#installables) with `.drv` suffix being interpreted as all of the given [store derivation](@docroot@/glossary.md#gloss-store-derivation)'s output paths is removed, and instead taken as the literal store path that it represents. +* The special handling of an [installable](../command-ref/new-cli/nix.md#installables) with `.drv` suffix being interpreted as all of the given [derivation](@docroot@/glossary.md#gloss-derivation)'s output paths is removed, and instead taken as the literal store path that it represents. The new `^` syntax for store paths introduced in Nix 2.13 allows explicitly referencing output paths of a derivation. Using this is better and more clear than relying on the now-removed `.drv` special handling. diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md new file mode 100644 index 00000000000..08d8117e188 --- /dev/null +++ b/doc/manual/source/store/drv.md @@ -0,0 +1,172 @@ +# Derivation and Deriving Path + +So far, we have covered "inert" store objects. +But the point of the Nix store layer is to be a build system. +Other system (like Git or IPFS) also store and transfer immutable data, but they don't concern themselves with *how* that data was created. + +This is where Nix distinguishes itself. +*Derivations* represent individual build steps, and *deriving paths* are needed to to the *outputs* of those build steps. +The two concepts need to be introduced together because, as described below, each depends on the other. + +## Derivation + +What is natural Unix analog for a build step *in action*? +Answer: a process that will eventually exit, leaving behind some output date. +What is the natural way to *plan* such a step? +An `execve` system call. + +A derivation consists of: + + - A (base) name + + - A set of *outputs*, consisting of names and possibly other data + + - A set of *inputs*, a set of deriving paths + + - Everything needed for an `execve` system call: + 1. Path to executable + 2. A list of arguments (except for `argv[0]`, which is taken from the path in the usual way) + 3. A set of environment variables. + + - A two-component "system" name (e.g. `x86_64-linux`) where the executable is to run. + +The path and list/set elements of the other two will presumably consist wholly or partly of store paths. +But just as we stored the references contained in the file data separately for store objects, so we store the set of inputs separately. + +The last bit of information is to take advantage of the fact that Nix allows *heterogenous* build plans, were not all steps can be run on the same machine or same sort of machine. + +The process's job is to produce the outputs, but have no other important side effects. +The rules around this will be discussed in following sections. + +### Output name + +Most outputs are named `drv.name + '-' + outputName`. +However, an output named "out" is just has name `drv.name`. +This is to allow derivations with a single output to avoid a superfluous `-` in their single output's name when no disambiguation is needed. + +### Placeholder + +TODO + +### Referencing + +Derivations are always referred to by the store path of the store object they are encoded to. +The store path name is the derivation name with `.drv` suffixed at the end. +The store path digest we will explain in a following section after we go over the different variants of derivations, as the exact algorithm depends on them. +Suffice to say for now, it is (a form of) content addressing based on the derivation and its inputs. + +## Deriving path + +Deriving references are close to their abstract version, but using `StorePath` as the type of all references, matching the end of the previous subsection. + +In pseudo code: + +```idris +type OutputName = String + +data DerivingPath + = ConstantPath { path : StorePath } + | Output { + drv : StorePath, + output : OutputName, + } +``` + +## Encoding + +### Derivation + +- The name is not encoded, because we can just get it from the store object! + +:::{.note} +Brief amusing history of PP-ATerm +::: + +#### `inputSrcs` vs `inputDrvs` + +### Deriving Path + +Constant deriving paths are encoded simply as the underlying store path is. +Thus, we see that every encoded store path is also a valid encoded (constant) deriving path. + +Output deriving paths are encoded by + +- encoding of a store path referring to a derivation + +- a separator (`^` or `!` depending on context) + +- the name of an output + +An example would be: + +``` +/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out +``` + +This parses like so: + +``` +/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out +|------------------------------------------------------------| |-| +store path (usual encoding) output name + |--| + note the ".drv" +``` + +## Extending the model to be higher-order + +**Experimental feature**: [`dynamic-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations) + +We can apply the same extension discussed for the abstract model to the concrete model. +Again, only the data type for Deriving Paths needs to be modified. +Derivations are the same except for using the new extended deriving path data type. + +```idris +type OutputName = String + +data DerivingPath + = ConstantPath { storeObj : StorePath } + | Output { + drv : DerivingPath, -- changed + output : OutputName, + } +``` + +Now, the `drv` field of `BuiltObject` is itself a `DerivingPath` instead of an `StorePath`. + +Under this extended model, `DerivingPath`s are thus inductively built up from an `ConstantPath`, contains in 0 or more outer `Outputs`. + +### Encoding + +The encoding is adjusted in a very simplest way, merely displaying the same + +``` +/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^foo.drv^bar.drv^out +|----------------------------------------------------------------------------| |-| +inner deriving path (usual encoding) output name +|--------------------------------------------------------------------| |-----| +even more inner deriving path (usual encoding) output name +|------------------------------------------------------------| |-----| +innermost constant store path (usual encoding) output name +``` + +## Extra extensions + +### `__structuredAttrs` + +Historically speaking, most users of Nix made GNU Bash with a script the command run, regardless of what they were doing. +Bash variable are automatically created from env vars, but bash also supports array and string-keyed map variables in addition to string variables. +People also usually create derivations using language which also support these richer data types. +It was thus desired a way to get this data from the language "planning" the derivation to language to bash, the language evaluated at "run time". + +`__structuredAttrs` does this by smuggling inside the core derivation format a map of named richer data. +At run time, this becomes two things: + +1. A JSON file containing that map. +2. A bash script setting those variables. + +The bash command can be passed a script which will "source" that Nix-created bash script, setting those variables with the richer data. +The outer script can then do whatever it likes with those richer variables as input. + +However, since derivations can already contain arbitary input sources, the vast majority of `__structuredAttrs` can be handled by upper layers. +We might consider implementing `__structuredAttrs` in higher layers in the future, and simplifying the store layer. diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 1a4c76ec5be..0be51d38669 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -144,7 +144,7 @@ MixOperateOnOptions::MixOperateOnOptions() addFlag({ .longName = "derivation", .description = - "Operate on the [store derivation](@docroot@/glossary.md#gloss-store-derivation) rather than its outputs.", + "Operate on the [derivation](@docroot@/glossary.md#gloss-derivation) rather than its outputs.", .category = installablesCategory, .handler = {&operateOn, OperateOn::Derivation}, }); diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index bf5759230f3..7604c1de7b7 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -24,7 +24,7 @@ enum class Realise { /** * Don't build the derivation. * - * Postcondition: the store derivation exists. + * Postcondition: the derivation exists. */ Derivation, /** diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index ea3319f9939..20e8abba2f9 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -777,7 +777,7 @@ StorePath AttrCursor::forceDerivation() been garbage-collected. So force it to be regenerated. */ aDrvPath->forceValue(); if (!root->state.store->isValidPath(drvPath)) - throw Error("don't know how to recreate store derivation '%s'!", + throw Error("don't know how to recreate derivation '%s'!", root->state.store->printStorePath(drvPath)); } return drvPath; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 45d9f86ac05..ea9090fc6a1 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1505,7 +1505,7 @@ static void derivationStrictInternal( } else { - /* Compute a hash over the "masked" store derivation, which is + /* Compute a hash over the "masked" derivation, which is the final one except that in the list of outputs, the output paths are empty strings, and the corresponding environment variables have an empty value. This ensures @@ -1551,7 +1551,7 @@ static void derivationStrictInternal( printMsg(lvlChatty, "instantiated '%1%' -> '%2%'", drvName, drvPathS); /* Optimisation, but required in read-only mode! because in that - case we don't actually write store derivations, so we can't + case we don't actually write derivations, so we can't read them later. */ { auto h = hashDerivationModulo(*state.store, drv, false); diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc index 02683b173aa..50850e187e5 100644 --- a/src/libexpr/primops/context.cc +++ b/src/libexpr/primops/context.cc @@ -236,7 +236,7 @@ static RegisterPrimOp primop_getContext({ Return the string context of *s*. The string context tracks references to derivations within a string. - It is represented as an attribute set of [store derivation](@docroot@/glossary.md#gloss-store-derivation) paths mapping to output names. + It is represented as an attribute set of [derivation](@docroot@/glossary.md#gloss-derivation) paths mapping to output names. Using [string interpolation](@docroot@/language/string-interpolation.md) on a derivation will add that derivation to the string context. For example, diff --git a/src/nix/derivation-add.cc b/src/nix/derivation-add.cc index 4d91d453800..720b54b84eb 100644 --- a/src/nix/derivation-add.cc +++ b/src/nix/derivation-add.cc @@ -14,7 +14,7 @@ struct CmdAddDerivation : MixDryRun, StoreCommand { std::string description() override { - return "Add a store derivation"; + return "Add a derivation"; } std::string doc() override diff --git a/src/nix/derivation-add.md b/src/nix/derivation-add.md index 35507d9ad46..8c4fa732a05 100644 --- a/src/nix/derivation-add.md +++ b/src/nix/derivation-add.md @@ -3,17 +3,16 @@ R""( # Description This command reads from standard input a JSON representation of a -[store derivation]. +[derivation]. Store derivations are used internally by Nix. They are store paths with extension `.drv` that represent the build-time dependency graph to which a Nix expression evaluates. - -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: @docroot@/glossary.md#gloss-derivation `nix derivation add` takes a single derivation in the following format: -{{#include ../../protocols/json/derivation.md}} +{{#include @docroot@/protocols/json/derivation.md}} )"" diff --git a/src/nix/derivation-show.cc b/src/nix/derivation-show.cc index bf637246d83..3e5ed4f1302 100644 --- a/src/nix/derivation-show.cc +++ b/src/nix/derivation-show.cc @@ -1,5 +1,4 @@ -// FIXME: integrate this with nix path-info? -// FIXME: rename to 'nix store derivation show' or 'nix debug derivation show'? +// FIXME: integrate this with `nix path-info`? #include "command.hh" #include "common-args.hh" @@ -27,7 +26,7 @@ struct CmdShowDerivation : InstallablesCommand std::string description() override { - return "show the contents of a store derivation"; + return "show the contents of a derivation"; } std::string doc() override diff --git a/src/nix/derivation-show.md b/src/nix/derivation-show.md index 9fff58ef97a..830771e46e7 100644 --- a/src/nix/derivation-show.md +++ b/src/nix/derivation-show.md @@ -2,7 +2,7 @@ R""( # Examples -* Show the [store derivation] that results from evaluating the Hello +* Show the [derivation] that results from evaluating the Hello package: ```console @@ -37,7 +37,7 @@ R""( # Description This command prints on standard output a JSON representation of the -[store derivation]s to which [*installables*](./nix.md#installables) evaluate. +[derivation]s to which [*installables*](./nix.md#installables) evaluate. Store derivations are used internally by Nix. They are store paths with extension `.drv` that represent the build-time dependency graph to which @@ -46,7 +46,7 @@ a Nix expression evaluates. By default, this command only shows top-level derivations, but with `--recursive`, it also shows their dependencies. -[store derivation]: @docroot@/glossary.md#gloss-store-derivation +[derivation]: ../../glossary.md#gloss-derivation `nix derivation show` outputs a JSON map of [store path]s to derivations in the following format: diff --git a/src/nix/nix.md b/src/nix/nix.md index b88bd9a949a..5c26d8a6cc5 100644 --- a/src/nix/nix.md +++ b/src/nix/nix.md @@ -144,11 +144,11 @@ Example: `/nix/store/v5sv61sszx301i0x6xysaqzla09nksnd-hello-2.10` These are paths inside the Nix store, or symlinks that resolve to a path in the Nix store. -A [store derivation] is also addressed by store path. +A [derivation] is also addressed by store path. Example: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv` -If you want to refer to an output path of that store derivation, add the output name preceded by a caret (`^`). +If you want to refer to an output path of that derivation, add the output name preceded by a caret (`^`). Example: `/nix/store/p7gp6lxdg32h4ka1q398wd9r2zkbbz2v-hello-2.10.drv^out` @@ -244,10 +244,10 @@ operate are determined as follows: a command like `nix shell nixpkgs#libxml2` will provide only those two outputs by default. - Note that a [store derivation] (given by its `.drv` file store path) doesn't have + Note that a [derivation] (given by its `.drv` file store path) doesn't have any attributes like `meta`, and thus this case doesn't apply to it. - [store derivation]: @docroot@/glossary.md#gloss-store-derivation + [derivation]: @docroot@/glossary.md#gloss-derivation * Otherwise, Nix will use all outputs of the derivation. diff --git a/src/nix/path-info.md b/src/nix/path-info.md index 2e39225b865..b241626d3bd 100644 --- a/src/nix/path-info.md +++ b/src/nix/path-info.md @@ -68,9 +68,9 @@ R""( ] ``` -* Print the path of the [store derivation] produced by `nixpkgs#hello`: +* Print the path of the [derivation] produced by `nixpkgs#hello`: - [store derivation]: @docroot@/glossary.md#gloss-store-derivation + [derivation]: @docroot@/glossary.md#gloss-derivation ```console # nix path-info --derivation nixpkgs#hello diff --git a/src/nix/search.md b/src/nix/search.md index f65ac9b1748..d355a7764dc 100644 --- a/src/nix/search.md +++ b/src/nix/search.md @@ -62,8 +62,8 @@ R""( # Description -`nix search` searches [*installable*](./nix.md#installables) (which can be evaluated, that is, a -flake or Nix expression, but not a store path or store derivation path) for packages whose name or description matches all of the +`nix search` searches [*installable*](./nix.md#installables) that can be evaluated, that is, a +flake or Nix expression, but not a [store path] or [deriving path]) for packages whose name or description matches all of the regular expressions *regex*. For each matching package, It prints the full attribute name (from the root of the [installable](./nix.md#installables)), the version and the `meta.description` field, highlighting the substrings that @@ -75,6 +75,9 @@ it avoids highlighting the entire name and description of every package. > Note that in this context, `^` is the regex character to match the beginning of a string, *not* the delimiter for > [selecting a derivation output](@docroot@/command-ref/new-cli/nix.md#derivation-output-selection). +[store path]: @docroot@/glossary.md#gloss-store-path +[deriving path]: @docroot@/glossary.md#gloss-deriving-path + # Flake output attributes If no flake output attribute is given, `nix search` searches for diff --git a/src/nix/store-copy-log.md b/src/nix/store-copy-log.md index 61daa75c178..e8527fe7320 100644 --- a/src/nix/store-copy-log.md +++ b/src/nix/store-copy-log.md @@ -18,9 +18,9 @@ R""( (The flag `--substituters ''` avoids querying `https://cache.nixos.org` for the log.) -* To copy the log for a specific [store derivation] via SSH: +* To copy the log for a specific [derivation] via SSH: - [store derivation]: @docroot@/glossary.md#gloss-store-derivation + [derivation]: @docroot@/glossary.md#gloss--derivation ```console # nix store copy-log --to ssh-ng://machine /nix/store/ilgm50plpmcgjhcp33z6n4qbnpqfhxym-glibc-2.33-59.drv From 5eeae8357815b5361405175dd129b0d7fc025048 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 17 Nov 2024 21:49:29 -0500 Subject: [PATCH 02/21] WIP --- doc/manual/source/glossary.md | 11 ++---- doc/manual/source/store/drv.md | 68 ++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index cd7d9e2cc6b..4e4b9083e9e 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -22,7 +22,7 @@ - [derivation]{#gloss-derivation} A single build task. - See [Derivation](@docroot@/doc/manual/src/store/drv.md#Derivation) for details. + See [Derivation](@docroot@/doc/manual/src/store/drv.md#derivation) for details. [derivation]: #gloss-derivation @@ -241,14 +241,9 @@ - [deriving path]{#gloss-deriving-path} - Deriving paths are a way to refer to [store objects][store object] that ar not yet [realised][realise]. - This is necessary because, in general and particularly for [content-addressed derivations][content-addressed derivation], the [output path] of an [output] is not known in advance. - There are two forms: + Deriving paths are a way to refer to [store objects][store object] that might not be yet [realised][realise]. - - *constant*: just a [store path] - It can be made [valid][validity] by copying it into the store: from the evaluator, command line interface or another store. - - - *output*: a pair of a [store path] to a [derivation] and an [output] name. + See [Deriving Path](./store/drv.md#deriving-path) for details. - [deriver]{#gloss-deriver} diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 08d8117e188..35e39fe04d4 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -8,7 +8,7 @@ This is where Nix distinguishes itself. *Derivations* represent individual build steps, and *deriving paths* are needed to to the *outputs* of those build steps. The two concepts need to be introduced together because, as described below, each depends on the other. -## Derivation +## [Derivation]{#derivation} What is natural Unix analog for a build step *in action*? Answer: a process that will eventually exit, leaving behind some output date. @@ -55,9 +55,16 @@ The store path name is the derivation name with `.drv` suffixed at the end. The store path digest we will explain in a following section after we go over the different variants of derivations, as the exact algorithm depends on them. Suffice to say for now, it is (a form of) content addressing based on the derivation and its inputs. -## Deriving path +## [Deriving path]{#deriving-path} -Deriving references are close to their abstract version, but using `StorePath` as the type of all references, matching the end of the previous subsection. +Deriving paths are a way to refer to [store objects][store object] that might not yet be [realised][realise]. +This is necessary because, in general and particularly for [content-addressed derivations][content-addressed derivation], the [store path] of an [output] is not known in advance. +There are two forms: + +- *constant*: just a [store path] + It can be made [valid][validity] by copying it into the store: from the evaluator, command line interface or another st ore. + +- *output*: a pair of a [store path] to a [derivation] and an [output] name. In pseudo code: @@ -72,46 +79,53 @@ data DerivingPath } ``` +[content-addressed derivation]: @docroot@/glossary.md#gloss-content-addressed-derivation +[realise]: @docroot@/glossary.md#gloss-realise +[store object]: @docroot@/store/store-object.md +[store path]: @docroot@/store/store-path.md + ## Encoding ### Derivation -- The name is not encoded, because we can just get it from the store object! +There are two formats, documented separately: -:::{.note} -Brief amusing history of PP-ATerm -::: +- The legacy [ATerm" format](protocols/derivation-aterm.md) -#### `inputSrcs` vs `inputDrvs` +- The modern [JSON format](source/protocols/json/derivation.md) ### Deriving Path -Constant deriving paths are encoded simply as the underlying store path is. -Thus, we see that every encoded store path is also a valid encoded (constant) deriving path. - -Output deriving paths are encoded by +- *constant* -- encoding of a store path referring to a derivation + Constant deriving paths are encoded simply as the underlying store path is. + Thus, we see that every encoded store path is also a valid encoded (constant) deriving path. -- a separator (`^` or `!` depending on context) +- *output* -- the name of an output + Output deriving paths are encoded by -An example would be: + - encoding of a store path referring to a derivation -``` -/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out -``` + - a separator (`^` or `!` depending on context) -This parses like so: + - the name of an output -``` -/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out -|------------------------------------------------------------| |-| -store path (usual encoding) output name - |--| - note the ".drv" -``` + > **Example** + > + > ``` + > /nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out + > ``` + > + > This parses like so: + > + > ``` + > /nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^out + > |------------------------------------------------------------| |-| + > store path (usual encoding) output name + > |--| + > note the ".drv" + > ``` ## Extending the model to be higher-order From 192616176d4303eab75f18ec5d87158024d9e865 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 17 Nov 2024 21:51:34 -0500 Subject: [PATCH 03/21] Small tweak --- doc/manual/source/store/drv.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 35e39fe04d4..0c0736f87fb 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -21,7 +21,7 @@ A derivation consists of: - A set of *outputs*, consisting of names and possibly other data - - A set of *inputs*, a set of deriving paths + - A set of *inputs*, a set of [deriving paths](#deriving-path) - Everything needed for an `execve` system call: 1. Path to executable @@ -74,8 +74,8 @@ type OutputName = String data DerivingPath = ConstantPath { path : StorePath } | Output { - drv : StorePath, - output : OutputName, + drvPath : StorePath, + output : OutputName, } ``` @@ -141,7 +141,7 @@ type OutputName = String data DerivingPath = ConstantPath { storeObj : StorePath } | Output { - drv : DerivingPath, -- changed + drv : DerivingPath, -- Note: changed output : OutputName, } ``` From a8b1e3f20241c4e9f25a4e73b6417dfe9caad74b Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 17 Nov 2024 22:21:34 -0500 Subject: [PATCH 04/21] WIP moving info from `builtins.derivation` docs --- doc/manual/source/language/derivations.md | 20 +++--- doc/manual/source/store/drv.md | 83 ++++++++++++++++++++--- 2 files changed, 82 insertions(+), 21 deletions(-) diff --git a/doc/manual/source/language/derivations.md b/doc/manual/source/language/derivations.md index 58fc8e7065b..fb3c40b7274 100644 --- a/doc/manual/source/language/derivations.md +++ b/doc/manual/source/language/derivations.md @@ -1,9 +1,10 @@ # Derivations -The most important built-in function is `derivation`, which is used to describe a single derivation: -a specification for running an executable on precisely defined input files to repeatably produce output files at uniquely determined file system paths. +The most important built-in function is `derivation`, which is used to describe a single store-layer [derivation]. +Consult the [store chapter](@docroot@/store/drv.md) for what a derivation is; +this section just concerns how to create one from the Nix language. -It takes as input an attribute set, the attributes of which specify the inputs to the process. +This builtin function takes as input an attribute set, the attributes of which specify the inputs to the process. It outputs an attribute set, and produces a [derivation] as a side effect of evaluation. [derivation]: @docroot@/glossary.md#gloss-derivation @@ -15,7 +16,7 @@ It outputs an attribute set, and produces a [derivation] as a side effect of eva - [`name`]{#attr-name} ([String](@docroot@/language/types.md#type-string)) A symbolic name for the derivation. - It is added to the [store path] of the corresponding [derivation] as well as to its [output paths](@docroot@/glossary.md#gloss-output-path). + See [derivation outputs](@docroot@/store/drv.md#outputs) for what this is affects. [store path]: @docroot@/store/store-path.md @@ -33,12 +34,7 @@ It outputs an attribute set, and produces a [derivation] as a side effect of eva - [`system`]{#attr-system} ([String](@docroot@/language/types.md#type-string)) - The system type on which the [`builder`](#attr-builder) executable is meant to be run. - - A necessary condition for Nix to build derivations locally is that the `system` attribute matches the current [`system` configuration option]. - It can automatically [build on other platforms](@docroot@/language/derivations.md#attr-builder) by forwarding build requests to other machines. - - [`system` configuration option]: @docroot@/command-ref/conf-file.md#conf-system + See [system](@docroot@/store/drv.md#system). > **Example** > @@ -68,7 +64,7 @@ It outputs an attribute set, and produces a [derivation] as a side effect of eva - [`builder`]{#attr-builder} ([Path](@docroot@/language/types.md#type-path) | [String](@docroot@/language/types.md#type-string)) - Path to an executable that will perform the build. + See [builder](@docroot@/store/drv.md#builder). > **Example** > @@ -117,7 +113,7 @@ It outputs an attribute set, and produces a [derivation] as a side effect of eva Default: `[ ]` - Command-line arguments to be passed to the [`builder`](#attr-builder) executable. + See [args](@docroot@/store/drv.md#args). > **Example** > diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 0c0736f87fb..a59a9c8d4f2 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -1,6 +1,6 @@ # Derivation and Deriving Path -So far, we have covered "inert" store objects. +So far, we have covered "inert" [store objects][store object]. But the point of the Nix store layer is to be a build system. Other system (like Git or IPFS) also store and transfer immutable data, but they don't concern themselves with *how* that data was created. @@ -10,6 +10,8 @@ The two concepts need to be introduced together because, as described below, eac ## [Derivation]{#derivation} +A derivation is a specification for running an executable on precisely defined input files to repeatably produce output files at uniquely determined file system paths. + What is natural Unix analog for a build step *in action*? Answer: a process that will eventually exit, leaving behind some output date. What is the natural way to *plan* such a step? @@ -38,22 +40,85 @@ The last bit of information is to take advantage of the fact that Nix allows *he The process's job is to produce the outputs, but have no other important side effects. The rules around this will be discussed in following sections. -### Output name +### Referencing + +Derivations are always referred to by the store path of the store object they are encoded to. +The store path name is the derivation name with `.drv` suffixed at the end. +The store path digest we will explain in a following section after we go over the different variants of derivations, as the exact algorithm depends on them. +Suffice to say for now, it is (a form of) content addressing based on the derivation and its inputs. + +> NOTE: +> Actually we have defined "text addressing" already in "content-addressing store objects". +> Note that we reserve the right to format new sorts of derivations on-disk differently in the future. +> The choice of "text hashing" should be deemd arbitrary along with the choice of "ATerm" serialization. +> Maybe this should be moved below to "encoding?". -Most outputs are named `drv.name + '-' + outputName`. -However, an output named "out" is just has name `drv.name`. +### Outputs {#outputs} + +The outputs are the derivations are the store objects it is obligated to produce. + +Outputs are assigned names, and also consistent of other information based on the type of derivation. + +Output names can be any string which is also a valid [store path] name. +The store path of the output store object (also called an [output path] for short), has a name based on the derivation name and the output name. +Most outputs are named `drvMame + '-' + outputName`. +However, an output named "out" is just has name `drvName`. This is to allow derivations with a single output to avoid a superfluous `-` in their single output's name when no disambiguation is needed. +> **Example** +> +> A derivation is named `hello`, and has two outputs, `out`, and `dev` +> +> - The derivation's path will be: `/nix/store/-hello.drv`. +> +> - The store path of `out` will be: `/nix/store/-hello`. +> +> - The store path of `dev` will be: `/nix/store/-hello-dev`. + +### System {#system} + +The system type on which the [`builder`](#attr-builder) executable is meant to be run. + +A necessary condition for Nix to build derivations locally is that the `system` attribute matches the current [`system` configuration option]. +It can automatically [build on other platforms](@docroot@/language/derivations.md#attr-builder) by forwarding build requests to other machines. + +[`system` configuration option]: @docroot@/command-ref/conf-file.md#conf-system + + +### Builder {#builder} + +Path to an executable that will perform the build. + +### Args {#args} + +Command-line arguments to be passed to the [`builder`](#builder) executable. + +### Environment Variables {#env} + +Environment variables which will be passed to the [`builder`](#builder) executable. + ### Placeholder TODO -### Referencing +Two types: -Derivations are always referred to by the store path of the store object they are encoded to. -The store path name is the derivation name with `.drv` suffixed at the end. -The store path digest we will explain in a following section after we go over the different variants of derivations, as the exact algorithm depends on them. -Suffice to say for now, it is (a form of) content addressing based on the derivation and its inputs. +- Reference to own outputs + +- output derived paths (see below), corresponding to store paths we haven't yet realized. + +> N.B. Current method of creating hashes which we substitute for string fields should be seen as an artifact of the current ATerm formula. +> In order to be more explicit, and avoid gotchas analogous to [SQL injection](https://en.wikipedia.org/wiki/SQL_injection), +> we ought to consider switching two a different format where we explicitly use a syntax for a oncatentation of plain strings and placeholders written more explicitly. + +### Inputs + +The inputs are a set of [deriving paths]. +Each of these must be [realised] prior to building the derivation in +question. +At that point, the derivation can be normalized replacing each input +derived path with its store path --- which we now now since we've +realised it. ## [Deriving path]{#deriving-path} From 97977b734800dd5dfb7ede92560a2229b10b9495 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 11:51:32 -0500 Subject: [PATCH 05/21] Fix formatting issue --- src/libcmd/command.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 85864401c33..f167aa75748 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -143,8 +143,7 @@ MixOperateOnOptions::MixOperateOnOptions() { addFlag({ .longName = "derivation", - .description = - "Operate on the [derivation](@docroot@/glossary.md#gloss-derivation) rather than its outputs.", + .description = "Operate on the [derivation](@docroot@/glossary.md#gloss-derivation) rather than its outputs.", .category = installablesCategory, .handler = {&operateOn, OperateOn::Derivation}, }); From 4b29ca84765c40ebcdb766d998d8b7992fba4c66 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 12:18:54 -0500 Subject: [PATCH 06/21] Fix typo --- doc/manual/source/store/drv.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index a59a9c8d4f2..999ad68bafa 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -211,9 +211,9 @@ data DerivingPath } ``` -Now, the `drv` field of `BuiltObject` is itself a `DerivingPath` instead of an `StorePath`. +Now, the `drv` field of `Output` is itself a `DerivingPath` instead of an `StorePath`. -Under this extended model, `DerivingPath`s are thus inductively built up from an `ConstantPath`, contains in 0 or more outer `Outputs`. +Under this extended model, `DerivingPath`s are thus inductively built up from an `ConstantPath`, contains in 0 or more outer `Output`s. ### Encoding From 4b9fb5495707efcefd7581dfef0a7d055655eb51 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 13:07:37 -0500 Subject: [PATCH 07/21] Derivation doc improvements --- doc/manual/source/glossary.md | 2 +- .../source/protocols/derivation-aterm.md | 21 +++++- doc/manual/source/store/drv.md | 65 ++++++++++++------- src/nix/derivation-add.md | 2 +- 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index 4e4b9083e9e..ef5969dce36 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -22,7 +22,7 @@ - [derivation]{#gloss-derivation} A single build task. - See [Derivation](@docroot@/doc/manual/src/store/drv.md#derivation) for details. + See [Derivation](@docroot@/store/drv.md#derivation) for details. [derivation]: #gloss-derivation diff --git a/doc/manual/source/protocols/derivation-aterm.md b/doc/manual/source/protocols/derivation-aterm.md index 5b2e130dc97..0761342878f 100644 --- a/doc/manual/source/protocols/derivation-aterm.md +++ b/doc/manual/source/protocols/derivation-aterm.md @@ -1,6 +1,8 @@ # Derivation "ATerm" file format -For historical reasons, [derivations](@docroot@/glossary.md#gloss-derivation) are stored on-disk in [ATerm](https://homepages.cwi.nl/~daybuild/daily-books/technology/aterm-guide/aterm-guide.html) format. +For historical reasons, [derivations][derivation] are stored on-disk in [ATerm](https://homepages.cwi.nl/~daybuild/daily-books/technology/aterm-guide/aterm-guide.html) format. + +## The ATerm format used Derivations are serialised in one of the following formats: @@ -17,3 +19,20 @@ Derivations are serialised in one of the following formats: The only `version-string`s that are in use today are for [experimental features](@docroot@/development/experimental-features.md): - `"xp-dyn-drv"` for the [`dynamic-derivations`](@docroot@/development/experimental-features.md#xp-feature-dynamic-derivations) experimental feature. + +## Use for encoding to store object + +When derivation is encoded to a [store object] we make the following choices: + +- The store path name is the derivation name with `.drv` suffixed at the end + + Indeed, the ATerm format above does *not* contain the name of the derivation, on the assumption that a store path will also be provided out-of-band. + +- The derivation is content-addressed using the ["Text" method] of content-addressing derivations + +Currently we always encode derivations to storee object using the ATerm format (and the previous two choices), +but we reserve the right to encode new sorts of derivations differently in the future. + +[derivation]: @docroot@/glossary.md#gloss-derivation +[store object]: @docroot@/glossary.md#gloss-store-object +["Text" method]: @docroot@/store/store-object/content-address.md#method-text diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 999ad68bafa..c7e6186fabc 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -8,7 +8,7 @@ This is where Nix distinguishes itself. *Derivations* represent individual build steps, and *deriving paths* are needed to to the *outputs* of those build steps. The two concepts need to be introduced together because, as described below, each depends on the other. -## [Derivation]{#derivation} +## Derivation {#derivation} A derivation is a specification for running an executable on precisely defined input files to repeatably produce output files at uniquely determined file system paths. @@ -32,30 +32,28 @@ A derivation consists of: - A two-component "system" name (e.g. `x86_64-linux`) where the executable is to run. -The path and list/set elements of the other two will presumably consist wholly or partly of store paths. +The information needed for the `execve` system call will presumably include many [store paths][store path]: + + - The path to the executable is almost surely starts with a store path + - The arguments and environment variables likely contain many other store paths. + But just as we stored the references contained in the file data separately for store objects, so we store the set of inputs separately. -The last bit of information is to take advantage of the fact that Nix allows *heterogenous* build plans, were not all steps can be run on the same machine or same sort of machine. +Finally, the system name is included take advantage of the fact that Nix allows *heterogenous* build plans, where not all steps can be run on the same machine or same sort of machine. The process's job is to produce the outputs, but have no other important side effects. The rules around this will be discussed in following sections. -### Referencing +### Referencing derivations -Derivations are always referred to by the store path of the store object they are encoded to. -The store path name is the derivation name with `.drv` suffixed at the end. -The store path digest we will explain in a following section after we go over the different variants of derivations, as the exact algorithm depends on them. -Suffice to say for now, it is (a form of) content addressing based on the derivation and its inputs. +Derivations are always referred to by the [store path] of the store object they are encoded to. +See the encoding [encoding section](#derivation-encoding) for more details on how this encoding works, and thus what exactly what store path we would end up with for a given derivations. -> NOTE: -> Actually we have defined "text addressing" already in "content-addressing store objects". -> Note that we reserve the right to format new sorts of derivations on-disk differently in the future. -> The choice of "text hashing" should be deemd arbitrary along with the choice of "ATerm" serialization. -> Maybe this should be moved below to "encoding?". +The store path of the store object which encodes a derivation is often called a "derivation path" for brevity. ### Outputs {#outputs} -The outputs are the derivations are the store objects it is obligated to produce. +The outputs are the derivations are the [store objects][store object] it is obligated to produce. Outputs are assigned names, and also consistent of other information based on the type of derivation. @@ -107,7 +105,7 @@ Two types: - output derived paths (see below), corresponding to store paths we haven't yet realized. -> N.B. Current method of creating hashes which we substitute for string fields should be seen as an artifact of the current ATerm formula. +> N.B. Current method of creating hashes which we substitute for string fields should be seen as an artifact of the current "ATerm" serialization format. > In order to be more explicit, and avoid gotchas analogous to [SQL injection](https://en.wikipedia.org/wiki/SQL_injection), > we ought to consider switching two a different format where we explicitly use a syntax for a oncatentation of plain strings and placeholders written more explicitly. @@ -120,7 +118,7 @@ At that point, the derivation can be normalized replacing each input derived path with its store path --- which we now now since we've realised it. -## [Deriving path]{#deriving-path} +## Deriving path {#deriving-path} Deriving paths are a way to refer to [store objects][store object] that might not yet be [realised][realise]. This is necessary because, in general and particularly for [content-addressed derivations][content-addressed derivation], the [store path] of an [output] is not known in advance. @@ -151,15 +149,38 @@ data DerivingPath ## Encoding -### Derivation +### Derivation {#derivation-encoding} There are two formats, documented separately: -- The legacy [ATerm" format](protocols/derivation-aterm.md) +- The legacy ["ATerm" format](@docroot@/protocols/derivation-aterm.md) + +- The modern [JSON format](@docroot@/protocols/json/derivation.md) + +Currently derivations are always serialized to store objects using the "ATerm" format, but this is subject to change. + +Regardless of the format used, when serializing to store object, content-addressing is always used. +In the common case the inputs to store objects are either: + + - constant deriving paths for content-addressed source objects, which are "initial inputs" rather than the outputs of some other derivation (except in the case of bootstrap binaries). + + - the outputs of other derivations abiding by this same invariant. + +This common case makes for the following useful property: +when we serialize such a derivation graph to store objects, the resulting closures are *entirely* content-addressed. + +Here is a sketch at the proof of this: + + - The inputs which are constant deriving paths become references of the serialized derivations, but they are content-addressed per the above. + + - For inputs which are output deriving paths, we cannot directly reference the input because in general it is not built yet. + We instead "peal back" the output deriving path to take its underlying serialized derivation (the `drvPath` field), and reference that. + Since it is a derivation, it must be content-addressed -- The modern [JSON format](source/protocols/json/derivation.md) + - There are no other ways a store object would end up in an input closure. + The references of a derivation in store object form always come from solely from the inputs of the derivation. -### Deriving Path +### Deriving Path {#deriving-path-encoding} - *constant* @@ -194,7 +215,7 @@ There are two formats, documented separately: ## Extending the model to be higher-order -**Experimental feature**: [`dynamic-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations) +**Experimental feature**: [`dynamic-derivations`](@docroot@/development/experimental-features.md#xp-feature-dynamic-derivations) We can apply the same extension discussed for the abstract model to the concrete model. Again, only the data type for Deriving Paths needs to be modified. @@ -215,7 +236,7 @@ Now, the `drv` field of `Output` is itself a `DerivingPath` instead of an `Store Under this extended model, `DerivingPath`s are thus inductively built up from an `ConstantPath`, contains in 0 or more outer `Output`s. -### Encoding +### Encoding {#deriving-path-encoding} The encoding is adjusted in a very simplest way, merely displaying the same diff --git a/src/nix/derivation-add.md b/src/nix/derivation-add.md index 8c4fa732a05..c2aee6933da 100644 --- a/src/nix/derivation-add.md +++ b/src/nix/derivation-add.md @@ -13,6 +13,6 @@ a Nix expression evaluates. `nix derivation add` takes a single derivation in the following format: -{{#include @docroot@/protocols/json/derivation.md}} +{{#include ../../protocols/json/derivation.md}} )"" From 87c559e4aab25c683f6a0352fb0c2067e927ed86 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 14:58:38 -0500 Subject: [PATCH 08/21] More doc improvements --- doc/manual/source/SUMMARY.md.in | 1 + doc/manual/source/store/drv.md | 86 ++++++++++++++----------- doc/manual/source/store/drv/building.md | 18 ++++++ 3 files changed, 67 insertions(+), 38 deletions(-) create mode 100644 doc/manual/source/store/drv/building.md diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index 7b6d3fe42d5..7c15c276ace 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -23,6 +23,7 @@ - [Content-Addressing Store Objects](store/store-object/content-address.md) - [Store Path](store/store-path.md) - [Derivation and Deriving Path](store/drv.md) + - [Building](store/drv/building.md) - [Store Types](store/types/index.md) {{#include ./store/types/SUMMARY.md}} - [Nix Language](language/index.md) diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index c7e6186fabc..f05f86cfd3e 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -21,37 +21,42 @@ A derivation consists of: - A (base) name - - A set of *outputs*, consisting of names and possibly other data + - A set of [*inputs*][inputs], a set of [deriving paths][deriving path] - - A set of *inputs*, a set of [deriving paths](#deriving-path) + - A map of [*outputs*][outputs], from names to other data - Everything needed for an `execve` system call: - 1. Path to executable - 2. A list of arguments (except for `argv[0]`, which is taken from the path in the usual way) - 3. A set of environment variables. - - A two-component "system" name (e.g. `x86_64-linux`) where the executable is to run. + - The ["builder"][builder], a path to an executable -The information needed for the `execve` system call will presumably include many [store paths][store path]: + - A list of [arguments][args] - - The path to the executable is almost surely starts with a store path - - The arguments and environment variables likely contain many other store paths. + - A map of [environment variables][env]. -But just as we stored the references contained in the file data separately for store objects, so we store the set of inputs separately. + - A two-component ["system" type][system] (e.g. `x86_64-linux`) where the executable is to run. -Finally, the system name is included take advantage of the fact that Nix allows *heterogenous* build plans, where not all steps can be run on the same machine or same sort of machine. +[derivation]: #derivation +[outputs]: #outputs +[inputs]: #inputs +[builder]: #builder +[args]: #args +[env]: #env +[system]: #system -The process's job is to produce the outputs, but have no other important side effects. -The rules around this will be discussed in following sections. +### Parts of a derivation -### Referencing derivations +#### Inputs {#inputs} -Derivations are always referred to by the [store path] of the store object they are encoded to. -See the encoding [encoding section](#derivation-encoding) for more details on how this encoding works, and thus what exactly what store path we would end up with for a given derivations. +The inputs are a set of [deriving paths][deriving path], refering to all store objects needed in order to perform this build step. -The store path of the store object which encodes a derivation is often called a "derivation path" for brevity. +The information needed for the `execve` system call will presumably include many [store paths][store path]: -### Outputs {#outputs} + - The path to the executable is almost surely starts with a store path + - The arguments and environment variables likely contain many other store paths. + +But just as we stored the references contained in the file data separately for store objects, so we store the set of inputs separately from the builder, arguments, and environment variables. + +#### Outputs {#outputs} The outputs are the derivations are the [store objects][store object] it is obligated to produce. @@ -73,27 +78,39 @@ This is to allow derivations with a single output to avoid a superfluous `- > - The store path of `dev` will be: `/nix/store/-hello-dev`. -### System {#system} +#### Builder {#builder} -The system type on which the [`builder`](#attr-builder) executable is meant to be run. +This is the path to an executable that will perform the build and produce the [outputs]. -A necessary condition for Nix to build derivations locally is that the `system` attribute matches the current [`system` configuration option]. -It can automatically [build on other platforms](@docroot@/language/derivations.md#attr-builder) by forwarding build requests to other machines. +#### Arguments {#args} -[`system` configuration option]: @docroot@/command-ref/conf-file.md#conf-system +Command-line arguments to be passed to the [`builder`](#builder) executable. +Note that these are the arguments after the first argument. +The first argument, `argv[0]`, is the "base name" of the `builder`, as per the usual convention on Unix. +See [Wikipedia](https://en.wikipedia.org/w/index.php?title=Argv) for details. -### Builder {#builder} +#### Environment Variables {#env} -Path to an executable that will perform the build. +Environment variables which will be passed to the [builder](#builder) executable. -### Args {#args} +#### System {#system} -Command-line arguments to be passed to the [`builder`](#builder) executable. +The system type on which the [`builder`](#attr-builder) executable is meant to be run. -### Environment Variables {#env} +A necessary condition for Nix to schedule a given derivation on given Nix instance is for the "system" of that derivation to match that instance's [`system` configuration option]. -Environment variables which will be passed to the [`builder`](#builder) executable. +By putting the `system` in each derivation, Nix allows *heterogenous* build plans, where not all steps can be run on the same machine or same sort of machine. +A Nix isntance scheduling builds can automatically [build on other platforms](@docroot@/language/derivations.md#attr-builder) by forwarding build requests to other Nix instances. + +[`system` configuration option]: @docroot@/command-ref/conf-file.md#conf-system + +### Referencing derivations + +Derivations are always referred to by the [store path] of the store object they are encoded to. +See the [encoding section](#derivation-encoding) for more details on how this encoding works, and thus what exactly what store path we would end up with for a given derivations. + +The store path of the store object which encodes a derivation is often called a "derivation path" for brevity. ### Placeholder @@ -109,15 +126,6 @@ Two types: > In order to be more explicit, and avoid gotchas analogous to [SQL injection](https://en.wikipedia.org/wiki/SQL_injection), > we ought to consider switching two a different format where we explicitly use a syntax for a oncatentation of plain strings and placeholders written more explicitly. -### Inputs - -The inputs are a set of [deriving paths]. -Each of these must be [realised] prior to building the derivation in -question. -At that point, the derivation can be normalized replacing each input -derived path with its store path --- which we now now since we've -realised it. - ## Deriving path {#deriving-path} Deriving paths are a way to refer to [store objects][store object] that might not yet be [realised][realise]. @@ -142,6 +150,8 @@ data DerivingPath } ``` +[deriving path]: #deriving-path + [content-addressed derivation]: @docroot@/glossary.md#gloss-content-addressed-derivation [realise]: @docroot@/glossary.md#gloss-realise [store object]: @docroot@/store/store-object.md diff --git a/doc/manual/source/store/drv/building.md b/doc/manual/source/store/drv/building.md new file mode 100644 index 00000000000..1f6e45c1a6d --- /dev/null +++ b/doc/manual/source/store/drv/building.md @@ -0,0 +1,18 @@ +# Building + +TODO + +## Normalizing derivation inputs + +TODO + +Each input must be [realised] prior to building the derivation in question. +At that point, the derivation can be *normalized*, by replacing each input deriving path with its store path --- which we now know since we've realised it. + +## Building + +TODO + +## Processing outputs and Reference scanning + +TODO From 96a46f9995b224e38d474bbf55575927b91f97f8 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 15:16:42 -0500 Subject: [PATCH 09/21] Move builder execution to store layer It is not a language topic. --- doc/manual/redirects.js | 3 + doc/manual/source/language/derivations.md | 74 ----------------------- doc/manual/source/store/drv/building.md | 74 ++++++++++++++++++++++- 3 files changed, 75 insertions(+), 76 deletions(-) diff --git a/doc/manual/redirects.js b/doc/manual/redirects.js index dea141391df..026079d0943 100644 --- a/doc/manual/redirects.js +++ b/doc/manual/redirects.js @@ -346,6 +346,9 @@ const redirects = { "scoping-rules": "scoping.html", "string-literal": "string-literals.html", }, + "language/derivations.md": { + "builder-execution": "store/drv/building.md#building" + }, "installation/installing-binary.html": { "linux": "uninstall.html#linux", "macos": "uninstall.html#macos", diff --git a/doc/manual/source/language/derivations.md b/doc/manual/source/language/derivations.md index fb3c40b7274..d3391bfb905 100644 --- a/doc/manual/source/language/derivations.md +++ b/doc/manual/source/language/derivations.md @@ -235,77 +235,3 @@ It outputs an attribute set, and produces a [derivation] as a side effect of eva passed as an empty string. - -## Builder execution - -The [`builder`](#attr-builder) is executed as follows: - -- A temporary directory is created under the directory specified by - `TMPDIR` (default `/tmp`) where the build will take place. The - current directory is changed to this directory. - -- The environment is cleared and set to the derivation attributes, as - specified above. - -- In addition, the following variables are set: - - - `NIX_BUILD_TOP` contains the path of the temporary directory for - this build. - - - Also, `TMPDIR`, `TEMPDIR`, `TMP`, `TEMP` are set to point to the - temporary directory. This is to prevent the builder from - accidentally writing temporary files anywhere else. Doing so - might cause interference by other processes. - - - `PATH` is set to `/path-not-set` to prevent shells from - initialising it to their built-in default value. - - - `HOME` is set to `/homeless-shelter` to prevent programs from - using `/etc/passwd` or the like to find the user's home - directory, which could cause impurity. Usually, when `HOME` is - set, it is used as the location of the home directory, even if - it points to a non-existent path. - - - `NIX_STORE` is set to the path of the top-level Nix store - directory (typically, `/nix/store`). - - - `NIX_ATTRS_JSON_FILE` & `NIX_ATTRS_SH_FILE` if `__structuredAttrs` - is set to `true` for the derivation. A detailed explanation of this - behavior can be found in the - [section about structured attrs](./advanced-attributes.md#adv-attr-structuredAttrs). - - - For each output declared in `outputs`, the corresponding - environment variable is set to point to the intended path in the - Nix store for that output. Each output path is a concatenation - of the cryptographic hash of all build inputs, the `name` - attribute and the output name. (The output name is omitted if - it’s `out`.) - -- If an output path already exists, it is removed. Also, locks are - acquired to prevent multiple Nix instances from performing the same - build at the same time. - -- A log of the combined standard output and error is written to - `/nix/var/log/nix`. - -- The builder is executed with the arguments specified by the - attribute `args`. If it exits with exit code 0, it is considered to - have succeeded. - -- The temporary directory is removed (unless the `-K` option was - specified). - -- If the build was successful, Nix scans each output path for - references to input paths by looking for the hash parts of the input - paths. Since these are potential runtime dependencies, Nix registers - them as dependencies of the output paths. - -- After the build, Nix sets the last-modified timestamp on all files - in the build result to 1 (00:00:01 1/1/1970 UTC), sets the group to - the default group, and sets the mode of the file to 0444 or 0555 - (i.e., read-only, with execute permission enabled if the file was - originally executable). Note that possible `setuid` and `setgid` - bits are cleared. Setuid and setgid programs are not currently - supported by Nix. This is because the Nix archives used in - deployment have no concept of ownership information, and because it - makes the build result dependent on the user performing the build. diff --git a/doc/manual/source/store/drv/building.md b/doc/manual/source/store/drv/building.md index 1f6e45c1a6d..231c1546727 100644 --- a/doc/manual/source/store/drv/building.md +++ b/doc/manual/source/store/drv/building.md @@ -9,9 +9,79 @@ TODO Each input must be [realised] prior to building the derivation in question. At that point, the derivation can be *normalized*, by replacing each input deriving path with its store path --- which we now know since we've realised it. -## Building +## Builder Execution -TODO +The [`builder`](../drv.md#builder) is executed as follows: + +- A temporary directory is created under the directory specified by + `TMPDIR` (default `/tmp`) where the build will take place. The + current directory is changed to this directory. + +- The environment is cleared and set to the derivation attributes, as + specified above. + +- In addition, the following variables are set: + + - `NIX_BUILD_TOP` contains the path of the temporary directory for + this build. + + - Also, `TMPDIR`, `TEMPDIR`, `TMP`, `TEMP` are set to point to the + temporary directory. This is to prevent the builder from + accidentally writing temporary files anywhere else. Doing so + might cause interference by other processes. + + - `PATH` is set to `/path-not-set` to prevent shells from + initialising it to their built-in default value. + + - `HOME` is set to `/homeless-shelter` to prevent programs from + using `/etc/passwd` or the like to find the user's home + directory, which could cause impurity. Usually, when `HOME` is + set, it is used as the location of the home directory, even if + it points to a non-existent path. + + - `NIX_STORE` is set to the path of the top-level Nix store + directory (typically, `/nix/store`). + + - `NIX_ATTRS_JSON_FILE` & `NIX_ATTRS_SH_FILE` if `__structuredAttrs` + is set to `true` for the derivation. A detailed explanation of this + behavior can be found in the + [section about structured attrs](@docroot@/language/advanced-attributes.md#adv-attr-structuredAttrs). + + - For each output declared in `outputs`, the corresponding + environment variable is set to point to the intended path in the + Nix store for that output. Each output path is a concatenation + of the cryptographic hash of all build inputs, the `name` + attribute and the output name. (The output name is omitted if + it’s `out`.) + +- If an output path already exists, it is removed. Also, locks are + acquired to prevent multiple Nix instances from performing the same + build at the same time. + +- A log of the combined standard output and error is written to + `/nix/var/log/nix`. + +- The builder is executed with the arguments specified by the + attribute `args`. If it exits with exit code 0, it is considered to + have succeeded. + +- The temporary directory is removed (unless the `-K` option was + specified). + +- If the build was successful, Nix scans each output path for + references to input paths by looking for the hash parts of the input + paths. Since these are potential runtime dependencies, Nix registers + them as dependencies of the output paths. + +- After the build, Nix sets the last-modified timestamp on all files + in the build result to 1 (00:00:01 1/1/1970 UTC), sets the group to + the default group, and sets the mode of the file to 0444 or 0555 + (i.e., read-only, with execute permission enabled if the file was + originally executable). Note that possible `setuid` and `setgid` + bits are cleared. Setuid and setgid programs are not currently + supported by Nix. This is because the Nix archives used in + deployment have no concept of ownership information, and because it + makes the build result dependent on the user performing the build. ## Processing outputs and Reference scanning From 624690100d73396af88722aa94c0da98023b441a Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 15:17:12 -0500 Subject: [PATCH 10/21] Formatting example --- doc/manual/source/store/drv.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index f05f86cfd3e..11e792301a5 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -250,15 +250,17 @@ Under this extended model, `DerivingPath`s are thus inductively built up from an The encoding is adjusted in a very simplest way, merely displaying the same -``` -/nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^foo.drv^bar.drv^out -|----------------------------------------------------------------------------| |-| -inner deriving path (usual encoding) output name -|--------------------------------------------------------------------| |-----| -even more inner deriving path (usual encoding) output name -|------------------------------------------------------------| |-----| -innermost constant store path (usual encoding) output name -``` +> **Example** +> +> ``` +> /nix/store/lxrn8v5aamkikg6agxwdqd1jz7746wz4-firefox-98.0.2.drv^foo.drv^bar.drv^out +> |----------------------------------------------------------------------------| |-| +> inner deriving path (usual encoding) output name +> |--------------------------------------------------------------------| |-----| +> even more inner deriving path (usual encoding) output name +> |------------------------------------------------------------| |-----| +> innermost constant store path (usual encoding) output name +> ``` ## Extra extensions From 80e69428a85f3ac504615c2d14e3aba1e67d8455 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 17:32:10 -0500 Subject: [PATCH 11/21] Fix redirect --- doc/manual/redirects.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/redirects.js b/doc/manual/redirects.js index 026079d0943..287517eca19 100644 --- a/doc/manual/redirects.js +++ b/doc/manual/redirects.js @@ -347,7 +347,7 @@ const redirects = { "string-literal": "string-literals.html", }, "language/derivations.md": { - "builder-execution": "store/drv/building.md#building" + "builder-execution": "store/drv/building.md#builder-execution" }, "installation/installing-binary.html": { "linux": "uninstall.html#linux", From e77338d87564cdfe78a6a2779a850e7e6d8cef2c Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 17:34:52 -0500 Subject: [PATCH 12/21] Fix redirects more --- doc/manual/redirects.js | 3 ++- doc/manual/source/glossary.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/manual/redirects.js b/doc/manual/redirects.js index 287517eca19..71147fc2d7c 100644 --- a/doc/manual/redirects.js +++ b/doc/manual/redirects.js @@ -347,7 +347,7 @@ const redirects = { "string-literal": "string-literals.html", }, "language/derivations.md": { - "builder-execution": "store/drv/building.md#builder-execution" + "builder-execution": "store/drv/building.md#builder-execution", }, "installation/installing-binary.html": { "linux": "uninstall.html#linux", @@ -375,6 +375,7 @@ const redirects = { "glossary.html": { "gloss-local-store": "store/types/local-store.html", "gloss-chroot-store": "store/types/local-store.html", + "gloss-store-derivation": "#gloss-derivation", }, }; diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index ef5969dce36..10b8789c295 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -26,7 +26,7 @@ [derivation]: #gloss-derivation -- [derivation expression]{#gloss-derivation} +- [derivation expression]{#gloss-derivation-expression} A description of a [derivation] in the Nix language. The result of a derivation is a store object. From fb7fc6a3731dc618ba530e5d7fb297be627a98a4 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 17:47:47 -0500 Subject: [PATCH 13/21] Fix another URL in the docs --- doc/manual/source/command-ref/nix-copy-closure.md | 2 +- doc/manual/source/language/string-interpolation.md | 4 ++-- doc/manual/source/protocols/json/derivation.md | 2 +- doc/manual/source/protocols/json/store-object-info.md | 2 +- src/libcmd/misc-store-flags.cc | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/manual/source/command-ref/nix-copy-closure.md b/doc/manual/source/command-ref/nix-copy-closure.md index 7a976fbdd82..50d16866e7c 100644 --- a/doc/manual/source/command-ref/nix-copy-closure.md +++ b/doc/manual/source/command-ref/nix-copy-closure.md @@ -44,7 +44,7 @@ When using public key authentication, you can avoid typing the passphrase with ` Also copy the outputs of [derivation]s included in the closure. - [derivation]: @docroot@/glossary.md#gloss-store-derivation + [derivation]: @docroot@/glossary.md#gloss-derivation - `--use-substitutes` / `-s` diff --git a/doc/manual/source/language/string-interpolation.md b/doc/manual/source/language/string-interpolation.md index 562d705f829..a503d5f04bd 100644 --- a/doc/manual/source/language/string-interpolation.md +++ b/doc/manual/source/language/string-interpolation.md @@ -22,9 +22,9 @@ Rather than writing "--with-freetype2-library=" + freetype + "/lib" ``` -(where `freetype` is an [output path]), you can instead write +(where `freetype` is a [derivation expression]), you can instead write -[derivation]: @docroot@/glossary.md#gloss-derivation +[derivation expression]: @docroot@/glossary.md#gloss-derivation-expression ```nix "--with-freetype2-library=${freetype}/lib" diff --git a/doc/manual/source/protocols/json/derivation.md b/doc/manual/source/protocols/json/derivation.md index 2f85340d6c5..7109c4efa74 100644 --- a/doc/manual/source/protocols/json/derivation.md +++ b/doc/manual/source/protocols/json/derivation.md @@ -7,7 +7,7 @@ > and subject to change. The JSON serialization of a -[derivations](@docroot@/glossary.md#gloss-store-derivation) +[derivations](@docroot@/glossary.md#gloss-derivation) is a JSON object with the following fields: * `name`: diff --git a/doc/manual/source/protocols/json/store-object-info.md b/doc/manual/source/protocols/json/store-object-info.md index 6b4f4843711..ba21bf5373e 100644 --- a/doc/manual/source/protocols/json/store-object-info.md +++ b/doc/manual/source/protocols/json/store-object-info.md @@ -44,7 +44,7 @@ In other words, the same store object residing in different store could have dif If known, the path to the [derivation] from which this store object was produced. Otherwise `null`. - [derivation]: @docroot@/glossary.md#gloss-store-derivation + [derivation]: @docroot@/glossary.md#gloss-derivation * `registrationTime` (optional): diff --git a/src/libcmd/misc-store-flags.cc b/src/libcmd/misc-store-flags.cc index 06552c03223..7a84385a5d8 100644 --- a/src/libcmd/misc-store-flags.cc +++ b/src/libcmd/misc-store-flags.cc @@ -120,7 +120,7 @@ Args::Flag contentAddressMethod(ContentAddressMethod * method) - [`text`](@docroot@/store/store-object/content-address.md#method-text): Like `flat`, but used for - [derivations](@docroot@/glossary.md#store-derivation) serialized in store object and + [derivations](@docroot@/glossary.md#gloss-derivation) serialized in store object and [`builtins.toFile`](@docroot@/language/builtins.html#builtins-toFile). For advanced use-cases only; for regular usage prefer `nar` and `flat`. From 0cd1e7828d3f9c38bfde474c2d3c84afded3f6e3 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 17:50:24 -0500 Subject: [PATCH 14/21] Change deriving path pseudo-code --- doc/manual/source/store/drv.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 11e792301a5..b9b6d1b31d1 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -143,7 +143,7 @@ In pseudo code: type OutputName = String data DerivingPath - = ConstantPath { path : StorePath } + = Constant { path : StorePath } | Output { drvPath : StorePath, output : OutputName, @@ -235,7 +235,7 @@ Derivations are the same except for using the new extended deriving path data ty type OutputName = String data DerivingPath - = ConstantPath { storeObj : StorePath } + = Constant { storeObj : StorePath } | Output { drv : DerivingPath, -- Note: changed output : OutputName, @@ -244,7 +244,7 @@ data DerivingPath Now, the `drv` field of `Output` is itself a `DerivingPath` instead of an `StorePath`. -Under this extended model, `DerivingPath`s are thus inductively built up from an `ConstantPath`, contains in 0 or more outer `Output`s. +Under this extended model, `DerivingPath`s are thus inductively built up from an `Constant`, contains in 0 or more outer `Output`s. ### Encoding {#deriving-path-encoding} From 05a38b8dad3c3111b0eb062643701a58d0163e8b Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sun, 19 Jan 2025 19:10:41 -0500 Subject: [PATCH 15/21] Further reworking --- doc/manual/source/SUMMARY.md.in | 2 +- doc/manual/source/glossary.md | 12 ++ doc/manual/source/store/{drv => }/building.md | 2 +- doc/manual/source/store/drv.md | 149 ++++++++++++------ src/libexpr/primops.cc | 24 ++- 5 files changed, 128 insertions(+), 61 deletions(-) rename doc/manual/source/store/{drv => }/building.md (98%) diff --git a/doc/manual/source/SUMMARY.md.in b/doc/manual/source/SUMMARY.md.in index 7c15c276ace..38432d064b5 100644 --- a/doc/manual/source/SUMMARY.md.in +++ b/doc/manual/source/SUMMARY.md.in @@ -23,7 +23,7 @@ - [Content-Addressing Store Objects](store/store-object/content-address.md) - [Store Path](store/store-path.md) - [Derivation and Deriving Path](store/drv.md) - - [Building](store/drv/building.md) + - [Building](store/building.md) - [Store Types](store/types/index.md) {{#include ./store/types/SUMMARY.md}} - [Nix Language](language/index.md) diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index 10b8789c295..6ada5df7490 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -26,6 +26,16 @@ [derivation]: #gloss-derivation +- [derivation path]{#gloss-derivation-path} + + A [store path] which uniquely identifies a [derivation]. + + See [Referencing Derivations](@docroot@/store/drv.md#derivation-path) for details. + + Not to be confused with [deriving path]. + + [derivation path]: #gloss-derivation-path + - [derivation expression]{#gloss-derivation-expression} A description of a [derivation] in the Nix language. @@ -245,6 +255,8 @@ See [Deriving Path](./store/drv.md#deriving-path) for details. + Not to be confused with [derivation path]. + - [deriver]{#gloss-deriver} The [derivation] that produced an [output path]. diff --git a/doc/manual/source/store/drv/building.md b/doc/manual/source/store/building.md similarity index 98% rename from doc/manual/source/store/drv/building.md rename to doc/manual/source/store/building.md index 231c1546727..c6218ec9422 100644 --- a/doc/manual/source/store/drv/building.md +++ b/doc/manual/source/store/building.md @@ -11,7 +11,7 @@ At that point, the derivation can be *normalized*, by replacing each input deriv ## Builder Execution -The [`builder`](../drv.md#builder) is executed as follows: +The [`builder`](./drv.md#builder) is executed as follows: - A temporary directory is created under the directory specified by `TMPDIR` (default `/tmp`) where the build will take place. The diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index b9b6d1b31d1..88c8da44bd9 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -5,7 +5,7 @@ But the point of the Nix store layer is to be a build system. Other system (like Git or IPFS) also store and transfer immutable data, but they don't concern themselves with *how* that data was created. This is where Nix distinguishes itself. -*Derivations* represent individual build steps, and *deriving paths* are needed to to the *outputs* of those build steps. +*Derivations* represent individual build steps, and *deriving paths* are needed to refer to the *outputs* of those build steps before they are built. The two concepts need to be introduced together because, as described below, each depends on the other. ## Derivation {#derivation} @@ -25,9 +25,10 @@ A derivation consists of: - A map of [*outputs*][outputs], from names to other data - - Everything needed for an `execve` system call: + - The [process creation fields]: to spawn the arbitrary process which will perform the build step: - - The ["builder"][builder], a path to an executable + + - The [*builder*][builder], a path to an executable - A list of [arguments][args] @@ -36,16 +37,56 @@ A derivation consists of: - A two-component ["system" type][system] (e.g. `x86_64-linux`) where the executable is to run. [derivation]: #derivation -[outputs]: #outputs [inputs]: #inputs +[input]: #inputs +[outputs]: #outputs +[output]: #outputs +[process creation fields]: #process-creation-fields [builder]: #builder [args]: #args [env]: #env [system]: #system -### Parts of a derivation +### Referencing derivations {#derivation-path} + +Derivations are always referred to by the [store path] of the store object they are encoded to. +See the [encoding section](#derivation-encoding) for more details on how this encoding works, and thus what exactly what store path we would end up with for a given derivation. + +The store path of the store object which encodes a derivation is often called a *derivation path* for brevity. + +## Deriving path {#deriving-path} + +Deriving paths are a way to refer to [store objects][store object] that might not yet be [realised][realise]. +This is necessary because, in general and particularly for [content-addressed derivations][content-addressed derivation], the [store path] of an [output] is not known in advance. +There are two forms: + +- [*constant*]{#deriving-path-constant}: just a [store path]. + It can be made [valid][validity] by copying it into the store: from the evaluator, command line interface or another st ore. + +- [*output*]{#deriving-path-output}: a pair of a [store path] to a [derivation] and an [output] name. -#### Inputs {#inputs} +In pseudo code: + +```idris +type OutputName = String + +data DerivingPath + = Constant { path : StorePath } + | Output { + drvPath : StorePath, + output : OutputName, + } +``` + +[deriving path]: #deriving-path +[validity]: @docroot@/glossary.md#gloss-validity + +## Parts of a derivation + +With both [derivations][derivation] introduced and [deriving paths][deriving path] defined, +it is now possible to define the parts of a derivation. + +### Inputs {#inputs} The inputs are a set of [deriving paths][deriving path], refering to all store objects needed in order to perform this build step. @@ -56,7 +97,7 @@ The information needed for the `execve` system call will presumably include many But just as we stored the references contained in the file data separately for store objects, so we store the set of inputs separately from the builder, arguments, and environment variables. -#### Outputs {#outputs} +### Outputs {#outputs} The outputs are the derivations are the [store objects][store object] it is obligated to produce. @@ -78,6 +119,11 @@ This is to allow derivations with a single output to avoid a superfluous `- > - The store path of `dev` will be: `/nix/store/-hello-dev`. +### Process creation fields {#process-creation-fields} + +These are the three fields which describe out to spawn the process which (along with any of its own child processes) will perform the build. +As state in the derivation introduction, this is everything needed for an `execve` system call. + #### Builder {#builder} This is the path to an executable that will perform the build and produce the [outputs]. @@ -94,63 +140,57 @@ See [Wikipedia](https://en.wikipedia.org/w/index.php?title=Argv) for details. Environment variables which will be passed to the [builder](#builder) executable. -#### System {#system} - -The system type on which the [`builder`](#attr-builder) executable is meant to be run. - -A necessary condition for Nix to schedule a given derivation on given Nix instance is for the "system" of that derivation to match that instance's [`system` configuration option]. - -By putting the `system` in each derivation, Nix allows *heterogenous* build plans, where not all steps can be run on the same machine or same sort of machine. -A Nix isntance scheduling builds can automatically [build on other platforms](@docroot@/language/derivations.md#attr-builder) by forwarding build requests to other Nix instances. +#### Placeholders -[`system` configuration option]: @docroot@/command-ref/conf-file.md#conf-system +Placeholders are opaque values used within the [process creation fields] to [store objects] for which we don't yet know [store path]s. +The are strings in the form `/` that are embedded anywhere within the strings of those fields. -### Referencing derivations - -Derivations are always referred to by the [store path] of the store object they are encoded to. -See the [encoding section](#derivation-encoding) for more details on how this encoding works, and thus what exactly what store path we would end up with for a given derivations. +> **Note** +> +> Output Deriving Path exist to solve the same problem as placeholders --- that is, referring to store objects for which we don't yet know a store path. +> They also have a string syntax, [descibed in the encoding section](#deriving-path-encoding). +> We could use that syntax instead of `/` for placeholders, but its human-legibility would cuse problems. -The store path of the store object which encodes a derivation is often called a "derivation path" for brevity. +There are two types of placeholder, corresponding to the two cases where this problem arises: -### Placeholder +- [Output placeholder]{#output-placeholder}: -TODO + This is a placeholder for a derivation's own output. -Two types: +- [Input placeholder]{#input-placeholder}: -- Reference to own outputs + This is a placeholder to a derivation's non-constant [input], + i.e. an input that is an [output derived path]. -- output derived paths (see below), corresponding to store paths we haven't yet realized. +> **Explanation** +> +> In general, we need to realise [realise] a [store object] in order to be sure to have a store object for it. +> But for these two cases this is either impossible or impractical: +> +> - In the output case this is impossible: +> +> We cannot built the output until we have a correct derivation, and we cannot have a correct derivation (without using placeholders) until we have the output path. +> +> - In the input case this is impractical: +> +> We an always built a dependency, and then refer to its output by store path, but by doing so we loose the ability for a derivation graph to describe an entire build plan consisting of multiple build steps. -> N.B. Current method of creating hashes which we substitute for string fields should be seen as an artifact of the current "ATerm" serialization format. +> **Note** +> +> The current method of creating hashes which we substitute for string fields should be seen as an artifact of the current "ATerm" serialization format. > In order to be more explicit, and avoid gotchas analogous to [SQL injection](https://en.wikipedia.org/wiki/SQL_injection), -> we ought to consider switching two a different format where we explicitly use a syntax for a oncatentation of plain strings and placeholders written more explicitly. - -## Deriving path {#deriving-path} - -Deriving paths are a way to refer to [store objects][store object] that might not yet be [realised][realise]. -This is necessary because, in general and particularly for [content-addressed derivations][content-addressed derivation], the [store path] of an [output] is not known in advance. -There are two forms: - -- *constant*: just a [store path] - It can be made [valid][validity] by copying it into the store: from the evaluator, command line interface or another st ore. +> we ought to consider switching two a different format where we explicitly use a syntax for the concatenation of plain strings and [deriving paths] written more explicitly. -- *output*: a pair of a [store path] to a [derivation] and an [output] name. +### System {#system} -In pseudo code: +The system type on which the [`builder`](#attr-builder) executable is meant to be run. -```idris -type OutputName = String +A necessary condition for Nix to schedule a given derivation on given Nix instance is for the "system" of that derivation to match that instance's [`system` configuration option]. -data DerivingPath - = Constant { path : StorePath } - | Output { - drvPath : StorePath, - output : OutputName, - } -``` +By putting the `system` in each derivation, Nix allows *heterogenous* build plans, where not all steps can be run on the same machine or same sort of machine. +A Nix isntance scheduling builds can automatically [build on other platforms](@docroot@/language/derivations.md#attr-builder) by forwarding build requests to other Nix instances. -[deriving path]: #deriving-path +[`system` configuration option]: @docroot@/command-ref/conf-file.md#conf-system [content-addressed derivation]: @docroot@/glossary.md#gloss-content-addressed-derivation [realise]: @docroot@/glossary.md#gloss-realise @@ -167,9 +207,16 @@ There are two formats, documented separately: - The modern [JSON format](@docroot@/protocols/json/derivation.md) -Currently derivations are always serialized to store objects using the "ATerm" format, but this is subject to change. +Every derivation has a canonical choice of encoding used to serialize it to a store object. +This ensures that there is a canonical [store path] used to refer to the derivation, as described in [Referencing derivations](#derivation-path). + +> **Note** +> +> Currently, the canonical encoding for every derivation is the "ATerm" format, +> but this is subject to change for types derivations which are not yet stable. + +Regardless of the format used, when serializing to store objects, content-addressing is always used. -Regardless of the format used, when serializing to store object, content-addressing is always used. In the common case the inputs to store objects are either: - constant deriving paths for content-addressed source objects, which are "initial inputs" rather than the outputs of some other derivation (except in the case of bootstrap binaries). diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index e6d9feaf2c1..ff6cfe5454e 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1586,9 +1586,13 @@ static RegisterPrimOp primop_placeholder({ .name = "placeholder", .args = {"output"}, .doc = R"( - Return a placeholder string for the specified *output* that will be - substituted by the corresponding output path at build time. Typical - outputs would be `"out"`, `"bin"` or `"dev"`. + Return at + [output placeholder string](@docroot@/source/store/drv.md#output-placeholder) + for the specified *output* that will be substituted by the corresponding + [output path](@docroot@/glossary.md#gloss-output-path) + at build time. + + Typical outputs would be `"out"`, `"bin"` or `"dev"`. )", .fun = prim_placeholder, }); @@ -2126,12 +2130,16 @@ static RegisterPrimOp primop_outputOf({ .name = "__outputOf", .args = {"derivation-reference", "output-name"}, .doc = R"( - Return the output path of a derivation, literally or using a placeholder if needed. + Return at + Return the output path of a derivation, literally or using an + [input placeholder string](@docroot@/source/store/drv.md#input-placeholder) + if needed. If the derivation has a statically-known output path (i.e. the derivation output is input-addressed, or fixed content-addresed), the output path will just be returned. - But if the derivation is content-addressed or if the derivation is itself not-statically produced (i.e. is the output of another derivation), a placeholder will be returned instead. + But if the derivation is content-addressed or if the derivation is itself not-statically produced (i.e. is the output of another derivation), an input placeholder will be returned instead. - *`derivation reference`* must be a string that may contain a regular store path to a derivation, or may be a placeholder reference. If the derivation is produced by a derivation, you must explicitly select `drv.outPath`. + *`derivation reference`* must be a string that may contain a regular store path to a derivation, or may be an input placeholder reference. + If the derivation is produced by a derivation, you must explicitly select `drv.outPath`. This primop can be chained arbitrarily deeply. For instance, @@ -2141,9 +2149,9 @@ static RegisterPrimOp primop_outputOf({ "out" ``` - will return a placeholder for the output of the output of `myDrv`. + will return a input placeholder for the output of the output of `myDrv`. - This primop corresponds to the `^` sigil for derivable paths, e.g. as part of installable syntax on the command line. + This primop corresponds to the `^` sigil for [deriving paths](@docroot@/glossary.md#gloss-deriving-paths), e.g. as part of installable syntax on the command line. )", .fun = prim_outputOf, .experimentalFeature = Xp::DynamicDerivations, From e409ea77d06813fe8590a47db5b6753aaf0284c5 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 12:56:22 -0500 Subject: [PATCH 16/21] Apply suggestions from code review Thanks!! Co-authored-by: Robert Hensing --- .../source/command-ref/nix-instantiate.md | 2 +- doc/manual/source/glossary.md | 7 +++-- .../source/protocols/derivation-aterm.md | 4 +-- doc/manual/source/store/drv.md | 26 +++++++++---------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/doc/manual/source/command-ref/nix-instantiate.md b/doc/manual/source/command-ref/nix-instantiate.md index 0ae326538cd..0002901f0d9 100644 --- a/doc/manual/source/command-ref/nix-instantiate.md +++ b/doc/manual/source/command-ref/nix-instantiate.md @@ -43,7 +43,7 @@ standard input. Just parse and evaluate the input files, and print the resulting values on standard output. - Derivations are not serialized and written to the store, but instead just discarded. + Derivations are not serialized and written to the store, but instead just hashed and discarded. > **Warning** > diff --git a/doc/manual/source/glossary.md b/doc/manual/source/glossary.md index 6ada5df7490..9c132ab9076 100644 --- a/doc/manual/source/glossary.md +++ b/doc/manual/source/glossary.md @@ -39,10 +39,9 @@ - [derivation expression]{#gloss-derivation-expression} A description of a [derivation] in the Nix language. - The result of a derivation is a store object. + The output(s) of a derivation are store objects. Derivations are typically specified in Nix expressions using the [`derivation` primitive](./language/derivations.md). - These are translated into low-level *derivations* (implicitly by - `nix-env` and `nix-build`, or explicitly by `nix-instantiate`). + These are translated into store layer *derivations* (implicitly by `nix-env` and `nix-build`, or explicitly by `nix-instantiate`). [derivation expression]: #gloss-derivation-expression @@ -251,7 +250,7 @@ - [deriving path]{#gloss-deriving-path} - Deriving paths are a way to refer to [store objects][store object] that might not be yet [realised][realise]. + Deriving paths are a way to refer to [store objects][store object] that might not yet be [realised][realise]. See [Deriving Path](./store/drv.md#deriving-path) for details. diff --git a/doc/manual/source/protocols/derivation-aterm.md b/doc/manual/source/protocols/derivation-aterm.md index 0761342878f..3b26c0fa86d 100644 --- a/doc/manual/source/protocols/derivation-aterm.md +++ b/doc/manual/source/protocols/derivation-aterm.md @@ -30,8 +30,8 @@ When derivation is encoded to a [store object] we make the following choices: - The derivation is content-addressed using the ["Text" method] of content-addressing derivations -Currently we always encode derivations to storee object using the ATerm format (and the previous two choices), -but we reserve the right to encode new sorts of derivations differently in the future. +Currently we always encode derivations to store object using the ATerm format (and the previous two choices), +but we reserve the option to encode new sorts of derivations differently in the future. [derivation]: @docroot@/glossary.md#gloss-derivation [store object]: @docroot@/glossary.md#gloss-store-object diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 88c8da44bd9..31d00e419ac 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -6,20 +6,20 @@ Other system (like Git or IPFS) also store and transfer immutable data, but they This is where Nix distinguishes itself. *Derivations* represent individual build steps, and *deriving paths* are needed to refer to the *outputs* of those build steps before they are built. -The two concepts need to be introduced together because, as described below, each depends on the other. + ## Derivation {#derivation} A derivation is a specification for running an executable on precisely defined input files to repeatably produce output files at uniquely determined file system paths. -What is natural Unix analog for a build step *in action*? -Answer: a process that will eventually exit, leaving behind some output date. +What is the natural Unix analog for a build step *in action*? +Answer: a process that will eventually exit, leaving behind some output files. What is the natural way to *plan* such a step? An `execve` system call. A derivation consists of: - - A (base) name + - A name - A set of [*inputs*][inputs], a set of [deriving paths][deriving path] @@ -105,8 +105,8 @@ Outputs are assigned names, and also consistent of other information based on th Output names can be any string which is also a valid [store path] name. The store path of the output store object (also called an [output path] for short), has a name based on the derivation name and the output name. -Most outputs are named `drvMame + '-' + outputName`. -However, an output named "out" is just has name `drvName`. +Most outputs' store paths have name `drvMame + '-' + outputName`. +However, an output named "out" has a store path with name `drvName`. This is to allow derivations with a single output to avoid a superfluous `-` in their single output's name when no disambiguation is needed. > **Example** @@ -205,7 +205,7 @@ There are two formats, documented separately: - The legacy ["ATerm" format](@docroot@/protocols/derivation-aterm.md) -- The modern [JSON format](@docroot@/protocols/json/derivation.md) +- The experimental [JSON format](@docroot@/protocols/json/derivation.md) Every derivation has a canonical choice of encoding used to serialize it to a store object. This ensures that there is a canonical [store path] used to refer to the derivation, as described in [Referencing derivations](#derivation-path). @@ -219,7 +219,7 @@ Regardless of the format used, when serializing to store objects, content-addres In the common case the inputs to store objects are either: - - constant deriving paths for content-addressed source objects, which are "initial inputs" rather than the outputs of some other derivation (except in the case of bootstrap binaries). + - constant deriving paths for content-addressed source objects, which are "initial inputs" rather than the outputs of some other derivation - the outputs of other derivations abiding by this same invariant. @@ -231,7 +231,7 @@ Here is a sketch at the proof of this: - The inputs which are constant deriving paths become references of the serialized derivations, but they are content-addressed per the above. - For inputs which are output deriving paths, we cannot directly reference the input because in general it is not built yet. - We instead "peal back" the output deriving path to take its underlying serialized derivation (the `drvPath` field), and reference that. + We instead "peel back" the output deriving path to take its underlying serialized derivation (the `drvPath` field), and reference that. Since it is a derivation, it must be content-addressed - There are no other ways a store object would end up in an input closure. @@ -250,9 +250,9 @@ Here is a sketch at the proof of this: - encoding of a store path referring to a derivation - - a separator (`^` or `!` depending on context) + - a `^` separator (or `!` in some legacy contexts) - - the name of an output + - the name of an output of the previously referred derivation > **Example** > @@ -289,7 +289,7 @@ data DerivingPath } ``` -Now, the `drv` field of `Output` is itself a `DerivingPath` instead of an `StorePath`. +Now, the `drv` field of `Output` is itself a `DerivingPath` instead of a `StorePath`. Under this extended model, `DerivingPath`s are thus inductively built up from an `Constant`, contains in 0 or more outer `Output`s. @@ -327,5 +327,3 @@ At run time, this becomes two things: The bash command can be passed a script which will "source" that Nix-created bash script, setting those variables with the richer data. The outer script can then do whatever it likes with those richer variables as input. -However, since derivations can already contain arbitary input sources, the vast majority of `__structuredAttrs` can be handled by upper layers. -We might consider implementing `__structuredAttrs` in higher layers in the future, and simplifying the store layer. From f3fa9cfa1dffe15ee22f221931f1343a641bcdc6 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 13:20:19 -0500 Subject: [PATCH 17/21] Clean out some TODOs More can be written, but this will do for now. --- doc/manual/source/store/building.md | 20 +++++++++----------- doc/manual/source/store/drv.md | 3 ++- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/doc/manual/source/store/building.md b/doc/manual/source/store/building.md index c6218ec9422..a5929bc8304 100644 --- a/doc/manual/source/store/building.md +++ b/doc/manual/source/store/building.md @@ -1,13 +1,10 @@ # Building -TODO - ## Normalizing derivation inputs -TODO +- Each input must be [realised] prior to building the derivation in question. -Each input must be [realised] prior to building the derivation in question. -At that point, the derivation can be *normalized*, by replacing each input deriving path with its store path --- which we now know since we've realised it. +- Once this is done, the derivation is *normalized*, replacing each input deriving path with its store path, which we now know from realising the input. ## Builder Execution @@ -68,10 +65,7 @@ The [`builder`](./drv.md#builder) is executed as follows: - The temporary directory is removed (unless the `-K` option was specified). -- If the build was successful, Nix scans each output path for - references to input paths by looking for the hash parts of the input - paths. Since these are potential runtime dependencies, Nix registers - them as dependencies of the output paths. +## Processing outputs and Reference scanning - After the build, Nix sets the last-modified timestamp on all files in the build result to 1 (00:00:01 1/1/1970 UTC), sets the group to @@ -83,6 +77,10 @@ The [`builder`](./drv.md#builder) is executed as follows: deployment have no concept of ownership information, and because it makes the build result dependent on the user performing the build. -## Processing outputs and Reference scanning +- If the build was successful, Nix scans each output path for + references to input paths by looking for the hash parts of the input + paths. Since these are potential runtime dependencies, Nix registers + them as dependencies of the output paths. -TODO + Nix also scans for references to other outputs' paths in the same way, because outputs are allowed to refer to each other. + If the outputs' references to each other form a cycle, this is an error, because the references of store objects much be acyclic. diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 31d00e419ac..06ea16219a5 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -295,7 +295,8 @@ Under this extended model, `DerivingPath`s are thus inductively built up from an ### Encoding {#deriving-path-encoding} -The encoding is adjusted in a very simplest way, merely displaying the same +The encoding is adjusted in the natural way, encoding the `drv` field recursively using the same deriving path encoding. +The result of this is that it is possible to have a chain of `^` at the end of the final string, as opposed to just a single one. > **Example** > From f2d5be95cc454c653d3f481b5e127d45fc0e4457 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 13:34:00 -0500 Subject: [PATCH 18/21] Remove store-layer `__structuredAttrs` docs It is too much of an explanation. There are other docs we can move here later in the language section already. --- doc/manual/source/store/drv.md | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/doc/manual/source/store/drv.md b/doc/manual/source/store/drv.md index 06ea16219a5..58549ac14b2 100644 --- a/doc/manual/source/store/drv.md +++ b/doc/manual/source/store/drv.md @@ -309,22 +309,3 @@ The result of this is that it is possible to have a chain of `^` at > |------------------------------------------------------------| |-----| > innermost constant store path (usual encoding) output name > ``` - -## Extra extensions - -### `__structuredAttrs` - -Historically speaking, most users of Nix made GNU Bash with a script the command run, regardless of what they were doing. -Bash variable are automatically created from env vars, but bash also supports array and string-keyed map variables in addition to string variables. -People also usually create derivations using language which also support these richer data types. -It was thus desired a way to get this data from the language "planning" the derivation to language to bash, the language evaluated at "run time". - -`__structuredAttrs` does this by smuggling inside the core derivation format a map of named richer data. -At run time, this becomes two things: - -1. A JSON file containing that map. -2. A bash script setting those variables. - -The bash command can be passed a script which will "source" that Nix-created bash script, setting those variables with the richer data. -The outer script can then do whatever it likes with those richer variables as input. - From 86f23c2f555f411b7765705c931a2a65cd728d5d Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 13:38:33 -0500 Subject: [PATCH 19/21] Fix build failure --- src/libexpr/primops.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index ff6cfe5454e..9239ef81c03 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1587,7 +1587,7 @@ static RegisterPrimOp primop_placeholder({ .args = {"output"}, .doc = R"( Return at - [output placeholder string](@docroot@/source/store/drv.md#output-placeholder) + [output placeholder string](@docroot@/store/drv.md#output-placeholder) for the specified *output* that will be substituted by the corresponding [output path](@docroot@/glossary.md#gloss-output-path) at build time. @@ -2132,7 +2132,7 @@ static RegisterPrimOp primop_outputOf({ .doc = R"( Return at Return the output path of a derivation, literally or using an - [input placeholder string](@docroot@/source/store/drv.md#input-placeholder) + [input placeholder string](@docroot@/store/drv.md#input-placeholder) if needed. If the derivation has a statically-known output path (i.e. the derivation output is input-addressed, or fixed content-addresed), the output path will just be returned. From 3a3f6adde27abe0c4d4fbaf1efff9b54de76296b Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 16:57:29 -0500 Subject: [PATCH 20/21] Rework "Processing outputs" slightly --- doc/manual/source/store/building.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/doc/manual/source/store/building.md b/doc/manual/source/store/building.md index a5929bc8304..66a1add014d 100644 --- a/doc/manual/source/store/building.md +++ b/doc/manual/source/store/building.md @@ -65,19 +65,28 @@ The [`builder`](./drv.md#builder) is executed as follows: - The temporary directory is removed (unless the `-K` option was specified). -## Processing outputs and Reference scanning +## Processing outputs -- After the build, Nix sets the last-modified timestamp on all files +If the builder exited successfully, the following steps happen in order to turn the output directories left behind by the builder into proper store objects: + +- **Normalize the file permissions** + + Nix sets the last-modified timestamp on all files in the build result to 1 (00:00:01 1/1/1970 UTC), sets the group to the default group, and sets the mode of the file to 0444 or 0555 (i.e., read-only, with execute permission enabled if the file was - originally executable). Note that possible `setuid` and `setgid` - bits are cleared. Setuid and setgid programs are not currently - supported by Nix. This is because the Nix archives used in - deployment have no concept of ownership information, and because it - makes the build result dependent on the user performing the build. + originally executable). Any possible `setuid` and `setgid` + bits are cleared. + + > **Note** + > + > Setuid and setgid programs are not currently supported by Nix. + > This is because the Nix archives used in deployment have no concept of ownership information, + > and because it makes the build result dependent on the user performing the build. + +- **Calculate the references** -- If the build was successful, Nix scans each output path for + Nix scans each output path for references to input paths by looking for the hash parts of the input paths. Since these are potential runtime dependencies, Nix registers them as dependencies of the output paths. From b027e22758eef432a61a49bf853fb30978cf5219 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 20 Jan 2025 16:57:52 -0500 Subject: [PATCH 21/21] Fix missing link --- doc/manual/source/store/building.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/manual/source/store/building.md b/doc/manual/source/store/building.md index 66a1add014d..79808273edc 100644 --- a/doc/manual/source/store/building.md +++ b/doc/manual/source/store/building.md @@ -4,6 +4,8 @@ - Each input must be [realised] prior to building the derivation in question. +[realised]: @docroot@/glossary.md#gloss-realise + - Once this is done, the derivation is *normalized*, replacing each input deriving path with its store path, which we now know from realising the input. ## Builder Execution