github.com/gophergala2016/cmd-go-js@v0.0.0-20160421080227-24a7748a7d62/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 "debug/elf" 12 "errors" 13 "flag" 14 "fmt" 15 "go/build" 16 "io" 17 "io/ioutil" 18 "log" 19 "os" 20 "os/exec" 21 "path" 22 "path/filepath" 23 "regexp" 24 "runtime" 25 "strconv" 26 "strings" 27 "sync" 28 "time" 29 ) 30 31 var cmdBuild = &Command{ 32 UsageLine: "build [-o output] [-i] [build flags] [packages]", 33 Short: "compile packages and dependencies", 34 Long: ` 35 Build compiles the packages named by the import paths, 36 along with their dependencies, but it does not install the results. 37 38 If the arguments to build are a list of .go files, build treats 39 them as a list of source files specifying a single package. 40 41 When compiling a single main package, build writes 42 the resulting executable to an output file named after 43 the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') 44 or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). 45 The '.exe' suffix is added when writing a Windows executable. 46 47 When compiling multiple packages or a single non-main package, 48 build compiles the packages but discards the resulting object, 49 serving only as a check that the packages can be built. 50 51 The -o flag, only allowed when compiling a single package, 52 forces build to write the resulting executable or object 53 to the named output file, instead of the default behavior described 54 in the last two paragraphs. 55 56 The -i flag installs the packages that are dependencies of the target. 57 58 The build flags are shared by the build, clean, get, install, list, run, 59 and test commands: 60 61 -a 62 force rebuilding of packages that are already up-to-date. 63 -n 64 print the commands but do not run them. 65 -p n 66 the number of builds that can be run in parallel. 67 The default is the number of CPUs available, except 68 on darwin/arm which defaults to 1. 69 -race 70 enable data race detection. 71 Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. 72 -v 73 print the names of packages as they are compiled. 74 -work 75 print the name of the temporary work directory and 76 do not delete it when exiting. 77 -x 78 print the commands. 79 80 -asmflags 'flag list' 81 arguments to pass on each go tool asm invocation. 82 -buildmode mode 83 build mode to use. See 'go help buildmode' for more. 84 -compiler name 85 name of compiler to use, as in runtime.Compiler (gccgo, gc or gopherjs). 86 -gccgoflags 'arg list' 87 arguments to pass on each gccgo compiler/linker invocation. 88 -gcflags 'arg list' 89 arguments to pass on each go tool compile invocation. 90 -installsuffix suffix 91 a suffix to use in the name of the package installation directory, 92 in order to keep output separate from default builds. 93 If using the -race flag, the install suffix is automatically set to race 94 or, if set explicitly, has _race appended to it. Using a -buildmode 95 option that requires non-default compile flags has a similar effect. 96 -ldflags 'flag list' 97 arguments to pass on each go tool link invocation. 98 -linkshared 99 link against shared libraries previously created with 100 -buildmode=shared 101 -pkgdir dir 102 install and load all packages from dir instead of the usual locations. 103 For example, when building with a non-standard configuration, 104 use -pkgdir to keep generated packages in a separate location. 105 -tags 'tag list' 106 a list of build tags to consider satisfied during the build. 107 For more information about build tags, see the description of 108 build constraints in the documentation for the go/build package. 109 -toolexec 'cmd args' 110 a program to use to invoke toolchain programs like vet and asm. 111 For example, instead of running asm, the go command will run 112 'cmd args /path/to/asm <arguments for asm>'. 113 114 The list flags accept a space-separated list of strings. To embed spaces 115 in an element in the list, surround it with either single or double quotes. 116 117 For more about specifying packages, see 'go help packages'. 118 For more about where packages and binaries are installed, 119 run 'go help gopath'. 120 For more about calling between Go and C/C++, run 'go help c'. 121 122 Note: Build adheres to certain conventions such as those described 123 by 'go help gopath'. Not all projects can follow these conventions, 124 however. Installations that have their own conventions or that use 125 a separate software build system may choose to use lower-level 126 invocations such as 'go tool compile' and 'go tool link' to avoid 127 some of the overheads and design decisions of the build tool. 128 129 See also: go install, go get, go clean. 130 `, 131 } 132 133 func init() { 134 // break init cycle 135 cmdBuild.Run = runBuild 136 cmdInstall.Run = runInstall 137 138 cmdBuild.Flag.BoolVar(&buildI, "i", false, "") 139 140 addBuildFlags(cmdBuild) 141 addBuildFlags(cmdInstall) 142 143 if buildContext.GOOS == "darwin" { 144 switch buildContext.GOARCH { 145 case "arm", "arm64": 146 // darwin/arm cannot run multiple tests simultaneously. 147 // Parallelism is limited in go_darwin_arm_exec, but 148 // also needs to be limited here so go test std does not 149 // timeout tests that waiting to run. 150 buildP = 1 151 } 152 } 153 } 154 155 // Flags set by multiple commands. 156 var buildA bool // -a flag 157 var buildN bool // -n flag 158 var buildP = runtime.NumCPU() // -p flag 159 var buildV bool // -v flag 160 var buildX bool // -x flag 161 var buildI bool // -i flag 162 var buildO = cmdBuild.Flag.String("o", "", "output file") 163 var buildWork bool // -work flag 164 var buildAsmflags []string // -asmflags flag 165 var buildGcflags []string // -gcflags flag 166 var buildLdflags []string // -ldflags flag 167 var buildGccgoflags []string // -gccgoflags flag 168 var buildRace bool // -race flag 169 var buildToolExec []string // -toolexec flag 170 var buildBuildmode string // -buildmode flag 171 var buildLinkshared bool // -linkshared flag 172 var buildPkgdir string // -pkgdir flag 173 174 var buildContext = build.Default 175 var buildToolchain toolchain = noToolchain{} 176 var ldBuildmode string 177 178 // buildCompiler implements flag.Var. 179 // It implements Set by updating both 180 // buildToolchain and buildContext.Compiler. 181 type buildCompiler struct{} 182 183 func (c buildCompiler) Set(value string) error { 184 switch value { 185 case "gc": 186 buildToolchain = gcToolchain{} 187 case "gccgo": 188 buildToolchain = gccgoToolchain{} 189 default: 190 switch compilerBin, err := exec.LookPath(value); err { 191 case nil: 192 buildToolchain = generalToolchain{compilerBin: compilerBin} 193 default: 194 return fmt.Errorf("unknown compiler %q", value) 195 } 196 } 197 buildContext.Compiler = value 198 return nil 199 } 200 201 func (c buildCompiler) String() string { 202 return buildContext.Compiler 203 } 204 205 func init() { 206 switch build.Default.Compiler { 207 case "gc": 208 buildToolchain = gcToolchain{} 209 case "gccgo": 210 buildToolchain = gccgoToolchain{} 211 } 212 } 213 214 // addBuildFlags adds the flags common to the build, clean, get, 215 // install, list, run, and test commands. 216 func addBuildFlags(cmd *Command) { 217 cmd.Flag.BoolVar(&buildA, "a", false, "") 218 cmd.Flag.BoolVar(&buildN, "n", false, "") 219 cmd.Flag.IntVar(&buildP, "p", buildP, "") 220 cmd.Flag.BoolVar(&buildV, "v", false, "") 221 cmd.Flag.BoolVar(&buildX, "x", false, "") 222 223 cmd.Flag.Var((*stringsFlag)(&buildAsmflags), "asmflags", "") 224 cmd.Flag.Var(buildCompiler{}, "compiler", "") 225 cmd.Flag.StringVar(&buildBuildmode, "buildmode", "default", "") 226 cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "") 227 cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") 228 cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "") 229 cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "") 230 cmd.Flag.BoolVar(&buildLinkshared, "linkshared", false, "") 231 cmd.Flag.StringVar(&buildPkgdir, "pkgdir", "", "") 232 cmd.Flag.BoolVar(&buildRace, "race", false, "") 233 cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") 234 cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "") 235 cmd.Flag.BoolVar(&buildWork, "work", false, "") 236 } 237 238 func addBuildFlagsNX(cmd *Command) { 239 cmd.Flag.BoolVar(&buildN, "n", false, "") 240 cmd.Flag.BoolVar(&buildX, "x", false, "") 241 } 242 243 func isSpaceByte(c byte) bool { 244 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 245 } 246 247 // fileExtSplit expects a filename and returns the name 248 // and ext (without the dot). If the file has no 249 // extension, ext will be empty. 250 func fileExtSplit(file string) (name, ext string) { 251 dotExt := filepath.Ext(file) 252 name = file[:len(file)-len(dotExt)] 253 if dotExt != "" { 254 ext = dotExt[1:] 255 } 256 return 257 } 258 259 type stringsFlag []string 260 261 func (v *stringsFlag) Set(s string) error { 262 var err error 263 *v, err = splitQuotedFields(s) 264 if *v == nil { 265 *v = []string{} 266 } 267 return err 268 } 269 270 func splitQuotedFields(s string) ([]string, error) { 271 // Split fields allowing '' or "" around elements. 272 // Quotes further inside the string do not count. 273 var f []string 274 for len(s) > 0 { 275 for len(s) > 0 && isSpaceByte(s[0]) { 276 s = s[1:] 277 } 278 if len(s) == 0 { 279 break 280 } 281 // Accepted quoted string. No unescaping inside. 282 if s[0] == '"' || s[0] == '\'' { 283 quote := s[0] 284 s = s[1:] 285 i := 0 286 for i < len(s) && s[i] != quote { 287 i++ 288 } 289 if i >= len(s) { 290 return nil, fmt.Errorf("unterminated %c string", quote) 291 } 292 f = append(f, s[:i]) 293 s = s[i+1:] 294 continue 295 } 296 i := 0 297 for i < len(s) && !isSpaceByte(s[i]) { 298 i++ 299 } 300 f = append(f, s[:i]) 301 s = s[i:] 302 } 303 return f, nil 304 } 305 306 func (v *stringsFlag) String() string { 307 return "<stringsFlag>" 308 } 309 310 func pkgsMain(pkgs []*Package) (res []*Package) { 311 for _, p := range pkgs { 312 if p.Name == "main" { 313 res = append(res, p) 314 } 315 } 316 return res 317 } 318 319 func pkgsNotMain(pkgs []*Package) (res []*Package) { 320 for _, p := range pkgs { 321 if p.Name != "main" { 322 res = append(res, p) 323 } 324 } 325 return res 326 } 327 328 var pkgsFilter = func(pkgs []*Package) []*Package { return pkgs } 329 330 func buildModeInit() { 331 _, gccgo := buildToolchain.(gccgoToolchain) 332 var codegenArg string 333 platform := goos + "/" + goarch 334 switch buildBuildmode { 335 case "archive": 336 pkgsFilter = pkgsNotMain 337 case "c-archive": 338 pkgsFilter = func(p []*Package) []*Package { 339 if len(p) != 1 || p[0].Name != "main" { 340 fatalf("-buildmode=c-archive requires exactly one main package") 341 } 342 return p 343 } 344 exeSuffix = ".a" 345 ldBuildmode = "c-archive" 346 case "c-shared": 347 pkgsFilter = pkgsMain 348 if gccgo { 349 codegenArg = "-fPIC" 350 } else { 351 switch platform { 352 case "linux/amd64": 353 codegenArg = "-shared" 354 case "linux/arm": 355 buildAsmflags = append(buildAsmflags, "-shared") 356 case "darwin/amd64": 357 case "android/arm": 358 default: 359 fatalf("-buildmode=c-shared not supported on %s\n", platform) 360 } 361 } 362 ldBuildmode = "c-shared" 363 case "default": 364 ldBuildmode = "exe" 365 case "exe": 366 pkgsFilter = pkgsMain 367 ldBuildmode = "exe" 368 case "shared": 369 pkgsFilter = pkgsNotMain 370 if gccgo { 371 codegenArg = "-fPIC" 372 } else { 373 switch platform { 374 case "linux/amd64": 375 default: 376 fatalf("-buildmode=shared not supported on %s\n", platform) 377 } 378 codegenArg = "-dynlink" 379 } 380 if *buildO != "" { 381 fatalf("-buildmode=shared and -o not supported together") 382 } 383 ldBuildmode = "shared" 384 default: 385 fatalf("buildmode=%s not supported", buildBuildmode) 386 } 387 if buildLinkshared { 388 if gccgo { 389 codegenArg = "-fPIC" 390 } else { 391 if platform != "linux/amd64" { 392 fmt.Fprintf(os.Stderr, "go %s: -linkshared is only supported on linux/amd64\n", flag.Args()[0]) 393 os.Exit(2) 394 } 395 codegenArg = "-dynlink" 396 // TODO(mwhudson): remove -w when that gets fixed in linker. 397 buildLdflags = append(buildLdflags, "-linkshared", "-w") 398 } 399 } 400 if codegenArg != "" { 401 if gccgo { 402 buildGccgoflags = append(buildGccgoflags, codegenArg) 403 } else { 404 buildAsmflags = append(buildAsmflags, codegenArg) 405 buildGcflags = append(buildGcflags, codegenArg) 406 } 407 if buildContext.InstallSuffix != "" { 408 buildContext.InstallSuffix += "_" 409 } 410 buildContext.InstallSuffix += codegenArg[1:] 411 } 412 } 413 414 func runBuild(cmd *Command, args []string) { 415 raceInit() 416 buildModeInit() 417 var b builder 418 b.init() 419 420 pkgs := packagesForBuild(args) 421 422 if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" { 423 _, *buildO = path.Split(pkgs[0].ImportPath) 424 *buildO += exeSuffix 425 } 426 427 // sanity check some often mis-used options 428 switch buildContext.Compiler { 429 case "gccgo": 430 if len(buildGcflags) != 0 { 431 fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags") 432 } 433 if len(buildLdflags) != 0 { 434 fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags") 435 } 436 case "gc": 437 if len(buildGccgoflags) != 0 { 438 fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags") 439 } 440 } 441 442 depMode := modeBuild 443 if buildI { 444 depMode = modeInstall 445 } 446 447 if *buildO != "" { 448 if len(pkgs) > 1 { 449 fatalf("go build: cannot use -o with multiple packages") 450 } else if len(pkgs) == 0 { 451 fatalf("no packages to build") 452 } 453 p := pkgs[0] 454 p.target = *buildO 455 p.Stale = true // must build - not up to date 456 a := b.action(modeInstall, depMode, p) 457 b.do(a) 458 return 459 } 460 461 var a *action 462 if buildBuildmode == "shared" { 463 a = b.libaction(libname(args), pkgsFilter(packages(args)), modeBuild, depMode) 464 } else { 465 a = &action{} 466 for _, p := range pkgsFilter(packages(args)) { 467 a.deps = append(a.deps, b.action(modeBuild, depMode, p)) 468 } 469 } 470 b.do(a) 471 } 472 473 var cmdInstall = &Command{ 474 UsageLine: "install [build flags] [packages]", 475 Short: "compile and install packages and dependencies", 476 Long: ` 477 Install compiles and installs the packages named by the import paths, 478 along with their dependencies. 479 480 For more about the build flags, see 'go help build'. 481 For more about specifying packages, see 'go help packages'. 482 483 See also: go build, go get, go clean. 484 `, 485 } 486 487 // libname returns the filename to use for the shared library when using 488 // -buildmode=shared. The rules we use are: 489 // 1) Drop any trailing "/..."s if present 490 // 2) Change / to - 491 // 3) Join arguments with , 492 // So std -> libstd.so 493 // a b/... -> liba,b.so 494 // gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so 495 func libname(args []string) string { 496 var libname string 497 for _, arg := range args { 498 arg = strings.TrimSuffix(arg, "/...") 499 arg = strings.Replace(arg, "/", "-", -1) 500 if libname == "" { 501 libname = arg 502 } else { 503 libname += "," + arg 504 } 505 } 506 // TODO(mwhudson): Needs to change for platforms that use different naming 507 // conventions... 508 return "lib" + libname + ".so" 509 } 510 511 func runInstall(cmd *Command, args []string) { 512 raceInit() 513 buildModeInit() 514 pkgs := pkgsFilter(packagesForBuild(args)) 515 516 for _, p := range pkgs { 517 if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { 518 switch { 519 case p.gobinSubdir: 520 errorf("go install: cannot install cross-compiled binaries when GOBIN is set") 521 case p.cmdline: 522 errorf("go install: no install location for .go files listed on command line (GOBIN not set)") 523 case p.ConflictDir != "": 524 errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir) 525 default: 526 errorf("go install: no install location for directory %s outside GOPATH\n"+ 527 "\tFor more details see: go help gopath", p.Dir) 528 } 529 } 530 } 531 exitIfErrors() 532 533 var b builder 534 b.init() 535 var a *action 536 if buildBuildmode == "shared" { 537 a = b.libaction(libname(args), pkgs, modeInstall, modeInstall) 538 } else { 539 a = &action{} 540 var tools []*action 541 for _, p := range pkgs { 542 // If p is a tool, delay the installation until the end of the build. 543 // This avoids installing assemblers/compilers that are being executed 544 // by other steps in the build. 545 // cmd/cgo is handled specially in b.action, so that we can 546 // both build and use it in the same 'go install'. 547 action := b.action(modeInstall, modeInstall, p) 548 if goTools[p.ImportPath] == toTool && p.ImportPath != "cmd/cgo" { 549 a.deps = append(a.deps, action.deps...) 550 action.deps = append(action.deps, a) 551 tools = append(tools, action) 552 continue 553 } 554 a.deps = append(a.deps, action) 555 } 556 if len(tools) > 0 { 557 a = &action{ 558 deps: tools, 559 } 560 } 561 } 562 b.do(a) 563 exitIfErrors() 564 565 // Success. If this command is 'go install' with no arguments 566 // and the current directory (the implicit argument) is a command, 567 // remove any leftover command binary from a previous 'go build'. 568 // The binary is installed; it's not needed here anymore. 569 // And worse it might be a stale copy, which you don't want to find 570 // instead of the installed one if $PATH contains dot. 571 // One way to view this behavior is that it is as if 'go install' first 572 // runs 'go build' and the moves the generated file to the install dir. 573 // See issue 9645. 574 if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" { 575 // Compute file 'go build' would have created. 576 // If it exists and is an executable file, remove it. 577 _, targ := filepath.Split(pkgs[0].ImportPath) 578 targ += exeSuffix 579 if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory 580 fi, err := os.Stat(targ) 581 if err == nil { 582 m := fi.Mode() 583 if m.IsRegular() { 584 if m&0111 != 0 || goos == "windows" { // windows never sets executable bit 585 os.Remove(targ) 586 } 587 } 588 } 589 } 590 } 591 } 592 593 // Global build parameters (used during package load) 594 var ( 595 goarch string 596 goos string 597 exeSuffix string 598 ) 599 600 func init() { 601 goarch = buildContext.GOARCH 602 goos = buildContext.GOOS 603 if goos == "windows" { 604 exeSuffix = ".exe" 605 } 606 } 607 608 // A builder holds global state about a build. 609 // It does not hold per-package state, because we 610 // build packages in parallel, and the builder is shared. 611 type builder struct { 612 work string // the temporary work directory (ends in filepath.Separator) 613 actionCache map[cacheKey]*action // a cache of already-constructed actions 614 mkdirCache map[string]bool // a cache of created directories 615 print func(args ...interface{}) (int, error) 616 617 output sync.Mutex 618 scriptDir string // current directory in printed script 619 620 exec sync.Mutex 621 readySema chan bool 622 ready actionQueue 623 } 624 625 // An action represents a single action in the action graph. 626 type action struct { 627 p *Package // the package this action works on 628 deps []*action // actions that must happen before this one 629 triggers []*action // inverse of deps 630 cgo *action // action for cgo binary if needed 631 args []string // additional args for runProgram 632 testOutput *bytes.Buffer // test output buffer 633 634 f func(*builder, *action) error // the action itself (nil = no-op) 635 ignoreFail bool // whether to run f even if dependencies fail 636 637 // Generated files, directories. 638 link bool // target is executable, not just package 639 pkgdir string // the -I or -L argument to use when importing this package 640 objdir string // directory for intermediate objects 641 objpkg string // the intermediate package .a file created during the action 642 target string // goal of the action: the created package or executable 643 644 // Execution state. 645 pending int // number of deps yet to complete 646 priority int // relative execution priority 647 failed bool // whether the action failed 648 } 649 650 // cacheKey is the key for the action cache. 651 type cacheKey struct { 652 mode buildMode 653 p *Package 654 shlib string 655 } 656 657 // buildMode specifies the build mode: 658 // are we just building things or also installing the results? 659 type buildMode int 660 661 const ( 662 modeBuild buildMode = iota 663 modeInstall 664 ) 665 666 var ( 667 goroot = filepath.Clean(runtime.GOROOT()) 668 gobin = os.Getenv("GOBIN") 669 gorootBin = filepath.Join(goroot, "bin") 670 gorootPkg = filepath.Join(goroot, "pkg") 671 gorootSrc = filepath.Join(goroot, "src") 672 ) 673 674 func (b *builder) init() { 675 var err error 676 b.print = func(a ...interface{}) (int, error) { 677 return fmt.Fprint(os.Stderr, a...) 678 } 679 b.actionCache = make(map[cacheKey]*action) 680 b.mkdirCache = make(map[string]bool) 681 682 if buildN { 683 b.work = "$WORK" 684 } else { 685 b.work, err = ioutil.TempDir("", "go-build") 686 if err != nil { 687 fatalf("%s", err) 688 } 689 if buildX || buildWork { 690 fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work) 691 } 692 if !buildWork { 693 workdir := b.work 694 atexit(func() { os.RemoveAll(workdir) }) 695 } 696 } 697 } 698 699 // goFilesPackage creates a package for building a collection of Go files 700 // (typically named on the command line). The target is named p.a for 701 // package p or named after the first Go file for package main. 702 func goFilesPackage(gofiles []string) *Package { 703 // TODO: Remove this restriction. 704 for _, f := range gofiles { 705 if !strings.HasSuffix(f, ".go") { 706 fatalf("named files must be .go files") 707 } 708 } 709 710 var stk importStack 711 ctxt := buildContext 712 ctxt.UseAllFiles = true 713 714 // Synthesize fake "directory" that only shows the named files, 715 // to make it look like this is a standard package or 716 // command directory. So that local imports resolve 717 // consistently, the files must all be in the same directory. 718 var dirent []os.FileInfo 719 var dir string 720 for _, file := range gofiles { 721 fi, err := os.Stat(file) 722 if err != nil { 723 fatalf("%s", err) 724 } 725 if fi.IsDir() { 726 fatalf("%s is a directory, should be a Go file", file) 727 } 728 dir1, _ := filepath.Split(file) 729 if dir1 == "" { 730 dir1 = "./" 731 } 732 if dir == "" { 733 dir = dir1 734 } else if dir != dir1 { 735 fatalf("named files must all be in one directory; have %s and %s", dir, dir1) 736 } 737 dirent = append(dirent, fi) 738 } 739 ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } 740 741 var err error 742 if dir == "" { 743 dir = cwd 744 } 745 dir, err = filepath.Abs(dir) 746 if err != nil { 747 fatalf("%s", err) 748 } 749 750 bp, err := ctxt.ImportDir(dir, 0) 751 pkg := new(Package) 752 pkg.local = true 753 pkg.cmdline = true 754 pkg.load(&stk, bp, err) 755 pkg.localPrefix = dirToImportPath(dir) 756 pkg.ImportPath = "command-line-arguments" 757 pkg.target = "" 758 759 if pkg.Name == "main" { 760 _, elem := filepath.Split(gofiles[0]) 761 exe := elem[:len(elem)-len(".go")] + exeSuffix 762 if *buildO == "" { 763 *buildO = exe 764 } 765 if gobin != "" { 766 pkg.target = filepath.Join(gobin, exe) 767 } 768 } 769 770 pkg.Target = pkg.target 771 pkg.Stale = true 772 773 computeStale(pkg) 774 return pkg 775 } 776 777 // readpkglist returns the list of packages that were built into the shared library 778 // at shlibpath. For the native toolchain this list is stored, newline separated, in 779 // an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the 780 // .go_export section. 781 func readpkglist(shlibpath string) (pkgs []*Package) { 782 var stk importStack 783 if _, gccgo := buildToolchain.(gccgoToolchain); gccgo { 784 f, _ := elf.Open(shlibpath) 785 sect := f.Section(".go_export") 786 data, _ := sect.Data() 787 scanner := bufio.NewScanner(bytes.NewBuffer(data)) 788 for scanner.Scan() { 789 t := scanner.Text() 790 if strings.HasPrefix(t, "pkgpath ") { 791 t = strings.TrimPrefix(t, "pkgpath ") 792 t = strings.TrimSuffix(t, ";") 793 pkgs = append(pkgs, loadPackage(t, &stk)) 794 } 795 } 796 } else { 797 pkglistbytes, err := readELFNote(shlibpath, "Go\x00\x00", 1) 798 if err != nil { 799 fatalf("readELFNote failed: %v", err) 800 } 801 scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes)) 802 for scanner.Scan() { 803 t := scanner.Text() 804 pkgs = append(pkgs, loadPackage(t, &stk)) 805 } 806 } 807 return 808 } 809 810 // action returns the action for applying the given operation (mode) to the package. 811 // depMode is the action to use when building dependencies. 812 // action never looks for p in a shared library. 813 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action { 814 return b.action1(mode, depMode, p, false) 815 } 816 817 // action1 returns the action for applying the given operation (mode) to the package. 818 // depMode is the action to use when building dependencies. 819 // action1 will look for p in a shared library if lookshared is true. 820 func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool) *action { 821 shlib := "" 822 if lookshared { 823 shlib = p.Shlib 824 } 825 key := cacheKey{mode, p, shlib} 826 827 a := b.actionCache[key] 828 if a != nil { 829 return a 830 } 831 if shlib != "" { 832 key2 := cacheKey{modeInstall, nil, shlib} 833 a = b.actionCache[key2] 834 if a != nil { 835 b.actionCache[key] = a 836 return a 837 } 838 pkgs := readpkglist(shlib) 839 a = b.libaction(filepath.Base(shlib), pkgs, modeInstall, depMode) 840 b.actionCache[key2] = a 841 b.actionCache[key] = a 842 return a 843 } 844 845 a = &action{p: p, pkgdir: p.build.PkgRoot} 846 if p.pkgdir != "" { // overrides p.t 847 a.pkgdir = p.pkgdir 848 } 849 b.actionCache[key] = a 850 851 for _, p1 := range p.imports { 852 ls := buildLinkshared 853 // If p1 is part of the same shared library as p, we need the action 854 // that builds p here, not the shared libary or we get action loops. 855 if p1.Shlib == p.Shlib { 856 ls = false 857 } 858 a.deps = append(a.deps, b.action1(depMode, depMode, p1, ls)) 859 } 860 861 // If we are not doing a cross-build, then record the binary we'll 862 // generate for cgo as a dependency of the build of any package 863 // using cgo, to make sure we do not overwrite the binary while 864 // a package is using it. If this is a cross-build, then the cgo we 865 // are writing is not the cgo we need to use. 866 if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace { 867 if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" { 868 var stk importStack 869 p1 := loadPackage("cmd/cgo", &stk) 870 if p1.Error != nil { 871 fatalf("load cmd/cgo: %v", p1.Error) 872 } 873 a.cgo = b.action(depMode, depMode, p1) 874 a.deps = append(a.deps, a.cgo) 875 } 876 } 877 878 if p.Standard { 879 switch p.ImportPath { 880 case "builtin", "unsafe": 881 // Fake packages - nothing to build. 882 return a 883 } 884 // gccgo standard library is "fake" too. 885 if _, ok := buildToolchain.(gccgoToolchain); ok { 886 // the target name is needed for cgo. 887 a.target = p.target 888 return a 889 } 890 } 891 892 if !p.Stale && p.target != "" { 893 // p.Stale==false implies that p.target is up-to-date. 894 // Record target name for use by actions depending on this one. 895 a.target = p.target 896 return a 897 } 898 899 if p.local && p.target == "" { 900 // Imported via local path. No permanent target. 901 mode = modeBuild 902 } 903 work := p.pkgdir 904 if work == "" { 905 work = b.work 906 } 907 a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator) 908 a.objpkg = buildToolchain.pkgpath(work, a.p) 909 a.link = p.Name == "main" 910 911 switch mode { 912 case modeInstall: 913 a.f = (*builder).install 914 a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared)} 915 a.target = a.p.target 916 917 // Install header for cgo in c-archive and c-shared modes. 918 if p.usesCgo() && (buildBuildmode == "c-archive" || buildBuildmode == "c-shared") { 919 ah := &action{ 920 p: a.p, 921 deps: []*action{a.deps[0]}, 922 f: (*builder).installHeader, 923 pkgdir: a.pkgdir, 924 objdir: a.objdir, 925 target: a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h", 926 } 927 a.deps = append(a.deps, ah) 928 } 929 930 case modeBuild: 931 a.f = (*builder).build 932 a.target = a.objpkg 933 if a.link { 934 // An executable file. (This is the name of a temporary file.) 935 // Because we run the temporary file in 'go run' and 'go test', 936 // the name will show up in ps listings. If the caller has specified 937 // a name, use that instead of a.out. The binary is generated 938 // in an otherwise empty subdirectory named exe to avoid 939 // naming conflicts. The only possible conflict is if we were 940 // to create a top-level package named exe. 941 name := "a.out" 942 if p.exeName != "" { 943 name = p.exeName 944 } else if goos == "darwin" && buildBuildmode == "c-shared" && p.target != "" { 945 // On OS X, the linker output name gets recorded in the 946 // shared library's LC_ID_DYLIB load command. 947 // The code invoking the linker knows to pass only the final 948 // path element. Arrange that the path element matches what 949 // we'll install it as; otherwise the library is only loadable as "a.out". 950 _, name = filepath.Split(p.target) 951 } 952 a.target = a.objdir + filepath.Join("exe", name) + exeSuffix 953 } 954 } 955 956 return a 957 } 958 959 func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode buildMode) *action { 960 a := &action{} 961 if mode == modeBuild { 962 a.f = (*builder).linkShared 963 a.target = filepath.Join(b.work, libname) 964 for _, p := range pkgs { 965 if p.target == "" { 966 continue 967 } 968 a.deps = append(a.deps, b.action(depMode, depMode, p)) 969 } 970 } else if mode == modeInstall { 971 // Currently build mode shared forces external linking mode, and 972 // external linking mode forces an import of runtime/cgo. So if it 973 // was not passed on the command line and it is not present in 974 // another shared library, add it here. 975 seencgo := false 976 _, gccgo := buildToolchain.(gccgoToolchain) 977 if !gccgo { 978 for _, p := range pkgs { 979 seencgo = seencgo || (p.Standard && p.ImportPath == "runtime/cgo") 980 } 981 if !seencgo { 982 var stk importStack 983 p := loadPackage("runtime/cgo", &stk) 984 if p.Error != nil { 985 fatalf("load runtime/cgo: %v", p.Error) 986 } 987 computeStale(p) 988 // If runtime/cgo is in another shared library, then that's 989 // also the shared library that contains runtime, so 990 // something will depend on it and so runtime/cgo's staleness 991 // will be checked when processing that library. 992 if p.Shlib == "" || p.Shlib == libname { 993 pkgs = append([]*Package{}, pkgs...) 994 pkgs = append(pkgs, p) 995 } 996 } 997 } 998 999 // Figure out where the library will go. 1000 var libdir string 1001 for _, p := range pkgs { 1002 plibdir := p.build.PkgTargetRoot 1003 if gccgo { 1004 plibdir = filepath.Join(plibdir, "shlibs") 1005 } 1006 if libdir == "" { 1007 libdir = plibdir 1008 } else if libdir != plibdir { 1009 fatalf("multiple roots %s & %s", libdir, plibdir) 1010 } 1011 } 1012 a.target = filepath.Join(libdir, libname) 1013 1014 // Now we can check whether we need to rebuild it. 1015 stale := false 1016 var built time.Time 1017 if fi, err := os.Stat(a.target); err == nil { 1018 built = fi.ModTime() 1019 } 1020 for _, p := range pkgs { 1021 if p.target == "" { 1022 continue 1023 } 1024 stale = stale || p.Stale 1025 lstat, err := os.Stat(p.target) 1026 if err != nil || lstat.ModTime().After(built) { 1027 stale = true 1028 } 1029 a.deps = append(a.deps, b.action(depMode, depMode, p)) 1030 } 1031 1032 if stale { 1033 a.f = (*builder).install 1034 buildAction := b.libaction(libname, pkgs, modeBuild, depMode) 1035 a.deps = []*action{buildAction} 1036 for _, p := range pkgs { 1037 if p.target == "" { 1038 continue 1039 } 1040 shlibnameaction := &action{} 1041 shlibnameaction.f = (*builder).installShlibname 1042 shlibnameaction.target = p.target[:len(p.target)-2] + ".shlibname" 1043 a.deps = append(a.deps, shlibnameaction) 1044 shlibnameaction.deps = append(shlibnameaction.deps, buildAction) 1045 } 1046 } 1047 } else { 1048 fatalf("unregonized mode %v", mode) 1049 } 1050 return a 1051 } 1052 1053 // actionList returns the list of actions in the dag rooted at root 1054 // as visited in a depth-first post-order traversal. 1055 func actionList(root *action) []*action { 1056 seen := map[*action]bool{} 1057 all := []*action{} 1058 var walk func(*action) 1059 walk = func(a *action) { 1060 if seen[a] { 1061 return 1062 } 1063 seen[a] = true 1064 for _, a1 := range a.deps { 1065 walk(a1) 1066 } 1067 all = append(all, a) 1068 } 1069 walk(root) 1070 return all 1071 } 1072 1073 // allArchiveActions returns a list of the archive dependencies of root. 1074 // This is needed because if package p depends on package q that is in libr.so, the 1075 // action graph looks like p->libr.so->q and so just scanning through p's 1076 // dependencies does not find the import dir for q. 1077 func allArchiveActions(root *action) []*action { 1078 seen := map[*action]bool{} 1079 r := []*action{} 1080 var walk func(*action) 1081 walk = func(a *action) { 1082 if seen[a] { 1083 return 1084 } 1085 seen[a] = true 1086 if strings.HasSuffix(a.target, ".so") || a == root { 1087 for _, a1 := range a.deps { 1088 walk(a1) 1089 } 1090 } else if strings.HasSuffix(a.target, ".a") { 1091 r = append(r, a) 1092 } 1093 } 1094 walk(root) 1095 return r 1096 } 1097 1098 // do runs the action graph rooted at root. 1099 func (b *builder) do(root *action) { 1100 // Build list of all actions, assigning depth-first post-order priority. 1101 // The original implementation here was a true queue 1102 // (using a channel) but it had the effect of getting 1103 // distracted by low-level leaf actions to the detriment 1104 // of completing higher-level actions. The order of 1105 // work does not matter much to overall execution time, 1106 // but when running "go test std" it is nice to see each test 1107 // results as soon as possible. The priorities assigned 1108 // ensure that, all else being equal, the execution prefers 1109 // to do what it would have done first in a simple depth-first 1110 // dependency order traversal. 1111 all := actionList(root) 1112 for i, a := range all { 1113 a.priority = i 1114 } 1115 1116 b.readySema = make(chan bool, len(all)) 1117 1118 // Initialize per-action execution state. 1119 for _, a := range all { 1120 for _, a1 := range a.deps { 1121 a1.triggers = append(a1.triggers, a) 1122 } 1123 a.pending = len(a.deps) 1124 if a.pending == 0 { 1125 b.ready.push(a) 1126 b.readySema <- true 1127 } 1128 } 1129 1130 // Handle runs a single action and takes care of triggering 1131 // any actions that are runnable as a result. 1132 handle := func(a *action) { 1133 var err error 1134 if a.f != nil && (!a.failed || a.ignoreFail) { 1135 err = a.f(b, a) 1136 } 1137 1138 // The actions run in parallel but all the updates to the 1139 // shared work state are serialized through b.exec. 1140 b.exec.Lock() 1141 defer b.exec.Unlock() 1142 1143 if err != nil { 1144 if err == errPrintedOutput { 1145 setExitStatus(2) 1146 } else { 1147 errorf("%s", err) 1148 } 1149 a.failed = true 1150 } 1151 1152 for _, a0 := range a.triggers { 1153 if a.failed { 1154 a0.failed = true 1155 } 1156 if a0.pending--; a0.pending == 0 { 1157 b.ready.push(a0) 1158 b.readySema <- true 1159 } 1160 } 1161 1162 if a == root { 1163 close(b.readySema) 1164 } 1165 } 1166 1167 var wg sync.WaitGroup 1168 1169 // Kick off goroutines according to parallelism. 1170 // If we are using the -n flag (just printing commands) 1171 // drop the parallelism to 1, both to make the output 1172 // deterministic and because there is no real work anyway. 1173 par := buildP 1174 if buildN { 1175 par = 1 1176 } 1177 for i := 0; i < par; i++ { 1178 wg.Add(1) 1179 go func() { 1180 defer wg.Done() 1181 for { 1182 select { 1183 case _, ok := <-b.readySema: 1184 if !ok { 1185 return 1186 } 1187 // Receiving a value from b.readySema entitles 1188 // us to take from the ready queue. 1189 b.exec.Lock() 1190 a := b.ready.pop() 1191 b.exec.Unlock() 1192 handle(a) 1193 case <-interrupted: 1194 setExitStatus(1) 1195 return 1196 } 1197 } 1198 }() 1199 } 1200 1201 wg.Wait() 1202 } 1203 1204 // hasString reports whether s appears in the list of strings. 1205 func hasString(strings []string, s string) bool { 1206 for _, t := range strings { 1207 if s == t { 1208 return true 1209 } 1210 } 1211 return false 1212 } 1213 1214 // build is the action for building a single package or command. 1215 func (b *builder) build(a *action) (err error) { 1216 // Return an error if the package has CXX files but it's not using 1217 // cgo nor SWIG, since the CXX files can only be processed by cgo 1218 // and SWIG. 1219 if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() { 1220 return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG", 1221 a.p.ImportPath, strings.Join(a.p.CXXFiles, ",")) 1222 } 1223 // Same as above for Objective-C files 1224 if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() { 1225 return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG", 1226 a.p.ImportPath, strings.Join(a.p.MFiles, ",")) 1227 } 1228 defer func() { 1229 if err != nil && err != errPrintedOutput { 1230 err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err) 1231 } 1232 }() 1233 if buildN { 1234 // In -n mode, print a banner between packages. 1235 // The banner is five lines so that when changes to 1236 // different sections of the bootstrap script have to 1237 // be merged, the banners give patch something 1238 // to use to find its context. 1239 fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath) 1240 } 1241 1242 if buildV { 1243 fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath) 1244 } 1245 1246 if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" && 1247 (!hasString(a.p.GoFiles, "zgoos_"+buildContext.GOOS+".go") || 1248 !hasString(a.p.GoFiles, "zgoarch_"+buildContext.GOARCH+".go")) { 1249 return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix()) 1250 } 1251 1252 // Make build directory. 1253 obj := a.objdir 1254 if err := b.mkdir(obj); err != nil { 1255 return err 1256 } 1257 1258 // make target directory 1259 dir, _ := filepath.Split(a.target) 1260 if dir != "" { 1261 if err := b.mkdir(dir); err != nil { 1262 return err 1263 } 1264 } 1265 1266 var gofiles, cgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string 1267 1268 gofiles = append(gofiles, a.p.GoFiles...) 1269 cgofiles = append(cgofiles, a.p.CgoFiles...) 1270 cfiles = append(cfiles, a.p.CFiles...) 1271 sfiles = append(sfiles, a.p.SFiles...) 1272 cxxfiles = append(cxxfiles, a.p.CXXFiles...) 1273 1274 if a.p.usesCgo() || a.p.usesSwig() { 1275 if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil { 1276 return 1277 } 1278 } 1279 1280 // Run SWIG on each .swig and .swigcxx file. 1281 // Each run will generate two files, a .go file and a .c or .cxx file. 1282 // The .go file will use import "C" and is to be processed by cgo. 1283 if a.p.usesSwig() { 1284 outGo, outC, outCXX, err := b.swig(a.p, obj, pcCFLAGS) 1285 if err != nil { 1286 return err 1287 } 1288 cgofiles = append(cgofiles, outGo...) 1289 cfiles = append(cfiles, outC...) 1290 cxxfiles = append(cxxfiles, outCXX...) 1291 } 1292 1293 // Run cgo. 1294 if a.p.usesCgo() || a.p.usesSwig() { 1295 // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc. 1296 // There is one exception: runtime/cgo's job is to bridge the 1297 // cgo and non-cgo worlds, so it necessarily has files in both. 1298 // In that case gcc only gets the gcc_* files. 1299 var gccfiles []string 1300 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { 1301 filter := func(files, nongcc, gcc []string) ([]string, []string) { 1302 for _, f := range files { 1303 if strings.HasPrefix(f, "gcc_") { 1304 gcc = append(gcc, f) 1305 } else { 1306 nongcc = append(nongcc, f) 1307 } 1308 } 1309 return nongcc, gcc 1310 } 1311 cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles) 1312 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) 1313 } else { 1314 gccfiles = append(cfiles, sfiles...) 1315 cfiles = nil 1316 sfiles = nil 1317 } 1318 1319 cgoExe := tool("cgo") 1320 if a.cgo != nil && a.cgo.target != "" { 1321 cgoExe = a.cgo.target 1322 } 1323 outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, cxxfiles, a.p.MFiles) 1324 if err != nil { 1325 return err 1326 } 1327 cgoObjects = append(cgoObjects, outObj...) 1328 gofiles = append(gofiles, outGo...) 1329 } 1330 1331 if len(gofiles) == 0 { 1332 return &build.NoGoError{Dir: a.p.Dir} 1333 } 1334 1335 // If we're doing coverage, preprocess the .go files and put them in the work directory 1336 if a.p.coverMode != "" { 1337 for i, file := range gofiles { 1338 var sourceFile string 1339 var coverFile string 1340 var key string 1341 if strings.HasSuffix(file, ".cgo1.go") { 1342 // cgo files have absolute paths 1343 base := filepath.Base(file) 1344 sourceFile = file 1345 coverFile = filepath.Join(obj, base) 1346 key = strings.TrimSuffix(base, ".cgo1.go") + ".go" 1347 } else { 1348 sourceFile = filepath.Join(a.p.Dir, file) 1349 coverFile = filepath.Join(obj, file) 1350 key = file 1351 } 1352 cover := a.p.coverVars[key] 1353 if cover == nil || isTestFile(file) { 1354 // Not covering this file. 1355 continue 1356 } 1357 if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil { 1358 return err 1359 } 1360 gofiles[i] = coverFile 1361 } 1362 } 1363 1364 // Prepare Go import path list. 1365 inc := b.includeArgs("-I", allArchiveActions(a)) 1366 1367 // Compile Go. 1368 ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, len(sfiles) > 0, inc, gofiles) 1369 if len(out) > 0 { 1370 b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out)) 1371 if err != nil { 1372 return errPrintedOutput 1373 } 1374 } 1375 if err != nil { 1376 return err 1377 } 1378 if ofile != a.objpkg { 1379 objects = append(objects, ofile) 1380 } 1381 1382 // Copy .h files named for goos or goarch or goos_goarch 1383 // to names using GOOS and GOARCH. 1384 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. 1385 _goos_goarch := "_" + goos + "_" + goarch 1386 _goos := "_" + goos 1387 _goarch := "_" + goarch 1388 for _, file := range a.p.HFiles { 1389 name, ext := fileExtSplit(file) 1390 switch { 1391 case strings.HasSuffix(name, _goos_goarch): 1392 targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext 1393 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil { 1394 return err 1395 } 1396 case strings.HasSuffix(name, _goarch): 1397 targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext 1398 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil { 1399 return err 1400 } 1401 case strings.HasSuffix(name, _goos): 1402 targ := file[:len(name)-len(_goos)] + "_GOOS." + ext 1403 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil { 1404 return err 1405 } 1406 } 1407 } 1408 1409 for _, file := range cfiles { 1410 out := file[:len(file)-len(".c")] + ".o" 1411 if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil { 1412 return err 1413 } 1414 objects = append(objects, out) 1415 } 1416 1417 // Assemble .s files. 1418 for _, file := range sfiles { 1419 out := file[:len(file)-len(".s")] + ".o" 1420 if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil { 1421 return err 1422 } 1423 objects = append(objects, out) 1424 } 1425 1426 // NOTE(rsc): On Windows, it is critically important that the 1427 // gcc-compiled objects (cgoObjects) be listed after the ordinary 1428 // objects in the archive. I do not know why this is. 1429 // https://golang.org/issue/2601 1430 objects = append(objects, cgoObjects...) 1431 1432 // Add system object files. 1433 for _, syso := range a.p.SysoFiles { 1434 objects = append(objects, filepath.Join(a.p.Dir, syso)) 1435 } 1436 1437 // Pack into archive in obj directory. 1438 // If the Go compiler wrote an archive, we only need to add the 1439 // object files for non-Go sources to the archive. 1440 // If the Go compiler wrote an archive and the package is entirely 1441 // Go sources, there is no pack to execute at all. 1442 if len(objects) > 0 { 1443 if err := buildToolchain.pack(b, a.p, obj, a.objpkg, objects); err != nil { 1444 return err 1445 } 1446 } 1447 1448 // Link if needed. 1449 if a.link { 1450 // The compiler only cares about direct imports, but the 1451 // linker needs the whole dependency tree. 1452 all := actionList(a) 1453 all = all[:len(all)-1] // drop a 1454 if err := buildToolchain.ld(b, a, a.target, all, a.objpkg, objects); err != nil { 1455 return err 1456 } 1457 } 1458 1459 return nil 1460 } 1461 1462 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. 1463 func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) { 1464 if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { 1465 var out []byte 1466 out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) 1467 if err != nil { 1468 b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out)) 1469 b.print(err.Error() + "\n") 1470 err = errPrintedOutput 1471 return 1472 } 1473 if len(out) > 0 { 1474 cflags = strings.Fields(string(out)) 1475 } 1476 out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs) 1477 if err != nil { 1478 b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out)) 1479 b.print(err.Error() + "\n") 1480 err = errPrintedOutput 1481 return 1482 } 1483 if len(out) > 0 { 1484 ldflags = strings.Fields(string(out)) 1485 } 1486 } 1487 return 1488 } 1489 1490 func (b *builder) installShlibname(a *action) error { 1491 a1 := a.deps[0] 1492 err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0644) 1493 if err != nil { 1494 return err 1495 } 1496 if buildX { 1497 b.showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.target), a.target) 1498 } 1499 return nil 1500 } 1501 1502 func (b *builder) linkShared(a *action) (err error) { 1503 allactions := actionList(a) 1504 allactions = allactions[:len(allactions)-1] 1505 return buildToolchain.ldShared(b, a.deps, a.target, allactions) 1506 } 1507 1508 // install is the action for installing a single package or executable. 1509 func (b *builder) install(a *action) (err error) { 1510 defer func() { 1511 if err != nil && err != errPrintedOutput { 1512 err = fmt.Errorf("go install %s: %v", a.p.ImportPath, err) 1513 } 1514 }() 1515 a1 := a.deps[0] 1516 perm := os.FileMode(0644) 1517 if a1.link { 1518 switch buildBuildmode { 1519 case "c-archive", "c-shared": 1520 default: 1521 perm = 0755 1522 } 1523 } 1524 1525 // make target directory 1526 dir, _ := filepath.Split(a.target) 1527 if dir != "" { 1528 if err := b.mkdir(dir); err != nil { 1529 return err 1530 } 1531 } 1532 1533 // remove object dir to keep the amount of 1534 // garbage down in a large build. On an operating system 1535 // with aggressive buffering, cleaning incrementally like 1536 // this keeps the intermediate objects from hitting the disk. 1537 if !buildWork { 1538 defer os.RemoveAll(a1.objdir) 1539 defer os.Remove(a1.target) 1540 } 1541 1542 return b.moveOrCopyFile(a, a.target, a1.target, perm, false) 1543 } 1544 1545 // includeArgs returns the -I or -L directory list for access 1546 // to the results of the list of actions. 1547 func (b *builder) includeArgs(flag string, all []*action) []string { 1548 inc := []string{} 1549 incMap := map[string]bool{ 1550 b.work: true, // handled later 1551 gorootPkg: true, 1552 "": true, // ignore empty strings 1553 } 1554 1555 // Look in the temporary space for results of test-specific actions. 1556 // This is the $WORK/my/package/_test directory for the 1557 // package being built, so there are few of these. 1558 for _, a1 := range all { 1559 if a1.p == nil { 1560 continue 1561 } 1562 if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] { 1563 incMap[dir] = true 1564 inc = append(inc, flag, dir) 1565 } 1566 } 1567 1568 // Also look in $WORK for any non-test packages that have 1569 // been built but not installed. 1570 inc = append(inc, flag, b.work) 1571 1572 // Finally, look in the installed package directories for each action. 1573 for _, a1 := range all { 1574 if a1.p == nil { 1575 continue 1576 } 1577 if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] { 1578 incMap[dir] = true 1579 inc = append(inc, flag, a1.p.build.PkgTargetRoot) 1580 } 1581 } 1582 1583 return inc 1584 } 1585 1586 // moveOrCopyFile is like 'mv src dst' or 'cp src dst'. 1587 func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, force bool) error { 1588 if buildN { 1589 b.showcmd("", "mv %s %s", src, dst) 1590 return nil 1591 } 1592 1593 // If we can update the mode and rename to the dst, do it. 1594 // Otherwise fall back to standard copy. 1595 if err := os.Chmod(src, perm); err == nil { 1596 if err := os.Rename(src, dst); err == nil { 1597 if buildX { 1598 b.showcmd("", "mv %s %s", src, dst) 1599 } 1600 return nil 1601 } 1602 } 1603 1604 return b.copyFile(a, dst, src, perm, force) 1605 } 1606 1607 // copyFile is like 'cp src dst'. 1608 func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force bool) error { 1609 if buildN || buildX { 1610 b.showcmd("", "cp %s %s", src, dst) 1611 if buildN { 1612 return nil 1613 } 1614 } 1615 1616 sf, err := os.Open(src) 1617 if err != nil { 1618 return err 1619 } 1620 defer sf.Close() 1621 1622 // Be careful about removing/overwriting dst. 1623 // Do not remove/overwrite if dst exists and is a directory 1624 // or a non-object file. 1625 if fi, err := os.Stat(dst); err == nil { 1626 if fi.IsDir() { 1627 return fmt.Errorf("build output %q already exists and is a directory", dst) 1628 } 1629 if !force && !isObject(dst) { 1630 return fmt.Errorf("build output %q already exists and is not an object file", dst) 1631 } 1632 } 1633 1634 // On Windows, remove lingering ~ file from last attempt. 1635 if toolIsWindows { 1636 if _, err := os.Stat(dst + "~"); err == nil { 1637 os.Remove(dst + "~") 1638 } 1639 } 1640 1641 os.Remove(dst) 1642 df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) 1643 if err != nil && toolIsWindows { 1644 // Windows does not allow deletion of a binary file 1645 // while it is executing. Try to move it out of the way. 1646 // If the move fails, which is likely, we'll try again the 1647 // next time we do an install of this binary. 1648 if err := os.Rename(dst, dst+"~"); err == nil { 1649 os.Remove(dst + "~") 1650 } 1651 df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) 1652 } 1653 if err != nil { 1654 return err 1655 } 1656 1657 _, err = io.Copy(df, sf) 1658 df.Close() 1659 if err != nil { 1660 os.Remove(dst) 1661 return fmt.Errorf("copying %s to %s: %v", src, dst, err) 1662 } 1663 return nil 1664 } 1665 1666 // Install the cgo export header file, if there is one. 1667 func (b *builder) installHeader(a *action) error { 1668 src := a.objdir + "_cgo_install.h" 1669 if _, err := os.Stat(src); os.IsNotExist(err) { 1670 // If the file does not exist, there are no exported 1671 // functions, and we do not install anything. 1672 return nil 1673 } 1674 1675 dir, _ := filepath.Split(a.target) 1676 if dir != "" { 1677 if err := b.mkdir(dir); err != nil { 1678 return err 1679 } 1680 } 1681 1682 return b.moveOrCopyFile(a, a.target, src, 0644, true) 1683 } 1684 1685 // cover runs, in effect, 1686 // go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go 1687 func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error { 1688 return b.run(a.objdir, "cover "+a.p.ImportPath, nil, 1689 buildToolExec, 1690 tool("cover"), 1691 "-mode", a.p.coverMode, 1692 "-var", varName, 1693 "-o", dst, 1694 src) 1695 } 1696 1697 var objectMagic = [][]byte{ 1698 {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive 1699 {'\x7F', 'E', 'L', 'F'}, // ELF 1700 {0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit 1701 {0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit 1702 {0xCE, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 32-bit 1703 {0xCF, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 64-bit 1704 {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00}, // PE (Windows) as generated by 6l/8l and gcc 1705 {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386 1706 {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64 1707 } 1708 1709 func isObject(s string) bool { 1710 f, err := os.Open(s) 1711 if err != nil { 1712 return false 1713 } 1714 defer f.Close() 1715 buf := make([]byte, 64) 1716 io.ReadFull(f, buf) 1717 for _, magic := range objectMagic { 1718 if bytes.HasPrefix(buf, magic) { 1719 return true 1720 } 1721 } 1722 return false 1723 } 1724 1725 // fmtcmd formats a command in the manner of fmt.Sprintf but also: 1726 // 1727 // If dir is non-empty and the script is not in dir right now, 1728 // fmtcmd inserts "cd dir\n" before the command. 1729 // 1730 // fmtcmd replaces the value of b.work with $WORK. 1731 // fmtcmd replaces the value of goroot with $GOROOT. 1732 // fmtcmd replaces the value of b.gobin with $GOBIN. 1733 // 1734 // fmtcmd replaces the name of the current directory with dot (.) 1735 // but only when it is at the beginning of a space-separated token. 1736 // 1737 func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string { 1738 cmd := fmt.Sprintf(format, args...) 1739 if dir != "" && dir != "/" { 1740 cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:] 1741 if b.scriptDir != dir { 1742 b.scriptDir = dir 1743 cmd = "cd " + dir + "\n" + cmd 1744 } 1745 } 1746 if b.work != "" { 1747 cmd = strings.Replace(cmd, b.work, "$WORK", -1) 1748 } 1749 return cmd 1750 } 1751 1752 // showcmd prints the given command to standard output 1753 // for the implementation of -n or -x. 1754 func (b *builder) showcmd(dir string, format string, args ...interface{}) { 1755 b.output.Lock() 1756 defer b.output.Unlock() 1757 b.print(b.fmtcmd(dir, format, args...) + "\n") 1758 } 1759 1760 // showOutput prints "# desc" followed by the given output. 1761 // The output is expected to contain references to 'dir', usually 1762 // the source directory for the package that has failed to build. 1763 // showOutput rewrites mentions of dir with a relative path to dir 1764 // when the relative path is shorter. This is usually more pleasant. 1765 // For example, if fmt doesn't compile and we are in src/html, 1766 // the output is 1767 // 1768 // $ go build 1769 // # fmt 1770 // ../fmt/print.go:1090: undefined: asdf 1771 // $ 1772 // 1773 // instead of 1774 // 1775 // $ go build 1776 // # fmt 1777 // /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf 1778 // $ 1779 // 1780 // showOutput also replaces references to the work directory with $WORK. 1781 // 1782 func (b *builder) showOutput(dir, desc, out string) { 1783 prefix := "# " + desc 1784 suffix := "\n" + out 1785 if reldir := shortPath(dir); reldir != dir { 1786 suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1) 1787 suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1) 1788 } 1789 suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1) 1790 1791 b.output.Lock() 1792 defer b.output.Unlock() 1793 b.print(prefix, suffix) 1794 } 1795 1796 // shortPath returns an absolute or relative name for path, whatever is shorter. 1797 func shortPath(path string) string { 1798 if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) { 1799 return rel 1800 } 1801 return path 1802 } 1803 1804 // relPaths returns a copy of paths with absolute paths 1805 // made relative to the current directory if they would be shorter. 1806 func relPaths(paths []string) []string { 1807 var out []string 1808 pwd, _ := os.Getwd() 1809 for _, p := range paths { 1810 rel, err := filepath.Rel(pwd, p) 1811 if err == nil && len(rel) < len(p) { 1812 p = rel 1813 } 1814 out = append(out, p) 1815 } 1816 return out 1817 } 1818 1819 // errPrintedOutput is a special error indicating that a command failed 1820 // but that it generated output as well, and that output has already 1821 // been printed, so there's no point showing 'exit status 1' or whatever 1822 // the wait status was. The main executor, builder.do, knows not to 1823 // print this error. 1824 var errPrintedOutput = errors.New("already printed output - no need to show error") 1825 1826 var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`) 1827 var cgoTypeSigRe = regexp.MustCompile(`\b_Ctype_\B`) 1828 1829 // run runs the command given by cmdline in the directory dir. 1830 // If the command fails, run prints information about the failure 1831 // and returns a non-nil error. 1832 func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error { 1833 out, err := b.runOut(dir, desc, env, cmdargs...) 1834 if len(out) > 0 { 1835 if desc == "" { 1836 desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " ")) 1837 } 1838 b.showOutput(dir, desc, b.processOutput(out)) 1839 if err != nil { 1840 err = errPrintedOutput 1841 } 1842 } 1843 return err 1844 } 1845 1846 // processOutput prepares the output of runOut to be output to the console. 1847 func (b *builder) processOutput(out []byte) string { 1848 if out[len(out)-1] != '\n' { 1849 out = append(out, '\n') 1850 } 1851 messages := string(out) 1852 // Fix up output referring to cgo-generated code to be more readable. 1853 // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19. 1854 // Replace *[100]_Ctype_foo with *[100]C.foo. 1855 // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite. 1856 if !buildX && cgoLine.MatchString(messages) { 1857 messages = cgoLine.ReplaceAllString(messages, "") 1858 messages = cgoTypeSigRe.ReplaceAllString(messages, "C.") 1859 } 1860 return messages 1861 } 1862 1863 // runOut runs the command given by cmdline in the directory dir. 1864 // It returns the command output and any errors that occurred. 1865 func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) { 1866 cmdline := stringList(cmdargs...) 1867 if buildN || buildX { 1868 var envcmdline string 1869 for i := range env { 1870 envcmdline += env[i] 1871 envcmdline += " " 1872 } 1873 envcmdline += joinUnambiguously(cmdline) 1874 b.showcmd(dir, "%s", envcmdline) 1875 if buildN { 1876 return nil, nil 1877 } 1878 } 1879 1880 nbusy := 0 1881 for { 1882 var buf bytes.Buffer 1883 cmd := exec.Command(cmdline[0], cmdline[1:]...) 1884 cmd.Stdout = &buf 1885 cmd.Stderr = &buf 1886 cmd.Dir = dir 1887 cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir, os.Environ())) 1888 err := cmd.Run() 1889 1890 // cmd.Run will fail on Unix if some other process has the binary 1891 // we want to run open for writing. This can happen here because 1892 // we build and install the cgo command and then run it. 1893 // If another command was kicked off while we were writing the 1894 // cgo binary, the child process for that command may be holding 1895 // a reference to the fd, keeping us from running exec. 1896 // 1897 // But, you might reasonably wonder, how can this happen? 1898 // The cgo fd, like all our fds, is close-on-exec, so that we need 1899 // not worry about other processes inheriting the fd accidentally. 1900 // The answer is that running a command is fork and exec. 1901 // A child forked while the cgo fd is open inherits that fd. 1902 // Until the child has called exec, it holds the fd open and the 1903 // kernel will not let us run cgo. Even if the child were to close 1904 // the fd explicitly, it would still be open from the time of the fork 1905 // until the time of the explicit close, and the race would remain. 1906 // 1907 // On Unix systems, this results in ETXTBSY, which formats 1908 // as "text file busy". Rather than hard-code specific error cases, 1909 // we just look for that string. If this happens, sleep a little 1910 // and try again. We let this happen three times, with increasing 1911 // sleep lengths: 100+200+400 ms = 0.7 seconds. 1912 // 1913 // An alternate solution might be to split the cmd.Run into 1914 // separate cmd.Start and cmd.Wait, and then use an RWLock 1915 // to make sure that copyFile only executes when no cmd.Start 1916 // call is in progress. However, cmd.Start (really syscall.forkExec) 1917 // only guarantees that when it returns, the exec is committed to 1918 // happen and succeed. It uses a close-on-exec file descriptor 1919 // itself to determine this, so we know that when cmd.Start returns, 1920 // at least one close-on-exec file descriptor has been closed. 1921 // However, we cannot be sure that all of them have been closed, 1922 // so the program might still encounter ETXTBSY even with such 1923 // an RWLock. The race window would be smaller, perhaps, but not 1924 // guaranteed to be gone. 1925 // 1926 // Sleeping when we observe the race seems to be the most reliable 1927 // option we have. 1928 // 1929 // https://golang.org/issue/3001 1930 // 1931 if err != nil && nbusy < 3 && strings.Contains(err.Error(), "text file busy") { 1932 time.Sleep(100 * time.Millisecond << uint(nbusy)) 1933 nbusy++ 1934 continue 1935 } 1936 1937 // err can be something like 'exit status 1'. 1938 // Add information about what program was running. 1939 // Note that if buf.Bytes() is non-empty, the caller usually 1940 // shows buf.Bytes() and does not print err at all, so the 1941 // prefix here does not make most output any more verbose. 1942 if err != nil { 1943 err = errors.New(cmdline[0] + ": " + err.Error()) 1944 } 1945 return buf.Bytes(), err 1946 } 1947 } 1948 1949 // joinUnambiguously prints the slice, quoting where necessary to make the 1950 // output unambiguous. 1951 // TODO: See issue 5279. The printing of commands needs a complete redo. 1952 func joinUnambiguously(a []string) string { 1953 var buf bytes.Buffer 1954 for i, s := range a { 1955 if i > 0 { 1956 buf.WriteByte(' ') 1957 } 1958 q := strconv.Quote(s) 1959 if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 { 1960 buf.WriteString(q) 1961 } else { 1962 buf.WriteString(s) 1963 } 1964 } 1965 return buf.String() 1966 } 1967 1968 // mkdir makes the named directory. 1969 func (b *builder) mkdir(dir string) error { 1970 b.exec.Lock() 1971 defer b.exec.Unlock() 1972 // We can be a little aggressive about being 1973 // sure directories exist. Skip repeated calls. 1974 if b.mkdirCache[dir] { 1975 return nil 1976 } 1977 b.mkdirCache[dir] = true 1978 1979 if buildN || buildX { 1980 b.showcmd("", "mkdir -p %s", dir) 1981 if buildN { 1982 return nil 1983 } 1984 } 1985 1986 if err := os.MkdirAll(dir, 0777); err != nil { 1987 return err 1988 } 1989 return nil 1990 } 1991 1992 // mkAbs returns an absolute path corresponding to 1993 // evaluating f in the directory dir. 1994 // We always pass absolute paths of source files so that 1995 // the error messages will include the full path to a file 1996 // in need of attention. 1997 func mkAbs(dir, f string) string { 1998 // Leave absolute paths alone. 1999 // Also, during -n mode we use the pseudo-directory $WORK 2000 // instead of creating an actual work directory that won't be used. 2001 // Leave paths beginning with $WORK alone too. 2002 if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") { 2003 return f 2004 } 2005 return filepath.Join(dir, f) 2006 } 2007 2008 type toolchain interface { 2009 // gc runs the compiler in a specific directory on a set of files 2010 // and returns the name of the generated output file. 2011 // The compiler runs in the directory dir. 2012 gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) 2013 // cc runs the toolchain's C compiler in a directory on a C file 2014 // to produce an output file. 2015 cc(b *builder, p *Package, objdir, ofile, cfile string) error 2016 // asm runs the assembler in a specific directory on a specific file 2017 // to generate the named output file. 2018 asm(b *builder, p *Package, obj, ofile, sfile string) error 2019 // pkgpath builds an appropriate path for a temporary package file. 2020 pkgpath(basedir string, p *Package) string 2021 // pack runs the archive packer in a specific directory to create 2022 // an archive from a set of object files. 2023 // typically it is run in the object directory. 2024 pack(b *builder, p *Package, objDir, afile string, ofiles []string) error 2025 // ld runs the linker to create an executable starting at mainpkg. 2026 ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error 2027 // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions 2028 ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error 2029 2030 compiler() string 2031 linker() string 2032 } 2033 2034 type noToolchain struct{} 2035 2036 func noCompiler() error { 2037 log.Fatalf("unknown compiler %q", buildContext.Compiler) 2038 return nil 2039 } 2040 2041 func (noToolchain) compiler() string { 2042 noCompiler() 2043 return "" 2044 } 2045 2046 func (noToolchain) linker() string { 2047 noCompiler() 2048 return "" 2049 } 2050 2051 func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) { 2052 return "", nil, noCompiler() 2053 } 2054 2055 func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 2056 return noCompiler() 2057 } 2058 2059 func (noToolchain) pkgpath(basedir string, p *Package) string { 2060 noCompiler() 2061 return "" 2062 } 2063 2064 func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 2065 return noCompiler() 2066 } 2067 2068 func (noToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error { 2069 return noCompiler() 2070 } 2071 2072 func (noToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error { 2073 return noCompiler() 2074 } 2075 2076 func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 2077 return noCompiler() 2078 } 2079 2080 // General toolchain. 2081 type generalToolchain struct { 2082 compilerBin string 2083 } 2084 2085 func noGeneralToolchain(method string) error { 2086 log.Fatalf("generalToolchain.%s: not impl", method) 2087 return nil 2088 } 2089 2090 func (g generalToolchain) compiler() string { 2091 return g.compilerBin 2092 } 2093 2094 func (generalToolchain) linker() string { 2095 noGeneralToolchain("linker") 2096 return "" 2097 } 2098 2099 func (generalToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) { 2100 //goon.DumpExpr(p, archive, obj, asmhdr, importArgs, gofiles) 2101 //log.Println("generalToolchain.gc:", p.ImportPath) 2102 // Compiler (of individual packages) is not supported at this time. 2103 if archive != "" { 2104 ofile = archive 2105 } else { 2106 out := "_go_.o" 2107 ofile = obj + out 2108 } 2109 //log.Println("generalToolchain.gc:", ofile) 2110 return "", nil, nil 2111 } 2112 2113 func (generalToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 2114 //log.Println("generalToolchain.asm:", p.ImportPath) 2115 return nil 2116 } 2117 2118 func (generalToolchain) pkgpath(basedir string, p *Package) string { 2119 end := filepath.FromSlash(p.ImportPath + ".a") 2120 return filepath.Join(basedir, end) 2121 } 2122 2123 func (generalToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 2124 //log.Println("generalToolchain.pack:", p.ImportPath) 2125 return nil 2126 } 2127 2128 func (g generalToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error { 2129 //x// Linker is not supported at this time. 2130 /*goon.DumpExpr(root.p.Dir, root.p.GoFiles) //goon.DumpExpr(root) 2131 goon.DumpExpr(out) 2132 //goon.DumpExpr(allactions) 2133 goon.DumpExpr(mainpkg) 2134 goon.DumpExpr(ofiles) 2135 log.Println("generalToolchain.ld")*/ 2136 2137 // HACK: GopherJS-specific for now. 2138 /*var files[]string 2139 for _, goFile := range root.p.GoFiles { 2140 files = append(filepath.Join(root.p.Dir, goFile)) 2141 }*/ 2142 2143 // HACK: Try to remove GOARCH=js. 2144 env := []string{"GOARCH=amd64"} 2145 2146 // TODO: buildToolExec. 2147 cmdargs := []interface{}{g.compilerBin, "build", "-o", out} 2148 for _, goFile := range root.p.GoFiles { 2149 cmdargs = append(cmdargs, goFile) 2150 } 2151 2152 return b.run(root.p.Dir, root.p.ImportPath, env, cmdargs...) 2153 } 2154 2155 func (generalToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error { 2156 return noGeneralToolchain("ldShared") 2157 } 2158 2159 func (generalToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 2160 return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile)) 2161 } 2162 2163 // The Go toolchain. 2164 type gcToolchain struct{} 2165 2166 func (gcToolchain) compiler() string { 2167 return tool("compile") 2168 } 2169 2170 func (gcToolchain) linker() string { 2171 return tool("link") 2172 } 2173 2174 func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { 2175 if archive != "" { 2176 ofile = archive 2177 } else { 2178 out := "_go_.o" 2179 ofile = obj + out 2180 } 2181 2182 gcargs := []string{"-p", p.ImportPath} 2183 if p.Name == "main" { 2184 gcargs[1] = "main" 2185 } 2186 if p.Standard && p.ImportPath == "runtime" { 2187 // runtime compiles with a special gc flag to emit 2188 // additional reflect type data. 2189 gcargs = append(gcargs, "-+") 2190 } 2191 2192 // If we're giving the compiler the entire package (no C etc files), tell it that, 2193 // so that it can give good error messages about forward declarations. 2194 // Exceptions: a few standard packages have forward declarations for 2195 // pieces supplied behind-the-scenes by package runtime. 2196 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) 2197 if p.Standard { 2198 switch p.ImportPath { 2199 case "bytes", "net", "os", "runtime/pprof", "sync", "time": 2200 extFiles++ 2201 } 2202 } 2203 if extFiles == 0 { 2204 gcargs = append(gcargs, "-complete") 2205 } 2206 if buildContext.InstallSuffix != "" { 2207 gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix) 2208 } 2209 if p.buildID != "" { 2210 gcargs = append(gcargs, "-buildid", p.buildID) 2211 } 2212 2213 for _, path := range p.Imports { 2214 if i := strings.LastIndex(path, "/vendor/"); i >= 0 { 2215 gcargs = append(gcargs, "-importmap", path[i+len("/vendor/"):]+"="+path) 2216 } else if strings.HasPrefix(path, "vendor/") { 2217 gcargs = append(gcargs, "-importmap", path[len("vendor/"):]+"="+path) 2218 } 2219 } 2220 2221 args := []interface{}{buildToolExec, tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs} 2222 if ofile == archive { 2223 args = append(args, "-pack") 2224 } 2225 if asmhdr { 2226 args = append(args, "-asmhdr", obj+"go_asm.h") 2227 } 2228 for _, f := range gofiles { 2229 args = append(args, mkAbs(p.Dir, f)) 2230 } 2231 2232 output, err = b.runOut(p.Dir, p.ImportPath, nil, args...) 2233 return ofile, output, err 2234 } 2235 2236 func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 2237 // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. 2238 inc := filepath.Join(goroot, "pkg", "include") 2239 sfile = mkAbs(p.Dir, sfile) 2240 args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags, sfile} 2241 if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil { 2242 return err 2243 } 2244 return nil 2245 } 2246 2247 // toolVerify checks that the command line args writes the same output file 2248 // if run using newTool instead. 2249 // Unused now but kept around for future use. 2250 func toolVerify(b *builder, p *Package, newTool string, ofile string, args []interface{}) error { 2251 newArgs := make([]interface{}, len(args)) 2252 copy(newArgs, args) 2253 newArgs[1] = tool(newTool) 2254 newArgs[3] = ofile + ".new" // x.6 becomes x.6.new 2255 if err := b.run(p.Dir, p.ImportPath, nil, newArgs...); err != nil { 2256 return err 2257 } 2258 data1, err := ioutil.ReadFile(ofile) 2259 if err != nil { 2260 return err 2261 } 2262 data2, err := ioutil.ReadFile(ofile + ".new") 2263 if err != nil { 2264 return err 2265 } 2266 if !bytes.Equal(data1, data2) { 2267 return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(stringList(args...), " "), strings.Join(stringList(newArgs...), " ")) 2268 } 2269 os.Remove(ofile + ".new") 2270 return nil 2271 } 2272 2273 func (gcToolchain) pkgpath(basedir string, p *Package) string { 2274 end := filepath.FromSlash(p.ImportPath + ".a") 2275 return filepath.Join(basedir, end) 2276 } 2277 2278 func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 2279 var absOfiles []string 2280 for _, f := range ofiles { 2281 absOfiles = append(absOfiles, mkAbs(objDir, f)) 2282 } 2283 cmd := "c" 2284 absAfile := mkAbs(objDir, afile) 2285 appending := false 2286 if _, err := os.Stat(absAfile); err == nil { 2287 appending = true 2288 cmd = "r" 2289 } 2290 2291 cmdline := stringList("pack", cmd, absAfile, absOfiles) 2292 2293 if appending { 2294 if buildN || buildX { 2295 b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline)) 2296 } 2297 if buildN { 2298 return nil 2299 } 2300 if err := packInternal(b, absAfile, absOfiles); err != nil { 2301 b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n") 2302 return errPrintedOutput 2303 } 2304 return nil 2305 } 2306 2307 // Need actual pack. 2308 cmdline[0] = tool("pack") 2309 return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cmdline) 2310 } 2311 2312 func packInternal(b *builder, afile string, ofiles []string) error { 2313 dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0) 2314 if err != nil { 2315 return err 2316 } 2317 defer dst.Close() // only for error returns or panics 2318 w := bufio.NewWriter(dst) 2319 2320 for _, ofile := range ofiles { 2321 src, err := os.Open(ofile) 2322 if err != nil { 2323 return err 2324 } 2325 fi, err := src.Stat() 2326 if err != nil { 2327 src.Close() 2328 return err 2329 } 2330 // Note: Not using %-16.16s format because we care 2331 // about bytes, not runes. 2332 name := fi.Name() 2333 if len(name) > 16 { 2334 name = name[:16] 2335 } else { 2336 name += strings.Repeat(" ", 16-len(name)) 2337 } 2338 size := fi.Size() 2339 fmt.Fprintf(w, "%s%-12d%-6d%-6d%-8o%-10d`\n", 2340 name, 0, 0, 0, 0644, size) 2341 n, err := io.Copy(w, src) 2342 src.Close() 2343 if err == nil && n < size { 2344 err = io.ErrUnexpectedEOF 2345 } else if err == nil && n > size { 2346 err = fmt.Errorf("file larger than size reported by stat") 2347 } 2348 if err != nil { 2349 return fmt.Errorf("copying %s to %s: %v", ofile, afile, err) 2350 } 2351 if size&1 != 0 { 2352 w.WriteByte(0) 2353 } 2354 } 2355 2356 if err := w.Flush(); err != nil { 2357 return err 2358 } 2359 return dst.Close() 2360 } 2361 2362 // setextld sets the appropriate linker flags for the specified compiler. 2363 func setextld(ldflags []string, compiler []string) []string { 2364 for _, f := range ldflags { 2365 if f == "-extld" || strings.HasPrefix(f, "-extld=") { 2366 // don't override -extld if supplied 2367 return ldflags 2368 } 2369 } 2370 ldflags = append(ldflags, "-extld="+compiler[0]) 2371 if len(compiler) > 1 { 2372 extldflags := false 2373 add := strings.Join(compiler[1:], " ") 2374 for i, f := range ldflags { 2375 if f == "-extldflags" && i+1 < len(ldflags) { 2376 ldflags[i+1] = add + " " + ldflags[i+1] 2377 extldflags = true 2378 break 2379 } else if strings.HasPrefix(f, "-extldflags=") { 2380 ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] 2381 extldflags = true 2382 break 2383 } 2384 } 2385 if !extldflags { 2386 ldflags = append(ldflags, "-extldflags="+add) 2387 } 2388 } 2389 return ldflags 2390 } 2391 2392 func (gcToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error { 2393 importArgs := b.includeArgs("-L", allactions) 2394 cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0 2395 for _, a := range allactions { 2396 if a.p != nil && (len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0) { 2397 cxx = true 2398 } 2399 } 2400 var ldflags []string 2401 if buildContext.InstallSuffix != "" { 2402 ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix) 2403 } 2404 if root.p.omitDWARF { 2405 ldflags = append(ldflags, "-w") 2406 } 2407 2408 // If the user has not specified the -extld option, then specify the 2409 // appropriate linker. In case of C++ code, use the compiler named 2410 // by the CXX environment variable or defaultCXX if CXX is not set. 2411 // Else, use the CC environment variable and defaultCC as fallback. 2412 var compiler []string 2413 if cxx { 2414 compiler = envList("CXX", defaultCXX) 2415 } else { 2416 compiler = envList("CC", defaultCC) 2417 } 2418 ldflags = setextld(ldflags, compiler) 2419 ldflags = append(ldflags, "-buildmode="+ldBuildmode) 2420 if root.p.buildID != "" { 2421 ldflags = append(ldflags, "-buildid="+root.p.buildID) 2422 } 2423 ldflags = append(ldflags, buildLdflags...) 2424 2425 // On OS X when using external linking to build a shared library, 2426 // the argument passed here to -o ends up recorded in the final 2427 // shared library in the LC_ID_DYLIB load command. 2428 // To avoid putting the temporary output directory name there 2429 // (and making the resulting shared library useless), 2430 // run the link in the output directory so that -o can name 2431 // just the final path element. 2432 dir := "." 2433 if goos == "darwin" && buildBuildmode == "c-shared" { 2434 dir, out = filepath.Split(out) 2435 } 2436 2437 return b.run(dir, root.p.ImportPath, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags, mainpkg) 2438 } 2439 2440 func (gcToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error { 2441 importArgs := b.includeArgs("-L", allactions) 2442 ldflags := []string{"-installsuffix", buildContext.InstallSuffix} 2443 ldflags = append(ldflags, "-buildmode=shared") 2444 ldflags = append(ldflags, buildLdflags...) 2445 cxx := false 2446 for _, a := range allactions { 2447 if a.p != nil && (len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0) { 2448 cxx = true 2449 } 2450 } 2451 // If the user has not specified the -extld option, then specify the 2452 // appropriate linker. In case of C++ code, use the compiler named 2453 // by the CXX environment variable or defaultCXX if CXX is not set. 2454 // Else, use the CC environment variable and defaultCC as fallback. 2455 var compiler []string 2456 if cxx { 2457 compiler = envList("CXX", defaultCXX) 2458 } else { 2459 compiler = envList("CC", defaultCC) 2460 } 2461 ldflags = setextld(ldflags, compiler) 2462 for _, d := range toplevelactions { 2463 if !strings.HasSuffix(d.target, ".a") { // omit unsafe etc and actions for other shared libraries 2464 continue 2465 } 2466 ldflags = append(ldflags, d.p.ImportPath+"="+d.target) 2467 } 2468 return b.run(".", out, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags) 2469 } 2470 2471 func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 2472 return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile)) 2473 } 2474 2475 // The Gccgo toolchain. 2476 type gccgoToolchain struct{} 2477 2478 var gccgoName, gccgoBin string 2479 2480 func init() { 2481 gccgoName = os.Getenv("GCCGO") 2482 if gccgoName == "" { 2483 gccgoName = "gccgo" 2484 } 2485 gccgoBin, _ = exec.LookPath(gccgoName) 2486 } 2487 2488 func (gccgoToolchain) compiler() string { 2489 return gccgoBin 2490 } 2491 2492 func (gccgoToolchain) linker() string { 2493 return gccgoBin 2494 } 2495 2496 func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { 2497 out := "_go_.o" 2498 ofile = obj + out 2499 gcargs := []string{"-g"} 2500 gcargs = append(gcargs, b.gccArchArgs()...) 2501 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 2502 gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) 2503 } 2504 if p.localPrefix != "" { 2505 gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix) 2506 } 2507 args := stringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) 2508 for _, f := range gofiles { 2509 args = append(args, mkAbs(p.Dir, f)) 2510 } 2511 2512 output, err = b.runOut(p.Dir, p.ImportPath, nil, args) 2513 return ofile, output, err 2514 } 2515 2516 func (tools gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 2517 sfile = mkAbs(p.Dir, sfile) 2518 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} 2519 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 2520 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 2521 } 2522 defs = tools.maybePIC(defs) 2523 defs = append(defs, b.gccArchArgs()...) 2524 return b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-I", obj, "-o", ofile, defs, sfile) 2525 } 2526 2527 func (gccgoToolchain) pkgpath(basedir string, p *Package) string { 2528 end := filepath.FromSlash(p.ImportPath + ".a") 2529 afile := filepath.Join(basedir, end) 2530 // add "lib" to the final element 2531 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) 2532 } 2533 2534 func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 2535 var absOfiles []string 2536 for _, f := range ofiles { 2537 absOfiles = append(absOfiles, mkAbs(objDir, f)) 2538 } 2539 return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles) 2540 } 2541 2542 func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error { 2543 // gccgo needs explicit linking with all package dependencies, 2544 // and all LDFLAGS from cgo dependencies. 2545 apackagesSeen := make(map[*Package]bool) 2546 afiles := []string{} 2547 shlibs := []string{} 2548 xfiles := []string{} 2549 ldflags := b.gccArchArgs() 2550 cgoldflags := []string{} 2551 usesCgo := false 2552 cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0 2553 objc := len(root.p.MFiles) > 0 2554 2555 actionsSeen := make(map[*action]bool) 2556 // Make a pre-order depth-first traversal of the action graph, taking note of 2557 // whether a shared library action has been seen on the way to an action (the 2558 // construction of the graph means that if any path to a node passes through 2559 // a shared library action, they all do). 2560 var walk func(a *action, seenShlib bool) 2561 walk = func(a *action, seenShlib bool) { 2562 if actionsSeen[a] { 2563 return 2564 } 2565 actionsSeen[a] = true 2566 if a.p != nil && !seenShlib { 2567 if a.p.Standard { 2568 return 2569 } 2570 // We record the target of the first time we see a .a file 2571 // for a package to make sure that we prefer the 'install' 2572 // rather than the 'build' location (which may not exist any 2573 // more). We still need to traverse the dependencies of the 2574 // build action though so saying 2575 // if apackagesSeen[a.p] { return } 2576 // doesn't work. 2577 if !apackagesSeen[a.p] { 2578 apackagesSeen[a.p] = true 2579 if a.p.fake && a.p.external { 2580 // external _tests, if present must come before 2581 // internal _tests. Store these on a separate list 2582 // and place them at the head after this loop. 2583 xfiles = append(xfiles, a.target) 2584 } else if a.p.fake { 2585 // move _test files to the top of the link order 2586 afiles = append([]string{a.target}, afiles...) 2587 } else { 2588 afiles = append(afiles, a.target) 2589 } 2590 } 2591 } 2592 if strings.HasSuffix(a.target, ".so") { 2593 shlibs = append(shlibs, a.target) 2594 seenShlib = true 2595 } 2596 for _, a1 := range a.deps { 2597 walk(a1, seenShlib) 2598 } 2599 } 2600 for _, a1 := range root.deps { 2601 walk(a1, false) 2602 } 2603 afiles = append(xfiles, afiles...) 2604 2605 for _, a := range allactions { 2606 // Gather CgoLDFLAGS, but not from standard packages. 2607 // The go tool can dig up runtime/cgo from GOROOT and 2608 // think that it should use its CgoLDFLAGS, but gccgo 2609 // doesn't use runtime/cgo. 2610 if a.p == nil { 2611 continue 2612 } 2613 if !a.p.Standard { 2614 cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...) 2615 } 2616 if len(a.p.CgoFiles) > 0 { 2617 usesCgo = true 2618 } 2619 if a.p.usesSwig() { 2620 usesCgo = true 2621 } 2622 if len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0 { 2623 cxx = true 2624 } 2625 if len(a.p.MFiles) > 0 { 2626 objc = true 2627 } 2628 } 2629 2630 switch ldBuildmode { 2631 case "c-archive", "c-shared": 2632 ldflags = append(ldflags, "-Wl,--whole-archive") 2633 } 2634 2635 ldflags = append(ldflags, afiles...) 2636 2637 switch ldBuildmode { 2638 case "c-archive", "c-shared": 2639 ldflags = append(ldflags, "-Wl,--no-whole-archive") 2640 } 2641 2642 ldflags = append(ldflags, cgoldflags...) 2643 ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...) 2644 ldflags = append(ldflags, root.p.CgoLDFLAGS...) 2645 2646 ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)") 2647 2648 for _, shlib := range shlibs { 2649 ldflags = append( 2650 ldflags, 2651 "-L"+filepath.Dir(shlib), 2652 "-Wl,-rpath="+filepath.Dir(shlib), 2653 "-l"+strings.TrimSuffix( 2654 strings.TrimPrefix(filepath.Base(shlib), "lib"), 2655 ".so")) 2656 } 2657 2658 var realOut string 2659 switch ldBuildmode { 2660 case "exe": 2661 if usesCgo && goos == "linux" { 2662 ldflags = append(ldflags, "-Wl,-E") 2663 } 2664 2665 case "c-archive": 2666 // Link the Go files into a single .o, and also link 2667 // in -lgolibbegin. 2668 // 2669 // We need to use --whole-archive with -lgolibbegin 2670 // because it doesn't define any symbols that will 2671 // cause the contents to be pulled in; it's just 2672 // initialization code. 2673 // 2674 // The user remains responsible for linking against 2675 // -lgo -lpthread -lm in the final link. We can't use 2676 // -r to pick them up because we can't combine 2677 // split-stack and non-split-stack code in a single -r 2678 // link, and libgo picks up non-split-stack code from 2679 // libffi. 2680 ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive") 2681 2682 // We are creating an object file, so we don't want a build ID. 2683 ldflags = b.disableBuildID(ldflags) 2684 2685 realOut = out 2686 out = out + ".o" 2687 2688 case "c-shared": 2689 ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc") 2690 2691 default: 2692 fatalf("-buildmode=%s not supported for gccgo", ldBuildmode) 2693 } 2694 2695 switch ldBuildmode { 2696 case "exe", "c-shared": 2697 if cxx { 2698 ldflags = append(ldflags, "-lstdc++") 2699 } 2700 if objc { 2701 ldflags = append(ldflags, "-lobjc") 2702 } 2703 } 2704 2705 if err := b.run(".", root.p.ImportPath, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil { 2706 return err 2707 } 2708 2709 switch ldBuildmode { 2710 case "c-archive": 2711 if err := b.run(".", root.p.ImportPath, nil, "ar", "rc", realOut, out); err != nil { 2712 return err 2713 } 2714 } 2715 return nil 2716 } 2717 2718 func (tools gccgoToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error { 2719 args := []string{"-o", out, "-shared", "-nostdlib", "-zdefs", "-Wl,--whole-archive"} 2720 for _, a := range toplevelactions { 2721 args = append(args, a.target) 2722 } 2723 args = append(args, "-Wl,--no-whole-archive", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc") 2724 shlibs := []string{} 2725 for _, a := range allactions { 2726 if strings.HasSuffix(a.target, ".so") { 2727 shlibs = append(shlibs, a.target) 2728 } 2729 } 2730 for _, shlib := range shlibs { 2731 args = append( 2732 args, 2733 "-L"+filepath.Dir(shlib), 2734 "-Wl,-rpath="+filepath.Dir(shlib), 2735 "-l"+strings.TrimSuffix( 2736 strings.TrimPrefix(filepath.Base(shlib), "lib"), 2737 ".so")) 2738 } 2739 return b.run(".", out, nil, tools.linker(), args, buildGccgoflags) 2740 } 2741 2742 func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 2743 inc := filepath.Join(goroot, "pkg", "include") 2744 cfile = mkAbs(p.Dir, cfile) 2745 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} 2746 defs = append(defs, b.gccArchArgs()...) 2747 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 2748 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 2749 } 2750 switch goarch { 2751 case "386", "amd64": 2752 defs = append(defs, "-fsplit-stack") 2753 } 2754 defs = tools.maybePIC(defs) 2755 return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g", 2756 "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) 2757 } 2758 2759 // maybePIC adds -fPIC to the list of arguments if needed. 2760 func (tools gccgoToolchain) maybePIC(args []string) []string { 2761 switch buildBuildmode { 2762 case "c-shared", "shared": 2763 args = append(args, "-fPIC") 2764 } 2765 return args 2766 } 2767 2768 func gccgoPkgpath(p *Package) string { 2769 if p.build.IsCommand() && !p.forceLibrary { 2770 return "" 2771 } 2772 return p.ImportPath 2773 } 2774 2775 func gccgoCleanPkgpath(p *Package) string { 2776 clean := func(r rune) rune { 2777 switch { 2778 case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', 2779 '0' <= r && r <= '9': 2780 return r 2781 } 2782 return '_' 2783 } 2784 return strings.Map(clean, gccgoPkgpath(p)) 2785 } 2786 2787 // libgcc returns the filename for libgcc, as determined by invoking gcc with 2788 // the -print-libgcc-file-name option. 2789 func (b *builder) libgcc(p *Package) (string, error) { 2790 var buf bytes.Buffer 2791 2792 gccCmd := b.gccCmd(p.Dir) 2793 2794 prev := b.print 2795 if buildN { 2796 // In -n mode we temporarily swap out the builder's 2797 // print function to capture the command-line. This 2798 // let's us assign it to $LIBGCC and produce a valid 2799 // buildscript for cgo packages. 2800 b.print = func(a ...interface{}) (int, error) { 2801 return fmt.Fprint(&buf, a...) 2802 } 2803 } 2804 f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name") 2805 if err != nil { 2806 return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f) 2807 } 2808 if buildN { 2809 s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1)) 2810 b.print = prev 2811 b.print(s) 2812 return "$LIBGCC", nil 2813 } 2814 2815 // The compiler might not be able to find libgcc, and in that case, 2816 // it will simply return "libgcc.a", which is of no use to us. 2817 if !filepath.IsAbs(string(f)) { 2818 return "", nil 2819 } 2820 2821 return strings.Trim(string(f), "\r\n"), nil 2822 } 2823 2824 // gcc runs the gcc C compiler to create an object from a single C file. 2825 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error { 2826 return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir)) 2827 } 2828 2829 // gxx runs the g++ C++ compiler to create an object from a single C++ file. 2830 func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error { 2831 return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir)) 2832 } 2833 2834 // ccompile runs the given C or C++ compiler and creates an object from a single source file. 2835 func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error { 2836 file = mkAbs(p.Dir, file) 2837 return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file) 2838 } 2839 2840 // gccld runs the gcc linker to create an executable from a set of object files. 2841 func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error { 2842 var cmd []string 2843 if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 { 2844 cmd = b.gxxCmd(p.Dir) 2845 } else { 2846 cmd = b.gccCmd(p.Dir) 2847 } 2848 return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags) 2849 } 2850 2851 // gccCmd returns a gcc command line prefix 2852 // defaultCC is defined in zdefaultcc.go, written by cmd/dist. 2853 func (b *builder) gccCmd(objdir string) []string { 2854 return b.ccompilerCmd("CC", defaultCC, objdir) 2855 } 2856 2857 // gxxCmd returns a g++ command line prefix 2858 // defaultCXX is defined in zdefaultcc.go, written by cmd/dist. 2859 func (b *builder) gxxCmd(objdir string) []string { 2860 return b.ccompilerCmd("CXX", defaultCXX, objdir) 2861 } 2862 2863 // ccompilerCmd returns a command line prefix for the given environment 2864 // variable and using the default command when the variable is empty. 2865 func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string { 2866 // NOTE: env.go's mkEnv knows that the first three 2867 // strings returned are "gcc", "-I", objdir (and cuts them off). 2868 2869 compiler := envList(envvar, defcmd) 2870 a := []string{compiler[0], "-I", objdir} 2871 a = append(a, compiler[1:]...) 2872 2873 // Definitely want -fPIC but on Windows gcc complains 2874 // "-fPIC ignored for target (all code is position independent)" 2875 if goos != "windows" { 2876 a = append(a, "-fPIC") 2877 } 2878 a = append(a, b.gccArchArgs()...) 2879 // gcc-4.5 and beyond require explicit "-pthread" flag 2880 // for multithreading with pthread library. 2881 if buildContext.CgoEnabled { 2882 switch goos { 2883 case "windows": 2884 a = append(a, "-mthreads") 2885 default: 2886 a = append(a, "-pthread") 2887 } 2888 } 2889 2890 if strings.Contains(a[0], "clang") { 2891 // disable ASCII art in clang errors, if possible 2892 a = append(a, "-fno-caret-diagnostics") 2893 // clang is too smart about command-line arguments 2894 a = append(a, "-Qunused-arguments") 2895 } 2896 2897 // disable word wrapping in error messages 2898 a = append(a, "-fmessage-length=0") 2899 2900 // On OS X, some of the compilers behave as if -fno-common 2901 // is always set, and the Mach-O linker in 6l/8l assumes this. 2902 // See https://golang.org/issue/3253. 2903 if goos == "darwin" { 2904 a = append(a, "-fno-common") 2905 } 2906 2907 return a 2908 } 2909 2910 // gccArchArgs returns arguments to pass to gcc based on the architecture. 2911 func (b *builder) gccArchArgs() []string { 2912 switch goarch { 2913 case "386": 2914 return []string{"-m32"} 2915 case "amd64", "amd64p32": 2916 return []string{"-m64"} 2917 case "arm": 2918 return []string{"-marm"} // not thumb 2919 } 2920 return nil 2921 } 2922 2923 // envList returns the value of the given environment variable broken 2924 // into fields, using the default value when the variable is empty. 2925 func envList(key, def string) []string { 2926 v := os.Getenv(key) 2927 if v == "" { 2928 v = def 2929 } 2930 return strings.Fields(v) 2931 } 2932 2933 // Return the flags to use when invoking the C or C++ compilers, or cgo. 2934 func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) { 2935 var defaults string 2936 if def { 2937 defaults = "-g -O2" 2938 } 2939 2940 cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) 2941 cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) 2942 cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) 2943 ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) 2944 return 2945 } 2946 2947 var cgoRe = regexp.MustCompile(`[/\\:]`) 2948 2949 var ( 2950 cgoLibGccFile string 2951 cgoLibGccErr error 2952 cgoLibGccFileOnce sync.Once 2953 ) 2954 2955 func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { 2956 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true) 2957 _, cgoexeCFLAGS, _, _ := b.cflags(p, false) 2958 cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) 2959 cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) 2960 // If we are compiling Objective-C code, then we need to link against libobjc 2961 if len(mfiles) > 0 { 2962 cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") 2963 } 2964 2965 // Allows including _cgo_export.h from .[ch] files in the package. 2966 cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj) 2967 2968 // cgo 2969 // TODO: CGOPKGPATH, CGO_FLAGS? 2970 gofiles := []string{obj + "_cgo_gotypes.go"} 2971 cfiles := []string{"_cgo_main.c", "_cgo_export.c"} 2972 for _, fn := range cgofiles { 2973 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") 2974 gofiles = append(gofiles, obj+f+"cgo1.go") 2975 cfiles = append(cfiles, f+"cgo2.c") 2976 } 2977 defunC := obj + "_cgo_defun.c" 2978 2979 cgoflags := []string{} 2980 // TODO: make cgo not depend on $GOARCH? 2981 2982 if p.Standard && p.ImportPath == "runtime/cgo" { 2983 cgoflags = append(cgoflags, "-import_runtime_cgo=false") 2984 } 2985 if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") { 2986 cgoflags = append(cgoflags, "-import_syscall=false") 2987 } 2988 2989 // Update $CGO_LDFLAGS with p.CgoLDFLAGS. 2990 var cgoenv []string 2991 if len(cgoLDFLAGS) > 0 { 2992 flags := make([]string, len(cgoLDFLAGS)) 2993 for i, f := range cgoLDFLAGS { 2994 flags[i] = strconv.Quote(f) 2995 } 2996 cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} 2997 } 2998 2999 if _, ok := buildToolchain.(gccgoToolchain); ok { 3000 switch goarch { 3001 case "386", "amd64": 3002 cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack") 3003 } 3004 cgoflags = append(cgoflags, "-gccgo") 3005 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 3006 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) 3007 } 3008 } 3009 3010 switch buildBuildmode { 3011 case "c-archive", "c-shared": 3012 // Tell cgo that if there are any exported functions 3013 // it should generate a header file that C code can 3014 // #include. 3015 cgoflags = append(cgoflags, "-exportheader="+obj+"_cgo_install.h") 3016 } 3017 3018 if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, cgofiles); err != nil { 3019 return nil, nil, err 3020 } 3021 outGo = append(outGo, gofiles...) 3022 3023 // cc _cgo_defun.c 3024 _, gccgo := buildToolchain.(gccgoToolchain) 3025 if gccgo { 3026 defunObj := obj + "_cgo_defun.o" 3027 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { 3028 return nil, nil, err 3029 } 3030 outObj = append(outObj, defunObj) 3031 } 3032 3033 // gcc 3034 var linkobj []string 3035 3036 var bareLDFLAGS []string 3037 // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X 3038 for i := 0; i < len(cgoLDFLAGS); i++ { 3039 f := cgoLDFLAGS[i] 3040 switch { 3041 // skip "-lc" or "-l somelib" 3042 case strings.HasPrefix(f, "-l"): 3043 if f == "-l" { 3044 i++ 3045 } 3046 // skip "-framework X" on Darwin 3047 case goos == "darwin" && f == "-framework": 3048 i++ 3049 // skip "*.{dylib,so,dll}" 3050 case strings.HasSuffix(f, ".dylib"), 3051 strings.HasSuffix(f, ".so"), 3052 strings.HasSuffix(f, ".dll"): 3053 continue 3054 // Remove any -fsanitize=foo flags. 3055 // Otherwise the compiler driver thinks that we are doing final link 3056 // and links sanitizer runtime into the object file. But we are not doing 3057 // the final link, we will link the resulting object file again. And 3058 // so the program ends up with two copies of sanitizer runtime. 3059 // See issue 8788 for details. 3060 case strings.HasPrefix(f, "-fsanitize="): 3061 continue 3062 default: 3063 bareLDFLAGS = append(bareLDFLAGS, f) 3064 } 3065 } 3066 3067 cgoLibGccFileOnce.Do(func() { 3068 cgoLibGccFile, cgoLibGccErr = b.libgcc(p) 3069 }) 3070 if cgoLibGccFile == "" && cgoLibGccErr != nil { 3071 return nil, nil, err 3072 } 3073 3074 var staticLibs []string 3075 if goos == "windows" { 3076 // libmingw32 and libmingwex might also use libgcc, so libgcc must come last, 3077 // and they also have some inter-dependencies, so must use linker groups. 3078 staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"} 3079 } 3080 if cgoLibGccFile != "" { 3081 staticLibs = append(staticLibs, cgoLibGccFile) 3082 } 3083 3084 cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) 3085 for _, cfile := range cfiles { 3086 ofile := obj + cfile[:len(cfile)-1] + "o" 3087 if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil { 3088 return nil, nil, err 3089 } 3090 linkobj = append(linkobj, ofile) 3091 if !strings.HasSuffix(ofile, "_cgo_main.o") { 3092 outObj = append(outObj, ofile) 3093 } 3094 } 3095 3096 for _, file := range gccfiles { 3097 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" 3098 if err := b.gcc(p, ofile, cflags, file); err != nil { 3099 return nil, nil, err 3100 } 3101 linkobj = append(linkobj, ofile) 3102 outObj = append(outObj, ofile) 3103 } 3104 3105 cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) 3106 for _, file := range gxxfiles { 3107 // Append .o to the file, just in case the pkg has file.c and file.cpp 3108 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 3109 if err := b.gxx(p, ofile, cxxflags, file); err != nil { 3110 return nil, nil, err 3111 } 3112 linkobj = append(linkobj, ofile) 3113 outObj = append(outObj, ofile) 3114 } 3115 3116 for _, file := range mfiles { 3117 // Append .o to the file, just in case the pkg has file.c and file.m 3118 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" 3119 if err := b.gcc(p, ofile, cflags, file); err != nil { 3120 return nil, nil, err 3121 } 3122 linkobj = append(linkobj, ofile) 3123 outObj = append(outObj, ofile) 3124 } 3125 3126 linkobj = append(linkobj, p.SysoFiles...) 3127 dynobj := obj + "_cgo_.o" 3128 pie := goarch == "arm" && (goos == "linux" || goos == "android") 3129 if pie { // we need to use -pie for Linux/ARM to get accurate imported sym 3130 cgoLDFLAGS = append(cgoLDFLAGS, "-pie") 3131 } 3132 if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil { 3133 return nil, nil, err 3134 } 3135 if pie { // but we don't need -pie for normal cgo programs 3136 cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1] 3137 } 3138 3139 if _, ok := buildToolchain.(gccgoToolchain); ok { 3140 // we don't use dynimport when using gccgo. 3141 return outGo, outObj, nil 3142 } 3143 3144 // cgo -dynimport 3145 importGo := obj + "_cgo_import.go" 3146 cgoflags = []string{} 3147 if p.Standard && p.ImportPath == "runtime/cgo" { 3148 cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker 3149 } 3150 if err := b.run(p.Dir, p.ImportPath, nil, buildToolExec, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil { 3151 return nil, nil, err 3152 } 3153 outGo = append(outGo, importGo) 3154 3155 ofile := obj + "_all.o" 3156 var gccObjs, nonGccObjs []string 3157 for _, f := range outObj { 3158 if strings.HasSuffix(f, ".o") { 3159 gccObjs = append(gccObjs, f) 3160 } else { 3161 nonGccObjs = append(nonGccObjs, f) 3162 } 3163 } 3164 ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs) 3165 3166 // We are creating an object file, so we don't want a build ID. 3167 ldflags = b.disableBuildID(ldflags) 3168 3169 if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil { 3170 return nil, nil, err 3171 } 3172 3173 // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows 3174 // must be processed before the gcc-generated objects. 3175 // Put it first. https://golang.org/issue/2601 3176 outObj = stringList(nonGccObjs, ofile) 3177 3178 return outGo, outObj, nil 3179 } 3180 3181 // Run SWIG on all SWIG input files. 3182 // TODO: Don't build a shared library, once SWIG emits the necessary 3183 // pragmas for external linking. 3184 func (b *builder) swig(p *Package, obj string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) { 3185 if err := b.swigVersionCheck(); err != nil { 3186 return nil, nil, nil, err 3187 } 3188 3189 intgosize, err := b.swigIntSize(obj) 3190 if err != nil { 3191 return nil, nil, nil, err 3192 } 3193 3194 for _, f := range p.SwigFiles { 3195 goFile, cFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize) 3196 if err != nil { 3197 return nil, nil, nil, err 3198 } 3199 if goFile != "" { 3200 outGo = append(outGo, goFile) 3201 } 3202 if cFile != "" { 3203 outC = append(outC, cFile) 3204 } 3205 } 3206 for _, f := range p.SwigCXXFiles { 3207 goFile, cxxFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize) 3208 if err != nil { 3209 return nil, nil, nil, err 3210 } 3211 if goFile != "" { 3212 outGo = append(outGo, goFile) 3213 } 3214 if cxxFile != "" { 3215 outCXX = append(outCXX, cxxFile) 3216 } 3217 } 3218 return outGo, outC, outCXX, nil 3219 } 3220 3221 // Make sure SWIG is new enough. 3222 var ( 3223 swigCheckOnce sync.Once 3224 swigCheck error 3225 ) 3226 3227 func (b *builder) swigDoVersionCheck() error { 3228 out, err := b.runOut("", "", nil, "swig", "-version") 3229 if err != nil { 3230 return err 3231 } 3232 re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`) 3233 matches := re.FindSubmatch(out) 3234 if matches == nil { 3235 // Can't find version number; hope for the best. 3236 return nil 3237 } 3238 3239 major, err := strconv.Atoi(string(matches[1])) 3240 if err != nil { 3241 // Can't find version number; hope for the best. 3242 return nil 3243 } 3244 const errmsg = "must have SWIG version >= 3.0.6" 3245 if major < 3 { 3246 return errors.New(errmsg) 3247 } 3248 if major > 3 { 3249 // 4.0 or later 3250 return nil 3251 } 3252 3253 // We have SWIG version 3.x. 3254 if len(matches[2]) > 0 { 3255 minor, err := strconv.Atoi(string(matches[2][1:])) 3256 if err != nil { 3257 return nil 3258 } 3259 if minor > 0 { 3260 // 3.1 or later 3261 return nil 3262 } 3263 } 3264 3265 // We have SWIG version 3.0.x. 3266 if len(matches[3]) > 0 { 3267 patch, err := strconv.Atoi(string(matches[3][1:])) 3268 if err != nil { 3269 return nil 3270 } 3271 if patch < 6 { 3272 // Before 3.0.6. 3273 return errors.New(errmsg) 3274 } 3275 } 3276 3277 return nil 3278 } 3279 3280 func (b *builder) swigVersionCheck() error { 3281 swigCheckOnce.Do(func() { 3282 swigCheck = b.swigDoVersionCheck() 3283 }) 3284 return swigCheck 3285 } 3286 3287 // This code fails to build if sizeof(int) <= 32 3288 const swigIntSizeCode = ` 3289 package main 3290 const i int = 1 << 32 3291 ` 3292 3293 // Determine the size of int on the target system for the -intgosize option 3294 // of swig >= 2.0.9 3295 func (b *builder) swigIntSize(obj string) (intsize string, err error) { 3296 if buildN { 3297 return "$INTBITS", nil 3298 } 3299 src := filepath.Join(b.work, "swig_intsize.go") 3300 if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil { 3301 return 3302 } 3303 srcs := []string{src} 3304 3305 p := goFilesPackage(srcs) 3306 3307 if _, _, e := buildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil { 3308 return "32", nil 3309 } 3310 return "64", nil 3311 } 3312 3313 // Run SWIG on one SWIG input file. 3314 func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) { 3315 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) 3316 var cflags []string 3317 if cxx { 3318 cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) 3319 } else { 3320 cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) 3321 } 3322 3323 n := 5 // length of ".swig" 3324 if cxx { 3325 n = 8 // length of ".swigcxx" 3326 } 3327 base := file[:len(file)-n] 3328 goFile := base + ".go" 3329 gccBase := base + "_wrap." 3330 gccExt := "c" 3331 if cxx { 3332 gccExt = "cxx" 3333 } 3334 3335 _, gccgo := buildToolchain.(gccgoToolchain) 3336 3337 // swig 3338 args := []string{ 3339 "-go", 3340 "-cgo", 3341 "-intgosize", intgosize, 3342 "-module", base, 3343 "-o", obj + gccBase + gccExt, 3344 "-outdir", obj, 3345 } 3346 3347 for _, f := range cflags { 3348 if len(f) > 3 && f[:2] == "-I" { 3349 args = append(args, f) 3350 } 3351 } 3352 3353 if gccgo { 3354 args = append(args, "-gccgo") 3355 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 3356 args = append(args, "-go-pkgpath", pkgpath) 3357 } 3358 } 3359 if cxx { 3360 args = append(args, "-c++") 3361 } 3362 3363 out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file) 3364 if err != nil { 3365 if len(out) > 0 { 3366 if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) { 3367 return "", "", errors.New("must have SWIG version >= 3.0.6") 3368 } 3369 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) // swig error 3370 return "", "", errPrintedOutput 3371 } 3372 return "", "", err 3373 } 3374 if len(out) > 0 { 3375 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) // swig warning 3376 } 3377 3378 return obj + goFile, obj + gccBase + gccExt, nil 3379 } 3380 3381 // disableBuildID adjusts a linker command line to avoid creating a 3382 // build ID when creating an object file rather than an executable or 3383 // shared library. Some systems, such as Ubuntu, always add 3384 // --build-id to every link, but we don't want a build ID when we are 3385 // producing an object file. On some of those system a plain -r (not 3386 // -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a 3387 // plain -r. I don't know how to turn off --build-id when using clang 3388 // other than passing a trailing --build-id=none. So that is what we 3389 // do, but only on systems likely to support it, which is to say, 3390 // systems that normally use gold or the GNU linker. 3391 func (b *builder) disableBuildID(ldflags []string) []string { 3392 switch goos { 3393 case "android", "dragonfly", "linux", "netbsd": 3394 ldflags = append(ldflags, "-Wl,--build-id=none") 3395 } 3396 return ldflags 3397 } 3398 3399 // An actionQueue is a priority queue of actions. 3400 type actionQueue []*action 3401 3402 // Implement heap.Interface 3403 func (q *actionQueue) Len() int { return len(*q) } 3404 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 3405 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } 3406 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) } 3407 func (q *actionQueue) Pop() interface{} { 3408 n := len(*q) - 1 3409 x := (*q)[n] 3410 *q = (*q)[:n] 3411 return x 3412 } 3413 3414 func (q *actionQueue) push(a *action) { 3415 heap.Push(q, a) 3416 } 3417 3418 func (q *actionQueue) pop() *action { 3419 return heap.Pop(q).(*action) 3420 } 3421 3422 func raceInit() { 3423 if !buildRace { 3424 return 3425 } 3426 if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" { 3427 fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) 3428 os.Exit(2) 3429 } 3430 buildGcflags = append(buildGcflags, "-race") 3431 buildLdflags = append(buildLdflags, "-race") 3432 if buildContext.InstallSuffix != "" { 3433 buildContext.InstallSuffix += "_" 3434 } 3435 buildContext.InstallSuffix += "race" 3436 buildContext.BuildTags = append(buildContext.BuildTags, "race") 3437 } 3438 3439 // defaultSuffix returns file extension used for command files in 3440 // current os environment. 3441 func defaultSuffix() string { 3442 switch runtime.GOOS { 3443 case "windows": 3444 return ".bat" 3445 case "plan9": 3446 return ".rc" 3447 default: 3448 return ".bash" 3449 } 3450 }