Subject: [PATCH v2 1/3] gnu: avr: Delay all cross compilation packages.

From: Maxim Cournoyer <[email-masked]>
Date: Sun, 17 Sep 2023 20:43:08 -0400

Partially addresses <https://issues.guix.gnu.org/65716>.

* gnu/packages/avr.scm: Add commentary comment.
(avr-gcc): Turn into this...
(make-avr-gcc): ... procedure.
(avr-libc): Likewise, into...
(make-avr-gcc): ... this.  Adjust native-inputs accordingly.
(avr-toolchain): Likewise, into...
(make-avr-toolchain): ... this.
* gnu/packages/avr-xyz.scm (simavr) [propagated-inputs]: replace avr-toolchain
with a call to the 'make-avr-toolchain' procedure.

---

Changes in v2:
- Use mlambda for procedures
- Fix ((make-avr-toolchain)) typo

 gnu/packages/avr-xyz.scm |   2 +-
 gnu/packages/avr.scm     | 214 +++++++++++++++++++++------------------
 2 files changed, 119 insertions(+), 97 deletions(-)

diff --git a/gnu/packages/avr-xyz.scm b/gnu/packages/avr-xyz.scm
index a05157ede78..e8844b8d438 100644
--- a/gnu/packages/avr-xyz.scm
+++ b/gnu/packages/avr-xyz.scm
@@ -71,7 +71,7 @@ (define-public simavr
                            (string-append "PREFIX=" #$output)
                            (string-append "DESTDIR=" #$output))))
     (propagated-inputs
-     (list avr-toolchain))
+     (list (make-avr-toolchain)))
     (native-inputs
      (list autoconf
            which
diff --git a/gnu/packages/avr.scm b/gnu/packages/avr.scm
index b9bee5e624c..1277634ce5a 100644
--- a/gnu/packages/avr.scm
+++ b/gnu/packages/avr.scm
@@ -25,6 +25,7 @@
 (define-module (gnu packages avr)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix gexp)
+  #:use-module (guix memoization)
   #:use-module (guix utils)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -37,113 +38,134 @@ (define-module (gnu packages avr)
   #:use-module (gnu packages flashing-tools)
   #:use-module (gnu packages gcc)
   #:use-module (gnu packages llvm)
-  #:use-module (gnu packages vim))
+  #:use-module (gnu packages vim)
+  #:export (make-avr-toolchain))
 
-(define-public avr-binutils
+;;; Commentary:
+;;;
+;;; This module defines a procedure that can be used to create a complete
+;;; avr-toolchain package.  The procedure must not be used at the top level,
+;;; to avoid cyclic module dependencies caused by the (gnu packages
+;;; cross-base) module referring to top level bindings from (gnu packages
+;;; gcc).
+;;;
+;;; It also contains packages for working with or targeting the AVR system.
+;;;
+
+(define (make-avr-binutils)
   (package
     (inherit (cross-binutils "avr"))
     (name "avr-binutils")))
 
-(define avr-gcc
-  (let ((xgcc (cross-gcc "avr" #:xbinutils avr-binutils)))
+(define make-avr-gcc
+  (mlambda ()
+    (let ((xgcc (cross-gcc "avr" #:xbinutils (make-avr-binutils))))
+      (package
+        (inherit xgcc)
+        (name "avr-gcc")
+        (arguments
+         (substitute-keyword-arguments (package-arguments xgcc)
+           ((#:phases phases)
+            #~(modify-phases #$phases
+                (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH
+                  (lambda* (#:key inputs #:allow-other-keys)
+                    (let ((gcc (assoc-ref inputs  "gcc")))
+                      ;; Remove the default compiler from CPLUS_INCLUDE_PATH
+                      ;; to prevent header conflict with the GCC from
+                      ;; native-inputs.
+                      (setenv "CPLUS_INCLUDE_PATH"
+                              (string-join
+                               (delete (string-append gcc "/include/c++")
+                                       (string-split (getenv "CPLUS_INCLUDE_PATH")
+                                                     #\:))
+                               ":"))
+                      (format #t
+                              "environment variable `CPLUS_INCLUDE_PATH' \
+changed to ~a~%"
+                              (getenv "CPLUS_INCLUDE_PATH")))))
+                ;; Without a working multilib build, the resulting GCC lacks
+                ;; support for nearly every AVR chip.
+                (add-after 'unpack 'fix-genmultilib
+                  (lambda _
+                    ;; patch-shebang doesn't work here because there are
+                    ;; actually several scripts inside this script, each with
+                    ;; a #!/bin/sh that needs patching.
+                    (substitute* "gcc/genmultilib"
+                      (("#!/bin/sh") (string-append "#!" (which "sh"))))))))
+           ((#:configure-flags flags)
+            #~(delete "--disable-multilib" #$flags))))
+        (native-search-paths
+         (list (search-path-specification
+                (variable "CROSS_C_INCLUDE_PATH")
+                (files '("avr/include")))
+               (search-path-specification
+                (variable "CROSS_CPLUS_INCLUDE_PATH")
+                (files '("avr/include")))
+               (search-path-specification
+                (variable "CROSS_OBJC_INCLUDE_PATH")
+                (files '("avr/include")))
+               (search-path-specification
+                (variable "CROSS_OBJCPLUS_INCLUDE_PATH")
+                (files '("avr/include")))
+               (search-path-specification
+                (variable "CROSS_LIBRARY_PATH")
+                (files '("avr/lib")))))
+        (native-inputs
+         `(("gcc" ,gcc)
+           ,@(package-native-inputs xgcc)))))))
+
+(define make-avr-libc
+  (mlambda ()
     (package
-      (inherit xgcc)
-      (name "avr-gcc")
+      (name "avr-libc")
+      (version "2.0.0")
+      (source (origin
+                (method url-fetch)
+                (uri (string-append "mirror://savannah//avr-libc/avr-libc-"
+                                    version ".tar.bz2"))
+                (sha256
+                 (base32
+                  "15svr2fx8j6prql2il2fc0ppwlv50rpmyckaxx38d3gxxv97zpdj"))))
+      (build-system gnu-build-system)
       (arguments
-       (substitute-keyword-arguments (package-arguments xgcc)
-         ((#:phases phases)
-          #~(modify-phases #$phases
-              (add-after 'set-paths 'augment-CPLUS_INCLUDE_PATH
-                (lambda* (#:key inputs #:allow-other-keys)
-                  (let ((gcc (assoc-ref inputs  "gcc")))
-                    ;; Remove the default compiler from CPLUS_INCLUDE_PATH to
-                    ;; prevent header conflict with the GCC from native-inputs.
-                    (setenv "CPLUS_INCLUDE_PATH"
-                            (string-join
-                             (delete (string-append gcc "/include/c++")
-                                     (string-split (getenv "CPLUS_INCLUDE_PATH")
-                                                   #\:))
-                             ":"))
-                    (format #t
-                            "environment variable `CPLUS_INCLUDE_PATH' changed to ~a~%"
-                            (getenv "CPLUS_INCLUDE_PATH")))))
-              ;; Without a working multilib build, the resulting GCC lacks
-              ;; support for nearly every AVR chip.
-              (add-after 'unpack 'fix-genmultilib
-                (lambda _
-                  ;; patch-shebang doesn't work here because there are actually
-                  ;; several scripts inside this script, each with a #!/bin/sh
-                  ;; that needs patching.
-                  (substitute* "gcc/genmultilib"
-                    (("#!/bin/sh") (string-append "#!" (which "sh"))))))))
-         ((#:configure-flags flags)
-          #~(delete "--disable-multilib" #$flags))))
-      (native-search-paths
-       (list (search-path-specification
-              (variable "CROSS_C_INCLUDE_PATH")
-              (files '("avr/include")))
-             (search-path-specification
-              (variable "CROSS_CPLUS_INCLUDE_PATH")
-              (files '("avr/include")))
-             (search-path-specification
-              (variable "CROSS_OBJC_INCLUDE_PATH")
-              (files '("avr/include")))
-             (search-path-specification
-              (variable "CROSS_OBJCPLUS_INCLUDE_PATH")
-              (files '("avr/include")))
-             (search-path-specification
-              (variable "CROSS_LIBRARY_PATH")
-              (files '("avr/lib")))))
-      (native-inputs
-       `(("gcc" ,gcc)
-         ,@(package-native-inputs xgcc))))))
+       '(#:out-of-source? #t
+         #:configure-flags '("--host=avr")))
+      (native-inputs `(("avr-binutils" ,(make-avr-binutils))
+                       ("avr-gcc" ,(make-avr-gcc))))
+      (home-page "https://www.nongnu.org/avr-libc/")
+      (synopsis "The AVR C Library")
+      (description
+       "AVR Libc is a project whose goal is to provide a high quality C
+library for use with GCC on Atmel AVR microcontrollers.")
+      (license
+       (license:non-copyleft "http://www.nongnu.org/avr-libc/LICENSE.txt")))))
 
-(define avr-libc
-  (package
-    (name "avr-libc")
-    (version "2.0.0")
-    (source (origin
-              (method url-fetch)
-              (uri (string-append "mirror://savannah//avr-libc/avr-libc-"
-                                  version ".tar.bz2"))
-              (sha256
-               (base32
-                "15svr2fx8j6prql2il2fc0ppwlv50rpmyckaxx38d3gxxv97zpdj"))))
-    (build-system gnu-build-system)
-    (arguments
-     '(#:out-of-source? #t
-       #:configure-flags '("--host=avr")))
-    (native-inputs `(("avr-binutils" ,avr-binutils)
-                     ("avr-gcc" ,avr-gcc)))
-    (home-page "https://www.nongnu.org/avr-libc/")
-    (synopsis "The AVR C Library")
-    (description
-     "AVR Libc is a project whose goal is to provide a high quality C library
-for use with GCC on Atmel AVR microcontrollers.")
-    (license
-     (license:non-copyleft "http://www.nongnu.org/avr-libc/LICENSE.txt"))))
-
-(define-public avr-toolchain
-  ;; avr-libc checks the compiler version and passes "--enable-device-lib" for avr-gcc > 5.1.0.
-  ;; It wouldn't install the library for atmega32u4 etc if we didn't use the corret avr-gcc.
-  (package
-    (name "avr-toolchain")
-    (version (package-version avr-gcc))
-    (source #f)
-    (build-system trivial-build-system)
-    (arguments '(#:builder (begin (mkdir %output) #t)))
-    (propagated-inputs
-     `(("avrdude" ,avrdude)
-       ("binutils" ,avr-binutils)
-       ("gcc" ,avr-gcc)
-       ("libc" ,avr-libc)))
-    (synopsis "Complete GCC tool chain for AVR microcontroller development")
-    (description "This package provides a complete GCC tool chain for AVR
+(define make-avr-toolchain
+  (mlambda ()
+    (let ((avr-binutils (make-avr-binutils))
+          (avr-libc (make-avr-libc))
+          (avr-gcc (make-avr-gcc)))
+      ;; avr-libc checks the compiler version and passes "--enable-device-lib"
+      ;; for avr-gcc > 5.1.0.  It wouldn't install the library for atmega32u4
+      ;; etc if we didn't use the corret avr-gcc.
+      (package
+        (name "avr-toolchain")
+        (version (package-version avr-gcc))
+        (source #f)
+        (build-system trivial-build-system)
+        (arguments '(#:builder (begin (mkdir %output) #t)))
+        (propagated-inputs
+         `(("avrdude" ,avrdude)
+           ("binutils" ,avr-binutils)
+           ("gcc" ,avr-gcc)
+           ("libc" ,avr-libc)))
+        (synopsis "Complete GCC tool chain for AVR microcontroller development")
+        (description "This package provides a complete GCC tool chain for AVR
 microcontroller development.  This includes the GCC AVR cross compiler and
 avrdude for firmware flashing.  The supported programming languages are C and
 C++.")
-    (home-page (package-home-page avr-libc))
-    (license (package-license avr-gcc))))
+        (home-page (package-home-page avr-libc))
+        (license (package-license avr-gcc))))))
 
 (define-public microscheme
   (package
-- 
2.41.0