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