golang.org/x/build@v0.0.0-20240506185731-218518f32b70/cmd/racebuild/racebuild.go (about) 1 // 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 // racebuild builds the race runtime (syso files) on all supported OSes using gomote. 6 // Usage: 7 // 8 // $ racebuild -rev <llvm_git_revision> -goroot <path_to_go_repo> 9 package main 10 11 import ( 12 "archive/tar" 13 "bytes" 14 "compress/gzip" 15 "context" 16 "flag" 17 "fmt" 18 "io" 19 "log" 20 "os" 21 "os/exec" 22 "os/signal" 23 "path/filepath" 24 "regexp" 25 "strings" 26 "sync" 27 28 "golang.org/x/build/internal/envutil" 29 "golang.org/x/sync/errgroup" 30 ) 31 32 var ( 33 flagGoroot = flag.String("goroot", "", "path to Go repository to update (required)") 34 flagRev = flag.String("rev", "", "llvm-project git revision from https://github.com/llvm/llvm-project (required)") 35 flagCherryPick = flag.String("cherrypick", "", "go.googlesource.com CL reference to cherry-pick on top of Go repo (takes form 'refs/changes/NNN/<CL number>/<patchset number>') (optional)") 36 flagCheckout = flag.String("checkout", "", "go.googlesource.com CL reference to check out on top of Go repo (takes form 'refs/changes/NNN/<CL number>/<patchset number>') (optional)") 37 flagCopyOnFail = flag.Bool("copyonfail", false, "Attempt to copy newly built race syso into Go repo even if script fails.") 38 flagGoRev = flag.String("gorev", "HEAD", "Go repository revision to use; HEAD is relative to --goroot") 39 flagPlatforms = flag.String("platforms", "all", `comma-separated platforms (such as "darwin/arm64" or "linux/amd64v1") to rebuild, or "all"`) 40 ) 41 42 // goRev is the resolved commit ID of flagGoRev. 43 var goRev string 44 45 // TODO: use buildlet package instead of calling out to gomote. 46 var platforms = []*Platform{ 47 &Platform{ 48 OS: "openbsd", 49 Arch: "amd64", 50 SubArch: "v1", 51 Skip: true, // openbsd support is removed from TSAN, see issue #52090 52 Type: "openbsd-amd64-72", 53 Script: `#!/usr/bin/env bash 54 set -e 55 git clone https://go.googlesource.com/go 56 pushd go 57 git checkout $GOREV 58 if [ "$GOGITOP" != "" ]; then 59 git fetch https://go.googlesource.com/go "$GOSRCREF" 60 git $GOGITOP FETCH_HEAD 61 fi 62 popd 63 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 64 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 65 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && CC=clang ./buildgo.sh) 66 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_openbsd_amd64.syso go/src/runtime/race/internal/amd64v1/race_openbsd.syso 67 # work around gomote gettar issue #64195 68 mkdir outdir 69 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_openbsd_amd64.syso outdir/race_openbsd.syso 70 # free some disk space 71 rm -r llvm.zip llvm-project-${REV} 72 (cd go/src && ./race.bash) 73 `, 74 }, 75 &Platform{ 76 OS: "freebsd", 77 Arch: "amd64", 78 SubArch: "v1", 79 Type: "freebsd-amd64-race", 80 Script: `#!/usr/bin/env bash 81 set -e 82 git clone https://go.googlesource.com/go 83 pushd go 84 git checkout $GOREV 85 if [ "$GOGITOP" != "" ]; then 86 git fetch https://go.googlesource.com/go "$GOSRCREF" 87 git $GOGITOP FETCH_HEAD 88 fi 89 popd 90 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 91 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 92 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && CC=clang ./buildgo.sh) 93 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_freebsd_amd64.syso go/src/runtime/race/internal/amd64v1/race_freebsd.syso 94 # work around gomote gettar issue #64195 95 mkdir outdir 96 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_freebsd_amd64.syso outdir/race_freebsd.syso 97 # free some disk space 98 rm -r llvm.zip llvm-project-${REV} 99 (cd go/src && ./race.bash) 100 `, 101 }, 102 &Platform{ 103 OS: "darwin", 104 Arch: "amd64", 105 SubArch: "v1", 106 Type: "darwin-amd64-12_0", 107 Script: `#!/usr/bin/env bash 108 set -e 109 git clone https://go.googlesource.com/go 110 pushd go 111 git checkout $GOREV 112 if [ "$GOGITOP" != "" ]; then 113 git fetch https://go.googlesource.com/go "$GOSRCREF" 114 git $GOGITOP FETCH_HEAD 115 fi 116 popd 117 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 118 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 119 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && CC=clang ./buildgo.sh) 120 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_darwin_amd64.syso go/src/runtime/race/internal/amd64v1/race_darwin.syso 121 # work around gomote gettar issue #64195 122 mkdir outdir 123 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_darwin_amd64.syso outdir/race_darwin.syso 124 # free some disk space 125 rm -r llvm.zip llvm-project-${REV} 126 (cd go/src && ./race.bash) 127 `, 128 }, 129 &Platform{ 130 OS: "darwin", 131 Arch: "amd64", 132 SubArch: "v3", 133 Skip: true, 134 Type: "darwin-amd64-12_0", 135 Script: `#!/usr/bin/env bash 136 set -e 137 git clone https://go.googlesource.com/go 138 pushd go 139 git checkout $GOREV 140 popd 141 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 142 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 143 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && CC=clang GOAMD64=v3 ./buildgo.sh) 144 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_darwin_amd64.syso go/src/runtime/race/internal/amd64v3/race_darwin.syso 145 # work around gomote gettar issue #64195 146 mkdir outdir 147 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_darwin_amd64.syso outdir/race_darwin.syso 148 # free some disk space 149 rm -r llvm.zip llvm-project-${REV} 150 (cd go/src && GOAMD64=v3 ./race.bash) 151 `, 152 }, 153 &Platform{ 154 OS: "darwin", 155 Arch: "arm64", 156 Type: "darwin-arm64-12", 157 Script: `#!/usr/bin/env bash 158 set -e 159 git clone https://go.googlesource.com/go 160 pushd go 161 git checkout $GOREV 162 if [ "$GOGITOP" != "" ]; then 163 git fetch https://go.googlesource.com/go "$GOSRCREF" 164 git $GOGITOP FETCH_HEAD 165 fi 166 popd 167 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 168 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 169 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && CC=clang ./buildgo.sh) 170 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_darwin_arm64.syso go/src/runtime/race 171 # work around gomote gettar issue #64195 172 mkdir outdir 173 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_darwin_arm64.syso outdir/race_darwin_arm64.syso 174 # free some disk space 175 rm -r llvm.zip llvm-project-${REV} 176 (cd go/src && ./race.bash) 177 `, 178 }, 179 &Platform{ 180 OS: "linux", 181 Arch: "amd64", 182 SubArch: "v1", 183 Type: "linux-amd64-race", 184 Script: `#!/usr/bin/env bash 185 set -e 186 apt-get update --allow-releaseinfo-change 187 apt-get install -y git g++ unzip 188 git clone https://go.googlesource.com/go 189 pushd go 190 git checkout $GOREV 191 if [ "$GOGITOP" != "" ]; then 192 git fetch https://go.googlesource.com/go "$GOSRCREF" 193 git $GOGITOP FETCH_HEAD 194 fi 195 popd 196 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 197 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 198 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && ./buildgo.sh) 199 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_amd64.syso go/src/runtime/race/internal/amd64v1/race_linux.syso 200 # work around gomote gettar issue #64195 201 mkdir outdir 202 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_amd64.syso outdir/race_linux.syso 203 # free some disk space 204 rm -r llvm.zip llvm-project-${REV} 205 (cd go/src && ./race.bash) 206 `, 207 }, 208 &Platform{ 209 OS: "linux", 210 Arch: "amd64", 211 SubArch: "v3", 212 Type: "linux-amd64-race", 213 Script: `#!/usr/bin/env bash 214 set -e 215 apt-get update 216 apt-get install -y git g++ unzip 217 git clone https://go.googlesource.com/go 218 pushd go 219 git checkout $GOREV 220 popd 221 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 222 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 223 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && GOAMD64=v3 ./buildgo.sh) 224 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_amd64.syso go/src/runtime/race/internal/amd64v3/race_linux.syso 225 # work around gomote gettar issue #64195 226 mkdir outdir 227 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_amd64.syso outdir/race_linux.syso 228 # free some disk space 229 rm -r llvm.zip llvm-project-${REV} 230 (cd go/src && GOAMD64=v3 ./race.bash) 231 `, 232 }, 233 &Platform{ 234 OS: "linux", 235 Arch: "ppc64le", 236 Type: "linux-ppc64le-buildlet", 237 Script: `#!/usr/bin/env bash 238 set -e 239 apt-get update --allow-releaseinfo-change 240 apt-get install -y git g++ unzip 241 git clone https://go.googlesource.com/go 242 pushd go 243 git checkout $GOREV 244 if [ "$GOGITOP" != "" ]; then 245 git fetch https://go.googlesource.com/go "$GOSRCREF" 246 git $GOGITOP FETCH_HEAD 247 fi 248 popd 249 workdir=$(pwd) 250 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 251 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 252 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && ./buildgo.sh) 253 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_ppc64le.syso $workdir/go/src/runtime/race 254 # work around gomote gettar issue #64195 255 mkdir outdir 256 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_ppc64le.syso outdir/race_linux_ppc64le.syso 257 # TODO(#23731): Uncomment to test the syso file before accepting it. 258 # free some disk space 259 # rm -r llvm.zip llvm-project-${REV} 260 # (cd go/src && ./race.bash) 261 `, 262 }, 263 &Platform{ 264 OS: "linux", 265 Arch: "arm64", 266 Type: "linux-arm64-race", 267 Script: `#!/usr/bin/env bash 268 set -e 269 apt-get update --allow-releaseinfo-change 270 apt-get install -y git g++ unzip 271 git clone https://go.googlesource.com/go 272 pushd go 273 git checkout $GOREV 274 if [ "$GOGITOP" != "" ]; then 275 git fetch https://go.googlesource.com/go "$GOSRCREF" 276 git $GOGITOP FETCH_HEAD 277 fi 278 popd 279 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 280 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 281 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && ./buildgo.sh) 282 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_arm64.syso go/src/runtime/race 283 # work around gomote gettar issue #64195 284 mkdir outdir 285 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_arm64.syso outdir/race_linux_arm64.syso 286 # free some disk space 287 rm -r llvm.zip llvm-project-${REV} 288 (cd go/src && ./race.bash) 289 `, 290 }, 291 &Platform{ 292 OS: "netbsd", 293 Arch: "amd64", 294 SubArch: "v1", 295 Type: "netbsd-amd64-9_3", 296 Script: `#!/usr/bin/env bash 297 set -e 298 git clone https://go.googlesource.com/go 299 pushd go 300 git checkout $GOREV 301 if [ "$GOGITOP" != "" ]; then 302 git fetch https://go.googlesource.com/go "$GOSRCREF" 303 git $GOGITOP FETCH_HEAD 304 fi 305 popd 306 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 307 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 308 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && CC=clang ./buildgo.sh) 309 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_netbsd_amd64.syso go/src/runtime/race/internal/amd64v1/race_netbsd.syso 310 # work around gomote gettar issue #64195 311 mkdir outdir 312 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_netbsd_amd64.syso outdir/race_netbsd.syso 313 # TODO(#24322): Uncomment to test the syso file before accepting it. 314 # free some disk space 315 # rm -r llvm.zip llvm-project-${REV} 316 # (cd go/src && ./race.bash) 317 `, 318 }, 319 &Platform{ 320 OS: "windows", 321 Arch: "amd64", 322 SubArch: "v1", 323 Type: "windows-amd64-race", 324 Script: ` 325 @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "[System.net.ServicePointManager]::SecurityProtocol = 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" 326 choco install git -y 327 if %errorlevel% neq 0 exit /b %errorlevel% 328 call refreshenv 329 echo adding back in compiler path 330 set PATH=C:\go\bin;%PATH%;C:\godep\gcc64\bin 331 rem make sure we have a working copy of gcc 332 gcc --version 333 if %errorlevel% neq 0 exit /b %errorlevel% 334 git clone https://go.googlesource.com/go 335 if %errorlevel% neq 0 exit /b %errorlevel% 336 cd go 337 git checkout %GOREV% 338 if %errorlevel% neq 0 exit /b %errorlevel% 339 if "%$GOGITOP%"=="" goto nogogitop 340 git fetch https://go.googlesource.com/go %GOSRCREF% 341 if %errorlevel% neq 0 exit /b %errorlevel% 342 git %GOGITOP% FETCH_HEAD 343 if %errorlevel% neq 0 exit /b %errorlevel% 344 :nogogitop 345 cd .. 346 git clone https://github.com/llvm/llvm-project 347 if %errorlevel% neq 0 exit /b %errorlevel% 348 cd llvm-project 349 git checkout %REV% 350 if %errorlevel% neq 0 exit /b %errorlevel% 351 cd .. 352 cd llvm-project/compiler-rt/lib/tsan/go 353 call build.bat 354 if %errorlevel% neq 0 exit /b %errorlevel% 355 cd ../../../../.. 356 xcopy llvm-project\compiler-rt\lib\tsan\go\race_windows_amd64.syso go\src\runtime\race\internal\amd64v1\race_windows.syso /Y 357 if %errorlevel% neq 0 exit /b %errorlevel% 358 rem work around gomote gettar issue #64195 359 mkdir outdir 360 if %errorlevel% neq 0 exit /b %errorlevel% 361 copy llvm-project\compiler-rt\lib\tsan\go\race_windows_amd64.syso outdir\race_windows.syso 362 if %errorlevel% neq 0 exit /b %errorlevel% 363 cd go/src 364 call race.bat 365 if %errorlevel% neq 0 exit /b %errorlevel% 366 `, 367 }, 368 &Platform{ 369 OS: "linux", 370 Arch: "s390x", 371 Type: "linux-s390x-ibm", 372 Script: `#!/usr/bin/env bash 373 set -e 374 cat /etc/os-release 375 yum install -y gcc-c++ git golang-bin unzip 376 git clone https://go.googlesource.com/go 377 pushd go 378 git checkout $GOREV 379 if [ "$GOGITOP" != "" ]; then 380 git fetch https://go.googlesource.com/go "$GOSRCREF" 381 git $GOGITOP FETCH_HEAD 382 fi 383 popd 384 curl -L -o llvm.zip https://github.com/llvm/llvm-project/archive/${REV}.zip 385 unzip -q llvm.zip llvm-project-${REV}/compiler-rt/* 386 (cd llvm-project-${REV}/compiler-rt/lib/tsan/go && ./buildgo.sh) 387 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_s390x.syso go/src/runtime/race 388 # work around gomote gettar issue #64195 389 mkdir outdir 390 cp llvm-project-${REV}/compiler-rt/lib/tsan/go/race_linux_s390x.syso outdir/race_linux_s390x.syso 391 # free some disk space 392 rm -r llvm.zip llvm-project-${REV} 393 (cd go/src && ./race.bash) 394 `, 395 }, 396 } 397 398 func init() { 399 // Ensure that there are no duplicate platform entries. 400 seen := make(map[string]bool) 401 for _, p := range platforms { 402 if seen[p.Name()] { 403 log.Fatalf("Duplicate platforms entry for %s.", p.Name()) 404 } 405 seen[p.Name()] = true 406 } 407 } 408 409 var platformEnabled = make(map[string]bool) 410 411 func parsePlatformsFlag() { 412 if *flagPlatforms == "all" { 413 for _, p := range platforms { 414 if !p.Skip { 415 platformEnabled[p.Name()] = true 416 } 417 } 418 return 419 } 420 421 var invalid []string 422 for _, name := range strings.Split(*flagPlatforms, ",") { 423 for _, p := range platforms { 424 if name == p.Name() { 425 platformEnabled[name] = true 426 break 427 } 428 } 429 if !platformEnabled[name] { 430 invalid = append(invalid, name) 431 } 432 } 433 434 if len(invalid) > 0 { 435 var msg bytes.Buffer 436 fmt.Fprintf(&msg, "Unrecognized platforms: %q. Supported platforms are:\n", invalid) 437 for _, p := range platforms { 438 fmt.Fprintf(&msg, "\t%s\n", p.Name()) 439 } 440 log.Fatal(&msg) 441 } 442 } 443 444 func main() { 445 flag.Parse() 446 if *flagRev == "" || *flagGoroot == "" || *flagGoRev == "" { 447 flag.PrintDefaults() 448 os.Exit(1) 449 } 450 if *flagCherryPick != "" && *flagCheckout != "" { 451 log.Fatalf("select at most one of -cherrypick and -checkout") 452 } 453 parsePlatformsFlag() 454 455 cmd := exec.Command("git", "rev-parse", *flagGoRev) 456 envutil.SetDir(cmd, *flagGoroot) 457 cmd.Stderr = os.Stderr 458 out, err := cmd.Output() 459 if err != nil { 460 log.Fatalf("%s failed: %v", strings.Join(cmd.Args, " "), err) 461 } 462 goRev = string(bytes.TrimSpace(out)) 463 log.Printf("using Go revision: %s", goRev) 464 465 // Start build on all platforms in parallel. 466 // On interrupt, destroy any in-flight builders before exiting. 467 ctx, cancel := context.WithCancel(context.Background()) 468 shutdown := make(chan os.Signal, 1) 469 signal.Notify(shutdown, os.Interrupt) 470 go func() { 471 <-shutdown 472 cancel() 473 }() 474 475 g, ctx := errgroup.WithContext(ctx) 476 for _, p := range platforms { 477 if !platformEnabled[p.Name()] { 478 continue 479 } 480 481 p := p 482 g.Go(func() error { 483 if err := p.Build(ctx); err != nil { 484 return fmt.Errorf("%v failed: %v", p.Name(), err) 485 } 486 return p.UpdateReadme() 487 }) 488 } 489 490 if err := g.Wait(); err != nil { 491 log.Fatal(err) 492 } 493 } 494 495 type Platform struct { 496 OS string 497 Arch string 498 SubArch string 499 Type string // gomote instance type 500 Inst string // actual gomote instance name 501 Script string 502 Skip bool // disabled by default 503 } 504 505 func (p *Platform) Name() string { 506 if p.SubArch != "" { 507 return fmt.Sprintf("%v/%v%v", p.OS, p.Arch, p.SubArch) 508 } 509 return fmt.Sprintf("%v/%v", p.OS, p.Arch) 510 } 511 512 // Basename returns the name of the output file relative to src/runtime/race. 513 func (p *Platform) Basename() string { 514 if p.SubArch != "" { 515 return fmt.Sprintf("internal/%s%s/race_%s.syso", p.Arch, p.SubArch, p.OS) 516 } 517 return fmt.Sprintf("race_%v_%s.syso", p.OS, p.Arch) 518 } 519 520 func setupForGoRepoGitOp() (string, string) { 521 if *flagCherryPick != "" { 522 return "cherry-pick -n", *flagCherryPick 523 } else if *flagCheckout != "" { 524 return "checkout", *flagCheckout 525 } 526 return "", "" 527 } 528 529 func (p *Platform) Build(ctx context.Context) error { 530 // Create gomote instance (or reuse an existing instance for debugging). 531 var lastErr error 532 for p.Inst == "" { 533 inst, err := p.Gomote(ctx, "create", "-status=false", p.Type) 534 if err != nil { 535 select { 536 case <-ctx.Done(): 537 if lastErr != nil { 538 return lastErr 539 } 540 return err 541 default: 542 // Creation sometimes fails with transient errors like: 543 // "buildlet didn't come up at http://10.240.0.13 in 3m0s". 544 log.Printf("%v: instance creation failed, retrying", p.Name()) 545 lastErr = err 546 continue 547 } 548 } 549 p.Inst = strings.Trim(string(inst), " \t\n") 550 defer p.Gomote(context.Background(), "destroy", p.Inst) 551 } 552 log.Printf("%s: using instance %v", p.Name(), p.Inst) 553 554 // putbootstrap 555 if _, err := p.Gomote(ctx, "putbootstrap", p.Inst); err != nil { 556 return err 557 } 558 559 // Execute the script. 560 script, err := os.CreateTemp("", "racebuild") 561 if err != nil { 562 return fmt.Errorf("failed to create temp file: %v", err) 563 } 564 defer func() { 565 script.Close() 566 os.Remove(script.Name()) 567 }() 568 if _, err := script.Write([]byte(p.Script)); err != nil { 569 return fmt.Errorf("failed to write temp file: %v", err) 570 } 571 script.Close() 572 targetName := "script.bash" 573 if p.OS == "windows" { 574 targetName = "script.bat" 575 } 576 if _, err := p.Gomote(ctx, "put", "-mode=0700", p.Inst, script.Name(), targetName); err != nil { 577 return err 578 } 579 var scriptRunErr error 580 gogitop, gosrcref := setupForGoRepoGitOp() 581 if _, err := p.Gomote(ctx, "run", "-e=REV="+*flagRev, "-e=GOREV="+goRev, 582 "-e=GOGITOP="+gogitop, "-e=GOSRCREF="+gosrcref, 583 p.Inst, targetName); err != nil { 584 if !*flagCopyOnFail { 585 return err 586 } 587 log.Printf("%v: gomote script run failed, continuing...\n", p.Name()) 588 scriptRunErr = err 589 } 590 591 // The script is supposed to leave updated runtime at that path. Copy it out. 592 syso := p.Basename() 593 _, err = p.Gomote(ctx, "gettar", "-dir=outdir", p.Inst) 594 if err != nil { 595 return err 596 } 597 598 // Untar the runtime and write it to goroot. 599 if err := p.WriteSyso(filepath.Join(*flagGoroot, "src", "runtime", "race", syso), p.Inst+".tar.gz"); err != nil { 600 return fmt.Errorf("%v", err) 601 } 602 if scriptRunErr != nil { 603 return err 604 } 605 606 log.Printf("%v: build completed", p.Name()) 607 return nil 608 } 609 610 func (p *Platform) WriteSyso(sysof string, targz string) error { 611 // Ungzip. 612 targzf, err := os.Open(targz) 613 if err != nil { 614 return fmt.Errorf("failed to open targz file %s: %v", targz, err) 615 } 616 defer targzf.Close() 617 gzipr, err := gzip.NewReader(targzf) 618 if err != nil { 619 return fmt.Errorf("failed to read gzip archive: %v", err) 620 } 621 defer gzipr.Close() 622 tr := tar.NewReader(gzipr) 623 if _, err := tr.Next(); err != nil { 624 return fmt.Errorf("failed to read tar archive: %v", err) 625 } 626 627 // Copy the file. 628 syso, err := os.Create(sysof) 629 if err != nil { 630 return fmt.Errorf("failed to open race runtime: %v", err) 631 } 632 defer syso.Close() 633 if _, err := io.Copy(syso, tr); err != nil { 634 return fmt.Errorf("failed to write race runtime: %v", err) 635 } 636 return nil 637 } 638 639 var readmeMu sync.Mutex 640 641 func (p *Platform) UpdateReadme() error { 642 readmeMu.Lock() 643 defer readmeMu.Unlock() 644 645 readmeFile := filepath.Join(*flagGoroot, "src", "runtime", "race", "README") 646 readme, err := os.ReadFile(readmeFile) 647 if err != nil { 648 log.Fatalf("bad -goroot? %v", err) 649 } 650 651 syso := p.Basename() 652 const ( 653 readmeTmpl = "%s built with LLVM %s and Go %s." 654 commitRE = "[0-9a-f]+" 655 ) 656 657 // TODO(bcmills): Extract the C++ toolchain version from the .syso file and 658 // record it in the README. 659 updatedLine := fmt.Sprintf(readmeTmpl, syso, *flagRev, goRev) 660 661 lineRE, err := regexp.Compile("(?m)^" + fmt.Sprintf(readmeTmpl, regexp.QuoteMeta(syso), commitRE, commitRE) + "$") 662 if err != nil { 663 return err 664 } 665 if lineRE.Match(readme) { 666 readme = lineRE.ReplaceAll(readme, []byte(updatedLine)) 667 } else { 668 readme = append(append(readme, []byte(updatedLine)...), '\n') 669 } 670 671 return os.WriteFile(readmeFile, readme, 0640) 672 } 673 674 func (p *Platform) Gomote(ctx context.Context, args ...string) ([]byte, error) { 675 log.Printf("%v: gomote %v", p.Name(), args) 676 677 cmd := exec.CommandContext(ctx, "gomote", args...) 678 outBuf := new(bytes.Buffer) 679 errBuf := outBuf 680 681 cmd.Stdout = outBuf 682 cmd.Stderr = errBuf 683 run := cmd.Run 684 if len(platformEnabled) == 1 { 685 // If building only one platform, stream gomote output to os.Stderr. 686 r, w := io.Pipe() 687 errTee := io.TeeReader(r, cmd.Stderr) 688 if cmd.Stdout == cmd.Stderr { 689 cmd.Stdout = w 690 } 691 cmd.Stderr = w 692 693 run = func() (err error) { 694 go func() { 695 err = cmd.Run() 696 w.Close() 697 }() 698 io.Copy(os.Stderr, errTee) 699 return 700 } 701 } 702 703 if err := run(); err != nil { 704 select { 705 case <-ctx.Done(): 706 return nil, ctx.Err() 707 default: 708 } 709 log.Printf("%v: gomote %v failed:\n%s", p.Name(), args, errBuf) 710 return nil, err 711 } 712 713 if errBuf.Len() == 0 { 714 log.Printf("%v: gomote %v succeeded: <no output>", p.Name(), args) 715 } else { 716 log.Printf("%v: gomote %v succeeded:\n%s", p.Name(), args, errBuf) 717 } 718 return outBuf.Bytes(), nil 719 }