Previous: The Store, Up: Programming Interface [Contents][Index]
Low-level build actions and the environment in which they are performed are represented by derivations. A derivation contain the following pieces of information:
x86_64-linux.
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:
Build a derivation with the given arguments. Return the resulting store
path and <derivation> object.
When hash, hash-algo, and hash-mode are given, a fixed-output derivation is created—i.e., one whose result is known in advance, such as a file download.
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))
(call-with-values
(lambda ()
(let ((builder ; add the Bash script to the store
(add-text-to-store store "my-builder.sh"
"echo hello world > $out\n" '())))
(derivation store "foo" (%current-system)
bash `("-e" ,builder)
'(("HOME" . "/homeless")) '())))
list)
⇒ ("/nix/store/…-foo.drv" #<<derivation> …>)
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:
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.
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 /nix/store/…-goo
(call-with-output-file (string-append out "/test")
(lambda (p)
(display '(hello guix) p))))))
(build-expression->derivation store "goo" (%current-system)
builder '()))
⇒ "/nix/store/…-goo.drv"
⇒ #<<derivation> …>
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 code3.
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.
Previous: The Store, Up: Programming Interface [Contents][Index]