Subject: Re: bug#60200: Incompatibilities between gcc-toolchain and R packages

From: Lars-Dominik Braun <[email-masked]>
Date: Wed, 21 Dec 2022 10:24:03 +0100

Hi Simon,

> Without any specification about the version, if a package name is
> defined at several versions, then the command-line uses the higher
> version of this package.
minor nit-pick: Not the command-line, but everything that uses
specifications. So manifests via SPECIFICATIONS->MANIFEST are also
affected, see:

    (use-modules (gnu packages) (guix profiles))
    (manifest-entries (specifications->manifest '("gcc-toolchain")))
    $2 = (#<<manifest-entry> name: "gcc-toolchain" version: "12.2.0" …)

The -next suffix has the obvious disadvantage that specifications may
become invalid as we move -next to the “regular” package. So maybe
marking packages “default” like the attached patch does could improve
the current situation. Not just for gcc, but also Haskell and Python
come to mind.

Cheers,
Lars

diff --git a/gnu/packages.scm b/gnu/packages.scm
index 61345f75a9..7e5a6d49c2 100644
--- a/gnu/packages.scm
+++ b/gnu/packages.scm
@@ -356,20 +356,24 @@ (define cache
            (find-packages-by-name/direct name version))))
 
 (define (find-best-packages-by-name name version)
-  "If version is #f, return the list of packages named NAME with the highest
-version numbers; otherwise, return the list of packages named NAME and at
-VERSION."
+  "If version is #f, return the list of packages named NAME with only
+packages marked default? or, if none exist, the highest version numbers;
+otherwise, return the list of packages named NAME and at VERSION."
   (if version
       (find-packages-by-name name version)
       (match (find-packages-by-name name)
         (()
          '())
         ((matches ...)
-         ;; Return the subset of MATCHES with the higher version number.
-         (let ((highest (package-version (first matches))))
-           (take-while (lambda (p)
-                         (string=? (package-version p) highest))
-                       matches))))))
+         ;; Return the subset of MATCHES which are marked default or those with
+         ;; the higher version number.
+         (let ((highest (package-version (first matches)))
+               (default (filter (lambda (p) (assoc-ref (package-properties p) 'default?)) matches)))
+           (if (not (null? default))
+               default
+               (take-while (lambda (p)
+                             (string=? (package-version p) highest))
+                           matches)))))))
 
 ;; Prevent Guile 3 from inlining this procedure so we can mock it in tests.
 (set! find-best-packages-by-name find-best-packages-by-name)
diff --git a/gnu/packages/commencement.scm b/gnu/packages/commencement.scm
index b4566b41cc..2d5e0add26 100644
--- a/gnu/packages/commencement.scm
+++ b/gnu/packages/commencement.scm
@@ -3855,7 +3855,10 @@ (define* (make-gcc-toolchain gcc
                 ("libc-static" ,libc "static"))))))
 
 (define-public gcc-toolchain
-  (make-gcc-toolchain gcc-final))
+  (let ((parent (make-gcc-toolchain gcc-final)))
+    (package
+      (inherit parent)
+      (properties (alist-cons 'default? #t (package-properties parent))))))
 
 (define-public gcc-toolchain-4.8
   (make-gcc-toolchain gcc-4.8))