|
|
(One intermediate revision by one other user not shown) |
Line 1: |
Line 1: |
| Import From Derivation (IFD) is where during a single Nix evaluation, the
| | See the Nix manual: [https://nixos.org/manual/nix/unstable/language/import-from-derivation Import From Derivation] |
| Nix expression:
| |
| | |
| # creates a derivation which will build a Nix expression
| |
| # imports that expression
| |
| # uses the results of the evaluation of the expression.
| |
| | |
| An example of IFD is:
| |
| | |
| <syntaxHighlight lang=nix>
| |
| let
| |
| pkgs = import <nixpkgs> {};
| |
| | |
| # Create a derivation which, when built, writes some Nix code to
| |
| # its $out path.
| |
| derivation-to-import = pkgs.writeText "example" ''
| |
| pkgs: {
| |
| ifd-example = pkgs.stdenv.mkDerivation rec {
| |
| name = "hello-2.10-ifd-example";
| |
| | |
| | |
| src = pkgs.fetchurl {
| |
| url = "mirror://gnu/hello/2.10.tar.gz";
| |
| sha256 = "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i";
| |
| };
| |
| };
| |
| }
| |
| '';
| |
| | |
| # Import the derivation. This forces `derivation-to-import` to become
| |
| # a string. This is normal behavior for Nix and Nixpkgs. The specific
| |
| # difference here is the evaluation itself requires the result to be
| |
| # built during the evaluation in order to continue evaluating.
| |
| imported-derivation = import derivation-to-import;
| |
| | |
| # Treat the imported-derivation variable as if we hadn't just created
| |
| # its Nix expression inside this same evaluation.
| |
| hello-package = (imported-derivation pkgs).ifd-example;
| |
| in hello-package
| |
| </syntaxHighlight>
| |
| | |
| Building this looks familiar, but with an extra <code>building ...</code> line:
| |
| | |
| {{Commands|<nowiki>
| |
| $ nix-build ./test.nix
| |
| building '/nix/store/8n001pyx2iqsnzd6niji1bvyjlg6x058-example.drv'... <- this build is forced at
| |
| evaluation time
| |
| | |
| these derivations will be built: <- now we're back to normal
| |
| nix-build behavior
| |
| /nix/store/3nm9rlv5smmvijcdifngjwl4v6zvll7k-hello-2.10-ifd-example.drv
| |
| | |
| building '/nix/store/3nm9rlv5smmvijcdifngjwl4v6zvll7k-hello-2.10-ifd-example.drv'...
| |
| [...snip...] | |
| </nowiki>}}
| |
| | |
| we'll see pretty similar output if we just evaluate it:
| |
| | |
| {{Commands|<nowiki>
| |
| $ nix-instantiate ./test.nix
| |
| building '/nix/store/8n001pyx2iqsnzd6niji1bvyjlg6x058-example.drv'...
| |
| | |
| /nix/store/3nm9rlv5smmvijcdifngjwl4v6zvll7k-hello-2.10-ifd-example.drv
| |
| </nowiki>}}
| |
| | |
| Some examples of IFD can be seen when using nixpkgs to fetch a specific
| |
| version of nixpkgs, and then importing the source.
| |
| | |
| == When to use IFD ==
| |
| | |
| IFD is a powerful feature, but it should be avoided _if possible_. IFD extends the duration of evaluation, which is single threaded and it affects the predictions of the `nix` progress bar.
| |
| | |
| Acceptable uses of IFD include importing a pinned nixpkgs and automation around lock files. Such uses vastly improve your development workflow, outweighing the slight disadvantages of IFD.
| |
| | |
| As a rule of thumb, if you can avoid IFD by refactoring Nix code or moving your build logic into the derivations themselves, you should do so.
| |
| | |
| == Recognizing IFD ==
| |
| | |
| The textbook case of IFD looks like <code>import (f drv)</code> where <code>f drv</code> is an expression that requires a build in order to return a value. However, <code>import</code> is not the only function that can require a build. For example, <code>builtins.readFile</code> can have the same effect.
| |
| | |
| All functions that query the filesystem will require a build when invoked on a derivation output path or subpath. This has the same effect and is therefore also called IFD. These include
| |
| | |
| * <code>import (f drv)</code>
| |
| * <code>builtins.readFile (f drv)</code>
| |
| * <code>builtins.readDir (f drv)</code>
| |
| * <code>builtins.pathExists (f drv)</code>
| |
| * <code>builtins.filterSource g (f drv) </code>
| |
| * <code>builtins.path { path = f drv; }</code>
| |
| * <code>builtins.hashFile t (f drv)</code>
| |
| * <code>builtins.scopedImport x (f drv)</code>
| |
| * potentially other functions if those read the filesystem in any way
| |
| * '''library functions''' that invoke the above, such as
| |
| * <code>lib.cleanSource { src = f drv; }</code>
| |
| * ...
| |
| | |
| == IFD and Haskell ==
| |
| | |
| <code>callCabal2nix</code>, which is implicitly used for building Haskell projects, uses IFD.[https://github.com/NixOS/templates/issues/28][https://discourse.nixos.org/t/another-simple-flake-for-haskell-development/18164/6]. This means that since IFD is disabled by default in certain nix commands,[https://github.com/NixOS/nix/pull/5253] the following commands will be broken for Haskell projects whose flake output specifies multiple system attributes:
| |
| | |
| * <code>nix flake show</code>
| |
| * <code>nix flake check</code>
| |
|
| |
|
| == Further reading == | | == Further reading == |
|
| |
|
| * https://fzakaria.com/2020/10/21/nix-parallelism-import-from-derivation.html | | * https://fzakaria.com/2020/10/20/nix-parallelism-import-from-derivation.html |
|
| |
|
| [[Category: Nix]] | | [[Category: Nix]] |