packages: Implement grafts.
Thanks to Mark H. Weaver <mhw@netris.org> for insightful discussions and suggestions. * guix/packages.scm (<package>)[graft]: New field. (patch-and-repack): Invoke 'package-derivation' with #:graft? #f. (package-source-derivation): Likewise. Do not use (%guile-for-build) in call to 'patch-and-repack', and we could end up using a grafted Guile. (expand-input): Likewise, also for 'package-cross-derivation' call. (package->bag): Add #:graft? parameter. Honor it. Use 'strip-append' instead of 'package-full-name'. (input-graft, input-cross-graft, bag-grafts, package-grafts): New procedures. (package-derivation, package-cross-derivation): Add #:graft? parameter and honor it. * gnu/packages/bootstrap.scm (package-with-bootstrap-guile): Add recursive call on 'graft'. * guix/build-system/gnu.scm (package-with-explicit-inputs, package-with-extra-configure-variable, static-package): Likewise. (gnu-build): Use the ungrafted Guile to avoid full rebuilds. (gnu-cross-build): Likewise. * guix/build-system/cmake.scm (cmake-build): Likewise. * guix/build-system/glib-or-gtk.scm (glib-or-gtk-build): Likewise. * guix/build-system/perl.scm (perl-build): Likewise. * guix/build-system/python.scm (python-build): Likewise. * guix/build-system/ruby.scm (ruby-build): Likewise. * guix/build-system/trivial.scm (guile-for-build): Likewise. * tests/packages.scm ("package-derivation, direct graft", "package-cross-derivation, direct graft", "package-grafts, indirect grafts", "package-grafts, indirect grafts, cross", "package-grafts, indirect grafts, propagated inputs", "package-derivation, indirect grafts"): New tests. ("bag->derivation", "bag->derivation, cross-compilation"): Wrap in 'parameterize'. * doc/guix.texi (Security Updates): New node. (Invoking guix build): Document --no-graft.
This commit is contained in:
parent
50373bab7a
commit
05962f2958
@ -2569,6 +2569,10 @@ candidates:
|
|||||||
guix build guile --with-source=../guile-2.0.9.219-e1bb7.tar.xz
|
guix build guile --with-source=../guile-2.0.9.219-e1bb7.tar.xz
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@item --no-grafts
|
||||||
|
Do not ``graft'' packages. In practice, this means that package updates
|
||||||
|
available as grafts are not applied. @xref{Security Updates}, for more
|
||||||
|
information on grafts.
|
||||||
|
|
||||||
@item --derivations
|
@item --derivations
|
||||||
@itemx -d
|
@itemx -d
|
||||||
@ -3003,6 +3007,7 @@ For information on porting to other architectures or kernels,
|
|||||||
* System Installation:: Installing the whole operating system.
|
* System Installation:: Installing the whole operating system.
|
||||||
* System Configuration:: Configuring a GNU system.
|
* System Configuration:: Configuring a GNU system.
|
||||||
* Installing Debugging Files:: Feeding the debugger.
|
* Installing Debugging Files:: Feeding the debugger.
|
||||||
|
* Security Updates:: Deploying security fixes quickly.
|
||||||
* Package Modules:: Packages from the programmer's viewpoint.
|
* Package Modules:: Packages from the programmer's viewpoint.
|
||||||
* Packaging Guidelines:: Growing the distribution.
|
* Packaging Guidelines:: Growing the distribution.
|
||||||
* Bootstrapping:: GNU/Linux built from scratch.
|
* Bootstrapping:: GNU/Linux built from scratch.
|
||||||
@ -4280,6 +4285,64 @@ the load. To check whether a package has a @code{debug} output, use
|
|||||||
@command{guix package --list-available} (@pxref{Invoking guix package}).
|
@command{guix package --list-available} (@pxref{Invoking guix package}).
|
||||||
|
|
||||||
|
|
||||||
|
@node Security Updates
|
||||||
|
@section Security Updates
|
||||||
|
|
||||||
|
@indentedblock
|
||||||
|
Note: As of version @value{VERSION}, the feature described in this
|
||||||
|
section is experimental.
|
||||||
|
@end indentedblock
|
||||||
|
|
||||||
|
@cindex security updates
|
||||||
|
Occasionally, important security vulnerabilities are discovered in core
|
||||||
|
software packages and must be patched. Guix follows a functional
|
||||||
|
package management discipline (@pxref{Introduction}), which implies
|
||||||
|
that, when a package is changed, @emph{every package that depends on it}
|
||||||
|
must be rebuilt. This can significantly slow down the deployment of
|
||||||
|
fixes in core packages such as libc or Bash, since basically the whole
|
||||||
|
distribution would need to be rebuilt. Using pre-built binaries helps
|
||||||
|
(@pxref{Substitutes}), but deployment may still take more time than
|
||||||
|
desired.
|
||||||
|
|
||||||
|
@cindex grafts
|
||||||
|
To address that, Guix implements @dfn{grafts}, a mechanism that allows
|
||||||
|
for fast deployment of critical updates without the costs associated
|
||||||
|
with a whole-distribution rebuild. The idea is to rebuild only the
|
||||||
|
package that needs to be patched, and then to ``graft'' it onto packages
|
||||||
|
explicitly installed by the user and that were previously referring to
|
||||||
|
the original package. The cost of grafting is typically very low, and
|
||||||
|
order of magnitudes lower than a full rebuild of the dependency chain.
|
||||||
|
|
||||||
|
@cindex replacements of packages, for grafts
|
||||||
|
For instance, suppose a security update needs to be applied to Bash.
|
||||||
|
Guix developers will provide a package definition for the ``fixed''
|
||||||
|
Bash, say @var{bash-fixed}, in the usual way (@pxref{Defining
|
||||||
|
Packages}). Then, the original package definition is augmented with a
|
||||||
|
@code{replacement} field pointing to the package containing the bug fix:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(define bash
|
||||||
|
(package
|
||||||
|
(name "bash")
|
||||||
|
;; @dots{}
|
||||||
|
(replacement bash-fixed)))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
From there on, any package depending directly or indirectly on Bash that
|
||||||
|
is installed will automatically be ``rewritten'' to refer to
|
||||||
|
@var{bash-fixed} instead of @var{bash}. This grafting process takes
|
||||||
|
time proportional to the size of the package, but expect less than a
|
||||||
|
minute for an ``average'' package on a recent machine.
|
||||||
|
|
||||||
|
Currently, the graft and the package it replaces (@var{bash-fixed} and
|
||||||
|
@var{bash} in the example above) must have the exact same @code{name}
|
||||||
|
and @code{version} fields. This restriction mostly comes from the fact
|
||||||
|
that grafting works by patching files, including binary files, directly.
|
||||||
|
Other restrictions may apply: for instance, when adding a graft to a
|
||||||
|
package providing a shared library, the original shared library and its
|
||||||
|
replacement must have the same @code{SONAME} and be binary-compatible.
|
||||||
|
|
||||||
|
|
||||||
@node Package Modules
|
@node Package Modules
|
||||||
@section Package Modules
|
@section Package Modules
|
||||||
|
|
||||||
|
@ -146,7 +146,9 @@ check whether everything is alright."
|
|||||||
(native-inputs (map rewritten-input
|
(native-inputs (map rewritten-input
|
||||||
(package-native-inputs p)))
|
(package-native-inputs p)))
|
||||||
(propagated-inputs (map rewritten-input
|
(propagated-inputs (map rewritten-input
|
||||||
(package-propagated-inputs p)))))))
|
(package-propagated-inputs p)))
|
||||||
|
(replacement (and=> (package-replacement p)
|
||||||
|
package-with-bootstrap-guile))))))
|
||||||
|
|
||||||
(define* (glibc-dynamic-linker
|
(define* (glibc-dynamic-linker
|
||||||
#:optional (system (or (and=> (%current-target-system)
|
#:optional (system (or (and=> (%current-target-system)
|
||||||
|
@ -125,11 +125,11 @@ provides a 'CMakeLists.txt' file as its build system."
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:system system
|
#:system system
|
||||||
|
@ -168,11 +168,11 @@
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:system system
|
#:system system
|
||||||
|
@ -91,6 +91,13 @@ builder, or the distro's final Guile when GUILE is #f."
|
|||||||
`(#:guile ,guile
|
`(#:guile ,guile
|
||||||
#:implicit-inputs? #f
|
#:implicit-inputs? #f
|
||||||
,@args)))
|
,@args)))
|
||||||
|
(replacement
|
||||||
|
(let ((replacement (package-replacement p)))
|
||||||
|
(and replacement
|
||||||
|
(package-with-explicit-inputs replacement inputs loc
|
||||||
|
#:native-inputs
|
||||||
|
native-inputs
|
||||||
|
#:guile guile))))
|
||||||
(native-inputs
|
(native-inputs
|
||||||
(let ((filtered (duplicate-filter native-inputs*)))
|
(let ((filtered (duplicate-filter native-inputs*)))
|
||||||
`(,@(call native-inputs*)
|
`(,@(call native-inputs*)
|
||||||
@ -132,6 +139,11 @@ flags for VARIABLE, the associated value is augmented."
|
|||||||
(substring flag ,len))
|
(substring flag ,len))
|
||||||
flag))
|
flag))
|
||||||
,flags)))))))
|
,flags)))))))
|
||||||
|
(replacement
|
||||||
|
(let ((replacement (package-replacement p)))
|
||||||
|
(and replacement
|
||||||
|
(package-with-extra-configure-variable replacement
|
||||||
|
variable value))))
|
||||||
(inputs (rewritten-inputs (package-inputs p)))
|
(inputs (rewritten-inputs (package-inputs p)))
|
||||||
(propagated-inputs (rewritten-inputs (package-propagated-inputs p))))))
|
(propagated-inputs (rewritten-inputs (package-propagated-inputs p))))))
|
||||||
|
|
||||||
@ -155,7 +167,8 @@ use `--strip-all' as the arguments to `strip'."
|
|||||||
((#:strip-flags flags)
|
((#:strip-flags flags)
|
||||||
(if strip-all?
|
(if strip-all?
|
||||||
''("--strip-all")
|
''("--strip-all")
|
||||||
flags)))))))
|
flags)))))
|
||||||
|
(replacement (and=> (package-replacement p) static-package))))
|
||||||
|
|
||||||
(define* (dist-package p source)
|
(define* (dist-package p source)
|
||||||
"Return a package that runs takes source files from the SOURCE directory,
|
"Return a package that runs takes source files from the SOURCE directory,
|
||||||
@ -290,9 +303,11 @@ are allowed to refer to."
|
|||||||
(define canonicalize-reference
|
(define canonicalize-reference
|
||||||
(match-lambda
|
(match-lambda
|
||||||
((? package? p)
|
((? package? p)
|
||||||
(derivation->output-path (package-derivation store p system)))
|
(derivation->output-path (package-derivation store p system
|
||||||
|
#:graft? #f)))
|
||||||
(((? package? p) output)
|
(((? package? p) output)
|
||||||
(derivation->output-path (package-derivation store p system)
|
(derivation->output-path (package-derivation store p system
|
||||||
|
#:graft? #f)
|
||||||
output))
|
output))
|
||||||
((? string? output)
|
((? string? output)
|
||||||
output)))
|
output)))
|
||||||
@ -328,11 +343,12 @@ are allowed to refer to."
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system
|
||||||
|
#:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:system system
|
#:system system
|
||||||
@ -472,11 +488,11 @@ platform."
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:system system
|
#:system system
|
||||||
|
@ -114,11 +114,11 @@ provides a `Makefile.PL' file as its build system."
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:system system
|
#:system system
|
||||||
|
@ -160,11 +160,11 @@ provides a 'setup.py' file as its build system."
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:inputs inputs
|
#:inputs inputs
|
||||||
|
@ -99,11 +99,11 @@
|
|||||||
(define guile-for-build
|
(define guile-for-build
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f
|
(#f
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(build-expression->derivation store name builder
|
(build-expression->derivation store name builder
|
||||||
#:inputs inputs
|
#:inputs inputs
|
||||||
|
@ -28,11 +28,11 @@
|
|||||||
(define (guile-for-build store guile system)
|
(define (guile-for-build store guile system)
|
||||||
(match guile
|
(match guile
|
||||||
((? package?)
|
((? package?)
|
||||||
(package-derivation store guile system))
|
(package-derivation store guile system #:graft? #f))
|
||||||
(#f ; the default
|
(#f ; the default
|
||||||
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
(let* ((distro (resolve-interface '(gnu packages commencement)))
|
||||||
(guile (module-ref distro 'guile-final)))
|
(guile (module-ref distro 'guile-final)))
|
||||||
(package-derivation store guile system)))))
|
(package-derivation store guile system #:graft? #f)))))
|
||||||
|
|
||||||
(define* (lower name
|
(define* (lower name
|
||||||
#:key source inputs native-inputs outputs system target
|
#:key source inputs native-inputs outputs system target
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-9 gnu)
|
#:use-module (srfi srfi-9 gnu)
|
||||||
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:use-module (srfi srfi-34)
|
#:use-module (srfi srfi-34)
|
||||||
#:use-module (srfi srfi-35)
|
#:use-module (srfi srfi-35)
|
||||||
@ -65,6 +66,7 @@
|
|||||||
package-outputs
|
package-outputs
|
||||||
package-native-search-paths
|
package-native-search-paths
|
||||||
package-search-paths
|
package-search-paths
|
||||||
|
package-replacement
|
||||||
package-synopsis
|
package-synopsis
|
||||||
package-description
|
package-description
|
||||||
package-license
|
package-license
|
||||||
@ -85,6 +87,7 @@
|
|||||||
package-derivation
|
package-derivation
|
||||||
package-cross-derivation
|
package-cross-derivation
|
||||||
package-output
|
package-output
|
||||||
|
package-grafts
|
||||||
|
|
||||||
%supported-systems
|
%supported-systems
|
||||||
|
|
||||||
@ -97,6 +100,7 @@
|
|||||||
&package-cross-build-system-error
|
&package-cross-build-system-error
|
||||||
package-cross-build-system-error?
|
package-cross-build-system-error?
|
||||||
|
|
||||||
|
%graft?
|
||||||
package->bag
|
package->bag
|
||||||
bag->derivation
|
bag->derivation
|
||||||
bag-transitive-inputs
|
bag-transitive-inputs
|
||||||
@ -211,6 +215,8 @@ corresponds to the arguments expected by `set-path-environment-variable'."
|
|||||||
; inputs
|
; inputs
|
||||||
(native-search-paths package-native-search-paths (default '()))
|
(native-search-paths package-native-search-paths (default '()))
|
||||||
(search-paths package-search-paths (default '()))
|
(search-paths package-search-paths (default '()))
|
||||||
|
(replacement package-replacement ; package | #f
|
||||||
|
(default #f) (thunked))
|
||||||
|
|
||||||
(synopsis package-synopsis) ; one-line description
|
(synopsis package-synopsis) ; one-line description
|
||||||
(description package-description) ; one or two paragraphs
|
(description package-description) ; one or two paragraphs
|
||||||
@ -445,8 +451,8 @@ IMPORTED-MODULES specify modules to use/import for use by SNIPPET."
|
|||||||
(and (member name (cons decompression-type
|
(and (member name (cons decompression-type
|
||||||
'("tar" "xz" "patch")))
|
'("tar" "xz" "patch")))
|
||||||
(list name
|
(list name
|
||||||
(package-derivation store p
|
(package-derivation store p system
|
||||||
system)))))
|
#:graft? #f)))))
|
||||||
(or inputs (%standard-patch-inputs))))
|
(or inputs (%standard-patch-inputs))))
|
||||||
(modules (delete-duplicates (cons '(guix build utils) modules))))
|
(modules (delete-duplicates (cons '(guix build utils) modules))))
|
||||||
|
|
||||||
@ -472,12 +478,10 @@ IMPORTED-MODULES specify modules to use/import for use by SNIPPET."
|
|||||||
;; Patches and/or a snippet.
|
;; Patches and/or a snippet.
|
||||||
(let ((source (method store uri 'sha256 sha256 name
|
(let ((source (method store uri 'sha256 sha256 name
|
||||||
#:system system))
|
#:system system))
|
||||||
(guile (match (or guile-for-build (%guile-for-build)
|
(guile (match (or guile-for-build (default-guile))
|
||||||
(default-guile))
|
|
||||||
((? package? p)
|
((? package? p)
|
||||||
(package-derivation store p system))
|
(package-derivation store p system
|
||||||
((? derivation? drv)
|
#:graft? #f)))))
|
||||||
drv))))
|
|
||||||
(patch-and-repack store source patches
|
(patch-and-repack store source patches
|
||||||
#:inputs inputs
|
#:inputs inputs
|
||||||
#:snippet snippet
|
#:snippet snippet
|
||||||
@ -617,8 +621,9 @@ information in exceptions."
|
|||||||
|
|
||||||
(define derivation
|
(define derivation
|
||||||
(if cross-system
|
(if cross-system
|
||||||
(cut package-cross-derivation store <> cross-system system)
|
(cut package-cross-derivation store <> cross-system system
|
||||||
(cut package-derivation store <> system)))
|
#:graft? #f)
|
||||||
|
(cut package-derivation store <> system #:graft? #f)))
|
||||||
|
|
||||||
(match input
|
(match input
|
||||||
(((? string? name) (? package? package))
|
(((? string? name) (? package? package))
|
||||||
@ -643,20 +648,27 @@ information in exceptions."
|
|||||||
(package package)
|
(package package)
|
||||||
(input x)))))))
|
(input x)))))))
|
||||||
|
|
||||||
|
(define %graft?
|
||||||
|
;; Whether to honor package grafts by default.
|
||||||
|
(make-parameter #t))
|
||||||
|
|
||||||
(define* (package->bag package #:optional
|
(define* (package->bag package #:optional
|
||||||
(system (%current-system))
|
(system (%current-system))
|
||||||
(target (%current-target-system)))
|
(target (%current-target-system))
|
||||||
|
#:key (graft? (%graft?)))
|
||||||
"Compile PACKAGE into a bag for SYSTEM, possibly cross-compiled to TARGET,
|
"Compile PACKAGE into a bag for SYSTEM, possibly cross-compiled to TARGET,
|
||||||
and return it."
|
and return it."
|
||||||
;; Bind %CURRENT-SYSTEM and %CURRENT-TARGET-SYSTEM so that thunked field
|
;; Bind %CURRENT-SYSTEM and %CURRENT-TARGET-SYSTEM so that thunked field
|
||||||
;; values can refer to it.
|
;; values can refer to it.
|
||||||
(parameterize ((%current-system system)
|
(parameterize ((%current-system system)
|
||||||
(%current-target-system target))
|
(%current-target-system target))
|
||||||
(match package
|
(match (if graft?
|
||||||
|
(or (package-replacement package) package)
|
||||||
|
package)
|
||||||
(($ <package> name version source build-system
|
(($ <package> name version source build-system
|
||||||
args inputs propagated-inputs native-inputs self-native-input?
|
args inputs propagated-inputs native-inputs self-native-input?
|
||||||
outputs)
|
outputs)
|
||||||
(or (make-bag build-system (package-full-name package)
|
(or (make-bag build-system (string-append name "-" version)
|
||||||
#:system system
|
#:system system
|
||||||
#:target target
|
#:target target
|
||||||
#:source source
|
#:source source
|
||||||
@ -676,6 +688,77 @@ and return it."
|
|||||||
(&package-error
|
(&package-error
|
||||||
(package package))))))))))
|
(package package))))))))))
|
||||||
|
|
||||||
|
(define (input-graft store system)
|
||||||
|
"Return a procedure that, given an input referring to a package with a
|
||||||
|
graft, returns a pair with the original derivation and the graft's derivation,
|
||||||
|
and returns #f for other inputs."
|
||||||
|
(match-lambda
|
||||||
|
((label (? package? package) sub-drv ...)
|
||||||
|
(let ((replacement (package-replacement package)))
|
||||||
|
(and replacement
|
||||||
|
(let ((orig (package-derivation store package system
|
||||||
|
#:graft? #f))
|
||||||
|
(new (package-derivation store replacement system)))
|
||||||
|
(graft
|
||||||
|
(origin orig)
|
||||||
|
(replacement new)
|
||||||
|
(origin-output (match sub-drv
|
||||||
|
(() "out")
|
||||||
|
((output) output)))
|
||||||
|
(replacement-output origin-output))))))
|
||||||
|
(x
|
||||||
|
#f)))
|
||||||
|
|
||||||
|
(define (input-cross-graft store target system)
|
||||||
|
"Same as 'input-graft', but for cross-compilation inputs."
|
||||||
|
(match-lambda
|
||||||
|
((label (? package? package) sub-drv ...)
|
||||||
|
(let ((replacement (package-replacement package)))
|
||||||
|
(and replacement
|
||||||
|
(let ((orig (package-cross-derivation store package target system
|
||||||
|
#:graft? #f))
|
||||||
|
(new (package-cross-derivation store replacement
|
||||||
|
target system)))
|
||||||
|
(graft
|
||||||
|
(origin orig)
|
||||||
|
(replacement new)
|
||||||
|
(origin-output (match sub-drv
|
||||||
|
(() "out")
|
||||||
|
((output) output)))
|
||||||
|
(replacement-output origin-output))))))
|
||||||
|
(_
|
||||||
|
#f)))
|
||||||
|
|
||||||
|
(define* (bag-grafts store bag)
|
||||||
|
"Return the list of grafts applicable to BAG. Each graft is a <graft>
|
||||||
|
record."
|
||||||
|
(let ((target (bag-target bag))
|
||||||
|
(system (bag-system bag)))
|
||||||
|
(define native-grafts
|
||||||
|
(filter-map (input-graft store system)
|
||||||
|
(append (bag-transitive-build-inputs bag)
|
||||||
|
(bag-transitive-target-inputs bag)
|
||||||
|
(if target
|
||||||
|
'()
|
||||||
|
(bag-transitive-host-inputs bag)))))
|
||||||
|
|
||||||
|
(define target-grafts
|
||||||
|
(if target
|
||||||
|
(filter-map (input-cross-graft store target system)
|
||||||
|
(bag-transitive-host-inputs bag))
|
||||||
|
'()))
|
||||||
|
|
||||||
|
(append native-grafts target-grafts)))
|
||||||
|
|
||||||
|
(define* (package-grafts store package
|
||||||
|
#:optional (system (%current-system))
|
||||||
|
#:key target)
|
||||||
|
"Return the list of grafts applicable to PACKAGE as built for SYSTEM and
|
||||||
|
TARGET."
|
||||||
|
(let* ((package (or (package-replacement package) package))
|
||||||
|
(bag (package->bag package system target)))
|
||||||
|
(bag-grafts store bag)))
|
||||||
|
|
||||||
(define* (bag->derivation store bag
|
(define* (bag->derivation store bag
|
||||||
#:optional context)
|
#:optional context)
|
||||||
"Return the derivation to build BAG for SYSTEM. Optionally, CONTEXT can be
|
"Return the derivation to build BAG for SYSTEM. Optionally, CONTEXT can be
|
||||||
@ -743,23 +826,47 @@ This is an internal procedure."
|
|||||||
(bag-arguments bag))))
|
(bag-arguments bag))))
|
||||||
|
|
||||||
(define* (package-derivation store package
|
(define* (package-derivation store package
|
||||||
#:optional (system (%current-system)))
|
#:optional (system (%current-system))
|
||||||
|
#:key (graft? (%graft?)))
|
||||||
"Return the <derivation> object of PACKAGE for SYSTEM."
|
"Return the <derivation> object of PACKAGE for SYSTEM."
|
||||||
|
|
||||||
;; Compute the derivation and cache the result. Caching is important
|
;; Compute the derivation and cache the result. Caching is important
|
||||||
;; because some derivations, such as the implicit inputs of the GNU build
|
;; because some derivations, such as the implicit inputs of the GNU build
|
||||||
;; system, will be queried many, many times in a row.
|
;; system, will be queried many, many times in a row.
|
||||||
(cached package system
|
(cached package (cons system graft?)
|
||||||
(bag->derivation store (package->bag package system #f)
|
(let* ((bag (package->bag package system #f #:graft? graft?))
|
||||||
package)))
|
(drv (bag->derivation store bag package)))
|
||||||
|
(if graft?
|
||||||
|
(match (bag-grafts store bag)
|
||||||
|
(()
|
||||||
|
drv)
|
||||||
|
(grafts
|
||||||
|
(let ((guile (package-derivation store (default-guile)
|
||||||
|
system #:graft? #f)))
|
||||||
|
(graft-derivation store (bag-name bag) drv grafts
|
||||||
|
#:system system
|
||||||
|
#:guile guile))))
|
||||||
|
drv))))
|
||||||
|
|
||||||
(define* (package-cross-derivation store package target
|
(define* (package-cross-derivation store package target
|
||||||
#:optional (system (%current-system)))
|
#:optional (system (%current-system))
|
||||||
|
#:key (graft? (%graft?)))
|
||||||
"Cross-build PACKAGE for TARGET (a GNU triplet) from host SYSTEM (a Guix
|
"Cross-build PACKAGE for TARGET (a GNU triplet) from host SYSTEM (a Guix
|
||||||
system identifying string)."
|
system identifying string)."
|
||||||
(cached package (cons system target)
|
(cached package (list system target graft?)
|
||||||
(bag->derivation store (package->bag package system target)
|
(let* ((bag (package->bag package system target #:graft? graft?))
|
||||||
package)))
|
(drv (bag->derivation store bag package)))
|
||||||
|
(if graft?
|
||||||
|
(match (bag-grafts store bag)
|
||||||
|
(()
|
||||||
|
drv)
|
||||||
|
(grafts
|
||||||
|
(graft-derivation store (bag-name bag) drv grafts
|
||||||
|
#:system system
|
||||||
|
#:guile
|
||||||
|
(package-derivation store (default-guile)
|
||||||
|
system #:graft? #f))))
|
||||||
|
drv))))
|
||||||
|
|
||||||
(define* (package-output store package
|
(define* (package-output store package
|
||||||
#:optional (output "out") (system (%current-system)))
|
#:optional (output "out") (system (%current-system)))
|
||||||
|
@ -202,6 +202,7 @@ options handled by 'set-build-options-from-command-line', and listed in
|
|||||||
(define %default-options
|
(define %default-options
|
||||||
;; Alist of default option values.
|
;; Alist of default option values.
|
||||||
`((system . ,(%current-system))
|
`((system . ,(%current-system))
|
||||||
|
(graft? . #t)
|
||||||
(substitutes? . #t)
|
(substitutes? . #t)
|
||||||
(build-hook? . #t)
|
(build-hook? . #t)
|
||||||
(print-build-trace? . #t)
|
(print-build-trace? . #t)
|
||||||
@ -222,6 +223,8 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
|
|||||||
(display (_ "
|
(display (_ "
|
||||||
--with-source=SOURCE
|
--with-source=SOURCE
|
||||||
use SOURCE when building the corresponding package"))
|
use SOURCE when building the corresponding package"))
|
||||||
|
(display (_ "
|
||||||
|
--no-grafts do not graft packages"))
|
||||||
(display (_ "
|
(display (_ "
|
||||||
-d, --derivations return the derivation paths of the given packages"))
|
-d, --derivations return the derivation paths of the given packages"))
|
||||||
(display (_ "
|
(display (_ "
|
||||||
@ -278,6 +281,10 @@ Build the given PACKAGE-OR-DERIVATION and return their output paths.\n"))
|
|||||||
(option '("with-source") #t #f
|
(option '("with-source") #t #f
|
||||||
(lambda (opt name arg result)
|
(lambda (opt name arg result)
|
||||||
(alist-cons 'with-source 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))
|
%standard-build-options))
|
||||||
|
|
||||||
@ -290,26 +297,28 @@ build."
|
|||||||
(triplet
|
(triplet
|
||||||
(cut package-cross-derivation <> <> triplet <>))))
|
(cut package-cross-derivation <> <> triplet <>))))
|
||||||
|
|
||||||
(define src? (assoc-ref opts 'source?))
|
(define src? (assoc-ref opts 'source?))
|
||||||
(define sys (assoc-ref opts 'system))
|
(define sys (assoc-ref opts 'system))
|
||||||
|
(define graft? (assoc-ref opts 'graft?))
|
||||||
|
|
||||||
(let ((opts (options/with-source store
|
(parameterize ((%graft? graft?))
|
||||||
(options/resolve-packages store opts))))
|
(let ((opts (options/with-source store
|
||||||
(filter-map (match-lambda
|
(options/resolve-packages store opts))))
|
||||||
(('argument . (? package? p))
|
(filter-map (match-lambda
|
||||||
(if src?
|
(('argument . (? package? p))
|
||||||
(let ((s (package-source p)))
|
(if src?
|
||||||
(package-source-derivation store s))
|
(let ((s (package-source p)))
|
||||||
(package->derivation store p sys)))
|
(package-source-derivation store s))
|
||||||
(('argument . (? derivation? drv))
|
(package->derivation store p sys)))
|
||||||
drv)
|
(('argument . (? derivation? drv))
|
||||||
(('argument . (? derivation-path? drv))
|
drv)
|
||||||
(call-with-input-file drv read-derivation))
|
(('argument . (? derivation-path? drv))
|
||||||
(('argument . (? store-path?))
|
(call-with-input-file drv read-derivation))
|
||||||
;; Nothing to do; maybe for --log-file.
|
(('argument . (? store-path?))
|
||||||
#f)
|
;; Nothing to do; maybe for --log-file.
|
||||||
(_ #f))
|
#f)
|
||||||
opts)))
|
(_ #f))
|
||||||
|
opts))))
|
||||||
|
|
||||||
(define (options/resolve-packages store opts)
|
(define (options/resolve-packages store opts)
|
||||||
"Return OPTS with package specification strings replaced by actual
|
"Return OPTS with package specification strings replaced by actual
|
||||||
|
@ -33,8 +33,9 @@
|
|||||||
#:use-module (guix build-system gnu)
|
#:use-module (guix build-system gnu)
|
||||||
#:use-module (gnu packages)
|
#:use-module (gnu packages)
|
||||||
#:use-module (gnu packages base)
|
#:use-module (gnu packages base)
|
||||||
|
#:use-module (gnu packages guile)
|
||||||
#:use-module (gnu packages bootstrap)
|
#:use-module (gnu packages bootstrap)
|
||||||
#:use-module (srfi srfi-11)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:use-module (srfi srfi-34)
|
#:use-module (srfi srfi-34)
|
||||||
#:use-module (srfi srfi-64)
|
#:use-module (srfi srfi-64)
|
||||||
@ -47,10 +48,6 @@
|
|||||||
(define %store
|
(define %store
|
||||||
(open-connection-for-tests))
|
(open-connection-for-tests))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(test-begin "packages")
|
|
||||||
|
|
||||||
(define-syntax-rule (dummy-package name* extra-fields ...)
|
(define-syntax-rule (dummy-package name* extra-fields ...)
|
||||||
(package (name name*) (version "0") (source #f)
|
(package (name name*) (version "0") (source #f)
|
||||||
(build-system gnu-build-system)
|
(build-system gnu-build-system)
|
||||||
@ -58,6 +55,9 @@
|
|||||||
(home-page #f) (license #f)
|
(home-page #f) (license #f)
|
||||||
extra-fields ...))
|
extra-fields ...))
|
||||||
|
|
||||||
|
|
||||||
|
(test-begin "packages")
|
||||||
|
|
||||||
(test-assert "printer with location"
|
(test-assert "printer with location"
|
||||||
(string-match "^#<package foo-0 foo.scm:42 [[:xdigit:]]+>$"
|
(string-match "^#<package foo-0 foo.scm:42 [[:xdigit:]]+>$"
|
||||||
(with-output-to-string
|
(with-output-to-string
|
||||||
@ -375,6 +375,80 @@
|
|||||||
(package-cross-derivation %store p "mips64el-linux-gnu")
|
(package-cross-derivation %store p "mips64el-linux-gnu")
|
||||||
#f)))
|
#f)))
|
||||||
|
|
||||||
|
(test-equal "package-derivation, direct graft"
|
||||||
|
(package-derivation %store gnu-make)
|
||||||
|
(let ((p (package (inherit coreutils)
|
||||||
|
(replacement gnu-make))))
|
||||||
|
(package-derivation %store p)))
|
||||||
|
|
||||||
|
(test-equal "package-cross-derivation, direct graft"
|
||||||
|
(package-cross-derivation %store gnu-make "mips64el-linux-gnu")
|
||||||
|
(let ((p (package (inherit coreutils)
|
||||||
|
(replacement gnu-make))))
|
||||||
|
(package-cross-derivation %store p "mips64el-linux-gnu")))
|
||||||
|
|
||||||
|
(test-assert "package-grafts, indirect grafts"
|
||||||
|
(let* ((new (dummy-package "dep"
|
||||||
|
(arguments '(#:implicit-inputs? #f))))
|
||||||
|
(dep (package (inherit new) (version "0.0")))
|
||||||
|
(dep* (package (inherit dep) (replacement new)))
|
||||||
|
(dummy (dummy-package "dummy"
|
||||||
|
(arguments '(#:implicit-inputs? #f))
|
||||||
|
(inputs `(("dep" ,dep*))))))
|
||||||
|
(equal? (package-grafts %store dummy)
|
||||||
|
(list (graft
|
||||||
|
(origin (package-derivation %store dep))
|
||||||
|
(replacement (package-derivation %store new)))))))
|
||||||
|
|
||||||
|
(test-assert "package-grafts, indirect grafts, cross"
|
||||||
|
(let* ((new (dummy-package "dep"
|
||||||
|
(arguments '(#:implicit-inputs? #f))))
|
||||||
|
(dep (package (inherit new) (version "0.0")))
|
||||||
|
(dep* (package (inherit dep) (replacement new)))
|
||||||
|
(dummy (dummy-package "dummy"
|
||||||
|
(arguments '(#:implicit-inputs? #f))
|
||||||
|
(inputs `(("dep" ,dep*)))))
|
||||||
|
(target "mips64el-linux-gnu"))
|
||||||
|
(equal? (package-grafts %store dummy #:target target)
|
||||||
|
(list (graft
|
||||||
|
(origin (package-cross-derivation %store dep target))
|
||||||
|
(replacement
|
||||||
|
(package-cross-derivation %store new target)))))))
|
||||||
|
|
||||||
|
(test-assert "package-grafts, indirect grafts, propagated inputs"
|
||||||
|
(let* ((new (dummy-package "dep"
|
||||||
|
(arguments '(#:implicit-inputs? #f))))
|
||||||
|
(dep (package (inherit new) (version "0.0")))
|
||||||
|
(dep* (package (inherit dep) (replacement new)))
|
||||||
|
(prop (dummy-package "propagated"
|
||||||
|
(propagated-inputs `(("dep" ,dep*)))
|
||||||
|
(arguments '(#:implicit-inputs? #f))))
|
||||||
|
(dummy (dummy-package "dummy"
|
||||||
|
(arguments '(#:implicit-inputs? #f))
|
||||||
|
(inputs `(("prop" ,prop))))))
|
||||||
|
(equal? (package-grafts %store dummy)
|
||||||
|
(list (graft
|
||||||
|
(origin (package-derivation %store dep))
|
||||||
|
(replacement (package-derivation %store new)))))))
|
||||||
|
|
||||||
|
(test-assert "package-derivation, indirect grafts"
|
||||||
|
(let* ((new (dummy-package "dep"
|
||||||
|
(arguments '(#:implicit-inputs? #f))))
|
||||||
|
(dep (package (inherit new) (version "0.0")))
|
||||||
|
(dep* (package (inherit dep) (replacement new)))
|
||||||
|
(dummy (dummy-package "dummy"
|
||||||
|
(arguments '(#:implicit-inputs? #f))
|
||||||
|
(inputs `(("dep" ,dep*)))))
|
||||||
|
(guile (package-derivation %store (canonical-package guile-2.0)
|
||||||
|
#:graft? #f)))
|
||||||
|
(equal? (package-derivation %store dummy)
|
||||||
|
(graft-derivation %store "dummy-0"
|
||||||
|
(package-derivation %store dummy #:graft? #f)
|
||||||
|
(package-grafts %store dummy)
|
||||||
|
|
||||||
|
;; Use the same Guile as 'package-derivation'.
|
||||||
|
#:guile guile))))
|
||||||
|
|
||||||
(test-equal "package->bag"
|
(test-equal "package->bag"
|
||||||
`("foo86-hurd" #f (,(package-source gnu-make))
|
`("foo86-hurd" #f (,(package-source gnu-make))
|
||||||
(,(canonical-package glibc)) (,(canonical-package coreutils)))
|
(,(canonical-package glibc)) (,(canonical-package coreutils)))
|
||||||
@ -406,17 +480,20 @@
|
|||||||
(eq? package dep)))))
|
(eq? package dep)))))
|
||||||
|
|
||||||
(test-assert "bag->derivation"
|
(test-assert "bag->derivation"
|
||||||
(let ((bag (package->bag gnu-make))
|
(parameterize ((%graft? #f))
|
||||||
(drv (package-derivation %store gnu-make)))
|
(let ((bag (package->bag gnu-make))
|
||||||
(parameterize ((%current-system "foox86-hurd")) ;should have no effect
|
(drv (package-derivation %store gnu-make)))
|
||||||
(equal? drv (bag->derivation %store bag)))))
|
(parameterize ((%current-system "foox86-hurd")) ;should have no effect
|
||||||
|
(equal? drv (bag->derivation %store bag))))))
|
||||||
|
|
||||||
(test-assert "bag->derivation, cross-compilation"
|
(test-assert "bag->derivation, cross-compilation"
|
||||||
(let ((bag (package->bag gnu-make (%current-system) "mips64el-linux-gnu"))
|
(parameterize ((%graft? #f))
|
||||||
(drv (package-cross-derivation %store gnu-make "mips64el-linux-gnu")))
|
(let* ((target "mips64el-linux-gnu")
|
||||||
(parameterize ((%current-system "foox86-hurd") ;should have no effect
|
(bag (package->bag gnu-make (%current-system) target))
|
||||||
(%current-target-system "foo64-linux-gnu"))
|
(drv (package-cross-derivation %store gnu-make target)))
|
||||||
(equal? drv (bag->derivation %store bag)))))
|
(parameterize ((%current-system "foox86-hurd") ;should have no effect
|
||||||
|
(%current-target-system "foo64-linux-gnu"))
|
||||||
|
(equal? drv (bag->derivation %store bag))))))
|
||||||
|
|
||||||
(unless (false-if-exception (getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV))
|
(unless (false-if-exception (getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV))
|
||||||
(test-skip 1))
|
(test-skip 1))
|
||||||
|
Loading…
Reference in New Issue
Block a user