summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEfraim Flashner <efraim@flashner.co.il>2021-04-26 21:13:06 +0300
committerEfraim Flashner <efraim@flashner.co.il>2021-09-13 15:33:30 +0300
commitde4f5df95db6c2e7071bf5e44c0d7ae928da1025 (patch)
treeb760d81f90354814819a41c11684d8084e322b95
parent43f9757f809d0fb3cd7c3e8b24bfb927179055e8 (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.texi7
-rw-r--r--guix/build-system/go.scm163
-rw-r--r--guix/build/go-build-system.scm20
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
7759the built output. The key @code{#:install-source?}, which defaults to 7759the 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
7761be set to @code{#f} for packages that only provide executable files. 7761be set to @code{#f} for packages that only provide executable files.
7762
7763Packages can be cross-built, and if a specific architecture or operating
7764system is desired then the keywords @code{#:goarch} and @code{#:goos}
7765can be used to force the package to be built for that architecture and
7766operating system. The combinations known to Go can be found
7767@url{"https://golang.org/doc/install/source#environment", in their
7768documentation}.
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."
78commit hash and its date rather than a proper release tag." 80commit 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
136union of INPUTS. Export GOPATH, which helps the compiler find the source code 136union of INPUTS. Export GOPATH, which helps the compiler find the source code
137of the package being built and its dependencies, and GOBIN, which determines 137of 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) ...)