summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2017-01-25 10:20:02 +0100
committerLudovic Courtès <ludo@gnu.org>2017-01-25 11:04:25 +0100
commit482fda2729c3e76999892cb8f9a0391a7bd37119 (patch)
tree377fa547185e3e9114d562033aac00de44efe226
parentad91454281506869f571e225a0ba7d09303f51a1 (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.scm25
-rw-r--r--tests/grafts.scm118
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.
305GRAFTS apply only indirectly to DRV, graft the dependencies of DRV, and graft 303That is, if GRAFTS apply only indirectly to DRV, graft the dependencies of
306DRV itself to refer to those grafted dependencies." 304DRV, 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))