Subject: Re: bug#50493: Update go-build-system to use Go 1.17.

From: Leo Famulari <[email-masked]>
Date: Sun, 19 Dec 2021 20:30:18 -0500

On Sun, Dec 19, 2021 at 10:19:02AM +0200, Efraim Flashner wrote:
> All of go is blocked on aarch64 with binutils-gold not compiling. I have
> a patch locally to add gcc:lib for (target-arm?) to go-1.17 which I'll
> push after testing with binutils-gold. I think going straight to 1.17 is
> fine, there's no regression against the current support for aarch64.

Oh, good point.

Based on the attached patches (rebased / adjusted for current master),
I'll proceed with testing the build of all Go packages on x86_64-linux.
From f26d2b8b30867d23a417af2c40ba8062adb87bd7 Mon Sep 17 00:00:00 2001
From: Sarah Morgensen <[email-masked]>
Date: Mon, 13 Dec 2021 20:11:47 -0500
Subject: [PATCH 1/4] build-system/go: Add #:substitutable? argument.

* guix/build-system/go.scm (go-build): Add 'substitutable?' argument.
(go-cross-build): Likewise.

Signed-off-by: Leo Famulari <[email-masked]>
---
 guix/build-system/go.scm | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/guix/build-system/go.scm b/guix/build-system/go.scm
