GNU bug report logs - #70895
[PATCH] grafts: Only compute necessary graft derivations.

Previous Next

Package: guix-patches;

Reported by: David Elsing <david.elsing <at> posteo.net>

Date: Sun, 12 May 2024 13:44:02 UTC

Severity: normal

Tags: patch

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Ludovic Courtès <ludo <at> gnu.org>
To: David Elsing <david.elsing <at> posteo.net>
Cc: 70895 <at> debbugs.gnu.org
Subject: [bug#70895] [PATCH] grafts: Only compute necessary graft derivations.
Date: Tue, 21 Jan 2025 00:27:30 +0100
[Message part 1 (text/plain, inline)]
Hi,

David Elsing <david.elsing <at> posteo.net> skribis:

> I meant that in 'graft-derivation/shallow', the 'mapping' variable is a
> list of gexps, where 'ungexp' is called on the graft-replacement of the
> grafts. So instead of turning the monadic value into a derivation
> beforehand, this could be done here instead, right? Considering a
> gexp-compiler returns a store monad value of a derivation (IIUC), my
> question was whether it is possible to use such a value in a gexp
> directly (i.e. without the 'return' in the gexp-compiler for a
> derivation, such that the evaluation of the derivation is delayed until
> the gexp is lowered to a derivation). These values would still need to
> be identified by 'procedure?' I guess, so it would not be better than
> currently.
> Does this make sense or did I misunderstand something?

Oh, got it.  Yes, we could keep a <package> in the ‘replacement’ field
instead of explicitly calling ‘package->derivation’.  It’s much simpler,
that’s a good idea.

I gave it a try, see patch attached.  Let me know what you think!

Ludo’.

[Message part 2 (text/x-patch, inline)]
diff --git a/guix/gexp.scm b/guix/gexp.scm
index e44aea6420..d6a429e60e 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014-2024 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2014-2025 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2018 Clément Lassieur <clement <at> lassieur.org>
 ;;; Copyright © 2018 Jan Nieuwenhuizen <janneke <at> gnu.org>
 ;;; Copyright © 2019, 2020 Mathieu Othacehe <m.othacehe <at> gmail.com>
@@ -747,7 +747,12 @@ (define-gexp-compiler compile-parameterized <parameterized>
                    (target (if (memq %current-target-system parameters)
                                (%current-target-system)
                                target)))
-               (lower-object (thunk) system #:target target))))))))
+               (match (thunk)
+                 ((? struct? obj)
+                  (lower-object obj system #:target target))
+                 (obj
+                  (with-monad %store-monad
+                    (return obj)))))))))))
 
   expander => (lambda (parameterized lowered output)
                 (match (parameterized-bindings parameterized)
@@ -758,10 +763,13 @@ (define-gexp-compiler compile-parameterized <parameterized>
                      (with-fluids* fluids
                        (map (lambda (thunk) (thunk)) values)
                        (lambda ()
-                         ;; Delegate to the expander of the wrapped object.
-                         (let* ((base   (thunk))
-                                (expand (lookup-expander base)))
-                           (expand base lowered output)))))))))
+                         (match (thunk)
+                           ((? struct? base)
+                            ;; Delegate to the expander of the wrapped object.
+                            (let ((expand (lookup-expander base)))
+                              (expand base lowered output)))
+                           (obj
+                            obj)))))))))
 
 
 ;;;
