Next: , Previous: , Up: Programming Interface   [Contents][Index]

4.4 Derivations

Low-level build actions and the environment in which they are performed are represented by derivations. A derivation contain the following pieces of information:

Derivations allow clients of the daemon to communicate build actions to the store. They exist in two forms: as an in-memory representation, both on the client- and daemon-side, and as files in the store whose name end in .drv—these files are referred to as derivation paths. Derivations paths can be passed to the build-derivations procedure to perform the build actions they prescribe (see The Store).

The (guix derivations) module provides a representation of derivations as Scheme objects, along with procedures to create and otherwise manipulate derivations. The lowest-level primitive to create a derivation is the derivation procedure:

Scheme Procedure: derivation store name builder args [#:outputs '("out")] [#:hash #f] [#:hash-algo #f] [#:recursive? #f] [#:inputs '()] [#:env-vars '()] [#:system (%current-system)] [#:references-graphs #f] [#:local-build? #f]

Build a derivation with the given arguments, and return the resulting <derivation> object.

When hash and hash-algo are given, a fixed-output derivation is created—i.e., one whose result is known in advance, such as a file download. If, in addition, recursive? is true, then that fixed output may be an executable file or a directory and hash must be the hash of an archive containing this output.

When references-graphs is true, it must be a list of file name/store path pairs. In that case, the reference graph of each store path is exported in the build environment in the corresponding file, in a simple text format.

When local-build? is true, declare that the derivation is not a good candidate for offloading and should rather be built locally (see Daemon Offload Setup). This is the case for small derivations where the costs of data transfers would outweigh the benefits.

Here’s an example with a shell script as its builder, assuming store is an open connection to the daemon, and bash points to a Bash executable in the store:

(use-modules (guix utils)
             (guix store)
             (guix derivations))

(let ((builder   ; add the Bash script to the store
        (add-text-to-store store ""
                           "echo hello world > $out\n" '())))
  (derivation store "foo"
              bash `("-e" ,builder)
              #:env-vars '(("HOME" . "/homeless"))))
⇒ #<derivation /gnu/store/…-foo.drv => /gnu/store/…-foo>

As can be guessed, this primitive is cumbersome to use directly. An improved variant is build-expression->derivation, which allows the caller to directly pass a Guile expression as the build script:

Scheme Procedure: build-expression->derivation store name exp [#:system (%current-system)] [#:inputs '()] [#:outputs '("out")] [#:hash #f] [#:hash-algo #f] [#:recursive? #f] [#:env-vars '()] [#:modules '()] [#:references-graphs #f] [#:local-build? #f] [#:guile-for-build #f]

Return a derivation that executes Scheme expression exp as a builder for derivation name. inputs must be a list of (name drv-path sub-drv) tuples; when sub-drv is omitted, "out" is assumed. modules is a list of names of Guile modules from the current search path to be copied in the store, compiled, and made available in the load path during the execution of exp—e.g., ((guix build utils) (guix build gnu-build-system)).

exp is evaluated in an environment where %outputs is bound to a list of output/path pairs, and where %build-inputs is bound to a list of string/output-path pairs made from inputs. Optionally, env-vars is a list of string pairs specifying the name and value of environment variables visible to the builder. The builder terminates by passing the result of exp to exit; thus, when exp returns #f, the build is considered to have failed.

exp is built using guile-for-build (a derivation). When guile-for-build is omitted or is #f, the value of the %guile-for-build fluid is used instead.

See the derivation procedure for the meaning of references-graphs and local-build?.

Here’s an example of a single-output derivation that creates a directory containing one file:

(let ((builder '(let ((out (assoc-ref %outputs "out")))
                  (mkdir out)    ; create /gnu/store/…-goo
                  (call-with-output-file (string-append out "/test")
                    (lambda (p)
                      (display '(hello guix) p))))))
  (build-expression->derivation store "goo" builder))

⇒ #<derivation /gnu/store/…-goo.drv => …>

Remember that the build expression passed to build-expression->derivation is run by a separate Guile process than the one that calls build-expression->derivation: it is run by a Guile process launched by the daemon, typically in a chroot. So, while there is a single language for both the host and the build side, there are really two strata of code: the host-side, and the build-side code5. This distinction is important to keep in mind, notably when using higher-level constructs such as gnu-build-system (see Defining Packages). For this reason, Guix modules that are meant to be used in the build stratum are kept in the (guix build …) name space.



The term stratum in this context was coined by Manuel Serrano et al. in the context of their work on Hop.

Next: , Previous: , Up: Programming Interface   [Contents][Index]