github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/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 if goos == "haiku" { 2122 a = append(a, "-Wl, -Bsymbolic") 2123 } 2124 2125 return a 2126 } 2127 2128 // gccNoPie returns the flag to use to request non-PIE. On systems 2129 // with PIE (position independent executables) enabled by default, 2130 // -no-pie must be passed when doing a partial link with -Wl,-r. 2131 // But -no-pie is not supported by all compilers, and clang spells it -nopie. 2132 func (b *builder) gccNoPie() string { 2133 if goos != "linux" { 2134 // On some BSD platforms, error messages from the 2135 // compiler make it to the console despite cmd.Std* 2136 // all being nil. As -no-pie is only required on linux 2137 // systems so far, we only test there. 2138 return "" 2139 } 2140 src := filepath.Join(b.work, "trivial.c") 2141 if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil { 2142 return "" 2143 } 2144 for _, nopie := range []string{"-no-pie", "-nopie"} { 2145 cmdArgs := b.gccCmd(b.work) 2146 cmdArgs = append(cmdArgs, nopie, "-c", "trivial.c") 2147 if buildN || buildX { 2148 b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs)) 2149 if buildN { 2150 return "" 2151 } 2152 } 2153 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 2154 cmd.Dir = b.work 2155 cmd.Env = envForDir(cmd.Dir) 2156 err := cmd.Run() 2157 if err == nil { 2158 return nopie 2159 } 2160 } 2161 return "" 2162 } 2163 2164 // gccArchArgs returns arguments to pass to gcc based on the architecture. 2165 func (b *builder) gccArchArgs() []string { 2166 switch archChar { 2167 case "8": 2168 return []string{"-m32"} 2169 case "6": 2170 return []string{"-m64"} 2171 case "5": 2172 return []string{"-marm"} // not thumb 2173 } 2174 return nil 2175 } 2176 2177 // envList returns the value of the given environment variable broken 2178 // into fields, using the default value when the variable is empty. 2179 func envList(key, def string) []string { 2180 v := os.Getenv(key) 2181 if v == "" { 2182 v = def 2183 } 2184 return strings.Fields(v) 2185 } 2186 2187 // Return the flags to use when invoking the C or C++ compilers, or cgo. 2188 func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) { 2189 var defaults string 2190 if def { 2191 defaults = "-g -O2" 2192 } 2193 2194 cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) 2195 cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) 2196 cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) 2197 ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) 2198 return 2199 } 2200 2201 var cgoRe = regexp.MustCompile(`[/\\:]`) 2202 2203 var ( 2204 cgoLibGccFile string 2205 cgoLibGccErr error 2206 cgoLibGccFileOnce sync.Once 2207 ) 2208 2209 func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { 2210 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true) 2211 _, cgoexeCFLAGS, _, _ := b.cflags(p, false) 2212 cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) 2213 cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) 2214 // If we are compiling Objective-C code, then we need to link against libobjc 2215 if len(mfiles) > 0 { 2216 cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") 2217 } 2218 2219 // Allows including _cgo_export.h from .[ch] files in the package. 2220 cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj) 2221 2222 // cgo 2223 // TODO: CGOPKGPATH, CGO_FLAGS? 2224 gofiles := []string{obj + "_cgo_gotypes.go"} 2225 cfiles := []string{"_cgo_main.c", "_cgo_export.c"} 2226 for _, fn := range p.CgoFiles { 2227 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") 2228 gofiles = append(gofiles, obj+f+"cgo1.go") 2229 cfiles = append(cfiles, f+"cgo2.c") 2230 } 2231 defunC := obj + "_cgo_defun.c" 2232 2233 cgoflags := []string{} 2234 // TODO: make cgo not depend on $GOARCH? 2235 2236 objExt := archChar 2237 2238 if p.Standard && p.ImportPath == "runtime/cgo" { 2239 cgoflags = append(cgoflags, "-import_runtime_cgo=false") 2240 } 2241 if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") { 2242 cgoflags = append(cgoflags, "-import_syscall=false") 2243 } 2244 2245 // Update $CGO_LDFLAGS with p.CgoLDFLAGS. 2246 var cgoenv []string 2247 if len(cgoLDFLAGS) > 0 { 2248 flags := make([]string, len(cgoLDFLAGS)) 2249 for i, f := range cgoLDFLAGS { 2250 flags[i] = strconv.Quote(f) 2251 } 2252 cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} 2253 } 2254 2255 if _, ok := buildToolchain.(gccgoToolchain); ok { 2256 cgoflags = append(cgoflags, "-gccgo") 2257 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 2258 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) 2259 } 2260 objExt = "o" 2261 } 2262 if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil { 2263 return nil, nil, err 2264 } 2265 outGo = append(outGo, gofiles...) 2266 2267 // cc _cgo_defun.c 2268 defunObj := obj + "_cgo_defun." + objExt 2269 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { 2270 return nil, nil, err 2271 } 2272 outObj = append(outObj, defunObj) 2273 2274 // gcc 2275 var linkobj []string 2276 2277 var bareLDFLAGS []string 2278 // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X 2279 for i := 0; i < len(cgoLDFLAGS); i++ { 2280 f := cgoLDFLAGS[i] 2281 switch { 2282 // skip "-lc" or "-l somelib" 2283 case strings.HasPrefix(f, "-l"): 2284 if f == "-l" { 2285 i++ 2286 } 2287 // skip "-framework X" on Darwin 2288 case goos == "darwin" && f == "-framework": 2289 i++ 2290 // skip "*.{dylib,so,dll}" 2291 case strings.HasSuffix(f, ".dylib"), 2292 strings.HasSuffix(f, ".so"), 2293 strings.HasSuffix(f, ".dll"): 2294 continue 2295 // Remove any -fsanitize=foo flags. 2296 // Otherwise the compiler driver thinks that we are doing final link 2297 // and links sanitizer runtime into the object file. But we are not doing 2298 // the final link, we will link the resulting object file again. And 2299 // so the program ends up with two copies of sanitizer runtime. 2300 // See issue 8788 for details. 2301 case strings.HasPrefix(f, "-fsanitize="): 2302 continue 2303 default: 2304 bareLDFLAGS = append(bareLDFLAGS, f) 2305 } 2306 } 2307 2308 cgoLibGccFileOnce.Do(func() { 2309 cgoLibGccFile, cgoLibGccErr = b.libgcc(p) 2310 }) 2311 if cgoLibGccFile == "" && cgoLibGccErr != nil { 2312 return nil, nil, err 2313 } 2314 2315 var staticLibs []string 2316 if goos == "windows" { 2317 // libmingw32 and libmingwex might also use libgcc, so libgcc must come last, 2318 // and they also have some inter-dependencies, so must use linker groups. 2319 staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"} 2320 } 2321 if cgoLibGccFile != "" { 2322 staticLibs = append(staticLibs, cgoLibGccFile) 2323 } 2324 2325 cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) 2326 for _, cfile := range cfiles { 2327 ofile := obj + cfile[:len(cfile)-1] + "o" 2328 if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil { 2329 return nil, nil, err 2330 } 2331 linkobj = append(linkobj, ofile) 2332 if !strings.HasSuffix(ofile, "_cgo_main.o") { 2333 outObj = append(outObj, ofile) 2334 } 2335 } 2336 2337 for _, file := range gccfiles { 2338 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" 2339 if err := b.gcc(p, ofile, cflags, file); err != nil { 2340 return nil, nil, err 2341 } 2342 linkobj = append(linkobj, ofile) 2343 outObj = append(outObj, ofile) 2344 } 2345 2346 cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) 2347 for _, file := range gxxfiles { 2348 // Append .o to the file, just in case the pkg has file.c and file.cpp 2349 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2350 if err := b.gxx(p, ofile, cxxflags, file); err != nil { 2351 return nil, nil, err 2352 } 2353 linkobj = append(linkobj, ofile) 2354 outObj = append(outObj, ofile) 2355 } 2356 2357 for _, file := range mfiles { 2358 // Append .o to the file, just in case the pkg has file.c and file.m 2359 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2360 if err := b.gcc(p, ofile, cflags, file); err != nil { 2361 return nil, nil, err 2362 } 2363 linkobj = append(linkobj, ofile) 2364 outObj = append(outObj, ofile) 2365 } 2366 2367 linkobj = append(linkobj, p.SysoFiles...) 2368 dynobj := obj + "_cgo_.o" 2369 pie := goarch == "arm" && (goos == "linux" || goos == "android") 2370 if pie { // we need to use -pie for Linux/ARM to get accurate imported sym 2371 cgoLDFLAGS = append(cgoLDFLAGS, "-pie") 2372 } 2373 if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil { 2374 return nil, nil, err 2375 } 2376 if pie { // but we don't need -pie for normal cgo programs 2377 cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1] 2378 } 2379 2380 if _, ok := buildToolchain.(gccgoToolchain); ok { 2381 // we don't use dynimport when using gccgo. 2382 return outGo, outObj, nil 2383 } 2384 2385 // cgo -dynimport 2386 importC := obj + "_cgo_import.c" 2387 cgoflags = []string{} 2388 if p.Standard && p.ImportPath == "runtime/cgo" { 2389 cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker 2390 } 2391 if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil { 2392 return nil, nil, err 2393 } 2394 2395 // cc _cgo_import.ARCH 2396 importObj := obj + "_cgo_import." + objExt 2397 if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil { 2398 return nil, nil, err 2399 } 2400 2401 ofile := obj + "_all.o" 2402 var gccObjs, nonGccObjs []string 2403 for _, f := range outObj { 2404 if strings.HasSuffix(f, ".o") { 2405 gccObjs = append(gccObjs, f) 2406 } else { 2407 nonGccObjs = append(nonGccObjs, f) 2408 } 2409 } 2410 ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs) 2411 2412 if flag := b.gccNoPie(); flag != "" { 2413 ldflags = append(ldflags, flag) 2414 } 2415 2416 // Some systems, such as Ubuntu, always add --build-id to 2417 // every link, but we don't want a build ID since we are 2418 // producing an object file. On some of those system a plain 2419 // -r (not -Wl,-r) will turn off --build-id, but clang 3.0 2420 // doesn't support a plain -r. I don't know how to turn off 2421 // --build-id when using clang other than passing a trailing 2422 // --build-id=none. So that is what we do, but only on 2423 // systems likely to support it, which is to say, systems that 2424 // normally use gold or the GNU linker. 2425 switch goos { 2426 case "android", "dragonfly", "linux", "netbsd": 2427 ldflags = append(ldflags, "-Wl,--build-id=none") 2428 case "haiku": 2429 ldflags = append(ldflags, "-fPIC") 2430 } 2431 2432 if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil { 2433 return nil, nil, err 2434 } 2435 2436 // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows 2437 // must be processed before the gcc-generated objects. 2438 // Put it first. http://golang.org/issue/2601 2439 outObj = stringList(importObj, nonGccObjs, ofile) 2440 2441 return outGo, outObj, nil 2442 } 2443 2444 // Run SWIG on all SWIG input files. 2445 // TODO: Don't build a shared library, once SWIG emits the necessary 2446 // pragmas for external linking. 2447 func (b *builder) swig(p *Package, obj string, pcCFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { 2448 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) 2449 cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) 2450 cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) 2451 2452 for _, file := range gccfiles { 2453 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" 2454 if err := b.gcc(p, ofile, cflags, file); err != nil { 2455 return nil, nil, err 2456 } 2457 outObj = append(outObj, ofile) 2458 } 2459 2460 for _, file := range gxxfiles { 2461 // Append .o to the file, just in case the pkg has file.c and file.cpp 2462 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2463 if err := b.gxx(p, ofile, cxxflags, file); err != nil { 2464 return nil, nil, err 2465 } 2466 outObj = append(outObj, ofile) 2467 } 2468 2469 for _, file := range mfiles { 2470 // Append .o to the file, just in case the pkg has file.c and file.cpp 2471 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 2472 if err := b.gcc(p, ofile, cflags, file); err != nil { 2473 return nil, nil, err 2474 } 2475 outObj = append(outObj, ofile) 2476 } 2477 2478 if err := b.swigVersionCheck(); err != nil { 2479 return nil, nil, err 2480 } 2481 2482 intgosize, err := b.swigIntSize(obj) 2483 if err != nil { 2484 return nil, nil, err 2485 } 2486 2487 for _, f := range p.SwigFiles { 2488 goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize) 2489 if err != nil { 2490 return nil, nil, err 2491 } 2492 if goFile != "" { 2493 outGo = append(outGo, goFile) 2494 } 2495 if objFile != "" { 2496 outObj = append(outObj, objFile) 2497 } 2498 if gccObjFile != "" { 2499 outObj = append(outObj, gccObjFile) 2500 } 2501 } 2502 for _, f := range p.SwigCXXFiles { 2503 goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize) 2504 if err != nil { 2505 return nil, nil, err 2506 } 2507 if goFile != "" { 2508 outGo = append(outGo, goFile) 2509 } 2510 if objFile != "" { 2511 outObj = append(outObj, objFile) 2512 } 2513 if gccObjFile != "" { 2514 outObj = append(outObj, gccObjFile) 2515 } 2516 } 2517 return outGo, outObj, nil 2518 } 2519 2520 // Make sure SWIG is new enough. 2521 var ( 2522 swigCheckOnce sync.Once 2523 swigCheck error 2524 ) 2525 2526 func (b *builder) swigDoVersionCheck() error { 2527 out, err := b.runOut("", "", nil, "swig", "-version") 2528 if err != nil { 2529 return err 2530 } 2531 re := regexp.MustCompile(`[vV]ersion +([\d])`) 2532 matches := re.FindSubmatch(out) 2533 if matches == nil { 2534 // Can't find version number; hope for the best. 2535 return nil 2536 } 2537 major, err := strconv.Atoi(string(matches[1])) 2538 if err != nil { 2539 // Can't find version number; hope for the best. 2540 return nil 2541 } 2542 if major < 3 { 2543 return errors.New("must have SWIG version >= 3.0") 2544 } 2545 return nil 2546 } 2547 2548 func (b *builder) swigVersionCheck() error { 2549 swigCheckOnce.Do(func() { 2550 swigCheck = b.swigDoVersionCheck() 2551 }) 2552 return swigCheck 2553 } 2554 2555 // This code fails to build if sizeof(int) <= 32 2556 const swigIntSizeCode = ` 2557 package main 2558 const i int = 1 << 32 2559 ` 2560 2561 // Determine the size of int on the target system for the -intgosize option 2562 // of swig >= 2.0.9 2563 func (b *builder) swigIntSize(obj string) (intsize string, err error) { 2564 if buildN { 2565 return "$INTBITS", nil 2566 } 2567 src := filepath.Join(b.work, "swig_intsize.go") 2568 if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil { 2569 return 2570 } 2571 srcs := []string{src} 2572 2573 p := goFilesPackage(srcs) 2574 2575 if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil { 2576 return "32", nil 2577 } 2578 return "64", nil 2579 } 2580 2581 // Run SWIG on one SWIG input file. 2582 func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) { 2583 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) 2584 var cflags []string 2585 if cxx { 2586 cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) 2587 } else { 2588 cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) 2589 } 2590 2591 n := 5 // length of ".swig" 2592 if cxx { 2593 n = 8 // length of ".swigcxx" 2594 } 2595 base := file[:len(file)-n] 2596 goFile := base + ".go" 2597 cBase := base + "_gc." 2598 gccBase := base + "_wrap." 2599 gccExt := "c" 2600 if cxx { 2601 gccExt = "cxx" 2602 } 2603 2604 _, gccgo := buildToolchain.(gccgoToolchain) 2605 2606 // swig 2607 args := []string{ 2608 "-go", 2609 "-intgosize", intgosize, 2610 "-module", base, 2611 "-o", obj + gccBase + gccExt, 2612 "-outdir", obj, 2613 } 2614 2615 for _, f := range cflags { 2616 if len(f) > 3 && f[:2] == "-I" { 2617 args = append(args, f) 2618 } 2619 } 2620 2621 if gccgo { 2622 args = append(args, "-gccgo") 2623 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 2624 args = append(args, "-go-pkgpath", pkgpath) 2625 } 2626 } 2627 if cxx { 2628 args = append(args, "-c++") 2629 } 2630 2631 if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil { 2632 if len(out) > 0 { 2633 if bytes.Contains(out, []byte("Unrecognized option -intgosize")) { 2634 return "", "", "", errors.New("must have SWIG version >= 3.0") 2635 } 2636 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) 2637 return "", "", "", errPrintedOutput 2638 } 2639 return "", "", "", err 2640 } 2641 2642 var cObj string 2643 if !gccgo { 2644 // cc 2645 cObj = obj + cBase + archChar 2646 if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil { 2647 return "", "", "", err 2648 } 2649 } 2650 2651 // gcc 2652 gccObj := obj + gccBase + "o" 2653 if !cxx { 2654 if err := b.gcc(p, gccObj, cflags, obj+gccBase+gccExt); err != nil { 2655 return "", "", "", err 2656 } 2657 } else { 2658 if err := b.gxx(p, gccObj, cflags, obj+gccBase+gccExt); err != nil { 2659 return "", "", "", err 2660 } 2661 } 2662 2663 return obj + goFile, cObj, gccObj, nil 2664 } 2665 2666 // An actionQueue is a priority queue of actions. 2667 type actionQueue []*action 2668 2669 // Implement heap.Interface 2670 func (q *actionQueue) Len() int { return len(*q) } 2671 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 2672 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } 2673 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) } 2674 func (q *actionQueue) Pop() interface{} { 2675 n := len(*q) - 1 2676 x := (*q)[n] 2677 *q = (*q)[:n] 2678 return x 2679 } 2680 2681 func (q *actionQueue) push(a *action) { 2682 heap.Push(q, a) 2683 } 2684 2685 func (q *actionQueue) pop() *action { 2686 return heap.Pop(q).(*action) 2687 } 2688 2689 func raceInit() { 2690 if !buildRace { 2691 return 2692 } 2693 if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" { 2694 fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) 2695 os.Exit(2) 2696 } 2697 buildGcflags = append(buildGcflags, "-race") 2698 buildLdflags = append(buildLdflags, "-race") 2699 buildCcflags = append(buildCcflags, "-D", "RACE") 2700 if buildContext.InstallSuffix != "" { 2701 buildContext.InstallSuffix += "_" 2702 } 2703 buildContext.InstallSuffix += "race" 2704 buildContext.BuildTags = append(buildContext.BuildTags, "race") 2705 } 2706 2707 // defaultSuffix returns file extension used for command files in 2708 // current os environment. 2709 func defaultSuffix() string { 2710 switch runtime.GOOS { 2711 case "windows": 2712 return ".bat" 2713 case "plan9": 2714 return ".rc" 2715 default: 2716 return ".bash" 2717 } 2718 }