doc: Add "Build Phases" section.
* doc/guix.texi (Build Phases): New section. (Build Systems): Remove 'modify-phases' example and add cross-reference to "Build Phases". (Build Utilities)[Build Phases]: Simplify intro and link to "Build Phases". (G-Expressions): Add index entries for "code staging" and add cross-reference to "Build Phases".
This commit is contained in:
		
							parent
							
								
									39befb6261
								
							
						
					
					
						commit
						5513d621e9
					
				
					 1 changed files with 169 additions and 18 deletions
				
			
		
							
								
								
									
										187
									
								
								doc/guix.texi
									
										
									
									
									
								
							
							
						
						
									
										187
									
								
								doc/guix.texi
									
										
									
									
									
								
							|  | @ -252,6 +252,7 @@ Programming Interface | |||
| * Package Modules::             Packages from the programmer's viewpoint. | ||||
| * Defining Packages::           Defining new packages. | ||||
| * Build Systems::               Specifying how packages are built. | ||||
| * Build Phases::                Phases of the build process of a package. | ||||
| * Build Utilities::             Helpers for your package definitions and more. | ||||
| * The Store::                   Manipulating the package store. | ||||
| * Derivations::                 Low-level interface to package derivations. | ||||
|  | @ -6086,6 +6087,7 @@ package definitions. | |||
| * Package Modules::             Packages from the programmer's viewpoint. | ||||
| * Defining Packages::           Defining new packages. | ||||
| * Build Systems::               Specifying how packages are built. | ||||
| * Build Phases::                Phases of the build process of a package. | ||||
| * Build Utilities::             Helpers for your package definitions and more. | ||||
| * The Store::                   Manipulating the package store. | ||||
| * Derivations::                 Low-level interface to package derivations. | ||||
|  | @ -6877,16 +6879,8 @@ The build-side module @code{(guix build gnu-build-system)} defines | |||
| @code{%standard-phases} is a list of symbol/procedure pairs, where the | ||||
| procedure implements the actual phase. | ||||
| 
 | ||||
