diff --git a/doc/guix.texi b/doc/guix.texi index cae55c1942..10ca9b76ad 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -3810,6 +3810,7 @@ described in the subsections below. @menu * Common Build Options:: Build options for most commands. +* Package Transformation Options:: Creating variants of packages. * Additional Build Options:: Options specific to 'guix build'. @end menu @@ -3939,6 +3940,56 @@ These options are parsed independently, and the result is appended to the parsed command-line options. @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 @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 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} @item --check @cindex determinism, checking diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm index 77f7a0c3bf..b37d923b3a 100644 --- a/guix/scripts/build.scm +++ b/guix/scripts/build.scm @@ -41,7 +41,10 @@ set-build-options-from-command-line set-build-options-from-command-line* show-build-options-help + + %transformation-options options->transformation + show-transformation-options-help guix-build)) @@ -140,6 +143,82 @@ the new package's version number from URI." (source (download-to-store store uri #: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. @@ -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\"")) (display (_ " --target=TRIPLET cross-build for TRIPLET--e.g., \"armel-linux-gnu\"")) - (display (_ " - --with-source=SOURCE - use SOURCE when building the corresponding package")) (display (_ " --no-grafts do not graft packages")) (display (_ " @@ -337,6 +413,8 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n")) (newline) (show-build-options-help) (newline) + (show-transformation-options-help) + (newline) (display (_ " -h, --help display this help and exit")) (display (_ " @@ -369,12 +447,12 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n")) (leave (_ "invalid argument: '~a' option argument: ~a, ~ must be one of 'package', 'all', or 'transitive'~%") name arg))))) - (option '("check") #f #f - (lambda (opt name arg result . rest) - (apply values - (alist-cons 'build-mode (build-mode check) - result) - rest))) + (option '("check") #f #f + (lambda (opt name arg result . rest) + (apply values + (alist-cons 'build-mode (build-mode check) + result) + rest))) (option '(#\s "system") #t #f (lambda (opt name arg result) (alist-cons 'system arg @@ -401,15 +479,13 @@ must be one of 'package', 'all', or 'transitive'~%") (option '("log-file") #f #f (lambda (opt name arg 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 (lambda (opt name arg result) (alist-cons 'graft? #f (alist-delete 'graft? result eq?)))) - %standard-build-options)) + (append %transformation-options + %standard-build-options))) (define (options->things-to-build opts) "Read the arguments from OPTS and return a list of high-level objects to @@ -488,63 +564,6 @@ build." (map (cut transform store <>) (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) "Show the build log for FILE, falling back to remote logs from URLS if needed."