Subject: Re: [bug#70895] [PATCH] grafts: Only compute necessary graft derivations.

From: Ludovic Courtès <[email-masked]>
Date: Mon, 03 Jun 2024 22:58:10 +0200

Hi David,

David Elsing <[email-masked]> skribis:

> Previously, derivations for grafted packages were computed for all
> packages with replacements, regardless of whether they are actually
> referenced by the package output in question. This can cause ungrafted
> packages to be built even if they are not required.
>
> This commit delays calculating these derivations until they are found to
> actually be applicable.

Neat, good idea!

[...]

>  (define-record-type* <graft> graft make-graft
>    graft?
>    (origin             graft-origin)               ;derivation | store item
>    (origin-output      graft-origin-output         ;string | #f
>                        (default "out"))
> -  (replacement        graft-replacement)          ;derivation | store item
> +  (replacement        graft-replacement)          ;derivation | store item | graft-package
>    (replacement-output graft-replacement-output    ;string | #f
>                        (default "out")))
>  
> @@ -283,6 +290,28 @@ (define (dependency-grafts items)
>                                        #:system system)))))
>            (reference-origins drv items)))
>  
> +  (define package-derivation
> +    (@ (guix packages) package-derivation))
> +  (define package-cross-derivation
> +    (@ (guix packages) package-cross-derivation))
> +
> +  ;; Turn all 'replacement' fields which are <graft-package> records into
> +  ;; grafted package derivations with #:grafts? #t.
> +  (define (calc-remaining-grafts grafts)
> +    (map
> +     (lambda (item)
> +       (graft
> +         (inherit item)
> +         (replacement
> +          (match (graft-replacement item)
> +            (($ <graft-package> package target)
> +             (if target
> +                 (package-cross-derivation
> +                  store package target system #:graft? #t)
> +                 (package-derivation store package system #:graft? #t)))
> +            (new new)))))
> +     grafts))

While this does the job, it breaks an abstraction (grafts are
lower-level than packages) and creates a circular dependency between
(guix grafts) and (guix packages) as a result (not technically a problem
at this point, but it shows that something’s deserves to be clarified).

Maybe there’s a simpler way to achieve this though.  What about allowing
monadic values in the ‘origin’ and ‘replacement’ fields of <graft>?
Their values would be bound lazily, only when needed by
‘graft-derivation’.

WDYT?

Thanks a lot for diving into this!

Ludo’.