blob: 7b2313469d35748be703cbdbd516dceb5072d560 [file] [log] [blame]
Andrew Gerrandf83f3e42015-02-02 12:05:01 +00001// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Command release builds a Go release.
6package main
7
8import (
Andrew Gerrandde0661e2015-07-13 11:18:56 -06009 "archive/tar"
Andrew Gerrandca5899f2015-07-23 12:30:44 +100010 "archive/zip"
Brad Fitzpatrickb5038352017-02-13 18:15:23 +000011 "bufio"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000012 "bytes"
Andrew Gerrandde0661e2015-07-13 11:18:56 -060013 "compress/gzip"
Kevin Burke392d3a92017-02-12 01:08:39 -080014 "context"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000015 "flag"
16 "fmt"
17 "io"
Brad Fitzpatrick4b956612015-07-07 09:57:08 -070018 "io/ioutil"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000019 "log"
Andrew Bonventre82242412017-09-11 14:22:38 -040020 "math/rand"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000021 "os"
Andrew Gerrand319667f2015-02-04 16:04:07 +000022 "path"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000023 "path/filepath"
Brad Fitzpatrick4b956612015-07-07 09:57:08 -070024 "runtime"
Andrew Gerrand319667f2015-02-04 16:04:07 +000025 "strings"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000026 "sync"
Andrew Bonventre82242412017-09-11 14:22:38 -040027 "time"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000028
Brad Fitzpatrick4b956612015-07-07 09:57:08 -070029 "golang.org/x/build"
Andrew Gerrand8e28dc92016-03-22 09:05:52 +110030 "golang.org/x/build/buildenv"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000031 "golang.org/x/build/buildlet"
32 "golang.org/x/build/dashboard"
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000033)
34
Dmitri Shuralyovded33d32019-08-10 15:16:18 -040035//go:generate go run makestatic.go
36
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000037var (
Brad Fitzpatrick5e1479f2018-08-20 17:17:18 +000038 target = flag.String("target", "", "If specified, build specific target platform (e.g. 'linux-amd64'). Default is to build all.")
Brad Fitzpatrickdcc7bc32015-12-17 14:53:55 -080039 watch = flag.Bool("watch", false, "Watch the build. Only compatible with -target")
Andrew Gerrand15af43e2015-02-11 11:47:03 +110040
Dmitri Shuralyov673ce342019-08-21 14:11:59 -040041 stagingDir = flag.String("staging_dir", "", "If specified, use this as the staging directory for untested release artifacts. Default is the system temporary directory.")
42
Filippo Valsorda702928c2018-12-12 14:37:02 -050043 rev = flag.String("rev", "", "Go revision to build, alternative to -tarball")
44 tarball = flag.String("tarball", "", "Go tree tarball to build, alternative to -rev")
Andrew Gerrandde0661e2015-07-13 11:18:56 -060045 version = flag.String("version", "", "Version string (go1.5.2)")
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100046 user = flag.String("user", username(), "coordinator username, appended to 'user-'")
Dmitri Shuralyove566a702020-05-18 19:06:44 -040047 skipTests = flag.Bool("skip_tests", false, "skip tests; run make.bash but not all.bash (only use if sufficient testing was done elsewhere)")
Andrew Gerrandf83f3e42015-02-02 12:05:01 +000048
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100049 uploadMode = flag.Bool("upload", false, "Upload files (exclusive to all other flags)")
Chris Broadfoot71359ad2017-10-24 12:52:01 -070050 uploadKick = flag.String("edge_kick_command", "", "Command to run to kick off an edge cache update")
Andrew Gerrand15af43e2015-02-11 11:47:03 +110051)
Andrew Gerrand319667f2015-02-04 16:04:07 +000052
Andrew Gerrand8e28dc92016-03-22 09:05:52 +110053var (
54 coordClient *buildlet.CoordinatorClient
55 buildEnv *buildenv.Environment
56)
Brad Fitzpatrick4b956612015-07-07 09:57:08 -070057
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100058func main() {
59 flag.Parse()
Andrew Bonventre82242412017-09-11 14:22:38 -040060 rand.Seed(time.Now().UnixNano())
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100061
62 if *uploadMode {
Brad Fitzpatrickf7da0f82018-08-20 22:49:40 +000063 buildenv.CheckUserCredentials()
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100064 if err := upload(flag.Args()); err != nil {
65 log.Fatal(err)
66 }
67 return
68 }
69
Filippo Valsorda702928c2018-12-12 14:37:02 -050070 if (*rev == "" && *tarball == "") || (*rev != "" && *tarball != "") {
Brad Fitzpatrick5bd98932019-04-29 17:28:21 +000071 log.Fatal("must specify one of -rev or -tarball")
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100072 }
73 if *version == "" {
Brad Fitzpatrick5bd98932019-04-29 17:28:21 +000074 log.Fatal(`must specify -version flag (such as "go1.12" or "go1.13beta1")`)
75 }
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100076
77 coordClient = coordinatorClient()
Andrew Gerrand8e28dc92016-03-22 09:05:52 +110078 buildEnv = buildenv.Production
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100079
80 var wg sync.WaitGroup
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +000081 matches := 0
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100082 for _, b := range builds {
83 b := b
84 if *target != "" && b.String() != *target {
85 continue
86 }
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -040087 if !match(b.GoQuery, *version) {
88 continue
89 }
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +000090 matches++
Andrew Gerrand063dc2f2015-07-22 17:21:16 +100091 b.logf("Start.")
92 wg.Add(1)
93 go func() {
94 defer wg.Done()
95 if err := b.make(); err != nil {
96 b.logf("Error: %v", err)
97 } else {
98 b.logf("Done.")
99 }
100 }()
101 }
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000102 if *target != "" && matches == 0 {
103 log.Fatalf("no targets matched %q", *target)
104 }
Andrew Gerrand063dc2f2015-07-22 17:21:16 +1000105 wg.Wait()
106}
107
Andrew Gerrand319667f2015-02-04 16:04:07 +0000108type Build struct {
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -0400109 // GoQuery is a Go version query specifying the Go versions
110 // the build applies to. Empty string means all Go versions.
111 GoQuery string
112
Andrew Gerrand319667f2015-02-04 16:04:07 +0000113 OS, Arch string
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600114 Source bool
Andrew Gerrand319667f2015-02-04 16:04:07 +0000115
Chris Broadfootc13f7d22015-12-17 14:02:46 -0800116 Race bool // Build race detector.
Andrew Gerrand319667f2015-02-04 16:04:07 +0000117
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400118 Builder string // Key for dashboard.Builders.
119 TestOnly bool // Run tests only; don't produce a release artifact.
Dave Cheney25a7b0c2015-12-11 14:00:21 +1100120
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400121 Goarm int // GOARM value if set.
122 SkipTests bool // skip tests (run make.bash but not all.bash); needed by cross-compile builders (s390x)
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000123}
124
Andrew Gerrand319667f2015-02-04 16:04:07 +0000125func (b *Build) String() string {
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400126 switch {
127 case b.Source:
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600128 return "src"
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400129 case b.TestOnly:
130 // Test-only builds are named after the builder used to
131 // perform them. For example, "linux-amd64-longtest".
132 return b.Builder
133 case b.Goarm != 0:
Shenghou Ma558ac4f2015-12-20 02:04:40 -0500134 return fmt.Sprintf("%v-%vv%vl", b.OS, b.Arch, b.Goarm)
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400135 default:
136 return fmt.Sprintf("%v-%v", b.OS, b.Arch)
Chris Broadfootf84ad522015-12-17 16:18:20 -0800137 }
Andrew Gerrand319667f2015-02-04 16:04:07 +0000138}
139
Brad Fitzpatricka2a69082015-11-11 17:34:48 +0000140func (b *Build) toolDir() string { return "go/pkg/tool/" + b.OS + "_" + b.Arch }
Brad Fitzpatrick5e1479f2018-08-20 17:17:18 +0000141func (b *Build) pkgDir() string { return "go/pkg/" + b.OS + "_" + b.Arch }
Brad Fitzpatricka2a69082015-11-11 17:34:48 +0000142
Andrew Gerrand78810b02015-07-07 11:00:09 -0600143func (b *Build) logf(format string, args ...interface{}) {
144 format = fmt.Sprintf("%v: %s", b, format)
145 log.Printf(format, args...)
146}
147
Andrew Gerrand319667f2015-02-04 16:04:07 +0000148var builds = []*Build{
149 {
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600150 Source: true,
Brad Fitzpatrick1fe20772019-04-09 01:48:33 +0000151 Builder: "linux-amd64",
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600152 },
153 {
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500154 GoQuery: ">= go1.16beta1",
Andrew Gerrand319667f2015-02-04 16:04:07 +0000155 OS: "linux",
156 Arch: "386",
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500157 Builder: "linux-386-stretch",
Andrew Gerrand319667f2015-02-04 16:04:07 +0000158 },
159 {
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500160 GoQuery: ">= go1.16beta1",
Andrew Gerrand319667f2015-02-04 16:04:07 +0000161 OS: "linux",
Dave Cheney25a7b0c2015-12-11 14:00:21 +1100162 Arch: "arm",
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500163 Builder: "linux-arm-aws",
164 Goarm: 6, // For compatibility with all Raspberry Pi models.
Dave Cheney25a7b0c2015-12-11 14:00:21 +1100165 },
166 {
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500167 GoQuery: ">= go1.16beta1",
Dave Cheney25a7b0c2015-12-11 14:00:21 +1100168 OS: "linux",
Andrew Gerrand319667f2015-02-04 16:04:07 +0000169 Arch: "amd64",
170 Race: true,
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500171 Builder: "linux-amd64-stretch", // Using Stretch as of Go 1.16 because Jessie LTS has ended (golang.org/issue/40561#issuecomment-731482962).
Andrew Gerrand319667f2015-02-04 16:04:07 +0000172 },
173 {
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500174 GoQuery: ">= go1.16beta1",
Brad Fitzpatrick07714b02017-06-15 19:46:22 +0000175 OS: "linux",
176 Arch: "arm64",
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500177 Builder: "linux-arm64-aws",
Brad Fitzpatrick07714b02017-06-15 19:46:22 +0000178 },
179 {
Carlos Amedee63087352021-04-30 17:38:39 -0400180 GoQuery: ">= go1.17beta1", // See #45727.
Andrew Gerrand319667f2015-02-04 16:04:07 +0000181 OS: "freebsd",
182 Arch: "386",
Carlos Amedee63087352021-04-30 17:38:39 -0400183 Builder: "freebsd-386-11_4",
Andrew Gerrand319667f2015-02-04 16:04:07 +0000184 },
185 {
Carlos Amedee63087352021-04-30 17:38:39 -0400186 GoQuery: ">= go1.17beta1", // See #45727.
Andrew Gerrand319667f2015-02-04 16:04:07 +0000187 OS: "freebsd",
188 Arch: "amd64",
189 Race: true,
Carlos Amedee63087352021-04-30 17:38:39 -0400190 Builder: "freebsd-amd64-11_4",
Andrew Gerrand319667f2015-02-04 16:04:07 +0000191 },
Andrew Gerrand78810b02015-07-07 11:00:09 -0600192 {
193 OS: "windows",
194 Arch: "386",
Chris Broadfootffc9f6c2017-08-07 13:50:52 -0700195 Builder: "windows-386-2008",
Andrew Gerrand78810b02015-07-07 11:00:09 -0600196 },
197 {
198 OS: "windows",
199 Arch: "amd64",
200 Race: true,
Brad Fitzpatrick97a4f812017-04-24 20:32:02 +0000201 Builder: "windows-amd64-2008",
Andrew Gerrand78810b02015-07-07 11:00:09 -0600202 },
203 {
204 OS: "darwin",
205 Arch: "amd64",
206 Race: true,
Andrew Bonventre48fb0f12019-11-21 19:27:45 -0500207 Builder: "darwin-amd64-10_15",
Andrew Gerrand78810b02015-07-07 11:00:09 -0600208 },
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000209 {
Dmitri Shuralyov4682f4a2020-12-15 19:06:56 -0500210 GoQuery: ">= go1.16beta1", // Go 1.16 Beta 1 is the first Go (pre-)release with the darwin/arm64 port.
211 OS: "darwin",
212 Arch: "arm64",
213 Race: true,
214 Builder: "darwin-arm64-11_0-toothrot",
215 },
216 {
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400217 OS: "linux",
218 Arch: "s390x",
219 SkipTests: true,
220 Builder: "linux-s390x-crosscompile",
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000221 },
Brad Fitzpatricka6cb7e42016-11-15 21:16:56 -0500222 // TODO(bradfitz): switch this ppc64 builder to a Kubernetes
223 // container cross-compiling ppc64 like the s390x one? For
224 // now, the ppc64le builders (5) are back, so let's see if we
225 // can just depend on them not going away.
226 {
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400227 OS: "linux",
228 Arch: "ppc64le",
229 SkipTests: true,
230 Builder: "linux-ppc64le-buildlet",
231 },
232
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -0400233 // Older builds.
234 {
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500235 GoQuery: "< go1.16beta1",
236 OS: "linux",
237 Arch: "386",
238 Builder: "linux-386-jessie",
239 },
240 {
241 GoQuery: "< go1.16beta1",
242 OS: "linux",
243 Arch: "arm",
Carlos Amedeec1822c72021-03-19 13:54:17 -0400244 Builder: "linux-arm-scaleway",
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -0500245 Goarm: 6, // For compatibility with all Raspberry Pi models.
246 // The tests take too long for the release packaging.
247 // Much of the time the whole buildlet times out.
248 SkipTests: true,
249 },
250 {
251 GoQuery: "< go1.16beta1",
252 OS: "linux",
253 Arch: "amd64",
254 Race: true,
255 Builder: "linux-amd64-jessie", // Using Jessie for Go 1.11 through Go 1.15 inclusive due to golang.org/issue/31293.
256 },
257 {
258 GoQuery: "< go1.16beta1",
259 OS: "linux",
260 Arch: "arm64",
261 Builder: "linux-arm64-packet",
262 },
Carlos Amedee63087352021-04-30 17:38:39 -0400263 {
264 GoQuery: "< go1.17beta1", // See #40563.
265 OS: "freebsd",
266 Arch: "386",
267 Builder: "freebsd-386-11_2",
268 },
269 {
270 GoQuery: "< go1.17beta1", // See #40563.
271 OS: "freebsd",
272 Arch: "amd64",
273 Race: true,
274 Builder: "freebsd-amd64-11_2",
275 },
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -0400276
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400277 // Test-only builds.
278 {
Dmitri Shuralyov305e1e32021-03-25 17:40:02 -0400279 Builder: "linux-386-longtest",
280 OS: "linux", Arch: "386",
281 TestOnly: true,
282 },
283 {
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400284 Builder: "linux-amd64-longtest",
285 OS: "linux", Arch: "amd64",
286 TestOnly: true,
287 },
288 {
289 Builder: "windows-amd64-longtest",
290 OS: "windows", Arch: "amd64",
291 TestOnly: true,
Brad Fitzpatricka6cb7e42016-11-15 21:16:56 -0500292 },
Andrew Gerrand319667f2015-02-04 16:04:07 +0000293}
294
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000295var preBuildCleanFiles = []string{
296 ".gitattributes",
Andrew Gerrand82423c12016-07-05 09:22:29 +1000297 ".github",
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000298 ".gitignore",
299 ".hgignore",
300 ".hgtags",
301 "misc/dashboard",
Andrew Gerrand78810b02015-07-07 11:00:09 -0600302 "misc/makerelease",
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000303}
304
Brad Fitzpatrick2742bc32015-07-03 16:20:37 -0700305func (b *Build) buildlet() (*buildlet.Client, error) {
Andrew Gerrand78810b02015-07-07 11:00:09 -0600306 b.logf("Creating buildlet.")
Brad Fitzpatrick4b956612015-07-07 09:57:08 -0700307 bc, err := coordClient.CreateBuildlet(b.Builder)
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000308 if err != nil {
Brad Fitzpatrick2742bc32015-07-03 16:20:37 -0700309 return nil, err
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000310 }
Brad Fitzpatrick1e7c6912017-02-13 17:38:27 +0000311 bc.SetReleaseMode(true) // disable pargzip; golang.org/issue/19052
Brad Fitzpatrick4b956612015-07-07 09:57:08 -0700312 return bc, nil
Brad Fitzpatrick2742bc32015-07-03 16:20:37 -0700313}
314
Andrew Gerrand78810b02015-07-07 11:00:09 -0600315func (b *Build) make() error {
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000316 ctx := context.TODO()
Brad Fitzpatrick2742bc32015-07-03 16:20:37 -0700317 bc, ok := dashboard.Builders[b.Builder]
318 if !ok {
319 return fmt.Errorf("unknown builder: %v", bc)
320 }
321
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000322 var hostArch string // non-empty if we're cross-compiling (s390x)
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400323 if b.SkipTests && bc.IsContainer() && (bc.GOARCH() != "amd64" && bc.GOARCH() != "386") {
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000324 hostArch = "amd64"
325 }
326
Brad Fitzpatrick2742bc32015-07-03 16:20:37 -0700327 client, err := b.buildlet()
328 if err != nil {
329 return err
330 }
331 defer client.Close()
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000332
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000333 work, err := client.WorkDir(ctx)
Andrew Gerrand319667f2015-02-04 16:04:07 +0000334 if err != nil {
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000335 return err
336 }
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000337
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400338 // Push source to buildlet.
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000339 b.logf("Pushing source to buildlet.")
Andrew Gerrand15af43e2015-02-11 11:47:03 +1100340 const (
341 goDir = "go"
342 goPath = "gopath"
Andrew Gerrand78810b02015-07-07 11:00:09 -0600343 go14 = "go1.4"
Andrew Gerrand15af43e2015-02-11 11:47:03 +1100344 )
Filippo Valsorda702928c2018-12-12 14:37:02 -0500345 if *tarball != "" {
346 tarFile, err := os.Open(*tarball)
347 if err != nil {
348 b.logf("failed to open tarball %q: %v", *tarball, err)
349 return err
350 }
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000351 if err := client.PutTar(ctx, tarFile, goDir); err != nil {
Filippo Valsorda702928c2018-12-12 14:37:02 -0500352 b.logf("failed to put tarball %q into dir %q: %v", *tarball, goDir, err)
353 return err
354 }
355 tarFile.Close()
356 } else {
357 tar := "https://go.googlesource.com/go/+archive/" + *rev + ".tar.gz"
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000358 if err := client.PutTarFromURL(ctx, tar, goDir); err != nil {
Filippo Valsorda702928c2018-12-12 14:37:02 -0500359 b.logf("failed to put tarball %q into dir %q: %v", tar, goDir, err)
360 return err
361 }
362 }
Andrew Gerrand319667f2015-02-04 16:04:07 +0000363
Andrew Gerrand8e28dc92016-03-22 09:05:52 +1100364 if u := bc.GoBootstrapURL(buildEnv); u != "" && !b.Source {
Andrew Gerrand78810b02015-07-07 11:00:09 -0600365 b.logf("Installing go1.4.")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000366 if err := client.PutTarFromURL(ctx, u, go14); err != nil {
Andrew Gerrand78810b02015-07-07 11:00:09 -0600367 return err
368 }
369 }
370
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000371 // Write out version file.
372 b.logf("Writing VERSION file.")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000373 if err := client.Put(ctx, strings.NewReader(*version), "go/VERSION", 0644); err != nil {
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000374 return err
375 }
376
Andrew Gerrand78810b02015-07-07 11:00:09 -0600377 b.logf("Cleaning goroot (pre-build).")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000378 if err := client.RemoveAll(ctx, addPrefix(goDir, preBuildCleanFiles)...); err != nil {
Andrew Gerrand319667f2015-02-04 16:04:07 +0000379 return err
380 }
381
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600382 if b.Source {
383 b.logf("Skipping build.")
Brad Fitzpatricke6f00552019-02-12 00:47:55 +0000384
385 // Remove unwanted top-level directories and verify only "go" remains:
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000386 if err := client.RemoveAll(ctx, "tmp", "gocache"); err != nil {
Brad Fitzpatricke6f00552019-02-12 00:47:55 +0000387 return err
388 }
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000389 if err := b.checkTopLevelDirs(ctx, client); err != nil {
Brad Fitzpatricke6f00552019-02-12 00:47:55 +0000390 return fmt.Errorf("verifying no unwanted top-level directories: %v", err)
391 }
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000392 if err := b.checkPerm(ctx, client); err != nil {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400393 return fmt.Errorf("verifying file permissions: %v", err)
394 }
Brad Fitzpatricke6f00552019-02-12 00:47:55 +0000395
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400396 finalFilename := *version + "." + b.String() + ".tar.gz"
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000397 return b.fetchTarball(ctx, client, finalFilename)
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600398 }
399
Andrew Gerrand319667f2015-02-04 16:04:07 +0000400 // Set up build environment.
401 sep := "/"
402 if b.OS == "windows" {
403 sep = "\\"
404 }
Andrew Gerrand78810b02015-07-07 11:00:09 -0600405 env := append(bc.Env(),
406 "GOROOT_FINAL="+bc.GorootFinal(),
407 "GOROOT="+work+sep+goDir,
Andrew Gerrand78810b02015-07-07 11:00:09 -0600408 "GOPATH="+work+sep+goPath,
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600409 "GOBIN=",
Andrew Gerrand78810b02015-07-07 11:00:09 -0600410 )
Dave Cheney25a7b0c2015-12-11 14:00:21 +1100411
412 if b.Goarm > 0 {
413 env = append(env, fmt.Sprintf("GOARM=%d", b.Goarm))
Cherry Zhang297480d2017-01-22 19:01:43 -0500414 env = append(env, fmt.Sprintf("CGO_CFLAGS=-march=armv%d", b.Goarm))
415 env = append(env, fmt.Sprintf("CGO_LDFLAGS=-march=armv%d", b.Goarm))
Dave Cheney25a7b0c2015-12-11 14:00:21 +1100416 }
417
Carlos Amedee5bb938e2020-01-24 16:07:47 -0500418 // Issues #36025 #35459
Carlos Amedee7ece5da2020-02-26 11:10:56 -0500419 if b.OS == "darwin" && b.Arch == "amd64" {
Carlos Amedee5bb938e2020-01-24 16:07:47 -0500420 minMacVersion := minSupportedMacOSVersion(*version)
421 env = append(env, fmt.Sprintf("CGO_CFLAGS=-mmacosx-version-min=%s", minMacVersion))
422 }
423
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400424 // Execute build (make.bash only first).
425 b.logf("Building (make.bash only).")
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000426 out := new(bytes.Buffer)
Brad Fitzpatrickdcc7bc32015-12-17 14:53:55 -0800427 var execOut io.Writer = out
428 if *watch && *target != "" {
429 execOut = io.MultiWriter(out, os.Stdout)
430 }
Brad Fitzpatrick5a368652019-11-20 03:30:26 +0000431 remoteErr, err := client.Exec(context.Background(), filepath.Join(goDir, bc.MakeScript()), buildlet.ExecOpts{
Brad Fitzpatrickdcc7bc32015-12-17 14:53:55 -0800432 Output: execOut,
Andrew Gerrand319667f2015-02-04 16:04:07 +0000433 ExtraEnv: env,
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400434 Args: bc.MakeScriptArgs(),
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000435 })
436 if err != nil {
437 return err
438 }
439 if remoteErr != nil {
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000440 return fmt.Errorf("Build failed: %v\nOutput:\n%v", remoteErr, out)
441 }
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000442
Brad Fitzpatrick0cea2062019-04-10 14:13:33 +0000443 if err := b.checkRelocations(client); err != nil {
444 return err
445 }
446
Andrew Gerrand319667f2015-02-04 16:04:07 +0000447 goCmd := path.Join(goDir, "bin/go")
448 if b.OS == "windows" {
449 goCmd += ".exe"
450 }
451 runGo := func(args ...string) error {
452 out := new(bytes.Buffer)
Chris Broadfoote296e7e2015-12-17 15:18:14 -0800453 var execOut io.Writer = out
454 if *watch && *target != "" {
455 execOut = io.MultiWriter(out, os.Stdout)
456 }
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000457 cmdEnv := append([]string(nil), env...)
458 if len(args) > 0 && args[0] == "run" && hostArch != "" {
459 cmdEnv = setGOARCH(cmdEnv, hostArch)
460 }
Brad Fitzpatrick5a368652019-11-20 03:30:26 +0000461 remoteErr, err := client.Exec(context.Background(), goCmd, buildlet.ExecOpts{
Chris Broadfoote296e7e2015-12-17 15:18:14 -0800462 Output: execOut,
Andrew Gerrand15af43e2015-02-11 11:47:03 +1100463 Dir: ".", // root of buildlet work directory
Andrew Gerrand319667f2015-02-04 16:04:07 +0000464 Args: args,
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000465 ExtraEnv: cmdEnv,
Andrew Gerrand319667f2015-02-04 16:04:07 +0000466 })
467 if err != nil {
468 return err
469 }
470 if remoteErr != nil {
471 return fmt.Errorf("go %v: %v\n%s", strings.Join(args, " "), remoteErr, out)
472 }
473 return nil
474 }
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000475
Andrew Gerrand319667f2015-02-04 16:04:07 +0000476 if b.Race {
Andrew Gerrand78810b02015-07-07 11:00:09 -0600477 b.logf("Building race detector.")
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000478
Andrew Gerrand319667f2015-02-04 16:04:07 +0000479 if err := runGo("install", "-race", "std"); err != nil {
480 return err
481 }
Andrew Gerrand319667f2015-02-04 16:04:07 +0000482 }
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000483
Brad Fitzpatrickbbe91e82018-10-24 19:05:40 +0000484 // postBuildCleanFiles are the list of files to remove in the go/ directory
485 // after things have been built.
486 postBuildCleanFiles := []string{
487 "VERSION.cache",
488 "pkg/bootstrap",
489 }
490
491 // Remove race detector *.syso files for other GOOS/GOARCHes (except for the source release).
492 if !b.Source {
493 okayRace := fmt.Sprintf("race_%s_%s.syso", b.OS, b.Arch)
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000494 err := client.ListDir(ctx, ".", buildlet.ListDirOpts{Recursive: true}, func(ent buildlet.DirEntry) {
Brad Fitzpatrickbbe91e82018-10-24 19:05:40 +0000495 name := strings.TrimPrefix(ent.Name(), "go/")
496 if strings.HasPrefix(name, "src/runtime/race/race_") &&
497 strings.HasSuffix(name, ".syso") &&
498 path.Base(name) != okayRace {
499 postBuildCleanFiles = append(postBuildCleanFiles, name)
500 }
501 })
502 if err != nil {
503 return fmt.Errorf("enumerating files to clean race syso files: %v", err)
504 }
505 }
506
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000507 b.logf("Cleaning goroot (post-build).")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000508 if err := client.RemoveAll(ctx, addPrefix(goDir, postBuildCleanFiles)...); err != nil {
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000509 return err
510 }
Brad Fitzpatrick5e1479f2018-08-20 17:17:18 +0000511 // Users don't need the api checker binary pre-built. It's
512 // used by tests, but all.bash builds it first.
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000513 if err := client.RemoveAll(ctx, b.toolDir()+"/api"); err != nil {
Brad Fitzpatricka2a69082015-11-11 17:34:48 +0000514 return err
515 }
Alexander Rakoczy6a30d042020-07-14 17:08:04 -0400516 // The oldlink tool is used for debugging differences during
517 // testing of the linker rewrite, and can be built by users
518 // if necessary. See issue 39509.
519 // This can be removed when oldlink is gone, likely once Go 1.16
520 // is no longer supported.
521 if err := client.RemoveAll(ctx, b.toolDir()+"/oldlink"); err != nil {
522 return err
523 }
Brad Fitzpatrick5e1479f2018-08-20 17:17:18 +0000524 // Remove go/pkg/${GOOS}_${GOARCH}/cmd. This saves a bunch of
525 // space, and users don't typically rebuild cmd/compile,
526 // cmd/link, etc. If they want to, they still can, but they'll
527 // have to pay the cost of rebuilding dependent libaries. No
528 // need to ship them just in case.
Brad Fitzpatrickc3605022019-01-31 23:54:08 +0000529 //
530 // Also remove go/pkg/${GOOS}_${GOARCH}_{dynlink,shared,testcshared_shared}
531 // per Issue 20038.
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000532 if err := client.RemoveAll(ctx,
Brad Fitzpatrickc3605022019-01-31 23:54:08 +0000533 b.pkgDir()+"/cmd",
534 b.pkgDir()+"_dynlink",
535 b.pkgDir()+"_shared",
536 b.pkgDir()+"_testcshared_shared",
537 ); err != nil {
Brad Fitzpatrick5e1479f2018-08-20 17:17:18 +0000538 return err
539 }
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000540
Andrew Gerrand78810b02015-07-07 11:00:09 -0600541 b.logf("Pushing and running releaselet.")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000542 err = client.Put(ctx, strings.NewReader(releaselet), "releaselet.go", 0666)
Andrew Gerrand15af43e2015-02-11 11:47:03 +1100543 if err != nil {
544 return err
545 }
Andrew Gerrandce7e7fd2015-08-06 04:28:33 +0000546 if err := runGo("run", "releaselet.go"); err != nil {
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000547 log.Printf("releaselet failed: %v", err)
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000548 client.ListDir(ctx, ".", buildlet.ListDirOpts{Recursive: true}, func(ent buildlet.DirEntry) {
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000549 log.Printf("remote: %v", ent)
550 })
Andrew Gerrand15af43e2015-02-11 11:47:03 +1100551 return err
552 }
Andrew Gerrand319667f2015-02-04 16:04:07 +0000553
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000554 cleanFiles := []string{"releaselet.go", goPath, go14, "tmp", "gocache"}
Andrew Gerrand78810b02015-07-07 11:00:09 -0600555
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400556 // So far, we've run make.bash. We want to create the release archive next.
557 // Since the release archive hasn't been tested yet, place it in a temporary
558 // location. After all.bash runs successfully (or gets explicitly skipped),
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400559 // we'll move the release archive to its final location. For TestOnly builds,
560 // we only care whether tests passed and do not produce release artifacts.
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400561 type releaseFile struct {
562 Untested string // Temporary location of the file before the release has been tested.
563 Final string // Final location where to move the file after the release has been tested.
564 }
565 var releases []releaseFile
Dmitri Shuralyov673ce342019-08-21 14:11:59 -0400566 stagingDir := *stagingDir
567 if stagingDir == "" {
568 var err error
Dmitri Shuralyov83da5c52019-08-22 10:30:51 -0400569 stagingDir, err = ioutil.TempDir("", "go-release-staging_")
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400570 if err != nil {
571 log.Fatal(err)
572 }
Dmitri Shuralyov673ce342019-08-21 14:11:59 -0400573 }
574 stagingFile := func(ext string) string {
575 return filepath.Join(stagingDir, *version+"."+b.String()+ext+".untested")
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400576 }
577
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400578 if !b.TestOnly && b.OS == "windows" {
Dmitri Shuralyov673ce342019-08-21 14:11:59 -0400579 untested := stagingFile(".msi")
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400580 if err := b.fetchFile(client, untested, "msi"); err != nil {
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000581 return err
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600582 }
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400583 releases = append(releases, releaseFile{
584 Untested: untested,
585 Final: *version + "." + b.String() + ".msi",
586 })
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400587 }
588
589 if b.OS == "windows" {
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000590 cleanFiles = append(cleanFiles, "msi")
Andrew Gerrand78810b02015-07-07 11:00:09 -0600591 }
592
Andrew Gerrand319667f2015-02-04 16:04:07 +0000593 // Need to delete everything except the final "go" directory,
594 // as we make the tarball relative to workdir.
Andrew Gerrandba1664c2015-07-16 11:51:19 +1000595 b.logf("Cleaning workdir.")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000596 if err := client.RemoveAll(ctx, cleanFiles...); err != nil {
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000597 return err
598 }
Andrew Gerrand319667f2015-02-04 16:04:07 +0000599
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000600 // And verify there's no other top-level stuff besides the "go" directory:
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000601 if err := b.checkTopLevelDirs(ctx, client); err != nil {
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000602 return fmt.Errorf("verifying no unwanted top-level directories: %v", err)
603 }
604
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000605 if err := b.checkPerm(ctx, client); err != nil {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400606 return fmt.Errorf("verifying file permissions: %v", err)
Andrew Gerrandca5899f2015-07-23 12:30:44 +1000607 }
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400608
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400609 switch {
610 case !b.TestOnly && b.OS != "windows":
Dmitri Shuralyov673ce342019-08-21 14:11:59 -0400611 untested := stagingFile(".tar.gz")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000612 if err := b.fetchTarball(ctx, client, untested); err != nil {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400613 return fmt.Errorf("fetching and writing tarball: %v", err)
614 }
615 releases = append(releases, releaseFile{
616 Untested: untested,
617 Final: *version + "." + b.String() + ".tar.gz",
618 })
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400619 case !b.TestOnly && b.OS == "windows":
Dmitri Shuralyov673ce342019-08-21 14:11:59 -0400620 untested := stagingFile(".zip")
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400621 if err := b.fetchZip(client, untested); err != nil {
622 return fmt.Errorf("fetching and writing zip: %v", err)
623 }
624 releases = append(releases, releaseFile{
625 Untested: untested,
626 Final: *version + "." + b.String() + ".zip",
627 })
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400628 case b.TestOnly:
629 // Use an empty .test-only file to indicate the test outcome.
630 // This file gets moved from its initial location in the
631 // release-staging directory to the final release directory
632 // when the test-only build passes tests successfully.
633 untested := stagingFile(".test-only")
634 if err := ioutil.WriteFile(untested, nil, 0600); err != nil {
635 return fmt.Errorf("writing empty test-only file: %v", err)
636 }
637 releases = append(releases, releaseFile{
638 Untested: untested,
639 Final: *version + "." + b.String() + ".test-only",
640 })
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400641 }
642
643 // Execute build (all.bash) if running tests.
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400644 if *skipTests || b.SkipTests {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400645 b.logf("Skipping all.bash tests.")
646 } else {
647 if u := bc.GoBootstrapURL(buildEnv); u != "" {
648 b.logf("Installing go1.4 (second time, for all.bash).")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000649 if err := client.PutTarFromURL(ctx, u, go14); err != nil {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400650 return err
651 }
652 }
653
654 b.logf("Building (all.bash to ensure tests pass).")
655 out := new(bytes.Buffer)
656 var execOut io.Writer = out
657 if *watch && *target != "" {
658 execOut = io.MultiWriter(out, os.Stdout)
659 }
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000660 remoteErr, err := client.Exec(ctx, filepath.Join(goDir, bc.AllScript()), buildlet.ExecOpts{
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400661 Output: execOut,
662 ExtraEnv: env,
663 Args: bc.AllScriptArgs(),
664 })
665 if err != nil {
666 return err
667 }
668 if remoteErr != nil {
669 return fmt.Errorf("Build failed: %v\nOutput:\n%v", remoteErr, out)
670 }
671 }
672
673 // If we get this far, the all.bash tests have passed (or been skipped).
674 // Move untested release files to their final locations.
675 for _, r := range releases {
676 b.logf("Moving %q to %q.", r.Untested, r.Final)
677 if err := os.Rename(r.Untested, r.Final); err != nil {
678 return err
679 }
680 }
681 return nil
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600682}
683
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000684// checkTopLevelDirs checks that all files under client's "."
685// ($WORKDIR) are are under "go/".
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000686func (b *Build) checkTopLevelDirs(ctx context.Context, client *buildlet.Client) error {
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000687 var badFileErr error // non-nil once an unexpected file/dir is found
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000688 if err := client.ListDir(ctx, ".", buildlet.ListDirOpts{Recursive: true}, func(ent buildlet.DirEntry) {
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000689 name := ent.Name()
690 if !(strings.HasPrefix(name, "go/") || strings.HasPrefix(name, `go\`)) {
Brad Fitzpatrick9fd15fa2019-01-24 05:41:21 +0000691 b.logf("unexpected file: %q", name)
692 if badFileErr == nil {
693 badFileErr = fmt.Errorf("unexpected filename %q found after cleaning", name)
694 }
Brad Fitzpatrick36bd60d2019-01-23 22:57:20 +0000695 }
696 }); err != nil {
697 return err
698 }
699 return badFileErr
700}
701
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400702// checkPerm checks that files in client's $WORKDIR/go directory
703// have expected permissions.
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000704func (b *Build) checkPerm(ctx context.Context, client *buildlet.Client) error {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400705 var badPermErr error // non-nil once an unexpected perm is found
706 checkPerm := func(ent buildlet.DirEntry, allowed ...string) {
707 for _, p := range allowed {
708 if ent.Perm() == p {
709 return
710 }
711 }
712 b.logf("unexpected file %q perm: %q", ent.Name(), ent.Perm())
713 if badPermErr == nil {
714 badPermErr = fmt.Errorf("unexpected file %q perm %q found", ent.Name(), ent.Perm())
715 }
716 }
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000717 if err := client.ListDir(ctx, "go", buildlet.ListDirOpts{Recursive: true}, func(ent buildlet.DirEntry) {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400718 switch b.OS {
719 default:
720 checkPerm(ent, "drwxr-xr-x", "-rw-r--r--", "-rwxr-xr-x")
721 case "windows":
722 checkPerm(ent, "drwxrwxrwx", "-rw-rw-rw-")
723 }
724 }); err != nil {
725 return err
726 }
727 if !b.Source {
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000728 if err := client.ListDir(ctx, "go/bin", buildlet.ListDirOpts{}, func(ent buildlet.DirEntry) {
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400729 switch b.OS {
730 default:
731 checkPerm(ent, "-rwxr-xr-x")
732 case "windows":
733 checkPerm(ent, "-rw-rw-rw-")
734 }
735 }); err != nil {
736 return err
737 }
738 }
739 return badPermErr
740}
741
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000742func (b *Build) fetchTarball(ctx context.Context, client *buildlet.Client, dest string) error {
Andrew Gerrand78810b02015-07-07 11:00:09 -0600743 b.logf("Downloading tarball.")
Brad Fitzpatrickd4e4f4e2019-11-20 16:34:11 +0000744 tgz, err := client.GetTar(ctx, ".")
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000745 if err != nil {
746 return err
747 }
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400748 return b.writeFile(dest, tgz)
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600749}
750
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400751func (b *Build) fetchZip(client *buildlet.Client, dest string) error {
Andrew Gerrandca5899f2015-07-23 12:30:44 +1000752 b.logf("Downloading tarball and re-compressing as zip.")
753
Kevin Burke392d3a92017-02-12 01:08:39 -0800754 tgz, err := client.GetTar(context.Background(), ".")
Andrew Gerrandca5899f2015-07-23 12:30:44 +1000755 if err != nil {
756 return err
757 }
758 defer tgz.Close()
759
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400760 f, err := os.Create(dest)
Andrew Gerrandca5899f2015-07-23 12:30:44 +1000761 if err != nil {
762 return err
763 }
764 if err := tgzToZip(f, tgz); err != nil {
765 f.Close()
766 return err
767 }
768 if err := f.Close(); err != nil {
769 return err
770 }
Dmitri Shuralyov6225d662019-08-09 19:11:39 -0400771 b.logf("Wrote %q.", dest)
Andrew Gerrandca5899f2015-07-23 12:30:44 +1000772 return nil
773}
774
775func tgzToZip(w io.Writer, r io.Reader) error {
776 zr, err := gzip.NewReader(r)
777 if err != nil {
778 return err
779 }
780 tr := tar.NewReader(zr)
781
782 zw := zip.NewWriter(w)
783 for {
784 th, err := tr.Next()
785 if err == io.EOF {
786 break
787 }
788 if err != nil {
789 return err
790 }
791 fi := th.FileInfo()
792 zh, err := zip.FileInfoHeader(fi)
793 if err != nil {
794 return err
795 }
796 zh.Name = th.Name // for the full path
797 switch strings.ToLower(path.Ext(zh.Name)) {
798 case ".jpg", ".jpeg", ".png", ".gif":
799 // Don't re-compress already compressed files.
800 zh.Method = zip.Store
801 default:
802 zh.Method = zip.Deflate
803 }
804 if fi.IsDir() {
Andrew Gerrandca5899f2015-07-23 12:30:44 +1000805 zh.Method = zip.Store
806 }
807 w, err := zw.CreateHeader(zh)
808 if err != nil {
809 return err
810 }
811 if fi.IsDir() {
812 continue
813 }
814 if _, err := io.Copy(w, tr); err != nil {
815 return err
816 }
817 }
818 return zw.Close()
819}
820
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600821// fetchFile fetches the specified directory from the given buildlet, and
822// writes the first file it finds in that directory to dest.
823func (b *Build) fetchFile(client *buildlet.Client, dest, dir string) error {
824 b.logf("Downloading file from %q.", dir)
Kevin Burke392d3a92017-02-12 01:08:39 -0800825 tgz, err := client.GetTar(context.Background(), dir)
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000826 if err != nil {
827 return err
828 }
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600829 defer tgz.Close()
830 zr, err := gzip.NewReader(tgz)
831 if err != nil {
832 return err
833 }
834 tr := tar.NewReader(zr)
835 for {
836 h, err := tr.Next()
837 if err == io.EOF {
838 return io.ErrUnexpectedEOF
839 }
840 if err != nil {
841 return err
842 }
843 if !h.FileInfo().IsDir() {
844 break
845 }
846 }
847 return b.writeFile(dest, tr)
848}
849
850func (b *Build) writeFile(name string, r io.Reader) error {
851 f, err := os.Create(name)
852 if err != nil {
853 return err
854 }
855 if _, err := io.Copy(f, r); err != nil {
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000856 f.Close()
857 return err
858 }
859 if err := f.Close(); err != nil {
860 return err
861 }
Brad Fitzpatrickb5038352017-02-13 18:15:23 +0000862 if strings.HasSuffix(name, ".gz") {
863 if err := verifyGzipSingleStream(name); err != nil {
864 return fmt.Errorf("error verifying that %s is a single-stream gzip: %v", name, err)
865 }
866 }
Andrew Gerrandde0661e2015-07-13 11:18:56 -0600867 b.logf("Wrote %q.", name)
Andrew Gerrandf83f3e42015-02-02 12:05:01 +0000868 return nil
869}
870
Brad Fitzpatrick0cea2062019-04-10 14:13:33 +0000871// checkRelocations runs readelf on pkg/linux_amd64/runtime/cgo.a and makes sure
Dmitri Shuralyov43ea6942021-02-19 12:17:28 -0500872// we don't see R_X86_64_REX_GOTPCRELX in new Go 1.15 minor releases.
Dmitri Shuralyovb0441a62020-12-15 12:11:20 -0500873// See golang.org/issue/31293 and golang.org/issue/40561#issuecomment-731482962.
Brad Fitzpatrick0cea2062019-04-10 14:13:33 +0000874func (b *Build) checkRelocations(client *buildlet.Client) error {
Dmitri Shuralyove566a702020-05-18 19:06:44 -0400875 if b.OS != "linux" || b.Arch != "amd64" || b.TestOnly {
876 // This check is only applicable to linux/amd64 builds.
877 // However, skip it on test-only builds because they
878 // don't produce binaries that are shipped to users.
Brad Fitzpatrick0cea2062019-04-10 14:13:33 +0000879 return nil
880 }
881 var out bytes.Buffer
882 file := fmt.Sprintf("go/pkg/linux_%s/runtime/cgo.a", b.Arch)
Brad Fitzpatrick5a368652019-11-20 03:30:26 +0000883 remoteErr, err := client.Exec(context.Background(), "readelf", buildlet.ExecOpts{
Brad Fitzpatrick0cea2062019-04-10 14:13:33 +0000884 Output: &out,
885 Args: []string{"-r", "--wide", file},
886 SystemLevel: true, // look for readelf in system's PATH
887 })
888 if err != nil {
889 return fmt.Errorf("failed to run readelf: %v", err)
890 }
891 got := out.String()
Dmitri Shuralyovb0441a62020-12-15 12:11:20 -0500892 switch {
893 default: // Go 1.16 and newer.
894 // Note: This check was kept and updated for Go 1.16, since it wasn't hard.
895 // Remove it at some point in the future if it becomes no longer useful or
896 // overly expensive to maintain.
897 if strings.Contains(got, "R_X86_64_GOTPCREL") {
898 return fmt.Errorf("%s contained a R_X86_64_GOTPCREL relocation", file)
899 }
900 if !strings.Contains(got, "R_X86_64_REX_GOTPCRELX") {
901 return fmt.Errorf("%s did not contain a R_X86_64_REX_GOTPCRELX relocation; remoteErr=%v, %s", file, remoteErr, got)
902 }
Dmitri Shuralyov43ea6942021-02-19 12:17:28 -0500903 case strings.HasPrefix(*version, "go1.15"):
Dmitri Shuralyovb0441a62020-12-15 12:11:20 -0500904 if strings.Contains(got, "R_X86_64_REX_GOTPCRELX") {
905 return fmt.Errorf("%s contained a R_X86_64_REX_GOTPCRELX relocation", file)
906 }
907 if !strings.Contains(got, "R_X86_64_GOTPCREL") {
908 return fmt.Errorf("%s did not contain a R_X86_64_GOTPCREL relocation; remoteErr=%v, %s", file, remoteErr, got)
909 }
Brad Fitzpatrick0cea2062019-04-10 14:13:33 +0000910 }
911 return nil
912}
913
Brad Fitzpatrickb5038352017-02-13 18:15:23 +0000914// verifyGzipSingleStream verifies that the named gzip file is not
915// a multi-stream file. See golang.org/issue/19052
916func verifyGzipSingleStream(name string) error {
917 f, err := os.Open(name)
918 if err != nil {
919 return err
920 }
921 defer f.Close()
922 br := bufio.NewReader(f)
923 zr, err := gzip.NewReader(br)
924 if err != nil {
925 return err
926 }
927 zr.Multistream(false)
928 if _, err := io.Copy(ioutil.Discard, zr); err != nil {
929 return fmt.Errorf("reading first stream: %v", err)
930 }
931 peek, err := br.Peek(1)
932 if len(peek) > 0 || err != io.EOF {
933 return fmt.Errorf("unexpected peek of %d, %v after first gzip stream", len(peek), err)
934 }
935 return nil
936}
937
Andrew Gerrand319667f2015-02-04 16:04:07 +0000938func addPrefix(prefix string, in []string) []string {
939 var out []string
940 for _, s := range in {
941 out = append(out, path.Join(prefix, s))
942 }
943 return out
944}
Brad Fitzpatrick4b956612015-07-07 09:57:08 -0700945
946func coordinatorClient() *buildlet.CoordinatorClient {
947 return &buildlet.CoordinatorClient{
948 Auth: buildlet.UserPass{
949 Username: "user-" + *user,
950 Password: userToken(),
951 },
Andrew Gerrand8e28dc92016-03-22 09:05:52 +1100952 Instance: build.ProdCoordinator,
Brad Fitzpatrick4b956612015-07-07 09:57:08 -0700953 }
954}
955
956func homeDir() string {
957 if runtime.GOOS == "windows" {
958 return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
959 }
960 return os.Getenv("HOME")
961}
962
963func configDir() string {
964 if runtime.GOOS == "windows" {
965 return filepath.Join(os.Getenv("APPDATA"), "Gomote")
966 }
967 if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" {
968 return filepath.Join(xdg, "gomote")
969 }
970 return filepath.Join(homeDir(), ".config", "gomote")
971}
972
973func username() string {
974 if runtime.GOOS == "windows" {
975 return os.Getenv("USERNAME")
976 }
977 return os.Getenv("USER")
978}
979
980func userToken() string {
981 if *user == "" {
982 panic("userToken called with user flag empty")
983 }
984 keyDir := configDir()
985 baseFile := "user-" + *user + ".token"
986 tokenFile := filepath.Join(keyDir, baseFile)
987 slurp, err := ioutil.ReadFile(tokenFile)
988 if os.IsNotExist(err) {
989 log.Printf("Missing file %s for user %q. Change --user or obtain a token and place it there.",
990 tokenFile, *user)
991 }
992 if err != nil {
993 log.Fatal(err)
994 }
995 return strings.TrimSpace(string(slurp))
996}
Brad Fitzpatrick9702f6a2016-08-30 20:32:33 +0000997
998func setGOARCH(env []string, goarch string) []string {
999 wantKV := "GOARCH=" + goarch
1000 existing := false
1001 for i, kv := range env {
1002 if strings.HasPrefix(kv, "GOARCH=") && kv != wantKV {
1003 env[i] = wantKV
1004 existing = true
1005 }
1006 }
1007 if existing {
1008 return env
1009 }
1010 return append(env, wantKV)
1011}
Brad Fitzpatrick790500f2018-10-19 15:15:16 -07001012
Carlos Amedee5bb938e2020-01-24 16:07:47 -05001013// minSupportedMacOSVersion provides the minimum supported macOS
Carlos Amedee7ece5da2020-02-26 11:10:56 -05001014// version (of the form N.M) for supported Go versions.
Carlos Amedee5bb938e2020-01-24 16:07:47 -05001015func minSupportedMacOSVersion(goVer string) string {
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -04001016 // TODO(amedee,dmitshur,golang.org/issue/40558): Use a version package to compare versions of Go.
Carlos Amedee5bb938e2020-01-24 16:07:47 -05001017
1018 // The minimum supported version of macOS with each version of go:
Carlos Amedee5bb938e2020-01-24 16:07:47 -05001019 // go1.15 - macOS 10.12
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -05001020 // go1.16 - macOS 10.12
Dmitri Shuralyov43ea6942021-02-19 12:17:28 -05001021 // go1.17 - macOS 10.13
1022 minMacVersion := "10.13"
1023 if match("< go1.17beta1", goVer) {
1024 minMacVersion = "10.12"
Carlos Amedee5bb938e2020-01-24 16:07:47 -05001025 return minMacVersion
1026 }
1027 return minMacVersion
1028}
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -04001029
1030// match reports whether the Go version goVer matches the provided version query.
1031// The empty query matches all Go versions.
1032// match panics if given a query that it doesn't support.
1033func match(query, goVer string) bool {
1034 // TODO(golang.org/issue/40558): This should help inform the API for a Go version parser.
1035 switch query {
1036 case "": // A special case to make the zero Build.GoQuery value useful.
1037 return true
Carlos Amedee63087352021-04-30 17:38:39 -04001038 case ">= go1.17beta1":
1039 return !strings.HasPrefix(goVer, "go1.16") && !strings.HasPrefix(goVer, "go1.15")
Dmitri Shuralyov43ea6942021-02-19 12:17:28 -05001040 case "< go1.17beta1":
1041 return strings.HasPrefix(goVer, "go1.16") || strings.HasPrefix(goVer, "go1.15")
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -05001042 case ">= go1.16beta1":
Dmitri Shuralyov43ea6942021-02-19 12:17:28 -05001043 return !strings.HasPrefix(goVer, "go1.15")
Dmitri Shuralyov90d5e7c2020-12-07 22:31:50 -05001044 case "< go1.16beta1":
Dmitri Shuralyov43ea6942021-02-19 12:17:28 -05001045 return strings.HasPrefix(goVer, "go1.15")
Dmitri Shuralyov56b7eea2020-08-03 23:22:08 -04001046 default:
1047 panic(fmt.Errorf("match: query %q is not supported", query))
1048 }
1049}