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