diff --git a/guix/grafts.scm b/guix/grafts.scm
index 7636df9267..98ef1e4058 100644
--- a/guix/grafts.scm
+++ b/guix/grafts.scm
@@ -101,9 +101,11 @@ (define* (graft-derivation/shallow drv grafts
     ;; List of store item pairs.
     (map (lambda (graft)
            (gexp
-            ((ungexp (graft-origin graft)
+            ((ungexp (with-parameters ((%graft? #f))
+                       (graft-origin graft))
                      (graft-origin-output graft))
-             . (ungexp (graft-replacement graft)
+             . (ungexp (with-parameters ((%graft? #t))
+                         (graft-replacement graft))
                        (graft-replacement-output graft)))))
          grafts))
 
@@ -275,20 +277,6 @@ (define* (cumulative-grafts store drv grafts
                                       #:system system)))))
           (reference-origins drv items)))
 
-  ;; If the 'replacement' field of the <graft> record is a procedure,
-  ;; this means that it is a value in the store monad and the actual
-  ;; derivation needs to be computed here.
-  (define (finalize-graft item)
-    (let ((replacement (graft-replacement item)))
-      (if (procedure? replacement)
-          (graft
-            (inherit item)
-            (replacement
-             (run-with-store store replacement
-                             #:guile-for-build guile
-                             #:system system)))
-          item)))
-
   (with-cache (list (derivation-file-name drv) outputs grafts)
     (match (non-self-references store drv outputs)
       (()                                         ;no dependencies
@@ -305,8 +293,7 @@ (define* (cumulative-grafts store drv grafts
               ;; Use APPLICABLE, the subset of GRAFTS that is really
               ;; applicable to DRV, to avoid creating several identical
               ;; grafted variants of DRV.
-              (let* ((new    (graft-derivation/shallow* store drv
-                                                        (map finalize-graft applicable)
+              (let* ((new    (graft-derivation/shallow* store drv applicable
                                                         #:outputs outputs
                                                         #:guile guile
                                                         #:system system))
diff --git a/guix/packages.scm b/guix/packages.scm
index d266805ba8..78726b089a 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -1818,15 +1818,13 @@ (define (input-graft system)
          (if replacement
              (mcached eq? (=> %package-graft-cache)
                       (mlet %store-monad ((orig (package->derivation package system
-                                                                     #:graft? #f))
-                                          (new -> (package->derivation replacement system
-                                                                       #:graft? #t)))
-                        ;; Keep NEW as a monadic value so that its computation
-                        ;; is delayed until necessary.
+                                                                     #:graft? #f)))
+                        ;; Keep REPLACEMENT as a package so that its
+                        ;; derivation is computed only when necessary.
                         (return (graft
                                   (origin orig)
                                   (origin-output output)
-                                  (replacement new)
+                                  (replacement replacement)
                                   (replacement-output output))))
                       package output system)
              (return #f))))
@@ -1842,16 +1840,13 @@ (define (input-cross-graft target system)
          (if replacement
              (mlet %store-monad ((orig (package->cross-derivation package
                                                                   target system
-                                                                  #:graft? #f))
-                                 (new -> (package->cross-derivation replacement
-                                                                    target system
-                                                                    #:graft? #t)))
-               ;; Keep NEW as a monadic value so that its computation
-               ;; is delayed until necessary.
+                                                                  #:graft? #f)))
+               ;; Keep REPLACEMENT as a package so that its derivation is
+               ;; computed only when necessary.
                (return (graft
                          (origin orig)
                          (origin-output output)
-                         (replacement new)
+                         (replacement replacement)
                          (replacement-output output))))
              (return #f))))
       (_
diff --git a/tests/packages.scm b/tests/packages.scm
index a4a0e2c3e8..2863fb5991 100644
--- a/tests/packages.scm
+++ b/tests/packages.scm
@@ -1095,9 +1095,7 @@ (define compressors '(("gzip"  . "gz")
       ((graft)
        (and (eq? (graft-origin graft)
                  (package-derivation %store dep))
-            (eq? (run-with-store %store
-                   (graft-replacement graft))
-                 (package-derivation %store new)))))))
+            (eq? (graft-replacement graft) new))))))
 
 ;; XXX: This test would require building the cross toolchain just to see if it
 ;; needs grafting, which is obviously too expensive, and thus disabled.
@@ -1134,9 +1132,7 @@ (define compressors '(("gzip"  . "gz")
       ((graft)
        (and (eq? (graft-origin graft)
                  (package-derivation %store dep))
-            (eq? (run-with-store %store
-                   (graft-replacement graft))
-                 (package-derivation %store new)))))))
+            (eq? (graft-replacement graft) new))))))
 
 (test-assert "package-grafts, same replacement twice"
   (let* ((new  (dummy-package "dep"
@@ -1161,9 +1157,7 @@ (define compressors '(("gzip"  . "gz")
                  (package-derivation %store
                                      (package (inherit dep)
                                               (replacement #f))))
-            (eq? (run-with-store %store
-                   (graft-replacement graft))
-                 (package-derivation %store new)))))))
+            (eq? (graft-replacement graft) new))))))
 
 (test-assert "package-grafts, dependency on several outputs"
   ;; Make sure we get one graft per output; see <https://bugs.gnu.org/41796>.
@@ -1183,9 +1177,9 @@ (define compressors '(("gzip"  . "gz")
       ((graft1 graft2)
        (and (eq? (graft-origin graft1) (graft-origin graft2)
                  (package-derivation %store p0))
-            (eq? (run-with-store %store (graft-replacement graft1))
-                 (run-with-store %store (graft-replacement graft2))
-                 (package-derivation %store p0*))
+            (eq? (graft-replacement graft1)
+                 (graft-replacement graft2)
+                 p0*)
             (string=? "lib"
                       (graft-origin-output graft1)
                       (graft-replacement-output graft1))
@@ -1262,14 +1256,10 @@ (define compressors '(("gzip"  . "gz")
       ((graft1 graft2)
        (and (eq? (graft-origin graft1)
                  (package-derivation %store p1 #:graft? #f))
-            (eq? (run-with-store %store
-                   (graft-replacement graft1))
-                 (package-derivation %store p1r))
+            (eq? (graft-replacement graft1) p1r)
             (eq? (graft-origin graft2)
                  (package-derivation %store p2 #:graft? #f))
-            (eq? (run-with-store %store
-                   (graft-replacement graft2))
-                 (package-derivation %store p2r #:graft? #t)))))))
+            (eq? (graft-replacement graft2) p2r))))))
 
 ;;; XXX: Nowadays 'graft-derivation' needs to build derivations beforehand to
 ;;; find out about their run-time dependencies, so this test is no longer

This bug report was last modified 107 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.