Subject: [bug#48044] [PATCH v3] build/go: Support cross compiling.

From: Sarah Morgensen <[email-masked]>
Date: Sun, 22 Aug 2021 11:52:29 -0700

Hi Efraim,

Thanks for doing this work!  I'm excited to see it in action.

Efraim Flashner <[email-masked]> writes:

> * guix/build-system/go.scm (lower): Only add target to private-keywords
> when not cross compiling. Adjust bag depending if doing a native or
> cross compile.
> (%go-build-system-modules): Use source-module-closure, add (guix utils).
> (go-cross-build): New procedure.
> * guix/build/go-build-system.scm (setup-go-environment): Accept target
> keyword. Add logic to choose correct target architecture when cross
> compiling.
> ---
>
> Third version of this patch. I think I'm ready to push it. I don't love
> using source-module-closure to include (guix utils), but I need it for
> gnu-triplet->nix-system in setup-go-environment instead of the custom
> parsing I was doing before.

Can you do the parsing host-side and pass e.g. TARGET-GOOS/TARGET-GOARCH
keyword arguments to the build-side?

> -(define* (setup-go-environment #:key inputs outputs #:allow-other-keys)
> +(define* (setup-go-environment #:key inputs outputs target #:allow-other-keys)
>    "Prepare a Go build environment for INPUTS and OUTPUTS.  Build a file system
>  union of INPUTS.  Export GOPATH, which helps the compiler find the source code
>  of the package being built and its dependencies, and GOBIN, which determines
> @@ -149,6 +150,38 @@ dependencies, so it should be self-contained."
>    ;; GOPATH behavior.
>    (setenv "GO111MODULE" "off")
>    (setenv "GOBIN" (string-append (assoc-ref outputs "out") "/bin"))
> +
> +  ;; Cross-build
> +  (when target
> +    ;; Parse the nix-system equivalent of the target and set the
> +    ;; target for compilation accordingly.
> +    (let* ((system (gnu-triplet->nix-system target))
> +           (dash   (string-index system #\-))
> +           (arch   (substring system 0 dash))
> +           (os     (substring system (+ 1 dash))))

And then, if this parsing is host-side, you can probably just do
something like

--8<---------------cut here---------------start------------->8---
(match (string-split (gnu-triplet->nix-system target) #\-)
  ((arch os)
   [...]
--8<---------------cut here---------------end--------------->8---

> +      (match arch
> +        ((or "arm" "armhf")
> +         (setenv "GOARM" "7"))
> +        ((or "mips" "mipsel")
> +         (setenv "GOMIPS" "hardfloat"))
> +        ((or "mips64" "mips64el")
> +         (setenv "GOMIPS64" "hardfloat"))
> +        ((or "powerpc64" "powerpc64le")
> +         (setenv "GOPPC64" "power8"))
> +        (_ #t))))

Are these choices obvious for those compiling for those architectures?
If not, this could probably do with some documentation on why these were
chosen.  (I note that these are all Go's defaults with the exception of
GOARM).

--
Sarah