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