github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/cmd/go/build.go (about) 1 // Copyright 2011 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 package main 6 7 import ( 8 "bufio" 9 "bytes" 10 "container/heap" 11 "errors" 12 "flag" 13 "fmt" 14 "go/build" 15 "io" 16 "io/ioutil" 17 "log" 18 "os" 19 "os/exec" 20 "path" 21 "path/filepath" 22 "regexp" 23 "runtime" 24 "strconv" 25 "strings" 26 "sync" 27 "time" 28 ) 29 30 var cmdBuild = &Command{ 31 UsageLine: "build [-o output] [-i] [build flags] [packages]", 32 Short: "compile packages and dependencies", 33 Long: ` 34 Build compiles the packages named by the import paths, 35 along with their dependencies, but it does not install the results. 36 37 If the arguments are a list of .go files, build treats them as a list 38 of source files specifying a single package. 39 40 When the command line specifies a single main package, 41 build writes the resulting executable to output. 42 Otherwise build compiles the packages but discards the results, 43 serving only as a check that the packages can be built. 44 45 The -o flag specifies the output file name. If not specified, the 46 output file name depends on the arguments and derives from the name 47 of the package, such as p.a for package p, unless p is 'main'. If 48 the package is main and file names are provided, the file name 49 derives from the first file name mentioned, such as f1 for 'go build 50 f1.go f2.go'; with no files provided ('go build'), the output file 51 name is the base name of the containing directory. 52 53 The -i flag installs the packages that are dependencies of the target. 54 55 The build flags are shared by the build, clean, get, install, list, run, 56 and test commands: 57 58 -a 59 force rebuilding of packages that are already up-to-date. 60 In Go releases, does not apply to the standard library. 61 -n 62 print the commands but do not run them. 63 -p n 64 the number of builds that can be run in parallel. 65 The default is the number of CPUs available. 66 -race 67 enable data race detection. 68 Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. 69 -v 70 print the names of packages as they are compiled. 71 -work 72 print the name of the temporary work directory and 73 do not delete it when exiting. 74 -x 75 print the commands. 76 77 -ccflags 'arg list' 78 arguments to pass on each 5c, 6c, or 8c compiler invocation. 79 -compiler name 80 name of compiler to use, as in runtime.Compiler (gccgo or gc). 81 -gccgoflags 'arg list' 82 arguments to pass on each gccgo compiler/linker invocation. 83 -gcflags 'arg list' 84 arguments to pass on each 5g, 6g, or 8g compiler invocation. 85 -installsuffix suffix 86 a suffix to use in the name of the package installation directory, 87 in order to keep output separate from default builds. 88 If using the -race flag, the install suffix is automatically set to race 89 or, if set explicitly, has _race appended to it. 90 -ldflags 'flag list' 91 arguments to pass on each 5l, 6l, or 8l linker invocation. 92 -tags 'tag list' 93 a list of build tags to consider satisfied during the build. 94 For more information about build tags, see the description of 95 build constraints in the documentation for the go/build package. 96 97 The list flags accept a space-separated list of strings. To embed spaces 98 in an element in the list, surround it with either single or double quotes. 99 100 For more about specifying packages, see 'go help packages'. 101 For more about where packages and binaries are installed, 102 run 'go help gopath'. For more about calling between Go and C/C++, 103 run 'go help c'. 104 105 See also: go install, go get, go clean. 106 `, 107 } 108 109 func init() { 110 // break init cycle 111 cmdBuild.Run = runBuild 112 cmdInstall.Run = runInstall 113 114 cmdBuild.Flag.BoolVar(&buildI, "i", false, "") 115 116 addBuildFlags(cmdBuild) 117 addBuildFlags(cmdInstall) 118 } 119 120 // Flags set by multiple commands. 121 var buildA bool // -a flag 122 var buildN bool // -n flag 123 var buildP = runtime.NumCPU() // -p flag 124 var buildV bool // -v flag 125 var buildX bool // -x flag 126 var buildI bool // -i flag 127 var buildO = cmdBuild.Flag.String("o", "", "output file") 128 var buildWork bool // -work flag 129 var buildGcflags []string // -gcflags flag 130 var buildCcflags []string // -ccflags flag 131 var buildLdflags []string // -ldflags flag 132 var buildGccgoflags []string // -gccgoflags flag 133 var buildRace bool // -race flag 134 135 var buildContext = build.Default 136 var buildToolchain toolchain = noToolchain{} 137 138 // buildCompiler implements flag.Var. 139 // It implements Set by updating both 140 // buildToolchain and buildContext.Compiler. 141 type buildCompiler struct{} 142 143 func (c buildCompiler) Set(value string) error { 144 switch value { 145 case "gc": 146 buildToolchain = gcToolchain{} 147 case "gccgo": 148 buildToolchain = gccgoToolchain{} 149 default: 150 return fmt.Errorf("unknown compiler %q", value) 151 } 152 buildContext.Compiler = value 153 return nil 154 } 155 156 func (c buildCompiler) String() string { 157 return buildContext.Compiler 158 } 159 160 func init() { 161 switch build.Default.Compiler { 162 case "gc": 163 buildToolchain = gcToolchain{} 164 case "gccgo": 165 buildToolchain = gccgoToolchain{} 166 } 167 } 168 169 // addBuildFlags adds the flags common to the build, clean, get, 170 // install, list, run, and test commands. 171 func addBuildFlags(cmd *Command) { 172 // NOTE: If you add flags here, also add them to testflag.go. 173 cmd.Flag.BoolVar(&buildA, "a", false, "") 174 cmd.Flag.BoolVar(&buildN, "n", false, "") 175 cmd.Flag.IntVar(&buildP, "p", buildP, "") 176 cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "") 177 cmd.Flag.BoolVar(&buildV, "v", false, "") 178 cmd.Flag.BoolVar(&buildX, "x", false, "") 179 cmd.Flag.BoolVar(&buildWork, "work", false, "") 180 cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "") 181 cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "") 182 cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "") 183 cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") 184 cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") 185 cmd.Flag.Var(buildCompiler{}, "compiler", "") 186 cmd.Flag.BoolVar(&buildRace, "race", false, "") 187 } 188 189 func addBuildFlagsNX(cmd *Command) { 190 cmd.Flag.BoolVar(&buildN, "n", false, "") 191 cmd.Flag.BoolVar(&buildX, "x", false, "") 192 } 193 194 func isSpaceByte(c byte) bool { 195 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 196 } 197 198 // fileExtSplit expects a filename and returns the name 199 // and ext (without the dot). If the file has no 200 // extension, ext will be empty. 201 func fileExtSplit(file string) (name, ext string) { 202 dotExt := filepath.Ext(file) 203 name = file[:len(file)-len(dotExt)] 204 if dotExt != "" { 205 ext = dotExt[1:] 206 } 207 return 208 } 209 210 type stringsFlag []string 211 212 func (v *stringsFlag) Set(s string) error { 213 var err error 214 *v, err = splitQuotedFields(s) 215 if *v == nil { 216 *v = []string{} 217 } 218 return err 219 } 220 221 func splitQuotedFields(s string) ([]string, error) { 222 // Split fields allowing '' or "" around elements. 223 // Quotes further inside the string do not count. 224 var f []string 225 for len(s) > 0 { 226 for len(s) > 0 && isSpaceByte(s[0]) { 227 s = s[1:] 228 } 229 if len(s) == 0 { 230 break 231 } 232 // Accepted quoted string. No unescaping inside. 233 if s[0] == '"' || s[0] == '\'' { 234 quote := s[0] 235 s = s[1:] 236 i := 0 237 for i < len(s) && s[i] != quote { 238 i++ 239 } 240 if i >= len(s) { 241 return nil, fmt.Errorf("unterminated %c string", quote) 242 } 243 f = append(f, s[:i]) 244 s = s[i+1:] 245 continue 246 } 247 i := 0 248 for i < len(s) && !isSpaceByte(s[i]) { 249 i++ 250 } 251 f = append(f, s[:i]) 252 s = s[i:] 253 } 254 return f, nil 255 } 256 257 func (v *stringsFlag) String() string { 258 return "<stringsFlag>" 259 } 260 261 func runBuild(cmd *Command, args []string) { 262 raceInit() 263 var b builder 264 b.init() 265 266 pkgs := packagesForBuild(args) 267 268 if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" { 269 _, *buildO = path.Split(pkgs[0].ImportPath) 270 *buildO += exeSuffix 271 } 272 273 // sanity check some often mis-used options 274 switch buildContext.Compiler { 275 case "gccgo": 276 if len(buildGcflags) != 0 { 277 fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags") 278 } 279 if len(buildLdflags) != 0 { 280 fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags") 281 } 282 case "gc": 283 if len(buildGccgoflags) != 0 { 284 fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags") 285 } 286 } 287 288 depMode := modeBuild 289 if buildI { 290 depMode = modeInstall 291 } 292 293 if *buildO != "" { 294 if len(pkgs) > 1 { 295 fatalf("go build: cannot use -o with multiple packages") 296 } else if len(pkgs) == 0 { 297 fatalf("no packages to build") 298 } 299 p := pkgs[0] 300 p.target = "" // must build - not up to date 301 a := b.action(modeInstall, depMode, p) 302 a.target = *buildO 303 b.do(a) 304 return 305 } 306 307 a := &action{} 308 for _, p := range packages(args) { 309 a.deps = append(a.deps, b.action(modeBuild, depMode, p)) 310 } 311 b.do(a) 312 } 313 314 var cmdInstall = &Command{ 315 UsageLine: "install [build flags] [packages]", 316 Short: "compile and install packages and dependencies", 317 Long: ` 318 Install compiles and installs the packages named by the import paths, 319 along with their dependencies. 320 321 For more about the build flags, see 'go help build'. 322 For more about specifying packages, see 'go help packages'. 323 324 See also: go build, go get, go clean. 325 `, 326 } 327 328 func runInstall(cmd *Command, args []string) { 329 raceInit() 330 pkgs := packagesForBuild(args) 331 332 for _, p := range pkgs { 333 if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { 334 if p.cmdline { 335 errorf("go install: no install location for .go files listed on command line (GOBIN not set)") 336 } else if p.ConflictDir != "" { 337 errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir) 338 } else { 339 errorf("go install: no install location for directory %s outside GOPATH", p.Dir) 340 } 341 } 342 } 343 exitIfErrors() 344 345 var b builder 346 b.init() 347 a := &action{} 348 for _, p := range pkgs { 349 a.deps = append(a.deps, b.action(modeInstall, modeInstall, p)) 350 } 351 b.do(a) 352 } 353 354 // Global build parameters (used during package load) 355 var ( 356 goarch string 357 goos string 358 archChar string 359 exeSuffix string 360 ) 361 362 func init() { 363 goarch = buildContext.GOARCH 364 goos = buildContext.GOOS 365 if goos == "windows" { 366 exeSuffix = ".exe" 367 } 368 var err error 369 archChar, err = build.ArchChar(goarch) 370 if err != nil { 371 if _, isgc := buildToolchain.(gcToolchain); isgc { 372 fatalf("%s", err) 373 } 374 // archChar is only required for gcToolchain, if we're using 375 // another toolchain leave it blank. 376 archChar = "" 377 } 378 } 379 380 // A builder holds global state about a build. 381 // It does not hold per-package state, because we 382 // build packages in parallel, and the builder is shared. 383 type builder struct { 384 work string // the temporary work directory (ends in filepath.Separator) 385 actionCache map[cacheKey]*action // a cache of already-constructed actions 386 mkdirCache map[string]bool // a cache of created directories 387 print func(args ...interface{}) (int, error) 388 389 output sync.Mutex 390 scriptDir string // current directory in printed script 391 392 exec sync.Mutex 393 readySema chan bool 394 ready actionQueue 395 } 396 397 // An action represents a single action in the action graph. 398 type action struct { 399 p *Package // the package this action works on 400 deps []*action // actions that must happen before this one 401 triggers []*action // inverse of deps 402 cgo *action // action for cgo binary if needed 403 args []string // additional args for runProgram 404 testOutput *bytes.Buffer // test output buffer 405 406 f func(*builder, *action) error // the action itself (nil = no-op) 407 ignoreFail bool // whether to run f even if dependencies fail 408 409 // Generated files, directories. 410 link bool // target is executable, not just package 411 pkgdir string // the -I or -L argument to use when importing this package 412 objdir string // directory for intermediate objects 413 objpkg string // the intermediate package .a file created during the action 414 target string // goal of the action: the created package or executable 415 416 // Execution state. 417 pending int // number of deps yet to complete 418 priority int // relative execution priority 419 failed bool // whether the action failed 420 } 421 422 // cacheKey is the key for the action cache. 423 type cacheKey struct { 424 mode buildMode 425 p *Package 426 } 427 428 // buildMode specifies the build mode: 429 // are we just building things or also installing the results? 430 type buildMode int 431 432 const ( 433 modeBuild buildMode = iota 434 modeInstall 435 ) 436 437 var ( 438 goroot = filepath.Clean(runtime.GOROOT()) 439 gobin = os.Getenv("GOBIN") 440 gorootBin = filepath.Join(goroot, "bin") 441 gorootPkg = filepath.Join(goroot, "pkg") 442 gorootSrc = filepath.Join(goroot, "src") 443 ) 444 445 func (b *builder) init() { 446 var err error 447 b.print = func(a ...interface{}) (int, error) { 448 return fmt.Fprint(os.Stderr, a...) 449 } 450 b.actionCache = make(map[cacheKey]*action) 451 b.mkdirCache = make(map[string]bool) 452 453 if buildN { 454 b.work = "$WORK" 455 } else { 456 b.work, err = ioutil.TempDir("", "go-build") 457 if err != nil { 458 fatalf("%s", err) 459 } 460 if buildX || buildWork { 461 fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work) 462 } 463 if !buildWork { 464 workdir := b.work 465 atexit(func() { os.RemoveAll(workdir) }) 466 } 467 } 468 } 469 470 // goFilesPackage creates a package for building a collection of Go files 471 // (typically named on the command line). The target is named p.a for 472 // package p or named after the first Go file for package main. 473 func goFilesPackage(gofiles []string) *Package { 474 // TODO: Remove this restriction. 475 for _, f := range gofiles { 476 if !strings.HasSuffix(f, ".go") { 477 fatalf("named files must be .go files") 478 } 479 } 480 481 var stk importStack 482 ctxt := buildContext 483 ctxt.UseAllFiles = true 484 485 // Synthesize fake "directory" that only shows the named files, 486 // to make it look like this is a standard package or 487 // command directory. So that local imports resolve 488 // consistently, the files must all be in the same directory. 489 var dirent []os.FileInfo 490 var dir string 491 for _, file := range gofiles { 492 fi, err := os.Stat(file) 493 if err != nil { 494 fatalf("%s", err) 495 } 496 if fi.IsDir() { 497 fatalf("%s is a directory, should be a Go file", file) 498 } 499 dir1, _ := filepath.Split(file) 500 if dir == "" { 501 dir = dir1 502 } else if dir != dir1 { 503 fatalf("named files must all be in one directory; have %s and %s", dir, dir1) 504 } 505 dirent = append(dirent, fi) 506 } 507 ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } 508 509 var err error 510 if dir == "" { 511 dir = cwd 512 } 513 dir, err = filepath.Abs(dir) 514 if err != nil { 515 fatalf("%s", err) 516 } 517 518 bp, err := ctxt.ImportDir(dir, 0) 519 pkg := new(Package) 520 pkg.local = true 521 pkg.cmdline = true 522 pkg.load(&stk, bp, err) 523 pkg.localPrefix = dirToImportPath(dir) 524 pkg.ImportPath = "command-line-arguments" 525 pkg.target = "" 526 527 if pkg.Name == "main" { 528 _, elem := filepath.Split(gofiles[0]) 529 exe := elem[:len(elem)-len(".go")] + exeSuffix 530 if *buildO == "" { 531 *buildO = exe 532 } 533 if gobin != "" { 534 pkg.target = filepath.Join(gobin, exe) 535 } 536 } else { 537 if *buildO == "" { 538 *buildO = pkg.Name + ".a" 539 } 540 } 541 pkg.Target = pkg.target 542 pkg.Stale = true 543 544 computeStale(pkg) 545 return pkg 546 } 547 548 // action returns the action for applying the given operation (mode) to the package. 549 // depMode is the action to use when building dependencies. 550 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action { 551 key := cacheKey{mode, p} 552 a := b.actionCache[key] 553 if a != nil { 554 return a 555 } 556 557 a = &action{p: p, pkgdir: p.build.PkgRoot} 558 if p.pkgdir != "" { // overrides p.t 559 a.pkgdir = p.pkgdir 560 } 561 562 b.actionCache[key] = a 563 564 for _, p1 := range p.imports { 565 a.deps = append(a.deps, b.action(depMode, depMode, p1)) 566 } 567 568 // If we are not doing a cross-build, then record the binary we'll 569 // generate for cgo as a dependency of the build of any package 570 // using cgo, to make sure we do not overwrite the binary while 571 // a package is using it. If this is a cross-build, then the cgo we 572 // are writing is not the cgo we need to use. 573 if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace { 574 if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" { 575 var stk importStack 576 p1 := loadPackage("cmd/cgo", &stk) 577 if p1.Error != nil { 578 fatalf("load cmd/cgo: %v", p1.Error) 579 } 580 a.cgo = b.action(depMode, depMode, p1) 581 a.deps = append(a.deps, a.cgo) 582 } 583 } 584 585 if p.Standard { 586 switch p.ImportPath { 587 case "builtin", "unsafe": 588 // Fake packages - nothing to build. 589 return a 590 } 591 // gccgo standard library is "fake" too. 592 if _, ok := buildToolchain.(gccgoToolchain); ok { 593 // the target name is needed for cgo. 594 a.target = p.target 595 return a 596 } 597 } 598 599 if !p.Stale && p.target != "" { 600 // p.Stale==false implies that p.target is up-to-date. 601 // Record target name for use by actions depending on this one. 602 a.target = p.target 603 return a 604 } 605 606 if p.local && p.target == "" { 607 // Imported via local path. No permanent target. 608 mode = modeBuild 609 } 610 work := p.pkgdir 611 if work == "" { 612 work = b.work 613 } 614 a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator) 615 a.objpkg = buildToolchain.pkgpath(work, a.p) 616 a.link = p.Name == "main" 617 618 switch mode { 619 case modeInstall: 620 a.f = (*builder).install 621 a.deps = []*action{b.action(modeBuild, depMode, p)} 622 a.target = a.p.target 623 case modeBuild: 624 a.f = (*builder).build 625 a.target = a.objpkg 626 if a.link { 627 // An executable file. (This is the name of a temporary file.) 628 // Because we run the temporary file in 'go run' and 'go test', 629 // the name will show up in ps listings. If the caller has specified 630 // a name, use that instead of a.out. The binary is generated 631 // in an otherwise empty subdirectory named exe to avoid 632 // naming conflicts. The only possible conflict is if we were 633 // to create a top-level package named exe. 634 name := "a.out" 635 if p.exeName != "" { 636 name = p.exeName 637 } 638 a.target = a.objdir + filepath.Join("exe", name) + exeSuffix 639 } 640 } 641 642 return a 643 } 644 645 // actionList returns the list of actions in the dag rooted at root 646 // as visited in a depth-first post-order traversal. 647 func actionList(root *action) []*action { 648 seen := map[*action]bool{} 649 all := []*action{} 650 var walk func(*action) 651 walk = func(a *action) { 652 if seen[a] { 653 return 654 } 655 seen[a] = true 656 for _, a1 := range a.deps { 657 walk(a1) 658 } 659 all = append(all, a) 660 } 661 walk(root) 662 return all 663 } 664 665 // do runs the action graph rooted at root. 666 func (b *builder) do(root *action) { 667 // Build list of all actions, assigning depth-first post-order priority. 668 // The original implementation here was a true queue 669 // (using a channel) but it had the effect of getting 670 // distracted by low-level leaf actions to the detriment 671 // of completing higher-level actions. The order of 672 // work does not matter much to overall execution time, 673 // but when running "go test std" it is nice to see each test 674 // results as soon as possible. The priorities assigned 675 // ensure that, all else being equal, the execution prefers 676 // to do what it would have done first in a simple depth-first 677 // dependency order traversal. 678 all := actionList(root) 679 for i, a := range all { 680 a.priority = i 681 } 682 683 b.readySema = make(chan bool, len(all)) 684 685 // Initialize per-action execution state. 686 for _, a := range all { 687 for _, a1 := range a.deps { 688 a1.triggers = append(a1.triggers, a) 689 } 690 a.pending = len(a.deps) 691 if a.pending == 0 { 692 b.ready.push(a) 693 b.readySema <- true 694 } 695 } 696 697 // Handle runs a single action and takes care of triggering 698 // any actions that are runnable as a result. 699 handle := func(a *action) { 700 var err error 701 if a.f != nil && (!a.failed || a.ignoreFail) { 702 err = a.f(b, a) 703 } 704 705 // The actions run in parallel but all the updates to the 706 // shared work state are serialized through b.exec. 707 b.exec.Lock() 708 defer b.exec.Unlock() 709 710 if err != nil { 711 if err == errPrintedOutput { 712 setExitStatus(2) 713 } else { 714 errorf("%s", err) 715 } 716 a.failed = true 717 } 718 719 for _, a0 := range a.triggers { 720 if a.failed { 721 a0.failed = true 722 } 723 if a0.pending--; a0.pending == 0 { 724 b.ready.push(a0) 725 b.readySema <- true 726 } 727 } 728 729 if a == root { 730 close(b.readySema) 731 } 732 } 733 734 var wg sync.WaitGroup 735 736 // Kick off goroutines according to parallelism. 737 // If we are using the -n flag (just printing commands) 738 // drop the parallelism to 1, both to make the output 739 // deterministic and because there is no real work anyway. 740 par := buildP 741 if buildN { 742 par = 1 743 } 744 for i := 0; i < par; i++ { 745 wg.Add(1) 746 go func() { 747 defer wg.Done() 748 for { 749 select { 750 case _, ok := <-b.readySema: 751 if !ok { 752 return 753 } 754 // Receiving a value from b.readySema entitles 755 // us to take from the ready queue. 756 b.exec.Lock() 757 a := b.ready.pop() 758 b.exec.Unlock() 759 handle(a) 760 case <-interrupted: 761 setExitStatus(1) 762 return 763 } 764 } 765 }() 766 } 767 768 wg.Wait() 769 } 770 771 // hasString reports whether s appears in the list of strings. 772 func hasString(strings []string, s string) bool { 773 for _, t := range strings { 774 if s == t { 775 return true 776 } 777 } 778 return false 779 } 780 781 // build is the action for building a single package or command. 782 func (b *builder) build(a *action) (err error) { 783 // Return an error if the package has CXX files but it's not using 784 // cgo nor SWIG, since the CXX files can only be processed by cgo 785 // and SWIG (it's possible to have packages with C files without 786 // using cgo, they will get compiled with the plan9 C compiler and 787 // linked with the rest of the package). 788 if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() { 789 return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG", 790 a.p.ImportPath, strings.Join(a.p.CXXFiles, ",")) 791 } 792 // Same as above for Objective-C files 793 if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() { 794 return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG", 795 a.p.ImportPath, strings.Join(a.p.MFiles, ",")) 796 } 797 defer func() { 798 if err != nil && err != errPrintedOutput { 799 err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err) 800 } 801 }() 802 if buildN { 803 // In -n mode, print a banner between packages. 804 // The banner is five lines so that when changes to 805 // different sections of the bootstrap script have to 806 // be merged, the banners give patch something 807 // to use to find its context. 808 fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath) 809 } 810 811 if buildV { 812 fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath) 813 } 814 815 if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" && 816 !hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") { 817 return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix()) 818 } 819 820 // Make build directory. 821 obj := a.objdir 822 if err := b.mkdir(obj); err != nil { 823 return err 824 } 825 826 // make target directory 827 dir, _ := filepath.Split(a.target) 828 if dir != "" { 829 if err := b.mkdir(dir); err != nil { 830 return err 831 } 832 } 833 834 var gofiles, cfiles, sfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string 835 836 gofiles = append(gofiles, a.p.GoFiles...) 837 cfiles = append(cfiles, a.p.CFiles...) 838 sfiles = append(sfiles, a.p.SFiles...) 839 840 if a.p.usesCgo() || a.p.usesSwig() { 841 if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil { 842 return 843 } 844 } 845 // Run cgo. 846 if a.p.usesCgo() { 847 // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc. 848 // There is one exception: runtime/cgo's job is to bridge the 849 // cgo and non-cgo worlds, so it necessarily has files in both. 850 // In that case gcc only gets the gcc_* files. 851 var gccfiles []string 852 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { 853 filter := func(files, nongcc, gcc []string) ([]string, []string) { 854 for _, f := range files { 855 if strings.HasPrefix(f, "gcc_") { 856 gcc = append(gcc, f) 857 } else { 858 nongcc = append(nongcc, f) 859 } 860 } 861 return nongcc, gcc 862 } 863 cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles) 864 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) 865 } else { 866 gccfiles = append(cfiles, sfiles...) 867 cfiles = nil 868 sfiles = nil 869 } 870 871 cgoExe := tool("cgo") 872 if a.cgo != nil && a.cgo.target != "" { 873 cgoExe = a.cgo.target 874 } 875 outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, gccfiles, a.p.CXXFiles, a.p.MFiles) 876 if err != nil { 877 return err 878 } 879 cgoObjects = append(cgoObjects, outObj...) 880 gofiles = append(gofiles, outGo...) 881 } 882 883 // Run SWIG. 884 if a.p.usesSwig() { 885 // In a package using SWIG, any .c or .s files are 886 // compiled with gcc. 887 gccfiles := append(cfiles, sfiles...) 888 cxxfiles, mfiles := a.p.CXXFiles, a.p.MFiles 889 cfiles = nil 890 sfiles = nil 891 892 // Don't build c/c++ files twice if cgo is enabled (mainly for pkg-config). 893 if a.p.usesCgo() { 894 cxxfiles = nil 895 gccfiles = nil 896 mfiles = nil 897 } 898 899 outGo, outObj, err := b.swig(a.p, obj, pcCFLAGS, gccfiles, cxxfiles, mfiles) 900 if err != nil { 901 return err 902 } 903 cgoObjects = append(cgoObjects, outObj...) 904 gofiles = append(gofiles, outGo...) 905 } 906 907 if len(gofiles) == 0 { 908 return &build.NoGoError{Dir: a.p.Dir} 909 } 910 911 // If we're doing coverage, preprocess the .go files and put them in the work directory 912 if a.p.coverMode != "" { 913 for i, file := range gofiles { 914 var sourceFile string 915 var coverFile string 916 var key string 917 if strings.HasSuffix(file, ".cgo1.go") { 918 // cgo files have absolute paths 919 base := filepath.Base(file) 920 sourceFile = file 921 coverFile = filepath.Join(obj, base) 922 key = strings.TrimSuffix(base, ".cgo1.go") + ".go" 923 } else { 924 sourceFile = filepath.Join(a.p.Dir, file) 925 coverFile = filepath.Join(obj, file) 926 key = file 927 } 928 cover := a.p.coverVars[key] 929 if cover == nil || isTestFile(file) { 930 // Not covering this file. 931 continue 932 } 933 if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil { 934 return err 935 } 936 gofiles[i] = coverFile 937 } 938 } 939 940 // Prepare Go import path list. 941 inc := b.includeArgs("-I", a.deps) 942 943 // Compile Go. 944 ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, inc, gofiles) 945 if len(out) > 0 { 946 b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out)) 947 if err != nil { 948 return errPrintedOutput 949 } 950 } 951 if err != nil { 952 return err 953 } 954 if ofile != a.objpkg { 955 objects = append(objects, ofile) 956 } 957 958 // Copy .h files named for goos or goarch or goos_goarch 959 // to names using GOOS and GOARCH. 960 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. 961 _goos_goarch := "_" + goos + "_" + goarch 962 _goos := "_" + goos 963 _goarch := "_" + goarch 964 for _, file := range a.p.HFiles { 965 name, ext := fileExtSplit(file) 966 switch { 967 case strings.HasSuffix(name, _goos_goarch): 968 targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext 969 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil { 970 return err 971 } 972 case strings.HasSuffix(name, _goarch): 973 targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext 974 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil { 975 return err 976 } 977 case strings.HasSuffix(name, _goos): 978 targ := file[:len(name)-len(_goos)] + "_GOOS." + ext 979 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil { 980 return err 981 } 982 } 983 } 984 985 objExt := archChar 986 if _, ok := buildToolchain.(gccgoToolchain); ok { 987 objExt = "o" 988 } 989 990 for _, file := range cfiles { 991 out := file[:len(file)-len(".c")] + "." + objExt 992 if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil { 993 return err 994 } 995 objects = append(objects, out) 996 } 997 998 // Assemble .s files. 999 for _, file := range sfiles { 1000 out := file[:len(file)-len(".s")] + "." + objExt 1001 if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil { 1002 return err 1003 } 1004 objects = append(objects, out) 1005 } 1006 1007 // NOTE(rsc): On Windows, it is critically important that the 1008 // gcc-compiled objects (cgoObjects) be listed after the ordinary 1009 // objects in the archive. I do not know why this is. 1010 // http://golang.org/issue/2601 1011 objects = append(objects, cgoObjects...) 1012 1013 // Add system object files. 1014 for _, syso := range a.p.SysoFiles { 1015 objects = append(objects, filepath.Join(a.p.Dir, syso)) 1016 } 1017 1018 // Pack into archive in obj directory. 1019 // If the Go compiler wrote an archive, we only need to add the 1020 // object files for non-Go sources to the archive. 1021 // If the Go compiler wrote an archive and the package is entirely 1022 // Go sources, there is no pack to execute at all. 1023 if len(objects) > 0 { 1024 if err := buildToolchain.pack(b, a.p, obj, a.objpkg, objects); err != nil { 1025 return err 1026 } 1027 } 1028 1029 // Link if needed. 1030 if a.link { 1031 // The compiler only cares about direct imports, but the 1032 // linker needs the whole dependency tree. 1033 all := actionList(a) 1034 all = all[:len(all)-1] // drop a 1035 if err := buildToolchain.ld(b, a.p, a.target, all, a.objpkg, objects); err != nil { 1036 return err 1037 } 1038 } 1039 1040 return nil 1041 } 1042 1043 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. 1044 func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) { 1045 if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { 1046 var out []byte 1047 out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) 1048 if err != nil { 1049 b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out)) 1050 b.print(err.Error() + "\n") 1051 err = errPrintedOutput 1052 return 1053 } 1054 if len(out) > 0 { 1055 cflags = strings.Fields(string(out)) 1056 } 1057 out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs) 1058 if err != nil { 1059 b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out)) 1060 b.print(err.Error() + "\n") 1061 err = errPrintedOutput 1062 return 1063 } 1064 if len(out) > 0 { 1065 ldflags = strings.Fields(string(out)) 1066 } 1067 } 1068 return 1069 } 1070 1071 // install is the action for installing a single package or executable. 1072 func (b *builder) install(a *action) (err error) { 1073 defer func() { 1074 if err != nil && err != errPrintedOutput { 1075 err = fmt.Errorf("go install %s: %v", a.p.ImportPath, err) 1076 } 1077 }() 1078 a1 := a.deps[0] 1079 perm := os.FileMode(0644) 1080 if a1.link { 1081 perm = 0755 1082 } 1083 1084 // make target directory 1085 dir, _ := filepath.Split(a.target) 1086 if dir != "" { 1087 if err := b.mkdir(dir); err != nil { 1088 return err 1089 } 1090 } 1091 1092 // remove object dir to keep the amount of 1093 // garbage down in a large build. On an operating system 1094 // with aggressive buffering, cleaning incrementally like 1095 // this keeps the intermediate objects from hitting the disk. 1096 if !buildWork { 1097 defer os.RemoveAll(a1.objdir) 1098 defer os.Remove(a1.target) 1099 } 1100 1101 return b.moveOrCopyFile(a, a.target, a1.target, perm) 1102 } 1103 1104 // includeArgs returns the -I or -L directory list for access 1105 // to the results of the list of actions. 1106 func (b *builder) includeArgs(flag string, all []*action) []string { 1107 inc := []string{} 1108 incMap := map[string]bool{ 1109 b.work: true, // handled later 1110 gorootPkg: true, 1111 "": true, // ignore empty strings 1112 } 1113 1114 // Look in the temporary space for results of test-specific actions. 1115 // This is the $WORK/my/package/_test directory for the 1116 // package being built, so there are few of these. 1117 for _, a1 := range all { 1118 if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] { 1119 incMap[dir] = true 1120 inc = append(inc, flag, dir) 1121 } 1122 } 1123 1124 // Also look in $WORK for any non-test packages that have 1125 // been built but not installed. 1126 inc = append(inc, flag, b.work) 1127 1128 // Finally, look in the installed package directories for each action. 1129 for _, a1 := range all { 1130 if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] { 1131 incMap[dir] = true 1132 if _, ok := buildToolchain.(gccgoToolchain); ok { 1133 dir = filepath.Join(dir, "gccgo_"+goos+"_"+goarch) 1134 } else { 1135 dir = filepath.Join(dir, goos+"_"+goarch) 1136 if buildContext.InstallSuffix != "" { 1137 dir += "_" + buildContext.InstallSuffix 1138 } 1139 } 1140 inc = append(inc, flag, dir) 1141 } 1142 } 1143 1144 return inc 1145 } 1146 1147 // moveOrCopyFile is like 'mv src dst' or 'cp src dst'. 1148 func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode) error { 1149 if buildN { 1150 b.showcmd("", "mv %s %s", src, dst) 1151 return nil 1152 } 1153 1154 // If we can update the mode and rename to the dst, do it. 1155 // Otherwise fall back to standard copy. 1156 if err := os.Chmod(src, perm); err == nil { 1157 if err := os.Rename(src, dst); err == nil { 1158 if buildX { 1159 b.showcmd("", "mv %s %s", src, dst) 1160 } 1161 return nil 1162 } 1163 } 1164 1165 return b.copyFile(a, dst, src, perm) 1166 } 1167 1168 // copyFile is like 'cp src dst'. 1169 func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode) error { 1170 if buildN || buildX { 1171 b.showcmd("", "cp %s %s", src, dst) 1172 if buildN { 1173 return nil 1174 } 1175 } 1176 1177 sf, err := os.Open(src) 1178 if err != nil { 1179 return err 1180 } 1181 defer sf.Close() 1182 1183 // Be careful about removing/overwriting dst. 1184 // Do not remove/overwrite if dst exists and is a directory 1185 // or a non-object file. 1186 if fi, err := os.Stat(dst); err == nil { 1187 if fi.IsDir() { 1188 return fmt.Errorf("build output %q already exists and is a directory", dst) 1189 } 1190 if !isObject(dst) { 1191 return fmt.Errorf("build output %q already exists and is not an object file", dst) 1192 } 1193 } 1194 1195 // On Windows, remove lingering ~ file from last attempt. 1196 if toolIsWindows { 1197 if _, err := os.Stat(dst + "~"); err == nil { 1198 os.Remove(dst + "~") 1199 } 1200 } 1201 1202 os.Remove(dst) 1203 df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) 1204 if err != nil && toolIsWindows { 1205 // Windows does not allow deletion of a binary file 1206 // while it is executing. Try to move it out of the way. 1207 // If the move fails, which is likely, we'll try again the 1208 // next time we do an install of this binary. 1209 if err := os.Rename(dst, dst+"~"); err == nil { 1210 os.Remove(dst + "~") 1211 } 1212 df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) 1213 } 1214 if err != nil { 1215 return err 1216 } 1217 1218 _, err = io.Copy(df, sf) 1219 df.Close() 1220 if err != nil { 1221 os.Remove(dst) 1222 return fmt.Errorf("copying %s to %s: %v", src, dst, err) 1223 } 1224 return nil 1225 } 1226 1227 // cover runs, in effect, 1228 // go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go 1229 func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error { 1230 return b.run(a.objdir, "cover "+a.p.ImportPath, nil, 1231 tool("cover"), 1232 "-mode", a.p.coverMode, 1233 "-var", varName, 1234 "-o", dst, 1235 src) 1236 } 1237 1238 var objectMagic = [][]byte{ 1239 {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive 1240 {'\x7F', 'E', 'L', 'F'}, // ELF 1241 {0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit 1242 {0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit 1243 {0xCE, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 32-bit 1244 {0xCF, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 64-bit 1245 {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x04, 0x00}, // PE (Windows) as generated by 6l/8l 1246 {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386 1247 {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64 1248 } 1249 1250 func isObject(s string) bool { 1251 f, err := os.Open(s) 1252 if err != nil { 1253 return false 1254 } 1255 defer f.Close() 1256 buf := make([]byte, 64) 1257 io.ReadFull(f, buf) 1258 for _, magic := range objectMagic { 1259 if bytes.HasPrefix(buf, magic) { 1260 return true 1261 } 1262 } 1263 return false 1264 } 1265 1266 // fmtcmd formats a command in the manner of fmt.Sprintf but also: 1267 // 1268 // If dir is non-empty and the script is not in dir right now, 1269 // fmtcmd inserts "cd dir\n" before the command. 1270 // 1271 // fmtcmd replaces the value of b.work with $WORK. 1272 // fmtcmd replaces the value of goroot with $GOROOT. 1273 // fmtcmd replaces the value of b.gobin with $GOBIN. 1274 // 1275 // fmtcmd replaces the name of the current directory with dot (.) 1276 // but only when it is at the beginning of a space-separated token. 1277 // 1278 func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string { 1279 cmd := fmt.Sprintf(format, args...) 1280 if dir != "" && dir != "/" { 1281 cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:] 1282 if b.scriptDir != dir { 1283 b.scriptDir = dir 1284 cmd = "cd " + dir + "\n" + cmd 1285 } 1286 } 1287 if b.work != "" { 1288 cmd = strings.Replace(cmd, b.work, "$WORK", -1) 1289 } 1290 return cmd 1291 } 1292 1293 // showcmd prints the given command to standard output 1294 // for the implementation of -n or -x. 1295 func (b *builder) showcmd(dir string, format string, args ...interface{}) { 1296 b.output.Lock() 1297 defer b.output.Unlock() 1298 b.print(b.fmtcmd(dir, format, args...) + "\n") 1299 } 1300 1301 // showOutput prints "# desc" followed by the given output. 1302 // The output is expected to contain references to 'dir', usually 1303 // the source directory for the package that has failed to build. 1304 // showOutput rewrites mentions of dir with a relative path to dir 1305 // when the relative path is shorter. This is usually more pleasant. 1306 // For example, if fmt doesn't compile and we are in src/html, 1307 // the output is 1308 // 1309 // $ go build 1310 // # fmt 1311 // ../fmt/print.go:1090: undefined: asdf 1312 // $ 1313 // 1314 // instead of 1315 // 1316 // $ go build 1317 // # fmt 1318 // /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf 1319 // $ 1320 // 1321 // showOutput also replaces references to the work directory with $WORK. 1322 // 1323 func (b *builder) showOutput(dir, desc, out string) { 1324 prefix := "# " + desc 1325 suffix := "\n" + out 1326 if reldir := shortPath(dir); reldir != dir { 1327 suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1) 1328 suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1) 1329 } 1330 suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1) 1331 1332 b.output.Lock() 1333 defer b.output.Unlock() 1334 b.print(prefix, suffix) 1335 } 1336 1337 // shortPath returns an absolute or relative name for path, whatever is shorter. 1338 func shortPath(path string) string { 1339 if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) { 1340 return rel 1341 } 1342 return path 1343 } 1344 1345 // relPaths returns a copy of paths with absolute paths 1346 // made relative to the current directory if they would be shorter. 1347 func relPaths(paths []string) []string { 1348 var out []string 1349 pwd, _ := os.Getwd() 1350 for _, p := range paths { 1351 rel, err := filepath.Rel(pwd, p) 1352 if err == nil && len(rel) < len(p) { 1353 p = rel 1354 } 1355 out = append(out, p) 1356 } 1357 return out 1358 } 1359 1360 // errPrintedOutput is a special error indicating that a command failed 1361 // but that it generated output as well, and that output has already 1362 // been printed, so there's no point showing 'exit status 1' or whatever 1363 // the wait status was. The main executor, builder.do, knows not to 1364 // print this error. 1365 var errPrintedOutput = errors.New("already printed output - no need to show error") 1366 1367 var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`) 1368 var cgoTypeSigRe = regexp.MustCompile(`\b_Ctype_\B`) 1369 1370 // run runs the command given by cmdline in the directory dir. 1371 // If the command fails, run prints information about the failure 1372 // and returns a non-nil error. 1373 func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error { 1374 out, err := b.runOut(dir, desc, env, cmdargs...) 1375 if len(out) > 0 { 1376 if desc == "" { 1377 desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " ")) 1378 } 1379 b.showOutput(dir, desc, b.processOutput(out)) 1380 if err != nil { 1381 err = errPrintedOutput 1382 } 1383 } 1384 return err 1385 } 1386 1387 // processOutput prepares the output of runOut to be output to the console. 1388 func (b *builder) processOutput(out []byte) string { 1389 if out[len(out)-1] != '\n' { 1390 out = append(out, '\n') 1391 } 1392 messages := string(out) 1393 // Fix up output referring to cgo-generated code to be more readable. 1394 // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19. 1395 // Replace *[100]_Ctype_foo with *[100]C.foo. 1396 // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite. 1397 if !buildX && cgoLine.MatchString(messages) { 1398 messages = cgoLine.ReplaceAllString(messages, "") 1399 messages = cgoTypeSigRe.ReplaceAllString(messages, "C.") 1400 } 1401 return messages 1402 } 1403 1404 // runOut runs the command given by cmdline in the directory dir. 1405 // It returns the command output and any errors that occurred. 1406 func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) { 1407 cmdline := stringList(cmdargs...) 1408 if buildN || buildX { 1409 var envcmdline string 1410 for i := range env { 1411 envcmdline += env[i] 1412 envcmdline += " " 1413 } 1414 envcmdline += joinUnambiguously(cmdline) 1415 b.showcmd(dir, "%s", envcmdline) 1416 if buildN { 1417 return nil, nil 1418 } 1419 } 1420 1421 nbusy := 0 1422 for { 1423 var buf bytes.Buffer 1424 cmd := exec.Command(cmdline[0], cmdline[1:]...) 1425 cmd.Stdout = &buf 1426 cmd.Stderr = &buf 1427 cmd.Dir = dir 1428 cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir)) 1429 err := cmd.Run() 1430 1431 // cmd.Run will fail on Unix if some other process has the binary 1432 // we want to run open for writing. This can happen here because 1433 // we build and install the cgo command and then run it. 1434 // If another command was kicked off while we were writing the 1435 // cgo binary, the child process for that command may be holding 1436 // a reference to the fd, keeping us from running exec. 1437 // 1438 // But, you might reasonably wonder, how can this happen? 1439 // The cgo fd, like all our fds, is close-on-exec, so that we need 1440 // not worry about other processes inheriting the fd accidentally. 1441 // The answer is that running a command is fork and exec. 1442 // A child forked while the cgo fd is open inherits that fd. 1443 // Until the child has called exec, it holds the fd open and the 1444 // kernel will not let us run cgo. Even if the child were to close 1445 // the fd explicitly, it would still be open from the time of the fork 1446 // until the time of the explicit close, and the race would remain. 1447 // 1448 // On Unix systems, this results in ETXTBSY, which formats 1449 // as "text file busy". Rather than hard-code specific error cases, 1450 // we just look for that string. If this happens, sleep a little 1451 // and try again. We let this happen three times, with increasing 1452 // sleep lengths: 100+200+400 ms = 0.7 seconds. 1453 // 1454 // An alternate solution might be to split the cmd.Run into 1455 // separate cmd.Start and cmd.Wait, and then use an RWLock 1456 // to make sure that copyFile only executes when no cmd.Start 1457 // call is in progress. However, cmd.Start (really syscall.forkExec) 1458 // only guarantees that when it returns, the exec is committed to 1459 // happen and succeed. It uses a close-on-exec file descriptor 1460 // itself to determine this, so we know that when cmd.Start returns, 1461 // at least one close-on-exec file descriptor has been closed. 1462 // However, we cannot be sure that all of them have been closed, 1463 // so the program might still encounter ETXTBSY even with such 1464 // an RWLock. The race window would be smaller, perhaps, but not 1465 // guaranteed to be gone. 1466 // 1467 // Sleeping when we observe the race seems to be the most reliable 1468 // option we have. 1469 // 1470 // http://golang.org/issue/3001 1471 // 1472 if err != nil && nbusy < 3 && strings.Contains(err.Error(), "text file busy") { 1473 time.Sleep(100 * time.Millisecond << uint(nbusy)) 1474 nbusy++ 1475 continue 1476 } 1477 1478 // err can be something like 'exit status 1'. 1479 // Add information about what program was running. 1480 // Note that if buf.Bytes() is non-empty, the caller usually 1481 // shows buf.Bytes() and does not print err at all, so the 1482 // prefix here does not make most output any more verbose. 1483 if err != nil { 1484 err = errors.New(cmdline[0] + ": " + err.Error()) 1485 } 1486 return buf.Bytes(), err 1487 } 1488 } 1489 1490 // joinUnambiguously prints the slice, quoting where necessary to make the 1491 // output unambiguous. 1492 // TODO: See issue 5279. The printing of commands needs a complete redo. 1493 func joinUnambiguously(a []string) string { 1494 var buf bytes.Buffer 1495 for i, s := range a { 1496 if i > 0 { 1497 buf.WriteByte(' ') 1498 } 1499 q := strconv.Quote(s) 1500 if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 { 1501 buf.WriteString(q) 1502 } else { 1503 buf.WriteString(s) 1504 } 1505 } 1506 return buf.String() 1507 } 1508 1509 // mkdir makes the named directory. 1510 func (b *builder) mkdir(dir string) error { 1511 b.exec.Lock() 1512 defer b.exec.Unlock() 1513 // We can be a little aggressive about being 1514 // sure directories exist. Skip repeated calls. 1515 if b.mkdirCache[dir] { 1516 return nil 1517 } 1518 b.mkdirCache[dir] = true 1519 1520 if buildN || buildX { 1521 b.showcmd("", "mkdir -p %s", dir) 1522 if buildN { 1523 return nil 1524 } 1525 } 1526 1527 if err := os.MkdirAll(dir, 0777); err != nil { 1528 return err 1529 } 1530 return nil 1531 } 1532 1533 // mkAbs returns an absolute path corresponding to 1534 // evaluating f in the directory dir. 1535 // We always pass absolute paths of source files so that 1536 // the error messages will include the full path to a file 1537 // in need of attention. 1538 func mkAbs(dir, f string) string { 1539 // Leave absolute paths alone. 1540 // Also, during -n mode we use the pseudo-directory $WORK 1541 // instead of creating an actual work directory that won't be used. 1542 // Leave paths beginning with $WORK alone too. 1543 if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") { 1544 return f 1545 } 1546 return filepath.Join(dir, f) 1547 } 1548 1549 type toolchain interface { 1550 // gc runs the compiler in a specific directory on a set of files 1551 // and returns the name of the generated output file. 1552 // The compiler runs in the directory dir. 1553 gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) 1554 // cc runs the toolchain's C compiler in a directory on a C file 1555 // to produce an output file. 1556 cc(b *builder, p *Package, objdir, ofile, cfile string) error 1557 // asm runs the assembler in a specific directory on a specific file 1558 // to generate the named output file. 1559 asm(b *builder, p *Package, obj, ofile, sfile string) error 1560 // pkgpath builds an appropriate path for a temporary package file. 1561 pkgpath(basedir string, p *Package) string 1562 // pack runs the archive packer in a specific directory to create 1563 // an archive from a set of object files. 1564 // typically it is run in the object directory. 1565 pack(b *builder, p *Package, objDir, afile string, ofiles []string) error 1566 // ld runs the linker to create a package starting at mainpkg. 1567 ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error 1568 1569 compiler() string 1570 linker() string 1571 } 1572 1573 type noToolchain struct{} 1574 1575 func noCompiler() error { 1576 log.Fatalf("unknown compiler %q", buildContext.Compiler) 1577 return nil 1578 } 1579 1580 func (noToolchain) compiler() string { 1581 noCompiler() 1582 return "" 1583 } 1584 1585 func (noToolchain) linker() string { 1586 noCompiler() 1587 return "" 1588 } 1589 1590 func (noToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) { 1591 return "", nil, noCompiler() 1592 } 1593 1594 func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 1595 return noCompiler() 1596 } 1597 1598 func (noToolchain) pkgpath(basedir string, p *Package) string { 1599 noCompiler() 1600 return "" 1601 } 1602 1603 func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 1604 return noCompiler() 1605 } 1606 1607 func (noToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { 1608 return noCompiler() 1609 } 1610 1611 func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 1612 return noCompiler() 1613 } 1614 1615 // The Go toolchain. 1616 type gcToolchain struct{} 1617 1618 func (gcToolchain) compiler() string { 1619 return tool(archChar + "g") 1620 } 1621 1622 func (gcToolchain) linker() string { 1623 return tool(archChar + "l") 1624 } 1625 1626 func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { 1627 if archive != "" { 1628 ofile = archive 1629 } else { 1630 out := "_go_." + archChar 1631 ofile = obj + out 1632 } 1633 1634 gcargs := []string{"-p", p.ImportPath} 1635 if p.Standard && p.ImportPath == "runtime" { 1636 // runtime compiles with a special 6g flag to emit 1637 // additional reflect type data. 1638 gcargs = append(gcargs, "-+") 1639 } 1640 1641 // If we're giving the compiler the entire package (no C etc files), tell it that, 1642 // so that it can give good error messages about forward declarations. 1643 // Exceptions: a few standard packages have forward declarations for 1644 // pieces supplied behind-the-scenes by package runtime. 1645 extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) 1646 if p.Standard { 1647 switch p.ImportPath { 1648 case "bytes", "net", "os", "runtime/pprof", "sync", "time": 1649 extFiles++ 1650 } 1651 } 1652 if extFiles == 0 { 1653 gcargs = append(gcargs, "-complete") 1654 } 1655 if buildContext.InstallSuffix != "" { 1656 gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix) 1657 } 1658 1659 args := stringList(tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs) 1660 if ofile == archive { 1661 args = append(args, "-pack") 1662 } 1663 for _, f := range gofiles { 1664 args = append(args, mkAbs(p.Dir, f)) 1665 } 1666 1667 output, err = b.runOut(p.Dir, p.ImportPath, nil, args) 1668 return ofile, output, err 1669 } 1670 1671 func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 1672 // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. 1673 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) 1674 sfile = mkAbs(p.Dir, sfile) 1675 return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) 1676 } 1677 1678 func (gcToolchain) pkgpath(basedir string, p *Package) string { 1679 end := filepath.FromSlash(p.ImportPath + ".a") 1680 return filepath.Join(basedir, end) 1681 } 1682 1683 func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 1684 var absOfiles []string 1685 for _, f := range ofiles { 1686 absOfiles = append(absOfiles, mkAbs(objDir, f)) 1687 } 1688 cmd := "c" 1689 absAfile := mkAbs(objDir, afile) 1690 appending := false 1691 if _, err := os.Stat(absAfile); err == nil { 1692 appending = true 1693 cmd = "r" 1694 } 1695 1696 cmdline := stringList("pack", cmd, absAfile, absOfiles) 1697 1698 if appending { 1699 if buildN || buildX { 1700 b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline)) 1701 } 1702 if buildN { 1703 return nil 1704 } 1705 if err := packInternal(b, absAfile, absOfiles); err != nil { 1706 b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n") 1707 return errPrintedOutput 1708 } 1709 return nil 1710 } 1711 1712 // Need actual pack. 1713 cmdline[0] = tool("pack") 1714 return b.run(p.Dir, p.ImportPath, nil, cmdline) 1715 } 1716 1717 func packInternal(b *builder, afile string, ofiles []string) error { 1718 dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0) 1719 if err != nil { 1720 return err 1721 } 1722 defer dst.Close() // only for error returns or panics 1723 w := bufio.NewWriter(dst) 1724 1725 for _, ofile := range ofiles { 1726 src, err := os.Open(ofile) 1727 if err != nil { 1728 return err 1729 } 1730 fi, err := src.Stat() 1731 if err != nil { 1732 src.Close() 1733 return err 1734 } 1735 // Note: Not using %-16.16s format because we care 1736 // about bytes, not runes. 1737 name := fi.Name() 1738 if len(name) > 16 { 1739 name = name[:16] 1740 } else { 1741 name += strings.Repeat(" ", 16-len(name)) 1742 } 1743 size := fi.Size() 1744 fmt.Fprintf(w, "%s%-12d%-6d%-6d%-8o%-10d`\n", 1745 name, 0, 0, 0, 0644, size) 1746 n, err := io.Copy(w, src) 1747 src.Close() 1748 if err == nil && n < size { 1749 err = io.ErrUnexpectedEOF 1750 } else if err == nil && n > size { 1751 err = fmt.Errorf("file larger than size reported by stat") 1752 } 1753 if err != nil { 1754 return fmt.Errorf("copying %s to %s: %v", ofile, afile, err) 1755 } 1756 if size&1 != 0 { 1757 w.WriteByte(0) 1758 } 1759 } 1760 1761 if err := w.Flush(); err != nil { 1762 return err 1763 } 1764 return dst.Close() 1765 } 1766 1767 func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { 1768 importArgs := b.includeArgs("-L", allactions) 1769 cxx := len(p.CXXFiles) > 0 1770 for _, a := range allactions { 1771 if a.p != nil && len(a.p.CXXFiles) > 0 { 1772 cxx = true 1773 } 1774 } 1775 ldflags := buildLdflags 1776 // Limit slice capacity so that concurrent appends do not race on the shared array. 1777 ldflags = ldflags[:len(ldflags):len(ldflags)] 1778 if buildContext.InstallSuffix != "" { 1779 ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix) 1780 } 1781 if p.omitDWARF { 1782 ldflags = append(ldflags, "-w") 1783 } 1784 1785 // If the user has not specified the -extld option, then specify the 1786 // appropriate linker. In case of C++ code, use the compiler named 1787 // by the CXX environment variable or defaultCXX if CXX is not set. 1788 // Else, use the CC environment variable and defaultCC as fallback. 1789 extld := false 1790 for _, f := range ldflags { 1791 if f == "-extld" || strings.HasPrefix(f, "-extld=") { 1792 extld = true 1793 break 1794 } 1795 } 1796 if !extld { 1797 var compiler []string 1798 if cxx { 1799 compiler = envList("CXX", defaultCXX) 1800 } else { 1801 compiler = envList("CC", defaultCC) 1802 } 1803 ldflags = append(ldflags, "-extld="+compiler[0]) 1804 if len(compiler) > 1 { 1805 extldflags := false 1806 add := strings.Join(compiler[1:], " ") 1807 for i, f := range ldflags { 1808 if f == "-extldflags" && i+1 < len(ldflags) { 1809 ldflags[i+1] = add + " " + ldflags[i+1] 1810 extldflags = true 1811 break 1812 } else if strings.HasPrefix(f, "-extldflags=") { 1813 ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] 1814 extldflags = true 1815 break 1816 } 1817 } 1818 if !extldflags { 1819 ldflags = append(ldflags, "-extldflags="+add) 1820 } 1821 } 1822 } 1823 return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg) 1824 } 1825 1826 func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 1827 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) 1828 cfile = mkAbs(p.Dir, cfile) 1829 warn := []string{"-w"} 1830 if p.usesSwig() { 1831 // When using SWIG, this compiler is only used to 1832 // compile the C files generated by SWIG. 1833 // We don't want warnings. 1834 // See issue 9065 for details. 1835 warn = nil 1836 } 1837 args := stringList(tool(archChar+"c"), "-F", "-V", warn, "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) 1838 return b.run(p.Dir, p.ImportPath, nil, args) 1839 } 1840 1841 // The Gccgo toolchain. 1842 type gccgoToolchain struct{} 1843 1844 var gccgoName, gccgoBin string 1845 1846 func init() { 1847 gccgoName = os.Getenv("GCCGO") 1848 if gccgoName == "" { 1849 gccgoName = "gccgo" 1850 } 1851 gccgoBin, _ = exec.LookPath(gccgoName) 1852 } 1853 1854 func (gccgoToolchain) compiler() string { 1855 return gccgoBin 1856 } 1857 1858 func (gccgoToolchain) linker() string { 1859 return gccgoBin 1860 } 1861 1862 func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { 1863 out := "_go_.o" 1864 ofile = obj + out 1865 gcargs := []string{"-g"} 1866 gcargs = append(gcargs, b.gccArchArgs()...) 1867 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 1868 gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) 1869 } 1870 if p.localPrefix != "" { 1871 gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix) 1872 } 1873 args := stringList(gccgoName, importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) 1874 for _, f := range gofiles { 1875 args = append(args, mkAbs(p.Dir, f)) 1876 } 1877 1878 output, err = b.runOut(p.Dir, p.ImportPath, nil, args) 1879 return ofile, output, err 1880 } 1881 1882 func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 1883 sfile = mkAbs(p.Dir, sfile) 1884 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} 1885 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 1886 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 1887 } 1888 defs = append(defs, b.gccArchArgs()...) 1889 return b.run(p.Dir, p.ImportPath, nil, gccgoName, "-I", obj, "-o", ofile, defs, sfile) 1890 } 1891 1892 func (gccgoToolchain) pkgpath(basedir string, p *Package) string { 1893 end := filepath.FromSlash(p.ImportPath + ".a") 1894 afile := filepath.Join(basedir, end) 1895 // add "lib" to the final element 1896 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) 1897 } 1898 1899 func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 1900 var absOfiles []string 1901 for _, f := range ofiles { 1902 absOfiles = append(absOfiles, mkAbs(objDir, f)) 1903 } 1904 return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles) 1905 } 1906 1907 func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { 1908 // gccgo needs explicit linking with all package dependencies, 1909 // and all LDFLAGS from cgo dependencies. 1910 apackagesSeen := make(map[*Package]bool) 1911 afiles := []string{} 1912 ldflags := b.gccArchArgs() 1913 cgoldflags := []string{} 1914 usesCgo := false 1915 cxx := len(p.CXXFiles) > 0 1916 objc := len(p.MFiles) > 0 1917 1918 // Prefer the output of an install action to the output of a build action, 1919 // because the install action will delete the output of the build action. 1920 // Iterate over the list backward (reverse dependency order) so that we 1921 // always see the install before the build. 1922 for i := len(allactions) - 1; i >= 0; i-- { 1923 a := allactions[i] 1924 if !a.p.Standard { 1925 if a.p != nil && !apackagesSeen[a.p] { 1926 apackagesSeen[a.p] = true 1927 if a.p.fake { 1928 // move _test files to the top of the link order 1929 afiles = append([]string{a.target}, afiles...) 1930 } else { 1931 afiles = append(afiles, a.target) 1932 } 1933 } 1934 } 1935 } 1936 1937 for _, a := range allactions { 1938 if a.p != nil { 1939 cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...) 1940 if len(a.p.CgoFiles) > 0 { 1941 usesCgo = true 1942 } 1943 if a.p.usesSwig() { 1944 usesCgo = true 1945 } 1946 if len(a.p.CXXFiles) > 0 { 1947 cxx = true 1948 } 1949 if len(a.p.MFiles) > 0 { 1950 objc = true 1951 } 1952 } 1953 } 1954 ldflags = append(ldflags, afiles...) 1955 ldflags = append(ldflags, cgoldflags...) 1956 ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...) 1957 ldflags = append(ldflags, p.CgoLDFLAGS...) 1958 if usesCgo && goos == "linux" { 1959 ldflags = append(ldflags, "-Wl,-E") 1960 } 1961 if cxx { 1962 ldflags = append(ldflags, "-lstdc++") 1963 } 1964 if objc { 1965 ldflags = append(ldflags, "-lobjc") 1966 } 1967 return b.run(".", p.ImportPath, nil, gccgoName, "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) 1968 } 1969 1970 func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 1971 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) 1972 cfile = mkAbs(p.Dir, cfile) 1973 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} 1974 defs = append(defs, b.gccArchArgs()...) 1975 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 1976 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 1977 } 1978 return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g", 1979 "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) 1980 } 1981 1982 func gccgoPkgpath(p *Package) string { 1983 if p.build.IsCommand() && !p.forceLibrary { 1984 return "" 1985 } 1986 return p.ImportPath 1987 } 1988 1989 func gccgoCleanPkgpath(p *Package) string { 1990 clean := func(r rune) rune { 1991 switch { 1992 case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', 1993 '0' <= r && r <= '9': 1994 return r 1995 } 1996 return '_' 1997 } 1998 return strings.Map(clean, gccgoPkgpath(p)) 1999 } 2000 2001 // libgcc returns the filename for libgcc, as determined by invoking gcc with 2002 // the -print-libgcc-file-name option. 2003 func (b *builder) libgcc(p *Package) (string, error) { 2004 var buf bytes.Buffer 2005 2006 gccCmd := b.gccCmd(p.Dir) 2007 2008 prev := b.print 2009 if buildN { 2010 // In -n mode we temporarily swap out the builder's 2011 // print function to capture the command-line. This 2012 // let's us assign it to $LIBGCC and produce a valid 2013 // buildscript for cgo packages. 2014 b.print = func(a ...interface{}) (int, error) { 2015 return fmt.Fprint(&buf, a...) 2016 } 2017 } 2018 f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name") 2019 if err != nil { 2020 return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f) 2021 } 2022 if buildN { 2023 s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1)) 2024 b.print = prev 2025 b.print(s) 2026 return "$LIBGCC", nil 2027 } 2028 2029 // The compiler might not be able to find libgcc, and in that case, 2030 // it will simply return "libgcc.a", which is of no use to us. 2031 if !filepath.IsAbs(string(f)) { 2032 return "", nil 2033 } 2034 2035 return strings.Trim(string(f), "\r\n"), nil 2036 } 2037 2038 // gcc runs the gcc C compiler to create an object from a single C file. 2039 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error { 2040 return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir)) 2041 } 2042 2043 // gxx runs the g++ C++ compiler to create an object from a single C++ file. 2044 func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error { 2045 return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir)) 2046 } 2047 2048 // ccompile runs the given C or C++ compiler and creates an object from a single source file. 2049 func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error { 2050 file = mkAbs(p.Dir, file) 2051 return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file) 2052 } 2053 2054 // gccld runs the gcc linker to create an executable from a set of object files. 2055 func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error { 2056 var cmd []string 2057 if len(p.CXXFiles) > 0 { 2058 cmd = b.gxxCmd(p.Dir) 2059 } else { 2060 cmd = b.gccCmd(p.Dir) 2061 } 2062 return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags) 2063 } 2064 2065 // gccCmd returns a gcc command line prefix 2066 // defaultCC is defined in zdefaultcc.go, written by cmd/dist. 2067 func (b *builder) gccCmd(objdir string) []string { 2068 return b.ccompilerCmd("CC", defaultCC, objdir) 2069 } 2070 2071 // gxxCmd returns a g++ command line prefix 2072 // defaultCXX is defined in zdefaultcc.go, written by cmd/dist. 2073 func (b *builder) gxxCmd(objdir string) []string { 2074 return b.ccompilerCmd("CXX", defaultCXX, objdir) 2075 } 2076 2077 // ccompilerCmd returns a command line prefix for the given environment 2078 // variable and using the default command when the variable is empty. 2079 func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string { 2080 // NOTE: env.go's mkEnv knows that the first three 2081 // strings returned are "gcc", "-I", objdir (and cuts them off). 2082 2083 compiler := envList(envvar, defcmd) 2084 a := []string{compiler[0], "-I", objdir} 2085 a = append(a, compiler[1:]...) 2086 2087 // Definitely want -fPIC but on Windows gcc complains 2088 // "-fPIC ignored for target (all code is position independent)" 2089 if goos != "windows" { 2090 a = append(a, "-fPIC") 2091 } 2092 a = append(a, b.gccArchArgs()...) 2093 // gcc-4.5 and beyond require explicit "-pthread" flag 2094 // for multithreading with pthread library. 2095 if buildContext.CgoEnabled { 2096 switch goos { 2097 case "windows": 2098 a = append(a, "-mthreads") 2099 default: 2100 a = append(a, "-pthread") 2101 } 2102 } 2103 2104 if strings.Contains(a[0], "clang") { 2105 // disable ASCII art in clang errors, if possible 2106 a = append(a, "-fno-caret-diagnostics") 2107 // clang is too smart about command-line arguments 2108 a = append(a, "-Qunused-arguments") 2109 } 2110 2111 // disable word wrapping in error messages 2112 a = append(a, "-fmessage-length=0") 2113 2114 // On OS X, some of the compilers behave as if -fno-common 2115 // is always set, and the Mach-O linker in 6l/8l assumes this. 2116 // See http://golang.org/issue/3253. 2117 if goos == "darwin" { 2118 a = append(a, "-fno-common") 2119 } 2120 2121 return a 2122 } 2123 2124 // gccNoPie returns the flag to use to request non-PIE. On systems 2125 // with PIE (position independent executables) enabled by default, 2126 // -no-pie must be passed when doing a partial link with -Wl,-r. 2127 // But -no-pie is not supported by all compilers, and clang spells it -nopie. 2128 func (b *builder) gccNoPie() string { 2129 if goos != "linux" { 2130 // On some BSD platforms, error messages from the 2131 // compiler make it to the console despite cmd.Std* 2132 // all being nil. As -no-pie is only required on linux 2133 // systems so far, we only test there. 2134 return "" 2135 } 2136 src := filepath.Join(b.work, "trivial.c") 2137 if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil { 2138 return "" 2139 } 2140 for _, nopie := range []string{"-no-pie", "-nopie"} { 2141 cmdArgs := b.gccCmd(b.work) 2142 cmdArgs = append(cmdArgs, nopie, "-c", "trivial.c") 2143 if buildN || buildX { 2144 b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs)) 2145 if buildN { 2146 return "" 2147 } 2148 } 2149 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 2150 cmd.Dir = b.work 2151 cmd.Env = envForDir(cmd.Dir) 2152 err := cmd.Run() 2153 if err == nil { 2154 return nopie 2155 } 2156 } 2157 return "" 2158 } 2159 2160 // gccArchArgs returns arguments to pass to gcc based on the architecture. 2161 func (b *builder) gccArchArgs() []string { 2162 switch archChar { 2163 case "8": 2164 return []string{"-m32"} 2165 case "6": 2166 return []string{"-m64"} 2167 case "5": 2168 return []string{"-marm"} // not thumb 2169 } 2170 return nil 2171 } 2172 2173 // envList returns the value of the given environment variable broken 2174 // into fields, using the default value when the variable is empty. 2175 func envList(key, def string) []string { 2176 v := os.Getenv(key) 2177 if v == "" { 2178 v = def 2179 } 2180 return strings.Fields(v) 2181 } 2182 2183 // Return the flags to use when invoking the C or C++ compilers, or cgo. 2184 func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) { 2185 var defaults string 2186 if def { 2187 defaults = "-g -O2" 2188 } 2189 2190 cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) 2191 cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) 2192 cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) 2193 ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) 2194 return 2195 } 2196 2197 var cgoRe = regexp.MustCompile(`[/\\:]`) 2198 2199 var ( 2200 cgoLibGccFile string 2201 cgoLibGccErr error 2202 cgoLibGccFileOnce sync.Once 2203 ) 2204 2205 func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { 2206 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true) 2207 _, cgoexeCFLAGS, _, _ := b.cflags(p, false) 2208 cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) 2209 cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) 2210 // If we are compiling Objective-C code, then we need to link against libobjc 2211 if len(mfiles) > 0 { 2212 cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") 2213 } 2214 2215 // Allows including _cgo_export.h from .[ch] files in the package. 2216 cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj) 2217 2218 // cgo 2219 // TODO: CGOPKGPATH, CGO_FLAGS? 2220 gofiles := []string{obj + "_cgo_gotypes.go"} 2221 cfiles := []string{"_cgo_main.c", "_cgo_export.c"} 2222 for _, fn := range p.CgoFiles { 2223 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") 2224 gofiles = append(gofiles, obj+f+"cgo1.go") 2225 cfiles = append(cfiles, f+"cgo2.c") 2226 } 2227 defunC := obj + "_cgo_defun.c" 2228 2229 cgoflags := []string{} 2230 // TODO: make cgo not depend on $GOARCH? 2231 2232 objExt := archChar 2233 2234 if p.Standard && p.ImportPath == "runtime/cgo" { 2235 cgoflags = append(cgoflags, "-import_runtime_cgo=false") 2236 } 2237 if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") { 2238 cgoflags = append(cgoflags, "-import_syscall=false") 2239 } 2240 2241 // Update $CGO_LDFLAGS with p.CgoLDFLAGS. 2242 var cgoenv []string 2243 if len(cgoLDFLAGS) > 0 { 2244 flags := make([]string, len(cgoLDFLAGS)) 2245 for i, f := range cgoLDFLAGS { 2246 flags[i] = strconv.Quote(f) 2247 } 2248 cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} 2249 } 2250 2251 if _, ok := buildToolchain.(gccgoToolchain); ok { 2252 cgoflags = append(cgoflags, "-gccgo") 2253 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 2254 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) 2255 } 2256 objExt = "o" 2257 } 2258 if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil { 2259 return nil, nil, err 2260 } 2261 outGo = append(outGo, gofiles...) 2262 2263 // cc _cgo_defun.c 2264 defunObj := obj + "_cgo_defun." + objExt 2265 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { 2266 return nil, nil, err 2267 } 2268 outObj = append(outObj, defunObj) 2269 2270 // gcc 2271 var linkobj []string 2272 2273 var bareLDFLAGS []string 2274 // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X 2275 for i := 0; i < len(cgoLDFLAGS); i++ { 2276 f := cgoLDFLAGS[i] 2277 switch { 2278 // skip "-lc" or "-l somelib" 2279 case strings.HasPrefix(f, "-l"): 2280 if f == "-l" { 2281 i++ 2282 } 2283 // skip "-framework X" on Darwin 2284 case goos == "darwin" && f == "-framework": 2285 i++ 2286 // skip "*.{dylib,so,dll}" 2287 case strings.HasSuffix(f, ".dylib"), 2288 strings.HasSuffix(f, ".so"), 2289 strings.HasSuffix(f, ".dll"): 2290 continue 2291 // Remove any -fsanitize=foo flags. 2292 // Otherwise the compiler driver thinks that we are doing final link 2293 // and links sanitizer runtime into the object file. But we are not doing 2294 // the final link, we will link the resulting object file again. And 2295 // so the program ends up with two copies of sanitizer runtime. 2296 // See issue 8788 for details. 2297 case strings.HasPrefix(f, "-fsanitize="): 2298 continue 2299 default: 2300 bareLDFLAGS = append(bareLDFLAGS, f) 2301 } 2302 } 2303 2304 cgoLibGccFileOnce.Do(func() { 2305 cgoLibGccFile, cgoLibGccErr = b.libgcc(p) 2306 }) 2307 if cgoLibGccFile == "" && cgoLibGccErr != nil { 2308 return nil, nil, err 2309 } 2310 2311 var staticLibs []string 2312 if goos == "windows" { 2313 // libmingw32 and libmingwex might also use libgcc, so libgcc must come last, 2314 // and they also have some inter-dependencies, so must use linker groups. 2315 staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"} 2316 } 2317 if cgoLibGccFile != "" { 2318 staticLibs = append(staticLibs, cgoLibGccFile) 2319 } 2320 2321 cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) 2322 for _, cfile := range cfiles { 2323 ofile := obj + cfile[:len(cfile)-1] + "o" 2324 if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil { 2325 return nil, nil, err 2326 } 2327 linkobj = append(linkobj, ofile) 2328 if !strings.HasSuffix(ofile, "_cgo_main.o") { 2329 outObj = append(outObj, ofile) 2330 } 2331 } 2332 2333 for _, file := range gccfiles { 2334 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" 2335 if err := b.gcc(p, ofile, cflags, file); err != nil { 2336 return nil, nil, err 2337 } 2338 linkobj = append(linkobj, ofile) 2339 outObj = append(outObj, ofile) 2340 } 2341 2342 cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) 2343 for _, file := range gxxfiles { 2344 // Append .o to the file, just in case the pkg has file.c and file.cpp 2345 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2346 if err := b.gxx(p, ofile, cxxflags, file); err != nil { 2347 return nil, nil, err 2348 } 2349 linkobj = append(linkobj, ofile) 2350 outObj = append(outObj, ofile) 2351 } 2352 2353 for _, file := range mfiles { 2354 // Append .o to the file, just in case the pkg has file.c and file.m 2355 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2356 if err := b.gcc(p, ofile, cflags, file); err != nil { 2357 return nil, nil, err 2358 } 2359 linkobj = append(linkobj, ofile) 2360 outObj = append(outObj, ofile) 2361 } 2362 2363 linkobj = append(linkobj, p.SysoFiles...) 2364 dynobj := obj + "_cgo_.o" 2365 pie := goarch == "arm" && (goos == "linux" || goos == "android") 2366 if pie { // we need to use -pie for Linux/ARM to get accurate imported sym 2367 cgoLDFLAGS = append(cgoLDFLAGS, "-pie") 2368 } 2369 if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil { 2370 return nil, nil, err 2371 } 2372 if pie { // but we don't need -pie for normal cgo programs 2373 cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1] 2374 } 2375 2376 if _, ok := buildToolchain.(gccgoToolchain); ok { 2377 // we don't use dynimport when using gccgo. 2378 return outGo, outObj, nil 2379 } 2380 2381 // cgo -dynimport 2382 importC := obj + "_cgo_import.c" 2383 cgoflags = []string{} 2384 if p.Standard && p.ImportPath == "runtime/cgo" { 2385 cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker 2386 } 2387 if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil { 2388 return nil, nil, err 2389 } 2390 2391 // cc _cgo_import.ARCH 2392 importObj := obj + "_cgo_import." + objExt 2393 if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil { 2394 return nil, nil, err 2395 } 2396 2397 ofile := obj + "_all.o" 2398 var gccObjs, nonGccObjs []string 2399 for _, f := range outObj { 2400 if strings.HasSuffix(f, ".o") { 2401 gccObjs = append(gccObjs, f) 2402 } else { 2403 nonGccObjs = append(nonGccObjs, f) 2404 } 2405 } 2406 ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs) 2407 2408 if flag := b.gccNoPie(); flag != "" { 2409 ldflags = append(ldflags, flag) 2410 } 2411 2412 // Some systems, such as Ubuntu, always add --build-id to 2413 // every link, but we don't want a build ID since we are 2414 // producing an object file. On some of those system a plain 2415 // -r (not -Wl,-r) will turn off --build-id, but clang 3.0 2416 // doesn't support a plain -r. I don't know how to turn off 2417 // --build-id when using clang other than passing a trailing 2418 // --build-id=none. So that is what we do, but only on 2419 // systems likely to support it, which is to say, systems that 2420 // normally use gold or the GNU linker. 2421 switch goos { 2422 case "android", "dragonfly", "linux", "netbsd": 2423 ldflags = append(ldflags, "-Wl,--build-id=none") 2424 } 2425 2426 if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil { 2427 return nil, nil, err 2428 } 2429 2430 // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows 2431 // must be processed before the gcc-generated objects. 2432 // Put it first. http://golang.org/issue/2601 2433 outObj = stringList(importObj, nonGccObjs, ofile) 2434 2435 return outGo, outObj, nil 2436 } 2437 2438 // Run SWIG on all SWIG input files. 2439 // TODO: Don't build a shared library, once SWIG emits the necessary 2440 // pragmas for external linking. 2441 func (b *builder) swig(p *Package, obj string, pcCFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { 2442 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) 2443 cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) 2444 cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) 2445 2446 for _, file := range gccfiles { 2447 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" 2448 if err := b.gcc(p, ofile, cflags, file); err != nil { 2449 return nil, nil, err 2450 } 2451 outObj = append(outObj, ofile) 2452 } 2453 2454 for _, file := range gxxfiles { 2455 // Append .o to the file, just in case the pkg has file.c and file.cpp 2456 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2457 if err := b.gxx(p, ofile, cxxflags, file); err != nil { 2458 return nil, nil, err 2459 } 2460 outObj = append(outObj, ofile) 2461 } 2462 2463 for _, file := range mfiles { 2464 // Append .o to the file, just in case the pkg has file.c and file.cpp 2465 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2466 if err := b.gcc(p, ofile, cflags, file); err != nil { 2467 return nil, nil, err 2468 } 2469 outObj = append(outObj, ofile) 2470 } 2471 2472 if err := b.swigVersionCheck(); err != nil { 2473 return nil, nil, err 2474 } 2475 2476 intgosize, err := b.swigIntSize(obj) 2477 if err != nil { 2478 return nil, nil, err 2479 } 2480 2481 for _, f := range p.SwigFiles { 2482 goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize) 2483 if err != nil { 2484 return nil, nil, err 2485 } 2486 if goFile != "" { 2487 outGo = append(outGo, goFile) 2488 } 2489 if objFile != "" { 2490 outObj = append(outObj, objFile) 2491 } 2492 if gccObjFile != "" { 2493 outObj = append(outObj, gccObjFile) 2494 } 2495 } 2496 for _, f := range p.SwigCXXFiles { 2497 goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize) 2498 if err != nil { 2499 return nil, nil, err 2500 } 2501 if goFile != "" { 2502 outGo = append(outGo, goFile) 2503 } 2504 if objFile != "" { 2505 outObj = append(outObj, objFile) 2506 } 2507 if gccObjFile != "" { 2508 outObj = append(outObj, gccObjFile) 2509 } 2510 } 2511 return outGo, outObj, nil 2512 } 2513 2514 // Make sure SWIG is new enough. 2515 var ( 2516 swigCheckOnce sync.Once 2517 swigCheck error 2518 ) 2519 2520 func (b *builder) swigDoVersionCheck() error { 2521 out, err := b.runOut("", "", nil, "swig", "-version") 2522 if err != nil { 2523 return err 2524 } 2525 re := regexp.MustCompile(`[vV]ersion +([\d])`) 2526 matches := re.FindSubmatch(out) 2527 if matches == nil { 2528 // Can't find version number; hope for the best. 2529 return nil 2530 } 2531 major, err := strconv.Atoi(string(matches[1])) 2532 if err != nil { 2533 // Can't find version number; hope for the best. 2534 return nil 2535 } 2536 if major < 3 { 2537 return errors.New("must have SWIG version >= 3.0") 2538 } 2539 return nil 2540 } 2541 2542 func (b *builder) swigVersionCheck() error { 2543 swigCheckOnce.Do(func() { 2544 swigCheck = b.swigDoVersionCheck() 2545 }) 2546 return swigCheck 2547 } 2548 2549 // This code fails to build if sizeof(int) <= 32 2550 const swigIntSizeCode = ` 2551 package main 2552 const i int = 1 << 32 2553 ` 2554 2555 // Determine the size of int on the target system for the -intgosize option 2556 // of swig >= 2.0.9 2557 func (b *builder) swigIntSize(obj string) (intsize string, err error) { 2558 if buildN { 2559 return "$INTBITS", nil 2560 } 2561 src := filepath.Join(b.work, "swig_intsize.go") 2562 if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil { 2563 return 2564 } 2565 srcs := []string{src} 2566 2567 p := goFilesPackage(srcs) 2568 2569 if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil { 2570 return "32", nil 2571 } 2572 return "64", nil 2573 } 2574 2575 // Run SWIG on one SWIG input file. 2576 func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) { 2577 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) 2578 var cflags []string 2579 if cxx { 2580 cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) 2581 } else { 2582 cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) 2583 } 2584 2585 n := 5 // length of ".swig" 2586 if cxx { 2587 n = 8 // length of ".swigcxx" 2588 } 2589 base := file[:len(file)-n] 2590 goFile := base + ".go" 2591 cBase := base + "_gc." 2592 gccBase := base + "_wrap." 2593 gccExt := "c" 2594 if cxx { 2595 gccExt = "cxx" 2596 } 2597 2598 _, gccgo := buildToolchain.(gccgoToolchain) 2599 2600 // swig 2601 args := []string{ 2602 "-go", 2603 "-intgosize", intgosize, 2604 "-module", base, 2605 "-o", obj + gccBase + gccExt, 2606 "-outdir", obj, 2607 } 2608 2609 for _, f := range cflags { 2610 if len(f) > 3 && f[:2] == "-I" { 2611 args = append(args, f) 2612 } 2613 } 2614 2615 if gccgo { 2616 args = append(args, "-gccgo") 2617 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 2618 args = append(args, "-go-pkgpath", pkgpath) 2619 } 2620 } 2621 if cxx { 2622 args = append(args, "-c++") 2623 } 2624 2625 if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil { 2626 if len(out) > 0 { 2627 if bytes.Contains(out, []byte("Unrecognized option -intgosize")) { 2628 return "", "", "", errors.New("must have SWIG version >= 3.0") 2629 } 2630 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) 2631 return "", "", "", errPrintedOutput 2632 } 2633 return "", "", "", err 2634 } 2635 2636 var cObj string 2637 if !gccgo { 2638 // cc 2639 cObj = obj + cBase + archChar 2640 if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil { 2641 return "", "", "", err 2642 } 2643 } 2644 2645 // gcc 2646 gccObj := obj + gccBase + "o" 2647 if !cxx { 2648 if err := b.gcc(p, gccObj, cflags, obj+gccBase+gccExt); err != nil { 2649 return "", "", "", err 2650 } 2651 } else { 2652 if err := b.gxx(p, gccObj, cflags, obj+gccBase+gccExt); err != nil { 2653 return "", "", "", err 2654 } 2655 } 2656 2657 return obj + goFile, cObj, gccObj, nil 2658 } 2659 2660 // An actionQueue is a priority queue of actions. 2661 type actionQueue []*action 2662 2663 // Implement heap.Interface 2664 func (q *actionQueue) Len() int { return len(*q) } 2665 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 2666 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } 2667 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) } 2668 func (q *actionQueue) Pop() interface{} { 2669 n := len(*q) - 1 2670 x := (*q)[n] 2671 *q = (*q)[:n] 2672 return x 2673 } 2674 2675 func (q *actionQueue) push(a *action) { 2676 heap.Push(q, a) 2677 } 2678 2679 func (q *actionQueue) pop() *action { 2680 return heap.Pop(q).(*action) 2681 } 2682 2683 func raceInit() { 2684 if !buildRace { 2685 return 2686 } 2687 if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" { 2688 fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) 2689 os.Exit(2) 2690 } 2691 buildGcflags = append(buildGcflags, "-race") 2692 buildLdflags = append(buildLdflags, "-race") 2693 buildCcflags = append(buildCcflags, "-D", "RACE") 2694 if buildContext.InstallSuffix != "" { 2695 buildContext.InstallSuffix += "_" 2696 } 2697 buildContext.InstallSuffix += "race" 2698 buildContext.BuildTags = append(buildContext.BuildTags, "race") 2699 } 2700 2701 // defaultSuffix returns file extension used for command files in 2702 // current os environment. 2703 func defaultSuffix() string { 2704 switch runtime.GOOS { 2705 case "windows": 2706 return ".bat" 2707 case "plan9": 2708 return ".rc" 2709 default: 2710 return ".bash" 2711 } 2712 }