guix build: Separate transformation options.

* guix/scripts/build.scm (%transformation-options): New variable.
(show-transformation-options-help): New procedure.
(show-help): Remove '--with-source' documentation and add
'show-transformation-options-help' call.
(%options): Remove "with-source" and append %TRANSFORMATION-OPTIONS.
* doc/guix.texi (Package Transformation Options): New node.  Document
'--with-source', moved from...
(Additional Build Options): ... here.
This commit is contained in:
Ludovic Courtès 2016-01-31 20:44:21 +01:00
parent ccd7158d2a
commit 88ad6deda6
2 changed files with 140 additions and 104 deletions

@ -3810,6 +3810,7 @@ described in the subsections below.
@menu @menu
* Common Build Options:: Build options for most commands. * Common Build Options:: Build options for most commands.
* Package Transformation Options:: Creating variants of packages.
* Additional Build Options:: Options specific to 'guix build'. * Additional Build Options:: Options specific to 'guix build'.
@end menu @end menu
@ -3939,6 +3940,56 @@ These options are parsed independently, and the result is appended to
the parsed command-line options. the parsed command-line options.
@end defvr @end defvr
@node Package Transformation Options
@subsection Package Transformation Options
@cindex package variants
Another set of command-line options supported by @command{guix build}
are @dfn{package transformation options}. These are options that allow,
from the command-line, to define @dfn{package variants}---for instance,
packages built from different source code. This is a convenient way to
create customized packages on the fly without having to type in the
definitions of package variants (@pxref{Defining Packages}).
@table @code
@item --with-source=@var{source}
Use @var{source} as the source of the corresponding package.
@var{source} must be a file name or a URL, as for @command{guix
download} (@pxref{Invoking guix download}).
The ``corresponding package'' is taken to be one specified on the
command line whose name matches the base of @var{source}---e.g., if
@var{source} is @code{/src/guile-2.0.10.tar.gz}, the corresponding
package is @code{guile}. Likewise, the version string is inferred from
@var{source}; in the previous example, it's @code{2.0.10}.
This option allows users to try out versions of packages other than the
one provided by the distribution. The example below downloads
@file{ed-1.7.tar.gz} from a GNU mirror and uses that as the source for
the @code{ed} package:
@example
guix build ed --with-source=mirror://gnu/ed/ed-1.7.tar.gz
@end example
As a developer, @code{--with-source} makes it easy to test release
candidates:
@example
guix build guile --with-source=../guile-2.0.9.219-e1bb7.tar.xz
@end example
@dots{} or to build from a checkout in a pristine environment:
@example
$ git clone git://git.sv.gnu.org/guix.git
$ guix build guix --with-source=./guix
@end example
@end table
@node Additional Build Options @node Additional Build Options
@subsection Additional Build Options @subsection Additional Build Options
@ -4047,40 +4098,6 @@ Cross-build for @var{triplet}, which must be a valid GNU triplet, such
as @code{"mips64el-linux-gnu"} (@pxref{Configuration Names, GNU as @code{"mips64el-linux-gnu"} (@pxref{Configuration Names, GNU
configuration triplets,, configure, GNU Configure and Build System}). configuration triplets,, configure, GNU Configure and Build System}).
@item --with-source=@var{source}
Use @var{source} as the source of the corresponding package.
@var{source} must be a file name or a URL, as for @command{guix
download} (@pxref{Invoking guix download}).
The ``corresponding package'' is taken to be one specified on the
command line whose name matches the base of @var{source}---e.g., if
@var{source} is @code{/src/guile-2.0.10.tar.gz}, the corresponding
package is @code{guile}. Likewise, the version string is inferred from
@var{source}; in the previous example, it's @code{2.0.10}.
This option allows users to try out versions of packages other than the
one provided by the distribution. The example below downloads
@file{ed-1.7.tar.gz} from a GNU mirror and uses that as the source for
the @code{ed} package:
@example
guix build ed --with-source=mirror://gnu/ed/ed-1.7.tar.gz
@end example
As a developer, @code{--with-source} makes it easy to test release
candidates:
@example
guix build guile --with-source=../guile-2.0.9.219-e1bb7.tar.xz
@end example
@dots{} or to build from a checkout in a pristine environment:
@example
$ git clone git://git.sv.gnu.org/guix.git
$ guix build guix --with-source=./guix
@end example
@anchor{build-check} @anchor{build-check}
@item --check @item --check
@cindex determinism, checking @cindex determinism, checking

