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