diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2013-08-26 22:12:46 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2013-08-26 22:20:53 +0200 |
| commit | 5b0c9d1635df1608a498db8718af575d2f0e1663 (patch) | |
| tree | c4e38d7d3b566507b8d966971b780705506fabb8 | |
| parent | a987d2c02525efd1bf37b4bb5b5df405a06bd15c (diff) | |
derivations: Add #:dependency-graphs `derivation' parameter.
* guix/derivations.scm (derivation): Add `dependency-graphs' keyword
parameter; honor it.
* tests/derivations.scm (bootstrap-binary): New procedure.
(%bash): Use it.
(%mkdir): New variable.
(directory-contents): Add `slurp' optional parameter.
("derivation with #:dependency-graphs"): New test.
* doc/guix.texi (Derivations): Update accordingly.
| -rw-r--r-- | doc/guix.texi | 7 | ||||
| -rw-r--r-- | guix/derivations.scm | 28 | ||||
| -rw-r--r-- | tests/derivations.scm | 68 |
3 files changed, 91 insertions, 12 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index c82d5f7480d..86912ecabf8 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -1113,13 +1113,18 @@ derivations as Scheme objects, along with procedures to create and | |||
| 1113 | otherwise manipulate derivations. The lowest-level primitive to create | 1113 | otherwise manipulate derivations. The lowest-level primitive to create |
| 1114 | a derivation is the @code{derivation} procedure: | 1114 | a derivation is the @code{derivation} procedure: |
| 1115 | 1115 | ||
| 1116 | @deffn {Scheme Procedure} derivation @var{store} @var{name} @var{builder} @var{args} [#:outputs '("out")] [#:hash #f] [#:hash-algo #f] [#:hash-mode #f] [#:inputs '()] [#:env-vars '()] [#:system (%current-system)] | 1116 | @deffn {Scheme Procedure} derivation @var{store} @var{name} @var{builder} @var{args} [#:outputs '("out")] [#:hash #f] [#:hash-algo #f] [#:hash-mode #f] [#:inputs '()] [#:env-vars '()] [#:system (%current-system)] [#:dependency-graphs #f] |
| 1117 | Build a derivation with the given arguments. Return the resulting store | 1117 | Build a derivation with the given arguments. Return the resulting store |
| 1118 | path and @code{<derivation>} object. | 1118 | path and @code{<derivation>} object. |
| 1119 | 1119 | ||
| 1120 | When @var{hash}, @var{hash-algo}, and @var{hash-mode} are given, a | 1120 | When @var{hash}, @var{hash-algo}, and @var{hash-mode} are given, a |
| 1121 | @dfn{fixed-output derivation} is created---i.e., one whose result is | 1121 | @dfn{fixed-output derivation} is created---i.e., one whose result is |
| 1122 | known in advance, such as a file download. | 1122 | known in advance, such as a file download. |
| 1123 | |||
| 1124 | When @var{dependency-graphs} is true, it must be a list of file | ||
| 1125 | name/store path pairs. In that case, the reference graph of each store | ||
| 1126 | path is exported in the build environment in the corresponding file, in | ||
| 1127 | a simple text format. | ||
| 1123 | @end deffn | 1128 | @end deffn |
| 1124 | 1129 | ||
| 1125 | @noindent | 1130 | @noindent |
diff --git a/guix/derivations.scm b/guix/derivations.scm index 3d7a30aaa8b..fea99843705 100644 --- a/guix/derivations.scm +++ b/guix/derivations.scm | |||
| @@ -501,11 +501,16 @@ the derivation called NAME with hash HASH." | |||
| 501 | #:key | 501 | #:key |
| 502 | (system (%current-system)) (env-vars '()) | 502 | (system (%current-system)) (env-vars '()) |
| 503 | (inputs '()) (outputs '("out")) | 503 | (inputs '()) (outputs '("out")) |
| 504 | hash hash-algo hash-mode) | 504 | hash hash-algo hash-mode |
| 505 | dependency-graphs) | ||
| 505 | "Build a derivation with the given arguments. Return the resulting | 506 | "Build a derivation with the given arguments. Return the resulting |
| 506 | store path and <derivation> object. When HASH, HASH-ALGO, and HASH-MODE | 507 | store path and <derivation> object. When HASH, HASH-ALGO, and HASH-MODE |
| 507 | are given, a fixed-output derivation is created---i.e., one whose result is | 508 | are given, a fixed-output derivation is created---i.e., one whose result is |
| 508 | known in advance, such as a file download." | 509 | known in advance, such as a file download. |
| 510 | |||
| 511 | When DEPENDENCY-GRAPHS is true, it must be a list of file name/store path | ||
| 512 | pairs. In that case, the reference graph of each store path is exported in | ||
| 513 | the build environment in the corresponding file, in a simple text format." | ||
| 509 | (define direct-store-path? | 514 | (define direct-store-path? |
| 510 | (let ((len (+ 1 (string-length (%store-prefix))))) | 515 | (let ((len (+ 1 (string-length (%store-prefix))))) |
| 511 | (lambda (p) | 516 | (lambda (p) |
| @@ -540,7 +545,22 @@ known in advance, such as a file download." | |||
| 540 | value)))) | 545 | value)))) |
| 541 | env-vars)))))) | 546 | env-vars)))))) |
| 542 | 547 | ||
| 543 | (define (env-vars-with-empty-outputs) | 548 | (define (user+system-env-vars) |
| 549 | ;; Some options are passed to the build daemon via the env. vars of | ||
| 550 | ;; derivations (urgh!). We hide that from our API, but here is the place | ||
| 551 | ;; where we kludgify those options. | ||
| 552 | (match dependency-graphs | ||
| 553 | (((file . path) ...) | ||
| 554 | (let ((value (map (cut string-append <> " " <>) | ||
| 555 | file path))) | ||
| 556 | ;; XXX: This all breaks down if an element of FILE or PATH contains | ||
| 557 | ;; white space. | ||
| 558 | `(("exportReferencesGraph" . ,(string-join value " ")) | ||
| 559 | ,@env-vars))) | ||
| 560 | (#f | ||
| 561 | env-vars))) | ||
| 562 | |||
| 563 | (define (env-vars-with-empty-outputs env-vars) | ||
| 544 | ;; Return a variant of ENV-VARS where each OUTPUTS is associated with an | 564 | ;; Return a variant of ENV-VARS where each OUTPUTS is associated with an |
| 545 | ;; empty string, even outputs that do not appear in ENV-VARS. | 565 | ;; empty string, even outputs that do not appear in ENV-VARS. |
| 546 | (let ((e (map (match-lambda | 566 | (let ((e (map (match-lambda |
| @@ -572,7 +592,7 @@ known in advance, such as a file download." | |||
| 572 | #t "sha256" input))) | 592 | #t "sha256" input))) |
| 573 | (make-derivation-input path '())))) | 593 | (make-derivation-input path '())))) |
| 574 | (delete-duplicates inputs))) | 594 | (delete-duplicates inputs))) |
| 575 | (env-vars (env-vars-with-empty-outputs)) | 595 | (env-vars (env-vars-with-empty-outputs (user+system-env-vars))) |
| 576 | (drv-masked (make-derivation outputs | 596 | (drv-masked (make-derivation outputs |
| 577 | (filter (compose derivation-path? | 597 | (filter (compose derivation-path? |
| 578 | derivation-input-path) | 598 | derivation-input-path) |
diff --git a/tests/derivations.scm b/tests/derivations.scm index 9833e151126..9b3d92a7bf7 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm | |||
| @@ -50,19 +50,23 @@ | |||
| 50 | (let ((drv (package-derivation %store %bootstrap-guile))) | 50 | (let ((drv (package-derivation %store %bootstrap-guile))) |
| 51 | (%guile-for-build drv))) | 51 | (%guile-for-build drv))) |
| 52 | 52 | ||
| 53 | (define %bash | 53 | (define (bootstrap-binary name) |
| 54 | (let ((bash (search-bootstrap-binary "bash" (%current-system)))) | 54 | (let ((bin (search-bootstrap-binary name (%current-system)))) |
| 55 | (and %store | 55 | (and %store |
| 56 | (add-to-store %store "bash" #t "sha256" bash)))) | 56 | (add-to-store %store name #t "sha256" bin)))) |
| 57 | |||
| 58 | (define %bash | ||
| 59 | (bootstrap-binary "bash")) | ||
| 60 | (define %mkdir | ||
| 61 | (bootstrap-binary "mkdir")) | ||
| 57 | 62 | ||
| 58 | (define (directory-contents dir) | 63 | (define* (directory-contents dir #:optional (slurp get-bytevector-all)) |
| 59 | "Return an alist representing the contents of DIR." | 64 | "Return an alist representing the contents of DIR." |
| 60 | (define prefix-len (string-length dir)) | 65 | (define prefix-len (string-length dir)) |
| 61 | (sort (file-system-fold (const #t) ; enter? | 66 | (sort (file-system-fold (const #t) ; enter? |
| 62 | (lambda (path stat result) ; leaf | 67 | (lambda (path stat result) ; leaf |
| 63 | (alist-cons (string-drop path prefix-len) | 68 | (alist-cons (string-drop path prefix-len) |
| 64 | (call-with-input-file path | 69 | (call-with-input-file path slurp) |
| 65 | get-bytevector-all) | ||
| 66 | result)) | 70 | result)) |
| 67 | (lambda (path stat result) result) ; down | 71 | (lambda (path stat result) result) ; down |
| 68 | (lambda (path stat result) result) ; up | 72 | (lambda (path stat result) result) ; up |
| @@ -84,7 +88,7 @@ | |||
| 84 | (and (equal? b1 b2) | 88 | (and (equal? b1 b2) |
| 85 | (equal? d1 d2)))) | 89 | (equal? d1 d2)))) |
| 86 | 90 | ||
| 87 | (test-skip (if %store 0 11)) | 91 | (test-skip (if %store 0 12)) |
| 88 | 92 | ||
| 89 | (test-assert "add-to-store, flat" | 93 | (test-assert "add-to-store, flat" |
| 90 | (let* ((file (search-path %load-path "language/tree-il/spec.scm")) | 94 | (let* ((file (search-path %load-path "language/tree-il/spec.scm")) |
| @@ -292,6 +296,56 @@ | |||
| 292 | (and (valid-path? %store p) | 296 | (and (valid-path? %store p) |
| 293 | (equal? '(one two) (call-with-input-file p read))))))) | 297 | (equal? '(one two) (call-with-input-file p read))))))) |
| 294 | 298 | ||
| 299 | (test-assert "derivation with #:dependency-graphs" | ||
| 300 | (let* ((input1 (add-text-to-store %store "foo" "hello" | ||
| 301 | (list %bash))) | ||
| 302 | (input2 (add-text-to-store %store "bar" | ||
| 303 | (number->string (random 7777)) | ||
| 304 | (list input1))) | ||
| 305 | (builder (add-text-to-store %store "build-graph" | ||
| 306 | (format #f " | ||
| 307 | ~a $out | ||
| 308 | (while read l ; do echo $l ; done) < bash > $out/bash | ||
| 309 | (while read l ; do echo $l ; done) < input1 > $out/input1 | ||
| 310 | (while read l ; do echo $l ; done) < input2 > $out/input2" | ||
| 311 | %mkdir) | ||
| 312 | (list %mkdir))) | ||
| 313 | (drv (derivation %store "closure-graphs" | ||
| 314 | %bash `(,builder) | ||
| 315 | #:dependency-graphs | ||
| 316 | `(("bash" . ,%bash) | ||
| 317 | ("input1" . ,input1) | ||
| 318 | ("input2" . ,input2)) | ||
| 319 | #:inputs `((,%bash) (,builder)))) | ||
| 320 | (out (derivation-path->output-path drv))) | ||
| 321 | (define (deps path . deps) | ||
| 322 | (let ((count (length deps))) | ||
| 323 | (string-append path "\n\n" (number->string count) "\n" | ||
| 324 | (string-join (sort deps string<?) "\n") | ||
| 325 | (if (zero? count) "" "\n")))) | ||
| 326 | |||
| 327 | (and (build-derivations %store (list drv)) | ||
| 328 | (equal? (directory-contents out get-string-all) | ||
| 329 | `(("/bash" . ,(string-append %bash "\n\n0\n")) | ||
| 330 | ("/input1" . ,(if (string>? input1 %bash) | ||
| 331 | (string-append (deps %bash) | ||
| 332 | (deps input1 %bash)) | ||
| 333 | (string-append (deps input1 %bash) | ||
| 334 | (deps %bash)))) | ||
| 335 | ("/input2" . ,(string-concatenate | ||
| 336 | (map cdr | ||
| 337 | (sort | ||
| 338 | (map (lambda (p d) | ||
| 339 | (cons p (apply deps p d))) | ||
| 340 | (list %bash input1 input2) | ||
| 341 | (list '() (list %bash) (list input1))) | ||
| 342 | (lambda (x y) | ||
| 343 | (match x | ||
| 344 | ((p1 . _) | ||
| 345 | (match y | ||
| 346 | ((p2 . _) | ||
| 347 | (string<? p1 p2))))))))))))))) | ||
| 348 | |||
| 295 | 349 | ||
| 296 | (define %coreutils | 350 | (define %coreutils |
| 297 | (false-if-exception | 351 | (false-if-exception |