@ -41,7 +41,10 @@
set-build-options-from-command-line set-build-options-from-command-line
set-build-options-from-command-line* set-build-options-from-command-line*
show-build-options-help show-build-options-help
%transformation-options
options->transformation options->transformation
show-transformation-options-help
guix-build)) guix-build))
@ -140,6 +143,82 @@ the new package's version number from URI."
(source (download-to-store store uri (source (download-to-store store uri
#:recursive? #t)))))) #:recursive? #t))))))
;;;
;;; Transformations.
;;;
(define (transform-package-source sources)
"Return a transformation procedure that replaces package sources with the
matching URIs given in SOURCES."
(define new-sources
(map (lambda (uri)
(cons (package-name->name+version (basename uri))
uri))
sources))
(lambda (store obj)
(let loop ((sources new-sources)
(result '()))
(match obj
((? package? p)
(let ((source (assoc-ref sources (package-name p))))
(if source
(package-with-source store p source)
p)))
(_
obj)))))
(define %transformations
;; Transformations that can be applied to things to build. The car is the
;; key used in the option alist, and the cdr is the transformation
;; procedure; it is called with two arguments: the store, and a list of
;; things to build.
`((with-source . ,transform-package-source)))
(define %transformation-options
;; The command-line interface to the above transformations.
(list (option '("with-source") #t #f
(lambda (opt name arg result . rest)
(apply values
(cons (alist-cons 'with-source arg result)
rest))))))
(define (show-transformation-options-help)
(display (_ "
--with-source=SOURCE
use SOURCE when building the corresponding package")))
(define (options->transformation opts)
"Return a procedure that, when passed an object to build (package,
derivation, etc.), applies the transformations specified by OPTS."
(define applicable
;; List of applicable transformations as symbol/procedure pairs.
(filter-map (match-lambda
((key . transform)
(match (filter-map (match-lambda
((k . arg)
(and (eq? k key) arg)))
opts)
(() #f)
(args (cons key (transform args))))))
%transformations))
(lambda (store obj)
(fold (match-lambda*
(((name . transform) obj)
(let ((new (transform store obj)))
(when (eq? new obj)
(warning (_ "transformation '~a' had no effect on ~a~%")
name
(if (package? obj)
(package-full-name obj)
obj)))
new)))
obj
applicable)))
;;; ;;;
;;; Standard command-line build options. ;;; Standard command-line build options.
@ -320,9 +399,6 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
-s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\"")) -s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
(display (_ " (display (_ "
--target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\"")) --target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\""))
(display (_ "
--with-source=SOURCE
use SOURCE when building the corresponding package"))
(display (_ " (display (_ "
--no-grafts do not graft packages")) --no-grafts do not graft packages"))
(display (_ " (display (_ "
@ -337,6 +413,8 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
(newline) (newline)
(show-build-options-help) (show-build-options-help)
(newline) (newline)
(show-transformation-options-help)
(newline)
(display (_ " (display (_ "
-h, --help display this help and exit")) -h, --help display this help and exit"))
(display (_ " (display (_ "
@ -369,12 +447,12 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
(leave (_ "invalid argument: '~a' option argument: ~a, ~ (leave (_ "invalid argument: '~a' option argument: ~a, ~
must be one of 'package', 'all', or 'transitive'~%") must be one of 'package', 'all', or 'transitive'~%")
name arg))))) name arg)))))
(option '("check") #f #f (option '("check") #f #f
(lambda (opt name arg result . rest) (lambda (opt name arg result . rest)
(apply values (apply values
(alist-cons 'build-mode (build-mode check) (alist-cons 'build-mode (build-mode check)
result) result)
rest))) rest)))
(option '(#\s "system") #t #f (option '(#\s "system") #t #f
(lambda (opt name arg result) (lambda (opt name arg result)
(alist-cons 'system arg (alist-cons 'system arg
@ -401,15 +479,13 @@ must be one of 'package', 'all', or 'transitive'~%")
(option '("log-file") #f #f (option '("log-file") #f #f
(lambda (opt name arg result) (lambda (opt name arg result)
(alist-cons 'log-file? #t result))) (alist-cons 'log-file? #t result)))
(option '("with-source") #t #f
(lambda (opt name arg result)
(alist-cons 'with-source arg result)))
(option '("no-grafts") #f #f (option '("no-grafts") #f #f
(lambda (opt name arg result) (lambda (opt name arg result)
(alist-cons 'graft? #f (alist-cons 'graft? #f
(alist-delete 'graft? result eq?)))) (alist-delete 'graft? result eq?))))
%standard-build-options)) (append %transformation-options
%standard-build-options)))
(define (options->things-to-build opts) (define (options->things-to-build opts)
"Read the arguments from OPTS and return a list of high-level objects to "Read the arguments from OPTS and return a list of high-level objects to
@ -488,63 +564,6 @@ build."
(map (cut transform store <>) (map (cut transform store <>)
(options->things-to-build opts))))) (options->things-to-build opts)))))
(define (transform-package-source sources)
"Return a transformation procedure that replaces package sources with the
matching URIs given in SOURCES."
(define new-sources
(map (lambda (uri)
(cons (package-name->name+version (basename uri))
uri))
sources))
(lambda (store obj)
(let loop ((sources new-sources)
(result '()))
(match obj
((? package? p)
(let ((source (assoc-ref sources (package-name p))))
(if source
(package-with-source store p source)
p)))
(_
obj)))))
(define %transformations
;; Transformations that can be applied to things to build. The car is the
;; key used in the option alist, and the cdr is the transformation
;; procedure; it is called with two arguments: the store, and a list of
;; things to build.
`((with-source . ,transform-package-source)))
(define (options->transformation opts)
"Return a procedure that, when passed an object to build (package,
derivation, etc.), applies the transformations specified by OPTS."
(define applicable
;; List of applicable transformations as symbol/procedure pairs.
(filter-map (match-lambda
((key . transform)
(match (filter-map (match-lambda
((k . arg)
(and (eq? k key) arg)))
opts)
(() #f)
(args (cons key (transform args))))))
%transformations))
(lambda (store obj)
(fold (match-lambda*
(((name . transform) obj)
(let ((new (transform store obj)))
(when (eq? new obj)
(warning (_ "transformation '~a' had no effect on ~a~%")
name
(if (package? obj)
(package-full-name obj)
obj)))
new)))
obj
applicable)))
(define (show-build-log store file urls) (define (show-build-log store file urls)
"Show the build log for FILE, falling back to remote logs from URLS if "Show the build log for FILE, falling back to remote logs from URLS if
needed." needed."