index 18824c79d9..0b2bf1c11b 100644
--- a/guix/build-system/go.scm
+++ b/guix/build-system/go.scm
@@ -172,7 +172,8 @@ (define* (go-build name inputs
                    (imported-modules %go-build-system-modules)
                    (modules '((guix build go-build-system)
                               (guix build union)
-                              (guix build utils))))
+                              (guix build utils)))
+                   (substitutable? #t))
   (define builder
     (with-imported-modules imported-modules
       #~(begin
@@ -182,6 +183,7 @@ (define builder
                     #:system #$system
                     #:phases #$phases
                     #:outputs #$(outputs->gexp outputs)
+                    #:substitutable? #$substitutable?
                     #:goarch #$goarch
                     #:goos #$goos
                     #:search-paths '#$(sexp->gexp
@@ -222,7 +224,8 @@ (define* (go-cross-build name
                          (imported-modules %go-build-system-modules)
                          (modules '((guix build go-build-system)
                                     (guix build union)
-                                    (guix build utils))))
+                                    (guix build utils)))
+                         (substitutable? #t))
   "Cross-build NAME using GO, where TARGET is a GNU triplet and with INPUTS."
   (define builder
     #~(begin

base-commit: 99f290bf5ba59e3218b95d7505ac27f989250aad
-- 
2.34.0

From a437f30bfaa4965cb42acb37f387e2c8106c7884 Mon Sep 17 00:00:00 2001
From: Sarah Morgensen <[email-masked]>
Date: Sun, 19 Sep 2021 22:20:49 -0700
Subject: [PATCH 2/4] build-system/go: Initialize build cache from input
 packages.

* guix/build/go-build-system.com (setup-go-environment): Set GOCACHE to
a location within the build directory.  Union "/var/cache/go/build"
input directories to initialize the cache.  Generate "trim.txt" within
the cache, with the current time.

Signed-off-by: Leo Famulari <[email-masked]>
---
 guix/build/go-build-system.scm | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/guix/build/go-build-system.scm b/guix/build/go-build-system.scm
index 4768ee8562..7f25e05d0d 100644
--- a/guix/build/go-build-system.scm
+++ b/guix/build/go-build-system.scm
@@ -5,6 +5,7 @@
 ;;; Copyright © 2020 Jack Hill <[email-masked]>
 ;;; Copyright © 2020 Jakub Kądziołka <[email-masked]>
 ;;; Copyright © 2020, 2021 Efraim Flashner <[email-masked]>
+;;; Copyright © 2021 Sarah Morgensen <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -138,9 +139,28 @@ (define* (setup-go-environment #:key inputs outputs goos goarch #:allow-other-ke
 where executables (\"commands\") are installed to.  This phase is sometimes used
 by packages that use (guix build-system gnu) but have a handful of Go
 dependencies, so it should be self-contained."
-  ;; The Go cache is required starting in Go 1.12.  We don't actually use it but
-  ;; we need it to be a writable directory.
-  (setenv "GOCACHE" "/tmp/go-cache")
+  (define (search-input-directories dir)
+    (filter directory-exists?
+            (map (match-lambda
+                   ((name . directory)
+                    (string-append directory "/" dir)))
+                 inputs)))
+
+  ;; Seed the Go build cache with the build caches from input packages.
+  (let ((cache (string-append (getcwd) "/go-build")))
+    (setenv "GOCACHE" cache)
+    (union-build cache
+                 (search-input-directories "/var/cache/go/build")
+                 ;; Creating all directories isn't that bad, because there are
+                 ;; only ever 256 of them.
+                 #:create-all-directories? #t
+                 #:log-port (%make-void-port "w"))
+
+    ;; Tell Go that the cache was recently trimmed, so it doesn't try to.
+    (call-with-output-file (string-append cache "/trim.txt")
+      (lambda (port)
+        (format port "~a" (current-time)))))
+
   ;; Using the current working directory as GOPATH makes it easier for packagers
   ;; who need to manipulate the unpacked source code.
   (setenv "GOPATH" (getcwd))
-- 
2.34.0

From cddf7d95c9134075aec45e2f2e49073f92aadfcb Mon Sep 17 00:00:00 2001
From: Sarah Morgensen <[email-masked]>
Date: Sun, 19 Sep 2021 22:20:50 -0700
Subject: [PATCH 3/4] build-system/go: Add pre-built standard library as
 implicit input.

* gnu/packages/golang.scm (make-go-std): New procedure.
* guix/build-system/go.scm (make-go-std): New procedure.
(lower): Use it.  Add pre-built standard library to inputs.

Signed-off-by: Leo Famulari <[email-masked]>
---
 gnu/packages/golang.scm  | 30 ++++++++++++++++++++++++++++++
 guix/build-system/go.scm | 16 ++++++++++++++--
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/gnu/packages/golang.scm b/gnu/packages/golang.scm
index c863388475..7989a3a138 100644
--- a/gnu/packages/golang.scm
+++ b/gnu/packages/golang.scm
@@ -806,6 +806,36 @@ (define-public go-1.17
 
 (define-public go go-1.14)
 
+(define-public (make-go-std go)
+  "Return a package which builds the standard library for Go compiler GO."
+  (package
+    (name (string-append (package-name go) "-std"))
+    (version (package-version go))
+    (source #f)
+    (build-system go-build-system)
+    (arguments
+     `(#:import-path "std"
+       #:build-flags `("-pkgdir" "pkg") ; "Install" to build directory.
+       #:allow-go-reference? #t
+       #:substitutable? #f ; Faster to build than download.
+       #:tests? #f ; Already tested in the main Go build.
+       #:go ,go
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'unpack)
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (out-cache (string-append out "/var/cache/go/build")))
+               (copy-recursively (getenv "GOCACHE") out-cache)
+               (delete-file (string-append out-cache "/trim.txt"))
+               (delete-file (string-append out-cache "/README")))))
+         (delete 'install-license-files))))
+    (home-page (package-home-page go))
+    (synopsis "Cached standard library build for Go")
+    (description (package-description go))
+    (license (package-license go))))
+
 (define-public go-0xacab-org-leap-shapeshifter
   (let ((commit "0aa6226582efb8e563540ec1d3c5cfcd19200474")
         (revision "12"))
diff --git a/guix/build-system/go.scm b/guix/build-system/go.scm
index 0b2bf1c11b..09148f8730 100644
--- a/guix/build-system/go.scm
+++ b/guix/build-system/go.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2020 Jakub Kądziołka <[email-masked]>
 ;;; Copyright © 2021 Ludovic Courtès <[email-masked]>
 ;;; Copyright © 2021 Efraim Flashner <[email-masked]>
+;;; Copyright © 2021 Sarah Morgensen <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -112,6 +113,9 @@ (define (default-go)
   (let ((go (resolve-interface '(gnu packages golang))))
     (module-ref go 'go)))
 
+(define (make-go-std)
+  (module-ref (resolve-interface '(gnu packages golang)) 'make-go-std))
+
 (define* (lower name
                 #:key source inputs native-inputs outputs system target
                 (go (default-go))
@@ -121,6 +125,14 @@ (define* (lower name
   (define private-keywords
     '(#:target #:go #:inputs #:native-inputs))
 
+  (define inputs-with-cache
+    ;; XXX: Avoid a circular dependency.  This should be rewritten with
+    ;; 'package-mapping' or similar.
+    (let ((go-std-name (string-append (package-name go) "-std")))
+      (if (string-prefix? go-std-name name)
+          inputs
+          (cons `(,go-std-name ,((make-go-std) go)) inputs))))
+
   (bag
     (name name)
     (system system)
@@ -130,7 +142,7 @@ (define private-keywords
                         '())
                      ,@`(("go" ,go))
                      ,@native-inputs
-                     ,@(if target '() inputs)
+                     ,@(if target '() inputs-with-cache)
                      ,@(if target
                          ;; Use the standard cross inputs of
                          ;; 'gnu-build-system'.
@@ -138,7 +150,7 @@ (define private-keywords
                          '())
                      ;; Keep the standard inputs of 'gnu-build-system'.
                      ,@(standard-packages)))
-    (host-inputs (if target inputs '()))
+    (host-inputs (if target inputs-with-cache '()))
 
     ;; The cross-libc is really a target package, but for bootstrapping
     ;; reasons, we can't put it in 'host-inputs'.  Namely, 'cross-gcc' is a
-- 
2.34.0

From 6f9d52c1117279be567e2ee9f56f88e470867e92 Mon Sep 17 00:00:00 2001
From: Sarah Morgensen <[email-masked]>
Date: Sun, 19 Sep 2021 22:20:51 -0700
Subject: [PATCH 4/4] build-system/go: Use go-1.17 by default.

Build all Go packages with go-1.17 by default.  Explicitly specify an
older Go version in packages which cannot build with go-1.17.

* gnu/packages/golang.scm (go): Update from 'go-1.14' to 'go-1.17'.
* gnu/packages/docker.scm (docker)[native-inputs]: Explicitly use 'go-1.14'.
* gnu/packages/ipfs.scm (go-github-com-ipfs-go-ipfs-cmdkit-files)[arguments]:
Set #:go to 'go-1.16'.

Signed-off-by: Leo Famulari <[email-masked]>
---
 gnu/packages/docker.scm | 2 +-
 gnu/packages/golang.scm | 2 +-
 gnu/packages/ipfs.scm   | 3 ++-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/gnu/packages/docker.scm b/gnu/packages/docker.scm
index cdf62f5e9a..d012ed43c6 100644
--- a/gnu/packages/docker.scm
+++ b/gnu/packages/docker.scm
@@ -585,7 +585,7 @@ (define-public docker
        ("xz" ,xz)))
     (native-inputs
      (list eudev ; TODO: Should be propagated by lvm2 (.pc -> .pc)
-           go gotestsum pkg-config))
+           go-1.14 gotestsum pkg-config))
     (synopsis "Docker container component library, and daemon")
     (description "This package provides a framework to assemble specialized
 container systems.  It includes components for orchestration, image
diff --git a/gnu/packages/golang.scm b/gnu/packages/golang.scm
index 7989a3a138..1ac6c81900 100644
--- a/gnu/packages/golang.scm
+++ b/gnu/packages/golang.scm
@@ -804,7 +804,7 @@ (define-public go-1.17
            (alist-replace "go" (list go-1.16) (package-native-inputs go-1.16))
            (package-native-inputs go-1.16))))))
 
-(define-public go go-1.14)
+(define-public go go-1.17)
 
 (define-public (make-go-std go)
   "Return a package which builds the standard library for Go compiler GO."
diff --git a/gnu/packages/ipfs.scm b/gnu/packages/ipfs.scm
index f566b850aa..b567b23353 100644
--- a/gnu/packages/ipfs.scm
+++ b/gnu/packages/ipfs.scm
@@ -48,7 +48,8 @@ (define-public go-github-com-ipfs-go-ipfs-cmdkit-files
               "0qk6fshgdmhp8dip2ksm13j6nywi41m9mn0czkvmw6b697z85l2r"))))
       (build-system go-build-system)
       (arguments
-       '(#:unpack-path "github.com/ipfs/go-ipfs-cmdkit"
+       `(#:go ,go-1.16
+         #:unpack-path "github.com/ipfs/go-ipfs-cmdkit"
          #:import-path "github.com/ipfs/go-ipfs-cmdkit/files"))
       (home-page "https://github.com/ipfs/go-ipfs-cmdkit")
       (synopsis "Shared types, functions and values for go-ipfs")
-- 
2.34.0