Subject: [bug#65317] [PATCH v2 1/1] gnu: Add go-1.21.

From: Katherine Cox-Buday <[email-masked]>
Date: Thu, 17 Aug 2023 13:40:50 -0600

On 8/15/23 5:20 PM, Katherine Cox-Buday wrote:
 > * gnu/packages/golang.scm (go-1.21): New variable.
 > ---
 >   gnu/packages/golang.scm | 132 ++++++++++++++++++++++++++++++++++++++++
 >   1 file changed, 132 insertions(+)
 >
 > diff --git a/gnu/packages/golang.scm b/gnu/packages/golang.scm
 > index 5a53838435..26022ea211 100644
 > --- a/gnu/packages/golang.scm
 > +++ b/gnu/packages/golang.scm
 > @@ -967,6 +967,138 @@ (define-public go-1.20
 >        ;; https://go.dev/issue/44505
 >        (alist-replace "go" (list go-1.17) (package-native-inputs 
go-1.17)))))
 >
 > +(define-public go-1.21
 > +  (package
 > +    (inherit go-1.20)
 > +    (name "go")
 > +    (version "1.21.0")
 > +    (source (origin
 > +              (method git-fetch)
 > +              (uri (git-reference
 > +                    (url "https://github.com/golang/go")
 > +                    (commit (string-append "go" version))))
 > +              (file-name (git-file-name name version))
 > +              (sha256
 > +               (base32
 > + "04cpahl10i1sncymdfm0vzcj3czv6lv0axwa1sisl9cz3rdrp7hj"))))
 > +    (arguments
 > +     (substitute-keyword-arguments (package-arguments go-1.20)
 > +       ;; Source patching phases are broken up into discrete steps 
to allow
 > +       ;; future versions to discard individual phases without having to
 > +       ;; discard all source patching.
 > +       ((#:phases phases)
 > +        #~(modify-phases #$phases
 > +            (delete 'skip-TestGoPathShlibGccgo-tests)
 > +            (delete 'patch-source)
 > +            (add-after 'unpack 'patch-os-tests
 > +              (lambda _
 > +                (substitute* "src/os/os_test.go"
 > +                  (("/usr/bin") (getcwd))
 > +                  (("/bin/sh") (which "sh")))))
 > +
 > +            (add-after 'unpack 'apply-patches
 > +              (lambda* (#:key inputs #:allow-other-keys)
 > +                ;; Having the patch in the 'patches' field of 
<origin> breaks
 > +                ;; the 'TestServeContent' test due to the fact that
 > +                ;; timestamps are reset.  Thus, apply it from here.
 > +                (invoke "patch" "-p1" "--force" "-i"
 > +                        (assoc-ref inputs 
"go-fix-script-tests.patch"))))
 > +
 > +            (add-after 'unpack 'patch-src/net
 > +              (lambda* (#:key inputs #:allow-other-keys)
 > +                (let ((net-base (assoc-ref inputs "net-base")))
 > +                  (substitute* "src/net/lookup_unix.go"
 > +                    (("/etc/protocols")
 > +                     (string-append net-base "/etc/protocols")))
 > +                  (substitute* "src/net/port_unix.go"
 > +                    (("/etc/services")
 > +                     (string-append net-base "/etc/services"))))))
 > +
 > +            (add-after 'unpack 'patch-zoneinfo
 > +              (lambda* (#:key inputs #:allow-other-keys)
 > +                ;; Add the path to this specific version of tzdata's 
zoneinfo
 > +                ;; file to the top of the list to search. We don't 
want to
 > +                ;; replace any sources because it will affect how 
binaries
 > +                ;; compiled with this Go toolchain behave on non-guix
 > +                ;; platforms.
 > +                (substitute* "src/time/zoneinfo_unix.go"
 > +                  (("var platformZoneSources.+" all)
 > +                   (format #f "~a~%\"~a/share/zoneinfo\",~%"
 > +                           all
 > +                           (assoc-ref inputs "tzdata"))))))
 > +
 > +            (add-after 'unpack 'patch-cmd/go/testdata/script
 > +              (lambda _
 > +                (substitute* 
"src/cmd/go/testdata/script/cgo_path_space.txt"
 > +                  (("/bin/sh") (which "sh")))))
 > +
 > +            (add-after 'enable-external-linking 
'enable-external-linking-1.21
 > +              (lambda _
 > +                ;; Invoke GCC to link any archives created with GCC 
(that is, any
 > +                ;; packages built using 'cgo'), because Go doesn't 
know how to
 > +                ;; handle the runpaths but GCC does.  Use 
substitute* rather than
 > +                ;; a patch since these files are liable to change often.
 > +                ;;
 > +                ;; XXX: Replace with GO_EXTLINK_ENABLED=1 or similar 
when
 > +                ;; <https://github.com/golang/go/issues/31544> and/or
 > +                ;; <https://github.com/golang/go/issues/43525> are 
resolved.
 > +                (substitute* "src/cmd/link/internal/ld/config.go"
 > +                  (("\\(iscgo && \\(.+\\)") "iscgo"))
 > +                (substitute* "src/internal/testenv/testenv.go"
 > +                  (("!CanInternalLink.+") "true {\n"))
 > +                (substitute* "src/syscall/exec_linux_test.go"
 > +                  (("testenv.MustHaveExecPath\\(t, \"whoami\"\\)")
 > +                   "t.Skipf(\"no passwd file present\")"))))
 > +
 > +            (replace 'install
 > +              (lambda* (#:key outputs #:allow-other-keys)
 > +                ;; Notably, we do not install archives (180M), which 
Go will
 > +                ;; happily recompile quickly (and cache) if needed, 
almost
 > +                ;; surely faster than they could be substituted.
 > +                ;;
 > +                ;; The main motivation for pre-compiled archives is 
to use
 > +                ;; libc-linked `net' or `os' packages without a C 
compiler,
 > +                ;; but on Guix a C compiler is necessary to properly 
link the
 > +                ;; final binaries anyway.  Many build flags also 
invalidate
 > +                ;; these pre-compiled archives, so in practice Go often
 > +                ;; recompiles them anyway.
 > +                ;;
 > +                ;; Upstream is also planning to no longer install these
 > +                ;; archives: <https://github.com/golang/go/issues/47257>
 > +                ;;
 > +                ;; When necessary, a custom pre-compiled library 
package can
 > +                ;; be created with `#:import-path "std"' and used with
 > +                ;; `-pkgdir'.
 > +                ;;
 > +                ;; When moving files into place, any files that come 
from
 > +                ;; GOROOT should remain in GOROOT to continue 
functioning. If
 > +                ;; they need to be referenced from some other 
directory, they
 > +                ;; need to be symlinked from GOROOT. For more 
information,
 > +                ;; please see https://github.com/golang/go/issues/61921
 > +                (let* ((out (assoc-ref outputs "out"))
 > +                       (tests (assoc-ref outputs "tests")))
 > +                  (for-each
 > +                   (lambda (file)
 > +                     (copy-recursively file (string-append out 
"/lib/go/" file)))
 > +                   '("bin" "lib" "VERSION" "pkg/include" "pkg/tool"))
We also need to install go.env here. See 
https://github.com/golang/go/issues/61928.

There is also some new functionality outlined in the GOTOOLCHAIN 
environment variable that we need to consider.

 From https://go.dev/doc/toolchain :

"The go command can use its bundled Go toolchain as well as other 
versions that it finds in the local PATH or downloads as needed.
[...]
When GOTOOLCHAIN is set to local, the go command always runs the bundled 
Go toolchain.
[...]
When using GOTOOLCHAIN=auto or GOTOOLCHAIN=<name>+auto, the Go command 
downloads newer toolchains as needed. These toolchains are packaged as 
special modules with module path golang.org/toolchain and version 
v0.0.1-goVERSION.GOOS-GOARCH. Toolchains are downloaded like any other 
module, meaning that toolchain downloads can be proxied by setting 
GOPROXY and have their checksums checked by the Go checksum database. 
Because the specific toolchain used depends on the system’s own default 
toolchain as well as the local operating system and architecture (GOOS 
and GOARCH), it is not practical to write toolchain module checksums to 
go.sum. Instead, toolchain downloads fail for lack of verification if 
GOSUMDB=off. GOPRIVATE and GONOSUMDB patterns do not apply to the 
toolchain downloads."

I think we should leave this set to "auto" for the following reasons:

- The toolchain is now considered part of a module's dependencies, and 
it will be downloaded just like any other dependency.

- This seems to be a major stance the Go project is taking on how things 
work, and if our package doesn't perform these automatic downloads it 
will be surprising/confusing for Go developers.

- Automatic downloads do not pollute the user's path nor do they attempt 
to pollute the store.

- When our packages are built with > 1.21.0, we'll still have 
reproducible builds because any modules requiring a greater versioned 
toolchain will fail to download it due to our isolated build container 
and thus the build will fail and the packager will still have to 
reference the correct version of Go.

More details here: https://go.dev/blog/toolchain

 > +
 > +                  (symlink "lib/go/bin" (string-append out "/bin"))
 > +
 > +                  (for-each
 > +                   (match-lambda
 > +                     ((file dest output)
 > +                      ;; Copy to output/dest and symlink from 
output/lib/go/file.
 > +                      (let ((file* (string-append output "/lib/go/" 
file))
 > +                            (dest* (string-append output "/" dest)))
 > +                        (copy-recursively file dest*)
 > +                        (mkdir-p (dirname file*))
 > +                        (symlink (string-append "../../" dest) file*))))
 > +                   `(("src"          "share/go/src"        ,out)
 > +                     ("misc"         "share/go/misc"       ,out)
 > +                     ("doc"          "share/doc/go/doc"    ,out)
 > +                     ("api"          "share/go/api"        ,tests)
 > +                     ("test"         "share/go/test" ,tests))))))))))))
 > +
 >   (define-public go go-1.17)
 >
 >   (define make-go-std
 >
 > base-commit: a4bed14c438dc0cbc1c1885a38f8409c7fef7957