diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2017-01-25 10:20:02 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2017-01-25 11:04:25 +0100 |
| commit | 482fda2729c3e76999892cb8f9a0391a7bd37119 (patch) | |
| tree | 377fa547185e3e9114d562033aac00de44efe226 | |
| parent | ad91454281506869f571e225a0ba7d09303f51a1 (diff) | |
grafts: Do not pull derivation outputs not depended on.
Fixes <http://bugs.gnu.org/24886>.
Previously, the grafting derivation of, say, brdf-explorer would pull in
qt:doc even though brdf-explorer depends only on qt:out, not qt:doc.
* guix/grafts.scm (with-cache): Use 'vhash-assoc' and 'vhash-cons'
instead of 'vhash-assq' and 'vhash-consq'.
(cumulative-grafts): Pass #:outputs to 'graft-derivation/shallow'. Use
OUTPUTS instead of (derivation-output-names drv).
(graft-derivation): Add #:outputs parameter; pass it to
'cumulative-grafts'.
* tests/grafts.scm (make-derivation-input): New variable.
("graft-derivation, replaced derivation has multiple outputs"): Make
sure P2:zzz is not part of the outputs of P3D.
("graft-derivation with #:outputs")
("graft-derivation, unused outputs not depended on"): New tests.
| -rw-r--r-- | guix/grafts.scm | 25 | ||||
| -rw-r--r-- | tests/grafts.scm | 118 |
2 files changed, 128 insertions, 15 deletions
diff --git a/guix/grafts.scm b/guix/grafts.scm index e44fc0544f8..11885db226d 100644 --- a/guix/grafts.scm +++ b/guix/grafts.scm | |||
| @@ -216,14 +216,14 @@ available." | |||
| 216 | (define-syntax-rule (with-cache key exp ...) | 216 | (define-syntax-rule (with-cache key exp ...) |
| 217 | "Cache the value of monadic expression EXP under KEY." | 217 | "Cache the value of monadic expression EXP under KEY." |
| 218 | (mlet %state-monad ((cache (current-state))) | 218 | (mlet %state-monad ((cache (current-state))) |
| 219 | (match (vhash-assq key cache) | 219 | (match (vhash-assoc key cache) |
| 220 | ((_ . result) ;cache hit | 220 | ((_ . result) ;cache hit |
| 221 | (return result)) | 221 | (return result)) |
| 222 | (#f ;cache miss | 222 | (#f ;cache miss |
| 223 | (mlet %state-monad ((result (begin exp ...)) | 223 | (mlet %state-monad ((result (begin exp ...)) |
| 224 | (cache (current-state))) | 224 | (cache (current-state))) |
| 225 | (mbegin %state-monad | 225 | (mbegin %state-monad |
| 226 | (set-current-state (vhash-consq key result cache)) | 226 | (set-current-state (vhash-cons key result cache)) |
| 227 | (return result))))))) | 227 | (return result))))))) |
| 228 | 228 | ||
| 229 | (define* (cumulative-grafts store drv grafts | 229 | (define* (cumulative-grafts store drv grafts |
| @@ -264,7 +264,7 @@ derivations to the corresponding set of grafts." | |||
| 264 | #:system system)) | 264 | #:system system)) |
| 265 | (state-return grafts)))) | 265 | (state-return grafts)))) |
| 266 | 266 | ||
| 267 | (with-cache drv | 267 | (with-cache (cons (derivation-file-name drv) outputs) |
| 268 | (match (non-self-references references drv outputs) | 268 | (match (non-self-references references drv outputs) |
| 269 | (() ;no dependencies | 269 | (() ;no dependencies |
| 270 | (return grafts)) | 270 | (return grafts)) |
| @@ -281,29 +281,27 @@ derivations to the corresponding set of grafts." | |||
| 281 | ;; applicable to DRV, to avoid creating several identical | 281 | ;; applicable to DRV, to avoid creating several identical |
| 282 | ;; grafted variants of DRV. | 282 | ;; grafted variants of DRV. |
| 283 | (let* ((new (graft-derivation/shallow store drv applicable | 283 | (let* ((new (graft-derivation/shallow store drv applicable |
| 284 | #:outputs outputs | ||
| 284 | #:guile guile | 285 | #:guile guile |
| 285 | #:system system)) | 286 | #:system system)) |
| 286 | |||
| 287 | ;; Replace references to any of the outputs of DRV, | ||
| 288 | ;; even if that's more than needed. This is so that | ||
| 289 | ;; the result refers only to the outputs of NEW and | ||
| 290 | ;; not to those of DRV. | ||
| 291 | (grafts (append (map (lambda (output) | 287 | (grafts (append (map (lambda (output) |
| 292 | (graft | 288 | (graft |
| 293 | (origin drv) | 289 | (origin drv) |
| 294 | (origin-output output) | 290 | (origin-output output) |
| 295 | (replacement new) | 291 | (replacement new) |
| 296 | (replacement-output output))) | 292 | (replacement-output output))) |
| 297 | (derivation-output-names drv)) | 293 | outputs) |
| 298 | grafts))) | 294 | grafts))) |
| 299 | (return grafts)))))))))) | 295 | (return grafts)))))))))) |
| 300 | 296 | ||
| 301 | (define* (graft-derivation store drv grafts | 297 | (define* (graft-derivation store drv grafts |
| 302 | #:key (guile (%guile-for-build)) | 298 | #:key |
| 299 | (guile (%guile-for-build)) | ||
| 300 | (outputs (derivation-output-names drv)) | ||
| 303 | (system (%current-system))) | 301 | (system (%current-system))) |
| 304 | "Applied GRAFTS to DRV and all its dependencies, recursively. That is, if | 302 | "Apply GRAFTS to the OUTPUTS of DRV and all their dependencies, recursively. |
| 305 | GRAFTS apply only indirectly to DRV, graft the dependencies of DRV, and graft | 303 | That is, if GRAFTS apply only indirectly to DRV, graft the dependencies of |
| 306 | DRV itself to refer to those grafted dependencies." | 304 | DRV, and graft DRV itself to refer to those grafted dependencies." |
| 307 | 305 | ||
| 308 | ;; First, pre-compute the dependency tree of the outputs of DRV. Do this | 306 | ;; First, pre-compute the dependency tree of the outputs of DRV. Do this |
| 309 | ;; upfront to have as much parallelism as possible when querying substitute | 307 | ;; upfront to have as much parallelism as possible when querying substitute |
| @@ -313,6 +311,7 @@ DRV itself to refer to those grafted dependencies." | |||
| 313 | 311 | ||
| 314 | (match (run-with-state | 312 | (match (run-with-state |
| 315 | (cumulative-grafts store drv grafts references | 313 | (cumulative-grafts store drv grafts references |
| 314 | #:outputs outputs | ||
| 316 | #:guile guile #:system system) | 315 | #:guile guile #:system system) |
| 317 | vlist-null) ;the initial cache | 316 | vlist-null) ;the initial cache |
| 318 | ((first . rest) | 317 | ((first . rest) |
diff --git a/tests/grafts.scm b/tests/grafts.scm index 6454a03b1f5..08f05c0f758 100644 --- a/tests/grafts.scm +++ b/tests/grafts.scm | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | 1 | ;;; GNU Guix --- Functional package management for GNU |
| 2 | ;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org> | 2 | ;;; Copyright © 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> |
| 3 | ;;; | 3 | ;;; |
| 4 | ;;; This file is part of GNU Guix. | 4 | ;;; This file is part of GNU Guix. |
| 5 | ;;; | 5 | ;;; |
| @@ -43,6 +43,9 @@ | |||
| 43 | (define %mkdir | 43 | (define %mkdir |
| 44 | (bootstrap-binary "mkdir")) | 44 | (bootstrap-binary "mkdir")) |
| 45 | 45 | ||
| 46 | (define make-derivation-input | ||
| 47 | (@@ (guix derivations) make-derivation-input)) | ||
| 48 | |||
| 46 | 49 | ||
| 47 | (test-begin "grafts") | 50 | (test-begin "grafts") |
| 48 | 51 | ||
| @@ -241,7 +244,18 @@ | |||
| 241 | (replacement p1r) | 244 | (replacement p1r) |
| 242 | (replacement-output "ONE"))) | 245 | (replacement-output "ONE"))) |
| 243 | (p3d (graft-derivation %store p3 (list p1g)))) | 246 | (p3d (graft-derivation %store p3 (list p1g)))) |
| 244 | (and (build-derivations %store (list p3d)) | 247 | |
| 248 | (and (not (find (lambda (input) | ||
| 249 | ;; INPUT should not be P2:zzz since the result of P3 | ||
| 250 | ;; does not depend on it. See | ||
| 251 | ;; <http://bugs.gnu.org/24886>. | ||
| 252 | (and (string=? (derivation-input-path input) | ||
| 253 | (derivation-file-name p2)) | ||
| 254 | (member "zzz" | ||
| 255 | (derivation-input-sub-derivations input)))) | ||
| 256 | (derivation-inputs p3d))) | ||
| 257 | |||
| 258 | (build-derivations %store (list p3d)) | ||
| 245 | (let ((out (derivation->output-path (pk 'p2d p3d)))) | 259 | (let ((out (derivation->output-path (pk 'p2d p3d)))) |
| 246 | (and (not (string=? (readlink out) | 260 | (and (not (string=? (readlink out) |
| 247 | (derivation->output-path p2 "aaa"))) | 261 | (derivation->output-path p2 "aaa"))) |
| @@ -249,6 +263,106 @@ | |||
| 249 | (readlink (string-append out "/two"))) | 263 | (readlink (string-append out "/two"))) |
| 250 | (file-exists? (string-append out "/one/replacement"))))))) | 264 | (file-exists? (string-append out "/one/replacement"))))))) |
| 251 | 265 | ||
| 266 | (test-assert "graft-derivation with #:outputs" | ||
| 267 | ;; Call 'graft-derivation' with a narrowed set of outputs passed as | ||
| 268 | ;; #:outputs. | ||
| 269 | (let* ((p1 (build-expression->derivation | ||
| 270 | %store "p1" | ||
| 271 | `(let ((one (assoc-ref %outputs "one")) | ||
| 272 | (two (assoc-ref %outputs "two"))) | ||
| 273 | (mkdir one) | ||
| 274 | (mkdir two)) | ||
| 275 | #:outputs '("one" "two"))) | ||
| 276 | (p1r (build-expression->derivation | ||
| 277 | %store "P1" | ||
| 278 | `(let ((other (assoc-ref %outputs "ONE"))) | ||
| 279 | (mkdir other) | ||
| 280 | (call-with-output-file (string-append other "/replacement") | ||
| 281 | (const #t))) | ||
| 282 | #:outputs '("ONE"))) | ||
| 283 | (p2 (build-expression->derivation | ||
| 284 | %store "p2" | ||
| 285 | `(let ((aaa (assoc-ref %outputs "aaa")) | ||
| 286 | (zzz (assoc-ref %outputs "zzz"))) | ||
| 287 | (mkdir zzz) (chdir zzz) | ||
| 288 | (mkdir aaa) (chdir aaa) | ||
| 289 | (symlink (assoc-ref %build-inputs "p1:two") "two")) | ||
| 290 | #:outputs '("aaa" "zzz") | ||
| 291 | #:inputs `(("p1:one" ,p1 "one") | ||
| 292 | ("p1:two" ,p1 "two")))) | ||
| 293 | (p1g (graft | ||
| 294 | (origin p1) | ||
| 295 | (origin-output "one") | ||
| 296 | (replacement p1r) | ||
| 297 | (replacement-output "ONE"))) | ||
| 298 | (p2g (graft-derivation %store p2 (list p1g) | ||
| 299 | #:outputs '("aaa")))) | ||
| 300 | ;; P2:aaa depends on P1:two, but not on P1:one, so nothing to graft. | ||
| 301 | (eq? p2g p2))) | ||
| 302 | |||
| 303 | (test-equal "graft-derivation, unused outputs not depended on" | ||
| 304 | '("aaa") | ||
| 305 | |||
| 306 | ;; Make sure that the result of 'graft-derivation' does not pull outputs | ||
| 307 | ;; that are irrelevant to the grafting process. See | ||
| 308 | ;; <http://bugs.gnu.org/24886>. | ||
| 309 | (let* ((p1 (build-expression->derivation | ||
| 310 | %store "p1" | ||
| 311 | `(let ((one (assoc-ref %outputs "one")) | ||
| 312 | (two (assoc-ref %outputs "two"))) | ||
| 313 | (mkdir one) | ||
| 314 | (mkdir two)) | ||
| 315 | #:outputs '("one" "two"))) | ||
| 316 | (p1r (build-expression->derivation | ||
| 317 | %store "P1" | ||
| 318 | `(let ((other (assoc-ref %outputs "ONE"))) | ||
| 319 | (mkdir other) | ||
| 320 | (call-with-output-file (string-append other "/replacement") | ||
| 321 | (const #t))) | ||
| 322 | #:outputs '("ONE"))) | ||
| 323 | (p2 (build-expression->derivation | ||
| 324 | %store "p2" | ||
| 325 | `(let ((aaa (assoc-ref %outputs "aaa")) | ||
| 326 | (zzz (assoc-ref %outputs "zzz"))) | ||
| 327 | (mkdir zzz) (chdir zzz) | ||
| 328 | (symlink (assoc-ref %build-inputs "p1:two") "two") | ||
| 329 | (mkdir aaa) (chdir aaa) | ||
| 330 | (symlink (assoc-ref %build-inputs "p1:one") "one")) | ||
| 331 | #:outputs '("aaa" "zzz") | ||
| 332 | #:inputs `(("p1:one" ,p1 "one") | ||
| 333 | ("p1:two" ,p1 "two")))) | ||
| 334 | (p1g (graft | ||
| 335 | (origin p1) | ||
| 336 | (origin-output "one") | ||
| 337 | (replacement p1r) | ||
| 338 | (replacement-output "ONE"))) | ||
| 339 | (p2g (graft-derivation %store p2 (list p1g) | ||
| 340 | #:outputs '("aaa")))) | ||
| 341 | |||
| 342 | ;; Here P2G should only depend on P1:one and P1R:one; it must not depend | ||
| 343 | ;; on P1:two or P1R:two since these are unused in the grafting process. | ||
| 344 | (and (not (eq? p2g p2)) | ||
| 345 | (let* ((inputs (derivation-inputs p2g)) | ||
| 346 | (match-input (lambda (drv) | ||
| 347 | (lambda (input) | ||
| 348 | (string=? (derivation-input-path input) | ||
| 349 | (derivation-file-name drv))))) | ||
| 350 | (p1-inputs (filter (match-input p1) inputs)) | ||
| 351 | (p1r-inputs (filter (match-input p1r) inputs)) | ||
| 352 | (p2-inputs (filter (match-input p2) inputs))) | ||
| 353 | (and (equal? p1-inputs | ||
| 354 | (list (make-derivation-input (derivation-file-name p1) | ||
| 355 | '("one")))) | ||
| 356 | (equal? p1r-inputs | ||
| 357 | (list | ||
| 358 | (make-derivation-input (derivation-file-name p1r) | ||
| 359 | '("ONE")))) | ||
| 360 | (equal? p2-inputs | ||
| 361 | (list | ||
| 362 | (make-derivation-input (derivation-file-name p2) | ||
| 363 | '("aaa")))) | ||
| 364 | (derivation-output-names p2g)))))) | ||
| 365 | |||
| 252 | (test-assert "graft-derivation, renaming" ;<http://bugs.gnu.org/23132> | 366 | (test-assert "graft-derivation, renaming" ;<http://bugs.gnu.org/23132> |
| 253 | (let* ((build `(begin | 367 | (let* ((build `(begin |
| 254 | (use-modules (guix build utils)) | 368 | (use-modules (guix build utils)) |