| The list of phases used for a particular package can be changed with the | ||||
| @code{#:phases} parameter.  For instance, passing: | ||||
| 
 | ||||
| @example | ||||
| #:phases (modify-phases %standard-phases (delete 'configure)) | ||||
| @end example | ||||
| 
 | ||||
| means that all the phases described above will be used, except the | ||||
| @code{configure} phase.  @xref{Build Utilities}, for more info on | ||||
| @code{modify-phases} and build phases in general. | ||||
| @xref{Build Phases}, for more info on build phases and ways to customize | ||||
| them. | ||||
| 
 | ||||
| In addition, this build system ensures that the ``standard'' environment | ||||
| for GNU packages is available.  This includes tools such as GCC, libc, | ||||
|  | @ -7716,6 +7710,162 @@ with @code{build-expression->derivation} (@pxref{Derivations, | |||
| @code{build-expression->derivation}}). | ||||
| @end defvr | ||||
| 
 | ||||
| @node Build Phases | ||||
| @section Build Phases | ||||
| 
 | ||||
| @cindex build phases, for packages | ||||
| Almost all package build systems implement a notion @dfn{build phases}: | ||||
| a sequence of actions that the build system executes, when you build the | ||||
| package, leading to the installed byproducts in the store.  A notable | ||||
| exception is the ``bare-bones'' @code{trivial-build-system} | ||||
| (@pxref{Build Systems}). | ||||
| 
 | ||||
| As discussed in the previous section, those build systems provide a | ||||
| standard list of phases.  For @code{gnu-build-system}, the standard | ||||
| phases include an @code{unpack} phase to unpack the source code tarball, | ||||
| a @command{configure} phase to run @code{./configure}, a @code{build} | ||||
| phase to run @command{make}, and (among others) an @code{install} phase | ||||
| to run @command{make install}; @pxref{Build Systems}, for a more | ||||
| detailed view of these phases.  Likewise, @code{cmake-build-system} | ||||
| inherits these phases, but its @code{configure} phase runs | ||||
| @command{cmake} instead of @command{./configure}.  Other build systems, | ||||
| such as @code{python-build-system}, have a wholly different list of | ||||
| standard phases.  All this code runs on the @dfn{build side}: it is | ||||
| evaluated when you actually build the package, in a dedicated build | ||||
| process spawned by the build daemon (@pxref{Invoking guix-daemon}). | ||||
| 
 | ||||
| Build phases are represented as association lists or ``alists'' | ||||
| (@pxref{Association Lists,,, guile, GNU Guile Reference Manual}) where | ||||
| each key is a symbol for the name of the phase and the associated value | ||||
| is a procedure that accepts an arbitrary number of arguments.  By | ||||
| convention, those procedures receive information about the build in the | ||||
| form of @dfn{keyword parameters}, which they can use or ignore. | ||||
| 
 | ||||
| For example, here is how @code{(guix build gnu-build-system)} defines | ||||
| @code{%standard-phases}, the variable holding its alist of build | ||||
| phases@footnote{We present a simplified view of those build phases, but | ||||
| do take a look at @code{(guix build gnu-build-system)} to see all the | ||||
| details!}: | ||||
| 
 | ||||
| @lisp | ||||
| ;; The build phases of 'gnu-build-system'. | ||||
| 
 | ||||
| (define* (unpack #:key source #:allow-other-keys) | ||||
|   ;; Extract the source tarball. | ||||
|   (invoke "tar" "xvf" source)) | ||||
| 
 | ||||
| (define* (configure #:key outputs #:allow-other-keys) | ||||
|   ;; Run the 'configure' script.  Install to output "out". | ||||
|   (let ((out (assoc-ref outputs "out"))) | ||||
|     (invoke "./configure" | ||||
|             (string-append "--prefix=" out)))) | ||||
| 
 | ||||
| (define* (build #:allow-other-keys) | ||||
|   ;; Compile. | ||||
|   (invoke "make")) | ||||
| 
 | ||||
| (define* (check #:key (test-target "check") (tests? #true) | ||||
|                 #:allow-other-keys) | ||||
|   ;; Run the test suite. | ||||
|   (if tests? | ||||
|       (invoke "make" test-target) | ||||
|       (display "test suite not run\n"))) | ||||
| 
 | ||||
| (define* (install #:allow-other-keys) | ||||
|   ;; Install files to the prefix 'configure' specified. | ||||
|   (invoke "make" "install")) | ||||
| 
 | ||||
| (define %standard-phases | ||||
|   ;; The list of standard phases (quite a few are omitted | ||||
|   ;; for brevity).  Each element is a symbol/procedure pair. | ||||
|   (list (cons 'unpack unpack) | ||||
|         (cons 'configure configure) | ||||
|         (cons 'build build) | ||||
|         (cons 'check check) | ||||
|         (cons 'install install))) | ||||
| @end lisp | ||||
| 
 | ||||
| This shows how @code{%standard-phases} is defined as a list of | ||||
| symbol/procedure pairs (@pxref{Pairs,,, guile, GNU Guile Reference | ||||
| Manual}).  The first pair associates the @code{unpack} procedure with | ||||
| the @code{unpack} symbol---a name; the second pair defines the | ||||
| @code{configure} phase similarly, and so on.  When building a package | ||||
| that uses @code{gnu-build-system} with its default list of phases, those | ||||
| phases are executed sequentially.  You can see the name of each phase | ||||
| started and completed in the build log of packages that you build. | ||||
| 
 | ||||
| Let's now look at the procedures themselves.  Each one is defined with | ||||
| @code{define*}: @code{#:key} lists keyword parameters the procedure | ||||
| accepts, possibly with a default value, and @code{#:allow-other-keys} | ||||
| specifies that other keyword parameters are ignored (@pxref{Optional | ||||
| Arguments,,, guile, GNU Guile Reference Manual}). | ||||
| 
 | ||||
| The @code{unpack} procedure honors the @code{source} parameter, which | ||||
| the build system uses to pass the file name of the source tarball (or | ||||
| version control checkout), and it ignores other parameters.  The | ||||
| @code{configure} phase only cares about the @code{outputs} parameter, an | ||||
| alist mapping package output names to their store file name | ||||
| (@pxref{Packages with Multiple Outputs}).  It extracts the file name of | ||||
| for @code{out}, the default output, and passes it to | ||||
| @command{./configure} as the installation prefix, meaning that | ||||
| @command{make install} will eventually copy all the files in that | ||||
| directory (@pxref{Configuration, configuration and makefile | ||||
| conventions,, standards, GNU Coding Standards}).  @code{build} and | ||||
| @code{install} ignore all their arguments.  @code{check} honors the | ||||
| @code{test-target} argument, which specifies the name of the Makefile | ||||
| target to run tests; it prints a message and skips tests when | ||||
| @code{tests?} is false. | ||||
| 
 | ||||
| @cindex build phases, customizing | ||||
| The list of phases used for a particular package can be changed with the | ||||
| @code{#:phases} parameter of the build system.  Changing the set of | ||||
| build phases boils down to building a new alist of phases based on the | ||||
| @code{%standard-phases} alist described above.  This can be done with | ||||
| standard alist procedures such as @code{alist-delete} (@pxref{SRFI-1 | ||||
| Association Lists,,, guile, GNU Guile Reference Manual}); however, it is | ||||
| more convenient to do so with @code{modify-phases} (@pxref{Build | ||||
| Utilities, @code{modify-phases}}). | ||||
| 
 | ||||
| Here is an example of a package definition that removes the | ||||
| @code{configure} phase of @code{%standard-phases} and inserts a new | ||||
| phase before the @code{build} phase, called | ||||
| @code{set-prefix-in-makefile}: | ||||
| 
 | ||||
| @example | ||||
| (define-public example | ||||
|   (package | ||||
|     (name "example") | ||||
|     ;; other fields omitted | ||||
|     (build-system gnu-build-system) | ||||
|     (arguments | ||||
|      '(#:phases (modify-phases %standard-phases | ||||
|                   (delete 'configure) | ||||
|                   (add-before 'build 'set-prefix-in-makefile | ||||
|                     (lambda* (#:key outputs #:allow-other-keys) | ||||
|                       ;; Modify the makefile so that its | ||||
|                       ;; 'PREFIX' variable points to "out". | ||||
|                       (let ((out (assoc-ref outputs "out"))) | ||||
|                         (substitute* "Makefile" | ||||
|                           (("PREFIX =.*") | ||||
|                            (string-append "PREFIX = " | ||||
|                                           out "\n"))) | ||||
|                         #true)))))))) | ||||
| @end example | ||||
| 
 | ||||
| The new phase that is inserted is written as an anonymous procedure, | ||||
| introduced with @code{lambda*}; it honors the @code{outputs} parameter | ||||
| we have seen before.  @xref{Build Utilities}, for more about the helpers | ||||
| used by this phase, and for more examples of @code{modify-phases}. | ||||
| 
 | ||||
| @cindex code staging | ||||
| @cindex staging, of code | ||||
| Keep in mind that build phases are code evaluated at the time the | ||||
| package is actually built.  This explains why the whole | ||||
| @code{modify-phases} expression above is quoted (it comes after the | ||||
| @code{'} or apostrophe): it is @dfn{staged} for later execution. | ||||
| @xref{G-Expressions}, for an explanation of code staging and the | ||||
| @dfn{code strata} involved. | ||||
| 
 | ||||
| @node Build Utilities | ||||
| @section Build Utilities | ||||
| 
 | ||||
|  | @ -7929,13 +8079,12 @@ Return the complete file name for @var{program} as found in | |||
| @subsection Build Phases | ||||
| 
 | ||||
| @cindex build phases | ||||
| The @code{(guix build utils)} also contains tools to manipulate | ||||
| @dfn{build phases} as found in @code{gnu-build-system} and in fact most | ||||
| build systems (@pxref{Build Systems}).  Build phases are represented as | ||||
| association lists or ``alists'' (@pxref{Association Lists,,, guile, GNU | ||||
| Guile Reference Manual}) where each key is a symbol for the name of the | ||||
| phase, and the associated value is a procedure that accepts an arbitrary | ||||
| number of arguments. | ||||
| The @code{(guix build utils)} also contains tools to manipulate build | ||||
| phases as used by build systems (@pxref{Build Systems}).  Build phases | ||||
| are represented as association lists or ``alists'' (@pxref{Association | ||||
| Lists,,, guile, GNU Guile Reference Manual}) where each key is a symbol | ||||
| naming the phase and the associated value is a procedure (@pxref{Build | ||||
| Phases}). | ||||
| 
 | ||||
| Guile core and the @code{(srfi srfi-1)} module both provide tools to | ||||
| manipulate alists.  The @code{(guix build utils)} module complements | ||||
|  | @ -8681,6 +8830,8 @@ These build actions are performed when asking the daemon to actually | |||
| build the derivations; they are run by the daemon in a container | ||||
| (@pxref{Invoking guix-daemon}). | ||||
| 
 | ||||
| @cindex code staging | ||||
| @cindex staging, of code | ||||
| @cindex strata of code | ||||
| It should come as no surprise that we like to write these build actions | ||||
| in Scheme.  When we do that, we end up with two @dfn{strata} of Scheme | ||||
|  | @ -8692,7 +8843,7 @@ on this topic}, refers to this kind of code generation as | |||
| @dfn{staging}.}: the ``host code''---code that defines packages, talks | ||||
| to the daemon, etc.---and the ``build code''---code that actually | ||||
| performs build actions, such as making directories, invoking | ||||
| @command{make}, etc. | ||||
| @command{make}, and so on (@pxref{Build Phases}). | ||||
| 
 | ||||
| To describe a derivation and its build actions, one typically needs to | ||||
| embed build code inside host code.  It boils down to manipulating build | ||||
|  |  | |||
		Reference in a new issue