Subject: bug#65665: package-mapping with #:deep? #t doesn't get all the implicit inputs

From: Ulf Herrman <[email-masked]>
Date: Thu, 12 Oct 2023 20:49:25 -0500

Maxim Cournoyer <[email-masked]> writes:

> Any build system accepting package as arguments are subject to this
> problem, if I understand correctly.

It's not quite everywhere a package is accepted as an argument: there
are many cases where a package is passed as a package argument but
doesn't end up in the arguments list of the corresponding bag.  This is
usually the case because that argument is only overriding a default
package that is just added as an input to the bag, with no special
treatment aside from being an implicit input.  For example, #:cmake in
cmake-build-system works this way.

This is however not the case for #:qtbase in qt-build-system, and, much
more prominently, for #:guile.  Neither qtbase nor guile are added to
bag inputs implicitly, but they do end up in the final builder, even if
not specified.

Concretely, this looks like this:
---------------------------------
(use-modules (guix packages)
             (guix profiles)
             (gnu packages base))

(define guile-named-lyle
  (package
    (inherit (default-guile))
    (name "lyle")))

;; contrived example that only replaces hello's immediate dependencies
(define hello-transformer
  (package-mapping (lambda (p0)
                     (if (eq? p0 (default-guile))
                         guile-named-lyle
                         p0))
                   (lambda (p)
                     (not (eq? p hello)))
                   #:deep? #t))

(define hello-with-lyle
  (hello-transformer hello))

(packages->manifest (list hello hello-with-lyle))

;; $ guix build --derivations --manifest=THISFILE
;; Expectation: build for hello-with-lyle is done with guile-named-lyle.
;; Reality: derivation for hello-with-lyle is the same as hello.
---------------------------------
(and I have confirmed that the above results in guile-named-lyle being
used with the proposed patches applied)

A similar problem manifests when one tries replacing (default-qtbase) in
a package using qt-build-system.  Both it and guile are in bag arguments
and not inputs because it's not enough that they be included as inputs,
the builder must also know which one is considered "used by the build
system" if there are multiple.  One could argue that this ambiguity also
exists with other build systems - "which cmake should be used, which gcc
should be used", etc - but they choose to resolve it with "eh, whatever
shows up first in PATH matching the required name is probably fine".
It's not unimaginable that there could be cases where explicitly
specifying which package should be used for a particular role would be
necessary, though.

- Ulf