diff options
| author | Efraim Flashner <efraim@flashner.co.il> | 2021-04-26 21:13:06 +0300 |
|---|---|---|
| committer | Efraim Flashner <efraim@flashner.co.il> | 2021-09-13 15:33:30 +0300 |
| commit | de4f5df95db6c2e7071bf5e44c0d7ae928da1025 (patch) | |
| tree | b760d81f90354814819a41c11684d8084e322b95 | |
| parent | 43f9757f809d0fb3cd7c3e8b24bfb927179055e8 (diff) | |
build/go: Support cross compiling.
* guix/build-system/go.scm (go-target): New procedure.
(go-build): Add goarch, goos keywords. Adjust bag depending if doing a
native or cross compile.
(go-cross-build): New procedure.
* guix/build/go-build-system.scm (setup-go-environment): Accept goarch,
goos keywords. Set go environment variables based on target architecture.
* doc/guix.texi (Build Systems): Mention new go-build-system keywords.
| -rw-r--r-- | doc/guix.texi | 7 | ||||
| -rw-r--r-- | guix/build-system/go.scm | 163 | ||||
| -rw-r--r-- | guix/build/go-build-system.scm | 20 |
3 files changed, 172 insertions, 18 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index 220499503d6..2fc96879106 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -7759,6 +7759,13 @@ Packages that provide Go libraries should install their source code into | |||
| 7759 | the built output. The key @code{#:install-source?}, which defaults to | 7759 | the built output. The key @code{#:install-source?}, which defaults to |
| 7760 | @code{#t}, controls whether or not the source code is installed. It can | 7760 | @code{#t}, controls whether or not the source code is installed. It can |
| 7761 | be set to @code{#f} for packages that only provide executable files. | 7761 | be set to @code{#f} for packages that only provide executable files. |
| 7762 | |||
| 7763 | Packages can be cross-built, and if a specific architecture or operating | ||
| 7764 | system is desired then the keywords @code{#:goarch} and @code{#:goos} | ||
| 7765 | can be used to force the package to be built for that architecture and | ||
| 7766 | operating system. The combinations known to Go can be found | ||
| 7767 | @url{"https://golang.org/doc/install/source#environment", in their | ||
| 7768 | documentation}. | ||
| 7762 | @end defvr | 7769 | @end defvr |
| 7763 | 7770 | ||
| 7764 | @defvr {Scheme Variable} glib-or-gtk-build-system | 7771 | @defvr {Scheme Variable} glib-or-gtk-build-system |
diff --git a/guix/build-system/go.scm b/guix/build-system/go.scm index 8f55796e864..4c1a732107e 100644 --- a/guix/build-system/go.scm +++ b/guix/build-system/go.scm | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | ;;; Copyright © 2016 Petter <petter@mykolab.ch> | 2 | ;;; Copyright © 2016 Petter <petter@mykolab.ch> |
| 3 | ;;; Copyright © 2017 Leo Famulari <leo@famulari.name> | 3 | ;;; Copyright © 2017 Leo Famulari <leo@famulari.name> |
| 4 | ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net> | 4 | ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net> |
| 5 | ;;; Copyright © 2021 Efraim Flashner <efraim@flashner.co.il> | ||
| 5 | ;;; | 6 | ;;; |
| 6 | ;;; This file is part of GNU Guix. | 7 | ;;; This file is part of GNU Guix. |
| 7 | ;;; | 8 | ;;; |
| @@ -27,6 +28,7 @@ | |||
| 27 | #:use-module (guix packages) | 28 | #:use-module (guix packages) |
| 28 | #:use-module (ice-9 match) | 29 | #:use-module (ice-9 match) |
| 29 | #:use-module (ice-9 regex) | 30 | #:use-module (ice-9 regex) |
| 31 | #:use-module (srfi srfi-1) | ||
| 30 | #:export (%go-build-system-modules | 32 | #:export (%go-build-system-modules |
| 31 | go-build | 33 | go-build |
| 32 | go-build-system | 34 | go-build-system |
| @@ -78,6 +80,24 @@ present) if a pseudo-version pattern is not recognized." | |||
| 78 | commit hash and its date rather than a proper release tag." | 80 | commit hash and its date rather than a proper release tag." |
| 79 | (regexp-exec %go-pseudo-version-rx version)) | 81 | (regexp-exec %go-pseudo-version-rx version)) |
| 80 | 82 | ||
| 83 | (define (go-target target) | ||
| 84 | ;; Parse the nix-system equivalent of the target and set the | ||
| 85 | ;; target for compilation accordingly. | ||
| 86 | (match (string-split (gnu-triplet->nix-system target) #\-) | ||
| 87 | ((arch os) | ||
| 88 | (list (match arch | ||
| 89 | ("aarch64" "arm64") | ||
| 90 | ("armhf" "arm") | ||
| 91 | ("powerpc64le" "ppc64le") | ||
| 92 | ("powerpc64" "ppc64") | ||
| 93 | ("i686" "386") | ||
| 94 | ("x86_64" "amd64") | ||
| 95 | ("mips64el" "mips64le") | ||
| 96 | (_ arch)) | ||
| 97 | (match os | ||
| 98 | ((or "mingw32" "cygwin") "windows") | ||
| 99 | (_ os)))))) | ||
| 100 | |||
| 81 | (define %go-build-system-modules | 101 | (define %go-build-system-modules |
| 82 | ;; Build-side modules imported and used by default. | 102 | ;; Build-side modules imported and used by default. |
| 83 | `((guix build go-build-system) | 103 | `((guix build go-build-system) |
| @@ -98,22 +118,37 @@ commit hash and its date rather than a proper release tag." | |||
| 98 | (define private-keywords | 118 | (define private-keywords |
| 99 | '(#:source #:target #:go #:inputs #:native-inputs)) | 119 | '(#:source #:target #:go #:inputs #:native-inputs)) |
| 100 | 120 | ||
| 101 | (and (not target) ;XXX: no cross-compilation | 121 | (bag |
| 102 | (bag | 122 | (name name) |
| 103 | (name name) | 123 | (system system) |
| 104 | (system system) | 124 | (target target) |
| 105 | (host-inputs `(,@(if source | 125 | (build-inputs `(,@(if source |
| 106 | `(("source" ,source)) | 126 | `(("source" ,source)) |
| 107 | '()) | 127 | '()) |
| 108 | ,@inputs | 128 | ,@`(("go" ,go)) |
| 109 | 129 | ,@native-inputs | |
| 110 | ;; Keep the standard inputs of 'gnu-build-system'. | 130 | ,@(if target '() inputs) |
| 111 | ,@(standard-packages))) | 131 | ,@(if target |
| 112 | (build-inputs `(("go" ,go) | 132 | ;; Use the standard cross inputs of |
| 113 | ,@native-inputs)) | 133 | ;; 'gnu-build-system'. |
| 114 | (outputs outputs) | 134 | (standard-cross-packages target 'host) |
| 115 | (build go-build) | 135 | '()) |
| 116 | (arguments (strip-keyword-arguments private-keywords arguments))))) | 136 | ;; Keep the standard inputs of 'gnu-build-system'. |
| 137 | ,@(standard-packages))) | ||
| 138 | (host-inputs (if target inputs '())) | ||
| 139 | |||
| 140 | ;; The cross-libc is really a target package, but for bootstrapping | ||
| 141 | ;; reasons, we can't put it in 'host-inputs'. Namely, 'cross-gcc' is a | ||
| 142 | ;; native package, so it would end up using a "native" variant of | ||
| 143 | ;; 'cross-libc' (built with 'gnu-build'), whereas all the other packages | ||
| 144 | ;; would use a target variant (built with 'gnu-cross-build'.) | ||
| 145 | (target-inputs (if target | ||
| 146 | (standard-cross-packages target 'target) | ||
| 147 | '())) | ||
| 148 | |||
| 149 | (outputs outputs) | ||
| 150 | (build (if target go-cross-build go-build)) | ||
| 151 | (arguments (strip-keyword-arguments private-keywords arguments)))) | ||
| 117 | 152 | ||
| 118 | (define* (go-build store name inputs | 153 | (define* (go-build store name inputs |
| 119 | #:key | 154 | #:key |
| @@ -128,6 +163,8 @@ commit hash and its date rather than a proper release tag." | |||
| 128 | (tests? #t) | 163 | (tests? #t) |
| 129 | (allow-go-reference? #f) | 164 | (allow-go-reference? #f) |
| 130 | (system (%current-system)) | 165 | (system (%current-system)) |
| 166 | (goarch (first (go-target (%current-system)))) | ||
| 167 | (goos (last (go-target (%current-system)))) | ||
| 131 | (guile #f) | 168 | (guile #f) |
| 132 | (imported-modules %go-build-system-modules) | 169 | (imported-modules %go-build-system-modules) |
| 133 | (modules '((guix build go-build-system) | 170 | (modules '((guix build go-build-system) |
| @@ -147,6 +184,8 @@ commit hash and its date rather than a proper release tag." | |||
| 147 | #:system ,system | 184 | #:system ,system |
| 148 | #:phases ,phases | 185 | #:phases ,phases |
| 149 | #:outputs %outputs | 186 | #:outputs %outputs |
| 187 | #:goarch ,goarch | ||
| 188 | #:goos ,goos | ||
| 150 | #:search-paths ',(map search-path-specification->sexp | 189 | #:search-paths ',(map search-path-specification->sexp |
| 151 | search-paths) | 190 | search-paths) |
| 152 | #:install-source? ,install-source? | 191 | #:install-source? ,install-source? |
| @@ -174,6 +213,98 @@ commit hash and its date rather than a proper release tag." | |||
| 174 | #:outputs outputs | 213 | #:outputs outputs |
| 175 | #:guile-for-build guile-for-build)) | 214 | #:guile-for-build guile-for-build)) |
| 176 | 215 | ||
| 216 | (define* (go-cross-build store name | ||
| 217 | #:key | ||
| 218 | target native-drvs target-drvs | ||
| 219 | (phases '(@ (guix build go-build-system) | ||
| 220 | %standard-phases)) | ||
| 221 | (outputs '("out")) | ||
| 222 | (search-paths '()) | ||
| 223 | (native-search-paths '()) | ||
| 224 | (install-source? #t) | ||
| 225 | (import-path "") | ||
| 226 | (unpack-path "") | ||
| 227 | (build-flags ''()) | ||
| 228 | (tests? #f) ; nothing can be done | ||
| 229 | (allow-go-reference? #f) | ||
| 230 | (system (%current-system)) | ||
| 231 | (goarch (first (go-target target))) | ||
| 232 | (goos (last (go-target target))) | ||
| 233 | (guile #f) | ||
| 234 | (imported-modules %go-build-system-modules) | ||
| 235 | (modules '((guix build go-build-system) | ||
| 236 | (guix build union) | ||
| 237 | (guix build utils)))) | ||
| 238 | "Cross-build NAME using GO, where TARGET is a GNU triplet and with INPUTS." | ||
| 239 | (define builder | ||
| 240 | `(begin | ||
| 241 | (use-modules ,@modules) | ||
| 242 | (let () | ||
| 243 | (define %build-host-inputs | ||
| 244 | ',(map (match-lambda | ||
| 245 | ((name (? derivation? drv) sub ...) | ||
| 246 | `(,name . ,(apply derivation->output-path drv sub))) | ||
| 247 | ((name path) | ||
| 248 | `(,name . ,path))) | ||
| 249 | native-drvs)) | ||
| 250 | |||
| 251 | (define %build-target-inputs | ||
| 252 | ',(map (match-lambda | ||
| 253 | ((name (? derivation? drv) sub ...) | ||
| 254 | `(,name . ,(apply derivation->output-path drv sub))) | ||
| 255 | ((name (? package? pkg) sub ...) | ||
| 256 | (let ((drv (package-cross-derivation store pkg | ||
| 257 | target system))) | ||
| 258 | `(,name . ,(apply derivation->output-path drv sub)))) | ||
| 259 | ((name path) | ||
| 260 | `(,name . ,path))) | ||
| 261 | target-drvs)) | ||
| 262 | |||
| 263 | (go-build #:name ,name | ||
| 264 | #:source ,(match (assoc-ref native-drvs "source") | ||
| 265 | (((? derivation? source)) | ||
| 266 | (derivation->output-path source)) | ||
| 267 | ((source) | ||
| 268 | source) | ||
| 269 | (source | ||
| 270 | source)) | ||
| 271 | #:system ,system | ||
| 272 | #:phases ,phases | ||
| 273 | #:outputs %outputs | ||
| 274 | #:target ,target | ||
| 275 | #:goarch ,goarch | ||
| 276 | #:goos ,goos | ||
| 277 | #:inputs %build-target-inputs | ||
| 278 | #:native-inputs %build-host-inputs | ||
| 279 | #:search-paths ',(map search-path-specification->sexp | ||
| 280 | search-paths) | ||
| 281 | #:native-search-paths ',(map | ||
| 282 | search-path-specification->sexp | ||
| 283 | native-search-paths) | ||
| 284 | #:install-source? ,install-source? | ||
| 285 | #:import-path ,import-path | ||
| 286 | #:unpack-path ,unpack-path | ||
| 287 | #:build-flags ,build-flags | ||
| 288 | #:tests? ,tests? | ||
| 289 | #:allow-go-reference? ,allow-go-reference? | ||
| 290 | #:inputs %build-inputs)))) | ||
| 291 | |||
| 292 | (define guile-for-build | ||
| 293 | (match guile | ||
| 294 | ((? package?) | ||
| 295 | (package-derivation store guile system #:graft? #f)) | ||
| 296 | (#f ; the default | ||
| 297 | (let* ((distro (resolve-interface '(gnu packages commencement))) | ||
| 298 | (guile (module-ref distro 'guile-final))) | ||
| 299 | (package-derivation store guile system #:graft? #f))))) | ||
| 300 | |||
| 301 | (build-expression->derivation store name builder | ||
| 302 | #:system system | ||
| 303 | #:inputs (append native-drvs target-drvs) | ||
| 304 | #:outputs outputs | ||
| 305 | #:modules imported-modules | ||
| 306 | #:guile-for-build guile-for-build)) | ||
| 307 | |||
| 177 | (define go-build-system | 308 | (define go-build-system |
| 178 | (build-system | 309 | (build-system |
| 179 | (name 'go) | 310 | (name 'go) |
diff --git a/guix/build/go-build-system.scm b/guix/build/go-build-system.scm index 227df820db2..645d2fe6806 100644 --- a/guix/build/go-build-system.scm +++ b/guix/build/go-build-system.scm | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | ;;; Copyright © 2019 Maxim Cournoyer <maxim.cournoyer@gmail.com> | 4 | ;;; Copyright © 2019 Maxim Cournoyer <maxim.cournoyer@gmail.com> |
| 5 | ;;; Copyright © 2020 Jack Hill <jackhill@jackhill.us> | 5 | ;;; Copyright © 2020 Jack Hill <jackhill@jackhill.us> |
| 6 | ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net> | 6 | ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net> |
| 7 | ;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il> | 7 | ;;; Copyright © 2020, 2021 Efraim Flashner <efraim@flashner.co.il> |
| 8 | ;;; | 8 | ;;; |
| 9 | ;;; This file is part of GNU Guix. | 9 | ;;; This file is part of GNU Guix. |
| 10 | ;;; | 10 | ;;; |
| @@ -131,7 +131,7 @@ | |||
| 131 | ;; | 131 | ;; |
| 132 | ;; Code: | 132 | ;; Code: |
| 133 | 133 | ||
| 134 | (define* (setup-go-environment #:key inputs outputs #:allow-other-keys) | 134 | (define* (setup-go-environment #:key inputs outputs goos goarch #:allow-other-keys) |
| 135 | "Prepare a Go build environment for INPUTS and OUTPUTS. Build a file system | 135 | "Prepare a Go build environment for INPUTS and OUTPUTS. Build a file system |
| 136 | union of INPUTS. Export GOPATH, which helps the compiler find the source code | 136 | union of INPUTS. Export GOPATH, which helps the compiler find the source code |
| 137 | of the package being built and its dependencies, and GOBIN, which determines | 137 | of the package being built and its dependencies, and GOBIN, which determines |
| @@ -149,6 +149,22 @@ dependencies, so it should be self-contained." | |||
| 149 | ;; GOPATH behavior. | 149 | ;; GOPATH behavior. |
| 150 | (setenv "GO111MODULE" "off") | 150 | (setenv "GO111MODULE" "off") |
| 151 | (setenv "GOBIN" (string-append (assoc-ref outputs "out") "/bin")) | 151 | (setenv "GOBIN" (string-append (assoc-ref outputs "out") "/bin")) |
| 152 | |||
| 153 | ;; Make sure we're building for the correct architecture and OS targets | ||
| 154 | ;; that Guix targets. | ||
| 155 | (setenv "GOARCH" goarch) | ||
| 156 | (setenv "GOOS" goos) | ||
| 157 | (match goarch | ||
| 158 | ("arm" | ||
| 159 | (setenv "GOARM" "7")) | ||
| 160 | ((or "mips" "mipsel") | ||
| 161 | (setenv "GOMIPS" "hardfloat")) | ||
| 162 | ((or "mips64" "mips64le") | ||
| 163 | (setenv "GOMIPS64" "hardfloat")) | ||
| 164 | ((or "ppc64" "ppc64le") | ||
| 165 | (setenv "GOPPC64" "power8")) | ||
| 166 | (_ #t)) | ||
| 167 | |||
| 152 | (let ((tmpdir (tmpnam))) | 168 | (let ((tmpdir (tmpnam))) |
| 153 | (match (go-inputs inputs) | 169 | (match (go-inputs inputs) |
| 154 | (((names . directories) ...) | 170 | (((names . directories) ...) |
