github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/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 2207 for _, path := range p.Imports { 2208 if i := strings.LastIndex(path, "/vendor/"); i >= 0 { 2209 gcargs = append(gcargs, "-importmap", path[i+len("/vendor/"):]+"="+path) 2210 } else if strings.HasPrefix(path, "vendor/") { 2211 gcargs = append(gcargs, "-importmap", path[len("vendor/"):]+"="+path) 2212 } 2213 } 2214 2215 gcflags := buildGcflags 2216 if compilingRuntime { 2217 // Remove -N, if present. 2218 // It is not possible to build the runtime with no optimizations, 2219 // because the compiler cannot eliminate enough write barriers. 2220 gcflags = make([]string, len(buildGcflags)) 2221 copy(gcflags, buildGcflags) 2222 for i := 0; i < len(gcflags); i++ { 2223 if gcflags[i] == "-N" { 2224 copy(gcflags[i:], gcflags[i+1:]) 2225 gcflags = gcflags[:len(gcflags)-1] 2226 i-- 2227 } 2228 } 2229 } 2230 args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.WorkDir, gcflags, gcargs, "-D", p.Internal.LocalPrefix, importArgs} 2231 if ofile == archive { 2232 args = append(args, "-pack") 2233 } 2234 if asmhdr { 2235 args = append(args, "-asmhdr", obj+"go_asm.h") 2236 } 2237 for _, f := range gofiles { 2238 args = append(args, mkAbs(p.Dir, f)) 2239 } 2240 2241 output, err = b.runOut(p.Dir, p.ImportPath, nil, args...) 2242 return ofile, output, err 2243 } 2244 2245 func (gcToolchain) asm(b *Builder, p *load.Package, obj string, sfiles []string) ([]string, error) { 2246 // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. 2247 inc := filepath.Join(cfg.GOROOT, "pkg", "include") 2248 args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", b.WorkDir, "-I", obj, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, buildAsmflags} 2249 if p.ImportPath == "runtime" && cfg.Goarch == "386" { 2250 for _, arg := range buildAsmflags { 2251 if arg == "-dynlink" { 2252 args = append(args, "-D=GOBUILDMODE_shared=1") 2253 } 2254 } 2255 } 2256 var ofiles []string 2257 for _, sfile := range sfiles { 2258 ofile := obj + sfile[:len(sfile)-len(".s")] + ".o" 2259 ofiles = append(ofiles, ofile) 2260 a := append(args, "-o", ofile, mkAbs(p.Dir, sfile)) 2261 if err := b.run(p.Dir, p.ImportPath, nil, a...); err != nil { 2262 return nil, err 2263 } 2264 } 2265 return ofiles, nil 2266 } 2267 2268 // toolVerify checks that the command line args writes the same output file 2269 // if run using newTool instead. 2270 // Unused now but kept around for future use. 2271 func toolVerify(b *Builder, p *load.Package, newTool string, ofile string, args []interface{}) error { 2272 newArgs := make([]interface{}, len(args)) 2273 copy(newArgs, args) 2274 newArgs[1] = base.Tool(newTool) 2275 newArgs[3] = ofile + ".new" // x.6 becomes x.6.new 2276 if err := b.run(p.Dir, p.ImportPath, nil, newArgs...); err != nil { 2277 return err 2278 } 2279 data1, err := ioutil.ReadFile(ofile) 2280 if err != nil { 2281 return err 2282 } 2283 data2, err := ioutil.ReadFile(ofile + ".new") 2284 if err != nil { 2285 return err 2286 } 2287 if !bytes.Equal(data1, data2) { 2288 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...), " ")) 2289 } 2290 os.Remove(ofile + ".new") 2291 return nil 2292 } 2293 2294 func (gcToolchain) Pkgpath(basedir string, p *load.Package) string { 2295 end := filepath.FromSlash(p.ImportPath + ".a") 2296 return filepath.Join(basedir, end) 2297 } 2298 2299 func (gcToolchain) pack(b *Builder, p *load.Package, objDir, afile string, ofiles []string) error { 2300 var absOfiles []string 2301 for _, f := range ofiles { 2302 absOfiles = append(absOfiles, mkAbs(objDir, f)) 2303 } 2304 absAfile := mkAbs(objDir, afile) 2305 2306 // The archive file should have been created by the compiler. 2307 // Since it used to not work that way, verify. 2308 if !cfg.BuildN { 2309 if _, err := os.Stat(absAfile); err != nil { 2310 base.Fatalf("os.Stat of archive file failed: %v", err) 2311 } 2312 } 2313 2314 if cfg.BuildN || cfg.BuildX { 2315 cmdline := str.StringList("pack", "r", absAfile, absOfiles) 2316 b.Showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline)) 2317 } 2318 if cfg.BuildN { 2319 return nil 2320 } 2321 if err := packInternal(b, absAfile, absOfiles); err != nil { 2322 b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n") 2323 return errPrintedOutput 2324 } 2325 return nil 2326 } 2327 2328 func packInternal(b *Builder, afile string, ofiles []string) error { 2329 dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0) 2330 if err != nil { 2331 return err 2332 } 2333 defer dst.Close() // only for error returns or panics 2334 w := bufio.NewWriter(dst) 2335 2336 for _, ofile := range ofiles { 2337 src, err := os.Open(ofile) 2338 if err != nil { 2339 return err 2340 } 2341 fi, err := src.Stat() 2342 if err != nil { 2343 src.Close() 2344 return err 2345 } 2346 // Note: Not using %-16.16s format because we care 2347 // about bytes, not runes. 2348 name := fi.Name() 2349 if len(name) > 16 { 2350 name = name[:16] 2351 } else { 2352 name += strings.Repeat(" ", 16-len(name)) 2353 } 2354 size := fi.Size() 2355 fmt.Fprintf(w, "%s%-12d%-6d%-6d%-8o%-10d`\n", 2356 name, 0, 0, 0, 0644, size) 2357 n, err := io.Copy(w, src) 2358 src.Close() 2359 if err == nil && n < size { 2360 err = io.ErrUnexpectedEOF 2361 } else if err == nil && n > size { 2362 err = fmt.Errorf("file larger than size reported by stat") 2363 } 2364 if err != nil { 2365 return fmt.Errorf("copying %s to %s: %v", ofile, afile, err) 2366 } 2367 if size&1 != 0 { 2368 w.WriteByte(0) 2369 } 2370 } 2371 2372 if err := w.Flush(); err != nil { 2373 return err 2374 } 2375 return dst.Close() 2376 } 2377 2378 // setextld sets the appropriate linker flags for the specified compiler. 2379 func setextld(ldflags []string, compiler []string) []string { 2380 for _, f := range ldflags { 2381 if f == "-extld" || strings.HasPrefix(f, "-extld=") { 2382 // don't override -extld if supplied 2383 return ldflags 2384 } 2385 } 2386 ldflags = append(ldflags, "-extld="+compiler[0]) 2387 if len(compiler) > 1 { 2388 extldflags := false 2389 add := strings.Join(compiler[1:], " ") 2390 for i, f := range ldflags { 2391 if f == "-extldflags" && i+1 < len(ldflags) { 2392 ldflags[i+1] = add + " " + ldflags[i+1] 2393 extldflags = true 2394 break 2395 } else if strings.HasPrefix(f, "-extldflags=") { 2396 ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] 2397 extldflags = true 2398 break 2399 } 2400 } 2401 if !extldflags { 2402 ldflags = append(ldflags, "-extldflags="+add) 2403 } 2404 } 2405 return ldflags 2406 } 2407 2408 func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error { 2409 importArgs := b.includeArgs("-L", allactions) 2410 cxx := len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0 2411 for _, a := range allactions { 2412 if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) { 2413 cxx = true 2414 } 2415 } 2416 var ldflags []string 2417 if cfg.BuildContext.InstallSuffix != "" { 2418 ldflags = append(ldflags, "-installsuffix", cfg.BuildContext.InstallSuffix) 2419 } 2420 if root.Package.Internal.OmitDebug { 2421 ldflags = append(ldflags, "-s", "-w") 2422 } 2423 if cfg.BuildBuildmode == "plugin" { 2424 pluginpath := root.Package.ImportPath 2425 if pluginpath == "command-line-arguments" { 2426 pluginpath = "plugin/unnamed-" + root.Package.Internal.BuildID 2427 } 2428 ldflags = append(ldflags, "-pluginpath", pluginpath) 2429 } 2430 2431 // If the user has not specified the -extld option, then specify the 2432 // appropriate linker. In case of C++ code, use the compiler named 2433 // by the CXX environment variable or defaultCXX if CXX is not set. 2434 // Else, use the CC environment variable and defaultCC as fallback. 2435 var compiler []string 2436 if cxx { 2437 compiler = envList("CXX", cfg.DefaultCXX) 2438 } else { 2439 compiler = envList("CC", cfg.DefaultCC) 2440 } 2441 ldflags = setextld(ldflags, compiler) 2442 ldflags = append(ldflags, "-buildmode="+ldBuildmode) 2443 if root.Package.Internal.BuildID != "" { 2444 ldflags = append(ldflags, "-buildid="+root.Package.Internal.BuildID) 2445 } 2446 ldflags = append(ldflags, cfg.BuildLdflags...) 2447 2448 // On OS X when using external linking to build a shared library, 2449 // the argument passed here to -o ends up recorded in the final 2450 // shared library in the LC_ID_DYLIB load command. 2451 // To avoid putting the temporary output directory name there 2452 // (and making the resulting shared library useless), 2453 // run the link in the output directory so that -o can name 2454 // just the final path element. 2455 dir := "." 2456 if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" { 2457 dir, out = filepath.Split(out) 2458 } 2459 2460 return b.run(dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags, mainpkg) 2461 } 2462 2463 func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error { 2464 importArgs := b.includeArgs("-L", allactions) 2465 ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix} 2466 ldflags = append(ldflags, "-buildmode=shared") 2467 ldflags = append(ldflags, cfg.BuildLdflags...) 2468 cxx := false 2469 for _, a := range allactions { 2470 if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) { 2471 cxx = true 2472 } 2473 } 2474 // If the user has not specified the -extld option, then specify the 2475 // appropriate linker. In case of C++ code, use the compiler named 2476 // by the CXX environment variable or defaultCXX if CXX is not set. 2477 // Else, use the CC environment variable and defaultCC as fallback. 2478 var compiler []string 2479 if cxx { 2480 compiler = envList("CXX", cfg.DefaultCXX) 2481 } else { 2482 compiler = envList("CC", cfg.DefaultCC) 2483 } 2484 ldflags = setextld(ldflags, compiler) 2485 for _, d := range toplevelactions { 2486 if !strings.HasSuffix(d.Target, ".a") { // omit unsafe etc and actions for other shared libraries 2487 continue 2488 } 2489 ldflags = append(ldflags, d.Package.ImportPath+"="+d.Target) 2490 } 2491 return b.run(".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags) 2492 } 2493 2494 func (gcToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error { 2495 return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile)) 2496 } 2497 2498 // The Gccgo toolchain. 2499 type gccgoToolchain struct{} 2500 2501 var GccgoName, GccgoBin string 2502 var gccgoErr error 2503 2504 func init() { 2505 GccgoName = os.Getenv("GCCGO") 2506 if GccgoName == "" { 2507 GccgoName = "gccgo" 2508 } 2509 GccgoBin, gccgoErr = exec.LookPath(GccgoName) 2510 } 2511 2512 func (gccgoToolchain) compiler() string { 2513 checkGccgoBin() 2514 return GccgoBin 2515 } 2516 2517 func (gccgoToolchain) linker() string { 2518 checkGccgoBin() 2519 return GccgoBin 2520 } 2521 2522 func checkGccgoBin() { 2523 if gccgoErr == nil { 2524 return 2525 } 2526 fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr) 2527 os.Exit(2) 2528 } 2529 2530 func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { 2531 out := "_go_.o" 2532 ofile = obj + out 2533 gcargs := []string{"-g"} 2534 gcargs = append(gcargs, b.gccArchArgs()...) 2535 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 2536 gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) 2537 } 2538 if p.Internal.LocalPrefix != "" { 2539 gcargs = append(gcargs, "-fgo-relative-import-path="+p.Internal.LocalPrefix) 2540 } 2541 2542 // Handle vendor directories 2543 savedirs := []string{} 2544 for _, incdir := range importArgs { 2545 if incdir != "-I" { 2546 savedirs = append(savedirs, incdir) 2547 } 2548 } 2549 2550 for _, path := range p.Imports { 2551 // If this is a new vendor path, add it to the list of importArgs 2552 if i := strings.LastIndex(path, "/vendor"); i >= 0 { 2553 for _, dir := range savedirs { 2554 // Check if the vendor path is already included in dir 2555 if strings.HasSuffix(dir, path[:i+len("/vendor")]) { 2556 continue 2557 } 2558 // Make sure this vendor path is not already in the list for importArgs 2559 vendorPath := dir + "/" + path[:i+len("/vendor")] 2560 for _, imp := range importArgs { 2561 if imp == "-I" { 2562 continue 2563 } 2564 // This vendorPath is already in the list 2565 if imp == vendorPath { 2566 goto nextSuffixPath 2567 } 2568 } 2569 // New vendorPath not yet in the importArgs list, so add it 2570 importArgs = append(importArgs, "-I", vendorPath) 2571 nextSuffixPath: 2572 } 2573 } else if strings.HasPrefix(path, "vendor/") { 2574 for _, dir := range savedirs { 2575 // Make sure this vendor path is not already in the list for importArgs 2576 vendorPath := dir + "/" + path[len("/vendor"):] 2577 for _, imp := range importArgs { 2578 if imp == "-I" { 2579 continue 2580 } 2581 if imp == vendorPath { 2582 goto nextPrefixPath 2583 } 2584 } 2585 // This vendor path is needed and not already in the list, so add it 2586 importArgs = append(importArgs, "-I", vendorPath) 2587 nextPrefixPath: 2588 } 2589 } 2590 } 2591 2592 args := str.StringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) 2593 for _, f := range gofiles { 2594 args = append(args, mkAbs(p.Dir, f)) 2595 } 2596 2597 output, err = b.runOut(p.Dir, p.ImportPath, nil, args) 2598 return ofile, output, err 2599 } 2600 2601 func (tools gccgoToolchain) asm(b *Builder, p *load.Package, obj string, sfiles []string) ([]string, error) { 2602 var ofiles []string 2603 for _, sfile := range sfiles { 2604 ofile := obj + sfile[:len(sfile)-len(".s")] + ".o" 2605 ofiles = append(ofiles, ofile) 2606 sfile = mkAbs(p.Dir, sfile) 2607 defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch} 2608 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 2609 defs = append(defs, `-D`, `GOPKGPATH=`+pkgpath) 2610 } 2611 defs = tools.maybePIC(defs) 2612 defs = append(defs, b.gccArchArgs()...) 2613 err := b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-xassembler-with-cpp", "-I", obj, "-c", "-o", ofile, defs, sfile) 2614 if err != nil { 2615 return nil, err 2616 } 2617 } 2618 return ofiles, nil 2619 } 2620 2621 func (gccgoToolchain) Pkgpath(basedir string, p *load.Package) string { 2622 end := filepath.FromSlash(p.ImportPath + ".a") 2623 afile := filepath.Join(basedir, end) 2624 // add "lib" to the final element 2625 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) 2626 } 2627 2628 func (gccgoToolchain) pack(b *Builder, p *load.Package, objDir, afile string, ofiles []string) error { 2629 var absOfiles []string 2630 for _, f := range ofiles { 2631 absOfiles = append(absOfiles, mkAbs(objDir, f)) 2632 } 2633 return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objDir, afile), absOfiles) 2634 } 2635 2636 func (tools gccgoToolchain) link(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string, buildmode, desc string) error { 2637 // gccgo needs explicit linking with all package dependencies, 2638 // and all LDFLAGS from cgo dependencies. 2639 apackagePathsSeen := make(map[string]bool) 2640 afiles := []string{} 2641 shlibs := []string{} 2642 ldflags := b.gccArchArgs() 2643 cgoldflags := []string{} 2644 usesCgo := false 2645 cxx := false 2646 objc := false 2647 fortran := false 2648 if root.Package != nil { 2649 cxx = len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0 2650 objc = len(root.Package.MFiles) > 0 2651 fortran = len(root.Package.FFiles) > 0 2652 } 2653 2654 readCgoFlags := func(flagsFile string) error { 2655 flags, err := ioutil.ReadFile(flagsFile) 2656 if err != nil { 2657 return err 2658 } 2659 const ldflagsPrefix = "_CGO_LDFLAGS=" 2660 for _, line := range strings.Split(string(flags), "\n") { 2661 if strings.HasPrefix(line, ldflagsPrefix) { 2662 newFlags := strings.Fields(line[len(ldflagsPrefix):]) 2663 for _, flag := range newFlags { 2664 // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS 2665 // but they don't mean anything to the linker so filter 2666 // them out. 2667 if flag != "-g" && !strings.HasPrefix(flag, "-O") { 2668 cgoldflags = append(cgoldflags, flag) 2669 } 2670 } 2671 } 2672 } 2673 return nil 2674 } 2675 2676 readAndRemoveCgoFlags := func(archive string) (string, error) { 2677 newa, err := ioutil.TempFile(b.WorkDir, filepath.Base(archive)) 2678 if err != nil { 2679 return "", err 2680 } 2681 olda, err := os.Open(archive) 2682 if err != nil { 2683 return "", err 2684 } 2685 _, err = io.Copy(newa, olda) 2686 if err != nil { 2687 return "", err 2688 } 2689 err = olda.Close() 2690 if err != nil { 2691 return "", err 2692 } 2693 err = newa.Close() 2694 if err != nil { 2695 return "", err 2696 } 2697 2698 newarchive := newa.Name() 2699 err = b.run(b.WorkDir, desc, nil, "ar", "x", newarchive, "_cgo_flags") 2700 if err != nil { 2701 return "", err 2702 } 2703 err = b.run(".", desc, nil, "ar", "d", newarchive, "_cgo_flags") 2704 if err != nil { 2705 return "", err 2706 } 2707 err = readCgoFlags(filepath.Join(b.WorkDir, "_cgo_flags")) 2708 if err != nil { 2709 return "", err 2710 } 2711 return newarchive, nil 2712 } 2713 2714 actionsSeen := make(map[*Action]bool) 2715 // Make a pre-order depth-first traversal of the action graph, taking note of 2716 // whether a shared library action has been seen on the way to an action (the 2717 // construction of the graph means that if any path to a node passes through 2718 // a shared library action, they all do). 2719 var walk func(a *Action, seenShlib bool) 2720 var err error 2721 walk = func(a *Action, seenShlib bool) { 2722 if actionsSeen[a] { 2723 return 2724 } 2725 actionsSeen[a] = true 2726 if a.Package != nil && !seenShlib { 2727 if a.Package.Standard { 2728 return 2729 } 2730 // We record the target of the first time we see a .a file 2731 // for a package to make sure that we prefer the 'install' 2732 // rather than the 'build' location (which may not exist any 2733 // more). We still need to traverse the dependencies of the 2734 // build action though so saying 2735 // if apackagePathsSeen[a.Package.ImportPath] { return } 2736 // doesn't work. 2737 if !apackagePathsSeen[a.Package.ImportPath] { 2738 apackagePathsSeen[a.Package.ImportPath] = true 2739 target := a.Target 2740 if len(a.Package.CgoFiles) > 0 || a.Package.UsesSwig() { 2741 target, err = readAndRemoveCgoFlags(target) 2742 if err != nil { 2743 return 2744 } 2745 } 2746 afiles = append(afiles, target) 2747 } 2748 } 2749 if strings.HasSuffix(a.Target, ".so") { 2750 shlibs = append(shlibs, a.Target) 2751 seenShlib = true 2752 } 2753 for _, a1 := range a.Deps { 2754 walk(a1, seenShlib) 2755 if err != nil { 2756 return 2757 } 2758 } 2759 } 2760 for _, a1 := range root.Deps { 2761 walk(a1, false) 2762 if err != nil { 2763 return err 2764 } 2765 } 2766 2767 for _, a := range allactions { 2768 // Gather CgoLDFLAGS, but not from standard packages. 2769 // The go tool can dig up runtime/cgo from GOROOT and 2770 // think that it should use its CgoLDFLAGS, but gccgo 2771 // doesn't use runtime/cgo. 2772 if a.Package == nil { 2773 continue 2774 } 2775 if !a.Package.Standard { 2776 cgoldflags = append(cgoldflags, a.Package.CgoLDFLAGS...) 2777 } 2778 if len(a.Package.CgoFiles) > 0 { 2779 usesCgo = true 2780 } 2781 if a.Package.UsesSwig() { 2782 usesCgo = true 2783 } 2784 if len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0 { 2785 cxx = true 2786 } 2787 if len(a.Package.MFiles) > 0 { 2788 objc = true 2789 } 2790 if len(a.Package.FFiles) > 0 { 2791 fortran = true 2792 } 2793 } 2794 2795 for i, o := range ofiles { 2796 if filepath.Base(o) == "_cgo_flags" { 2797 readCgoFlags(o) 2798 ofiles = append(ofiles[:i], ofiles[i+1:]...) 2799 break 2800 } 2801 } 2802 2803 ldflags = append(ldflags, "-Wl,--whole-archive") 2804 ldflags = append(ldflags, afiles...) 2805 ldflags = append(ldflags, "-Wl,--no-whole-archive") 2806 2807 ldflags = append(ldflags, cgoldflags...) 2808 ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...) 2809 if root.Package != nil { 2810 ldflags = append(ldflags, root.Package.CgoLDFLAGS...) 2811 } 2812 2813 ldflags = str.StringList("-Wl,-(", ldflags, "-Wl,-)") 2814 2815 for _, shlib := range shlibs { 2816 ldflags = append( 2817 ldflags, 2818 "-L"+filepath.Dir(shlib), 2819 "-Wl,-rpath="+filepath.Dir(shlib), 2820 "-l"+strings.TrimSuffix( 2821 strings.TrimPrefix(filepath.Base(shlib), "lib"), 2822 ".so")) 2823 } 2824 2825 var realOut string 2826 switch buildmode { 2827 case "exe": 2828 if usesCgo && cfg.Goos == "linux" { 2829 ldflags = append(ldflags, "-Wl,-E") 2830 } 2831 2832 case "c-archive": 2833 // Link the Go files into a single .o, and also link 2834 // in -lgolibbegin. 2835 // 2836 // We need to use --whole-archive with -lgolibbegin 2837 // because it doesn't define any symbols that will 2838 // cause the contents to be pulled in; it's just 2839 // initialization code. 2840 // 2841 // The user remains responsible for linking against 2842 // -lgo -lpthread -lm in the final link. We can't use 2843 // -r to pick them up because we can't combine 2844 // split-stack and non-split-stack code in a single -r 2845 // link, and libgo picks up non-split-stack code from 2846 // libffi. 2847 ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive") 2848 2849 if b.gccSupportsNoPie() { 2850 ldflags = append(ldflags, "-no-pie") 2851 } 2852 2853 // We are creating an object file, so we don't want a build ID. 2854 ldflags = b.disableBuildID(ldflags) 2855 2856 realOut = out 2857 out = out + ".o" 2858 2859 case "c-shared": 2860 ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc") 2861 case "shared": 2862 ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc") 2863 2864 default: 2865 base.Fatalf("-buildmode=%s not supported for gccgo", buildmode) 2866 } 2867 2868 switch buildmode { 2869 case "exe", "c-shared": 2870 if cxx { 2871 ldflags = append(ldflags, "-lstdc++") 2872 } 2873 if objc { 2874 ldflags = append(ldflags, "-lobjc") 2875 } 2876 if fortran { 2877 fc := os.Getenv("FC") 2878 if fc == "" { 2879 fc = "gfortran" 2880 } 2881 // support gfortran out of the box and let others pass the correct link options 2882 // via CGO_LDFLAGS 2883 if strings.Contains(fc, "gfortran") { 2884 ldflags = append(ldflags, "-lgfortran") 2885 } 2886 } 2887 } 2888 2889 if err := b.run(".", desc, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil { 2890 return err 2891 } 2892 2893 switch buildmode { 2894 case "c-archive": 2895 if err := b.run(".", desc, nil, "ar", "rc", realOut, out); err != nil { 2896 return err 2897 } 2898 } 2899 return nil 2900 } 2901 2902 func (tools gccgoToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error { 2903 return tools.link(b, root, out, allactions, mainpkg, ofiles, ldBuildmode, root.Package.ImportPath) 2904 } 2905 2906 func (tools gccgoToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error { 2907 fakeRoot := &Action{} 2908 fakeRoot.Deps = toplevelactions 2909 return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out) 2910 } 2911 2912 func (tools gccgoToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error { 2913 inc := filepath.Join(cfg.GOROOT, "pkg", "include") 2914 cfile = mkAbs(p.Dir, cfile) 2915 defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch} 2916 defs = append(defs, b.gccArchArgs()...) 2917 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 2918 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 2919 } 2920 switch cfg.Goarch { 2921 case "386", "amd64": 2922 defs = append(defs, "-fsplit-stack") 2923 } 2924 defs = tools.maybePIC(defs) 2925 return b.run(p.Dir, p.ImportPath, nil, envList("CC", cfg.DefaultCC), "-Wall", "-g", 2926 "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) 2927 } 2928 2929 // maybePIC adds -fPIC to the list of arguments if needed. 2930 func (tools gccgoToolchain) maybePIC(args []string) []string { 2931 switch cfg.BuildBuildmode { 2932 case "c-shared", "shared", "plugin": 2933 args = append(args, "-fPIC") 2934 } 2935 return args 2936 } 2937 2938 func gccgoPkgpath(p *load.Package) string { 2939 if p.Internal.Build.IsCommand() && !p.Internal.ForceLibrary { 2940 return "" 2941 } 2942 return p.ImportPath 2943 } 2944 2945 func gccgoCleanPkgpath(p *load.Package) string { 2946 clean := func(r rune) rune { 2947 switch { 2948 case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', 2949 '0' <= r && r <= '9': 2950 return r 2951 } 2952 return '_' 2953 } 2954 return strings.Map(clean, gccgoPkgpath(p)) 2955 } 2956 2957 // gcc runs the gcc C compiler to create an object from a single C file. 2958 func (b *Builder) gcc(p *load.Package, out string, flags []string, cfile string) error { 2959 return b.ccompile(p, out, flags, cfile, b.GccCmd(p.Dir)) 2960 } 2961 2962 // gxx runs the g++ C++ compiler to create an object from a single C++ file. 2963 func (b *Builder) gxx(p *load.Package, out string, flags []string, cxxfile string) error { 2964 return b.ccompile(p, out, flags, cxxfile, b.GxxCmd(p.Dir)) 2965 } 2966 2967 // gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file. 2968 func (b *Builder) gfortran(p *load.Package, out string, flags []string, ffile string) error { 2969 return b.ccompile(p, out, flags, ffile, b.gfortranCmd(p.Dir)) 2970 } 2971 2972 // ccompile runs the given C or C++ compiler and creates an object from a single source file. 2973 func (b *Builder) ccompile(p *load.Package, outfile string, flags []string, file string, compiler []string) error { 2974 file = mkAbs(p.Dir, file) 2975 desc := p.ImportPath 2976 output, err := b.runOut(p.Dir, desc, nil, compiler, flags, "-o", outfile, "-c", file) 2977 if len(output) > 0 { 2978 // On FreeBSD 11, when we pass -g to clang 3.8 it 2979 // invokes its internal assembler with -dwarf-version=2. 2980 // When it sees .section .note.GNU-stack, it warns 2981 // "DWARF2 only supports one section per compilation unit". 2982 // This warning makes no sense, since the section is empty, 2983 // but it confuses people. 2984 // We work around the problem by detecting the warning 2985 // and dropping -g and trying again. 2986 if bytes.Contains(output, []byte("DWARF2 only supports one section per compilation unit")) { 2987 newFlags := make([]string, 0, len(flags)) 2988 for _, f := range flags { 2989 if !strings.HasPrefix(f, "-g") { 2990 newFlags = append(newFlags, f) 2991 } 2992 } 2993 if len(newFlags) < len(flags) { 2994 return b.ccompile(p, outfile, newFlags, file, compiler) 2995 } 2996 } 2997 2998 b.showOutput(p.Dir, desc, b.processOutput(output)) 2999 if err != nil { 3000 err = errPrintedOutput 3001 } else if os.Getenv("GO_BUILDER_NAME") != "" { 3002 return errors.New("C compiler warning promoted to error on Go builders") 3003 } 3004 } 3005 return err 3006 } 3007 3008 // gccld runs the gcc linker to create an executable from a set of object files. 3009 func (b *Builder) gccld(p *load.Package, out string, flags []string, obj []string) error { 3010 var cmd []string 3011 if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 { 3012 cmd = b.GxxCmd(p.Dir) 3013 } else { 3014 cmd = b.GccCmd(p.Dir) 3015 } 3016 return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags) 3017 } 3018 3019 // gccCmd returns a gcc command line prefix 3020 // defaultCC is defined in zdefaultcc.go, written by cmd/dist. 3021 func (b *Builder) GccCmd(objdir string) []string { 3022 return b.ccompilerCmd("CC", cfg.DefaultCC, objdir) 3023 } 3024 3025 // gxxCmd returns a g++ command line prefix 3026 // defaultCXX is defined in zdefaultcc.go, written by cmd/dist. 3027 func (b *Builder) GxxCmd(objdir string) []string { 3028 return b.ccompilerCmd("CXX", cfg.DefaultCXX, objdir) 3029 } 3030 3031 // gfortranCmd returns a gfortran command line prefix. 3032 func (b *Builder) gfortranCmd(objdir string) []string { 3033 return b.ccompilerCmd("FC", "gfortran", objdir) 3034 } 3035 3036 // ccompilerCmd returns a command line prefix for the given environment 3037 // variable and using the default command when the variable is empty. 3038 func (b *Builder) ccompilerCmd(envvar, defcmd, objdir string) []string { 3039 // NOTE: env.go's mkEnv knows that the first three 3040 // strings returned are "gcc", "-I", objdir (and cuts them off). 3041 3042 compiler := envList(envvar, defcmd) 3043 a := []string{compiler[0], "-I", objdir} 3044 a = append(a, compiler[1:]...) 3045 3046 // Definitely want -fPIC but on Windows gcc complains 3047 // "-fPIC ignored for target (all code is position independent)" 3048 if cfg.Goos != "windows" { 3049 a = append(a, "-fPIC") 3050 } 3051 a = append(a, b.gccArchArgs()...) 3052 // gcc-4.5 and beyond require explicit "-pthread" flag 3053 // for multithreading with pthread library. 3054 if cfg.BuildContext.CgoEnabled { 3055 switch cfg.Goos { 3056 case "windows": 3057 a = append(a, "-mthreads") 3058 default: 3059 a = append(a, "-pthread") 3060 } 3061 } 3062 3063 if strings.Contains(a[0], "clang") { 3064 // disable ASCII art in clang errors, if possible 3065 a = append(a, "-fno-caret-diagnostics") 3066 // clang is too smart about command-line arguments 3067 a = append(a, "-Qunused-arguments") 3068 } 3069 3070 // disable word wrapping in error messages 3071 a = append(a, "-fmessage-length=0") 3072 3073 // Tell gcc not to include the work directory in object files. 3074 if b.gccSupportsFlag("-fdebug-prefix-map=a=b") { 3075 a = append(a, "-fdebug-prefix-map="+b.WorkDir+"=/tmp/go-build") 3076 } 3077 3078 // Tell gcc not to include flags in object files, which defeats the 3079 // point of -fdebug-prefix-map above. 3080 if b.gccSupportsFlag("-gno-record-gcc-switches") { 3081 a = append(a, "-gno-record-gcc-switches") 3082 } 3083 3084 // On OS X, some of the compilers behave as if -fno-common 3085 // is always set, and the Mach-O linker in 6l/8l assumes this. 3086 // See https://golang.org/issue/3253. 3087 if cfg.Goos == "darwin" { 3088 a = append(a, "-fno-common") 3089 } 3090 3091 return a 3092 } 3093 3094 // On systems with PIE (position independent executables) enabled by default, 3095 // -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is 3096 // not supported by all compilers. 3097 func (b *Builder) gccSupportsNoPie() bool { 3098 return b.gccSupportsFlag("-no-pie") 3099 } 3100 3101 // gccSupportsFlag checks to see if the compiler supports a flag. 3102 func (b *Builder) gccSupportsFlag(flag string) bool { 3103 b.exec.Lock() 3104 defer b.exec.Unlock() 3105 if b, ok := b.flagCache[flag]; ok { 3106 return b 3107 } 3108 if b.flagCache == nil { 3109 src := filepath.Join(b.WorkDir, "trivial.c") 3110 if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil { 3111 return false 3112 } 3113 b.flagCache = make(map[string]bool) 3114 } 3115 cmdArgs := append(envList("CC", cfg.DefaultCC), flag, "-c", "trivial.c") 3116 if cfg.BuildN || cfg.BuildX { 3117 b.Showcmd(b.WorkDir, "%s", joinUnambiguously(cmdArgs)) 3118 if cfg.BuildN { 3119 return false 3120 } 3121 } 3122 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 3123 cmd.Dir = b.WorkDir 3124 cmd.Env = base.MergeEnvLists([]string{"LC_ALL=C"}, base.EnvForDir(cmd.Dir, os.Environ())) 3125 out, err := cmd.CombinedOutput() 3126 supported := err == nil && !bytes.Contains(out, []byte("unrecognized")) 3127 b.flagCache[flag] = supported 3128 return supported 3129 } 3130 3131 // gccArchArgs returns arguments to pass to gcc based on the architecture. 3132 func (b *Builder) gccArchArgs() []string { 3133 switch cfg.Goarch { 3134 case "386": 3135 return []string{"-m32"} 3136 case "amd64", "amd64p32": 3137 return []string{"-m64"} 3138 case "arm": 3139 return []string{"-marm"} // not thumb 3140 case "s390x": 3141 return []string{"-m64", "-march=z196"} 3142 case "mips64", "mips64le": 3143 return []string{"-mabi=64"} 3144 case "mips", "mipsle": 3145 return []string{"-mabi=32", "-march=mips32"} 3146 } 3147 return nil 3148 } 3149 3150 // envList returns the value of the given environment variable broken 3151 // into fields, using the default value when the variable is empty. 3152 func envList(key, def string) []string { 3153 v := os.Getenv(key) 3154 if v == "" { 3155 v = def 3156 } 3157 return strings.Fields(v) 3158 } 3159 3160 // CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo. 3161 func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) { 3162 defaults := "-g -O2" 3163 3164 cppflags = str.StringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) 3165 cflags = str.StringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) 3166 cxxflags = str.StringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) 3167 fflags = str.StringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS) 3168 ldflags = str.StringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) 3169 return 3170 } 3171 3172 var cgoRe = regexp.MustCompile(`[/\\:]`) 3173 3174 func (b *Builder) cgo(a *Action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) { 3175 p := a.Package 3176 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.CFlags(p) 3177 cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) 3178 cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) 3179 // If we are compiling Objective-C code, then we need to link against libobjc 3180 if len(mfiles) > 0 { 3181 cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") 3182 } 3183 3184 // Likewise for Fortran, except there are many Fortran compilers. 3185 // Support gfortran out of the box and let others pass the correct link options 3186 // via CGO_LDFLAGS 3187 if len(ffiles) > 0 { 3188 fc := os.Getenv("FC") 3189 if fc == "" { 3190 fc = "gfortran" 3191 } 3192 if strings.Contains(fc, "gfortran") { 3193 cgoLDFLAGS = append(cgoLDFLAGS, "-lgfortran") 3194 } 3195 } 3196 3197 if cfg.BuildMSan { 3198 cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...) 3199 cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) 3200 } 3201 3202 // Allows including _cgo_export.h from .[ch] files in the package. 3203 cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj) 3204 3205 // If we have cgo files in the object directory, then copy any 3206 // other cgo files into the object directory, and pass a 3207 // -srcdir option to cgo. 3208 var srcdirarg []string 3209 if len(objdirCgofiles) > 0 { 3210 for _, fn := range cgofiles { 3211 if err := b.copyFile(a, obj+filepath.Base(fn), filepath.Join(p.Dir, fn), 0666, false); err != nil { 3212 return nil, nil, err 3213 } 3214 } 3215 cgofiles = append(cgofiles, objdirCgofiles...) 3216 srcdirarg = []string{"-srcdir", obj} 3217 } 3218 3219 // cgo 3220 // TODO: CGO_FLAGS? 3221 gofiles := []string{obj + "_cgo_gotypes.go"} 3222 cfiles := []string{"_cgo_export.c"} 3223 for _, fn := range cgofiles { 3224 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") 3225 gofiles = append(gofiles, obj+f+"cgo1.go") 3226 cfiles = append(cfiles, f+"cgo2.c") 3227 } 3228 3229 // TODO: make cgo not depend on $GOARCH? 3230 3231 cgoflags := []string{} 3232 if p.Standard && p.ImportPath == "runtime/cgo" { 3233 cgoflags = append(cgoflags, "-import_runtime_cgo=false") 3234 } 3235 if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") { 3236 cgoflags = append(cgoflags, "-import_syscall=false") 3237 } 3238 3239 // Update $CGO_LDFLAGS with p.CgoLDFLAGS. 3240 var cgoenv []string 3241 if len(cgoLDFLAGS) > 0 { 3242 flags := make([]string, len(cgoLDFLAGS)) 3243 for i, f := range cgoLDFLAGS { 3244 flags[i] = strconv.Quote(f) 3245 } 3246 cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} 3247 } 3248 3249 if cfg.BuildToolchainName == "gccgo" { 3250 switch cfg.Goarch { 3251 case "386", "amd64": 3252 cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack") 3253 } 3254 cgoflags = append(cgoflags, "-gccgo") 3255 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 3256 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) 3257 } 3258 } 3259 3260 switch cfg.BuildBuildmode { 3261 case "c-archive", "c-shared": 3262 // Tell cgo that if there are any exported functions 3263 // it should generate a header file that C code can 3264 // #include. 3265 cgoflags = append(cgoflags, "-exportheader="+obj+"_cgo_install.h") 3266 } 3267 3268 if err := b.run(p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, srcdirarg, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { 3269 return nil, nil, err 3270 } 3271 outGo = append(outGo, gofiles...) 3272 3273 // gcc 3274 cflags := str.StringList(cgoCPPFLAGS, cgoCFLAGS) 3275 for _, cfile := range cfiles { 3276 ofile := obj + cfile[:len(cfile)-1] + "o" 3277 if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil { 3278 return nil, nil, err 3279 } 3280 outObj = append(outObj, ofile) 3281 } 3282 3283 for _, file := range gccfiles { 3284 base := filepath.Base(file) 3285 ofile := obj + cgoRe.ReplaceAllString(base[:len(base)-1], "_") + "o" 3286 if err := b.gcc(p, ofile, cflags, file); err != nil { 3287 return nil, nil, err 3288 } 3289 outObj = append(outObj, ofile) 3290 } 3291 3292 cxxflags := str.StringList(cgoCPPFLAGS, cgoCXXFLAGS) 3293 for _, file := range gxxfiles { 3294 // Append .o to the file, just in case the pkg has file.c and file.cpp 3295 ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o" 3296 if err := b.gxx(p, ofile, cxxflags, file); err != nil { 3297 return nil, nil, err 3298 } 3299 outObj = append(outObj, ofile) 3300 } 3301 3302 for _, file := range mfiles { 3303 // Append .o to the file, just in case the pkg has file.c and file.m 3304 ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o" 3305 if err := b.gcc(p, ofile, cflags, file); err != nil { 3306 return nil, nil, err 3307 } 3308 outObj = append(outObj, ofile) 3309 } 3310 3311 fflags := str.StringList(cgoCPPFLAGS, cgoFFLAGS) 3312 for _, file := range ffiles { 3313 // Append .o to the file, just in case the pkg has file.c and file.f 3314 ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o" 3315 if err := b.gfortran(p, ofile, fflags, file); err != nil { 3316 return nil, nil, err 3317 } 3318 outObj = append(outObj, ofile) 3319 } 3320 3321 switch cfg.BuildToolchainName { 3322 case "gc": 3323 importGo := obj + "_cgo_import.go" 3324 if err := b.dynimport(p, obj, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil { 3325 return nil, nil, err 3326 } 3327 outGo = append(outGo, importGo) 3328 3329 ofile := obj + "_all.o" 3330 if err := b.collect(p, obj, ofile, cgoLDFLAGS, outObj); err != nil { 3331 return nil, nil, err 3332 } 3333 outObj = []string{ofile} 3334 3335 case "gccgo": 3336 defunC := obj + "_cgo_defun.c" 3337 defunObj := obj + "_cgo_defun.o" 3338 if err := BuildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { 3339 return nil, nil, err 3340 } 3341 outObj = append(outObj, defunObj) 3342 3343 default: 3344 noCompiler() 3345 } 3346 3347 return outGo, outObj, nil 3348 } 3349 3350 // dynimport creates a Go source file named importGo containing 3351 // //go:cgo_import_dynamic directives for each symbol or library 3352 // dynamically imported by the object files outObj. 3353 func (b *Builder) dynimport(p *load.Package, obj, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error { 3354 cfile := obj + "_cgo_main.c" 3355 ofile := obj + "_cgo_main.o" 3356 if err := b.gcc(p, ofile, cflags, cfile); err != nil { 3357 return err 3358 } 3359 3360 linkobj := str.StringList(ofile, outObj, p.SysoFiles) 3361 dynobj := obj + "_cgo_.o" 3362 3363 // we need to use -pie for Linux/ARM to get accurate imported sym 3364 ldflags := cgoLDFLAGS 3365 if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" { 3366 ldflags = append(ldflags, "-pie") 3367 } 3368 if err := b.gccld(p, dynobj, ldflags, linkobj); err != nil { 3369 return err 3370 } 3371 3372 // cgo -dynimport 3373 var cgoflags []string 3374 if p.Standard && p.ImportPath == "runtime/cgo" { 3375 cgoflags = []string{"-dynlinker"} // record path to dynamic linker 3376 } 3377 return b.run(p.Dir, p.ImportPath, nil, cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) 3378 } 3379 3380 // collect partially links the object files outObj into a single 3381 // relocatable object file named ofile. 3382 func (b *Builder) collect(p *load.Package, obj, ofile string, cgoLDFLAGS, outObj []string) error { 3383 // When linking relocatable objects, various flags need to be 3384 // filtered out as they are inapplicable and can cause some linkers 3385 // to fail. 3386 var ldflags []string 3387 for i := 0; i < len(cgoLDFLAGS); i++ { 3388 f := cgoLDFLAGS[i] 3389 switch { 3390 // skip "-lc" or "-l somelib" 3391 case strings.HasPrefix(f, "-l"): 3392 if f == "-l" { 3393 i++ 3394 } 3395 // skip "-framework X" on Darwin 3396 case cfg.Goos == "darwin" && f == "-framework": 3397 i++ 3398 // skip "*.{dylib,so,dll,o,a}" 3399 case strings.HasSuffix(f, ".dylib"), 3400 strings.HasSuffix(f, ".so"), 3401 strings.HasSuffix(f, ".dll"), 3402 strings.HasSuffix(f, ".o"), 3403 strings.HasSuffix(f, ".a"): 3404 // Remove any -fsanitize=foo flags. 3405 // Otherwise the compiler driver thinks that we are doing final link 3406 // and links sanitizer runtime into the object file. But we are not doing 3407 // the final link, we will link the resulting object file again. And 3408 // so the program ends up with two copies of sanitizer runtime. 3409 // See issue 8788 for details. 3410 case strings.HasPrefix(f, "-fsanitize="): 3411 continue 3412 // runpath flags not applicable unless building a shared 3413 // object or executable; see issue 12115 for details. This 3414 // is necessary as Go currently does not offer a way to 3415 // specify the set of LDFLAGS that only apply to shared 3416 // objects. 3417 case strings.HasPrefix(f, "-Wl,-rpath"): 3418 if f == "-Wl,-rpath" || f == "-Wl,-rpath-link" { 3419 // Skip following argument to -rpath* too. 3420 i++ 3421 } 3422 default: 3423 ldflags = append(ldflags, f) 3424 } 3425 } 3426 3427 ldflags = append(ldflags, "-Wl,-r", "-nostdlib") 3428 3429 if b.gccSupportsNoPie() { 3430 ldflags = append(ldflags, "-no-pie") 3431 } 3432 3433 // We are creating an object file, so we don't want a build ID. 3434 ldflags = b.disableBuildID(ldflags) 3435 3436 return b.gccld(p, ofile, ldflags, outObj) 3437 } 3438 3439 // Run SWIG on all SWIG input files. 3440 // TODO: Don't build a shared library, once SWIG emits the necessary 3441 // pragmas for external linking. 3442 func (b *Builder) swig(p *load.Package, obj string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) { 3443 if err := b.swigVersionCheck(); err != nil { 3444 return nil, nil, nil, err 3445 } 3446 3447 intgosize, err := b.swigIntSize(obj) 3448 if err != nil { 3449 return nil, nil, nil, err 3450 } 3451 3452 for _, f := range p.SwigFiles { 3453 goFile, cFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize) 3454 if err != nil { 3455 return nil, nil, nil, err 3456 } 3457 if goFile != "" { 3458 outGo = append(outGo, goFile) 3459 } 3460 if cFile != "" { 3461 outC = append(outC, cFile) 3462 } 3463 } 3464 for _, f := range p.SwigCXXFiles { 3465 goFile, cxxFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize) 3466 if err != nil { 3467 return nil, nil, nil, err 3468 } 3469 if goFile != "" { 3470 outGo = append(outGo, goFile) 3471 } 3472 if cxxFile != "" { 3473 outCXX = append(outCXX, cxxFile) 3474 } 3475 } 3476 return outGo, outC, outCXX, nil 3477 } 3478 3479 // Make sure SWIG is new enough. 3480 var ( 3481 swigCheckOnce sync.Once 3482 swigCheck error 3483 ) 3484 3485 func (b *Builder) swigDoVersionCheck() error { 3486 out, err := b.runOut("", "", nil, "swig", "-version") 3487 if err != nil { 3488 return err 3489 } 3490 re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`) 3491 matches := re.FindSubmatch(out) 3492 if matches == nil { 3493 // Can't find version number; hope for the best. 3494 return nil 3495 } 3496 3497 major, err := strconv.Atoi(string(matches[1])) 3498 if err != nil { 3499 // Can't find version number; hope for the best. 3500 return nil 3501 } 3502 const errmsg = "must have SWIG version >= 3.0.6" 3503 if major < 3 { 3504 return errors.New(errmsg) 3505 } 3506 if major > 3 { 3507 // 4.0 or later 3508 return nil 3509 } 3510 3511 // We have SWIG version 3.x. 3512 if len(matches[2]) > 0 { 3513 minor, err := strconv.Atoi(string(matches[2][1:])) 3514 if err != nil { 3515 return nil 3516 } 3517 if minor > 0 { 3518 // 3.1 or later 3519 return nil 3520 } 3521 } 3522 3523 // We have SWIG version 3.0.x. 3524 if len(matches[3]) > 0 { 3525 patch, err := strconv.Atoi(string(matches[3][1:])) 3526 if err != nil { 3527 return nil 3528 } 3529 if patch < 6 { 3530 // Before 3.0.6. 3531 return errors.New(errmsg) 3532 } 3533 } 3534 3535 return nil 3536 } 3537 3538 func (b *Builder) swigVersionCheck() error { 3539 swigCheckOnce.Do(func() { 3540 swigCheck = b.swigDoVersionCheck() 3541 }) 3542 return swigCheck 3543 } 3544 3545 // Find the value to pass for the -intgosize option to swig. 3546 var ( 3547 swigIntSizeOnce sync.Once 3548 swigIntSize string 3549 swigIntSizeError error 3550 ) 3551 3552 // This code fails to build if sizeof(int) <= 32 3553 const swigIntSizeCode = ` 3554 package main 3555 const i int = 1 << 32 3556 ` 3557 3558 // Determine the size of int on the target system for the -intgosize option 3559 // of swig >= 2.0.9. Run only once. 3560 func (b *Builder) swigDoIntSize(obj string) (intsize string, err error) { 3561 if cfg.BuildN { 3562 return "$INTBITS", nil 3563 } 3564 src := filepath.Join(b.WorkDir, "swig_intsize.go") 3565 if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil { 3566 return 3567 } 3568 srcs := []string{src} 3569 3570 p := load.GoFilesPackage(srcs) 3571 3572 if _, _, e := BuildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil { 3573 return "32", nil 3574 } 3575 return "64", nil 3576 } 3577 3578 // Determine the size of int on the target system for the -intgosize option 3579 // of swig >= 2.0.9. 3580 func (b *Builder) swigIntSize(obj string) (intsize string, err error) { 3581 swigIntSizeOnce.Do(func() { 3582 swigIntSize, swigIntSizeError = b.swigDoIntSize(obj) 3583 }) 3584 return swigIntSize, swigIntSizeError 3585 } 3586 3587 // Run SWIG on one SWIG input file. 3588 func (b *Builder) swigOne(p *load.Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) { 3589 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.CFlags(p) 3590 var cflags []string 3591 if cxx { 3592 cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) 3593 } else { 3594 cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) 3595 } 3596 3597 n := 5 // length of ".swig" 3598 if cxx { 3599 n = 8 // length of ".swigcxx" 3600 } 3601 base := file[:len(file)-n] 3602 goFile := base + ".go" 3603 gccBase := base + "_wrap." 3604 gccExt := "c" 3605 if cxx { 3606 gccExt = "cxx" 3607 } 3608 3609 gccgo := cfg.BuildToolchainName == "gccgo" 3610 3611 // swig 3612 args := []string{ 3613 "-go", 3614 "-cgo", 3615 "-intgosize", intgosize, 3616 "-module", base, 3617 "-o", obj + gccBase + gccExt, 3618 "-outdir", obj, 3619 } 3620 3621 for _, f := range cflags { 3622 if len(f) > 3 && f[:2] == "-I" { 3623 args = append(args, f) 3624 } 3625 } 3626 3627 if gccgo { 3628 args = append(args, "-gccgo") 3629 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 3630 args = append(args, "-go-pkgpath", pkgpath) 3631 } 3632 } 3633 if cxx { 3634 args = append(args, "-c++") 3635 } 3636 3637 out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file) 3638 if err != nil { 3639 if len(out) > 0 { 3640 if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) { 3641 return "", "", errors.New("must have SWIG version >= 3.0.6") 3642 } 3643 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) // swig error 3644 return "", "", errPrintedOutput 3645 } 3646 return "", "", err 3647 } 3648 if len(out) > 0 { 3649 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) // swig warning 3650 } 3651 3652 return goFile, obj + gccBase + gccExt, nil 3653 } 3654 3655 // disableBuildID adjusts a linker command line to avoid creating a 3656 // build ID when creating an object file rather than an executable or 3657 // shared library. Some systems, such as Ubuntu, always add 3658 // --build-id to every link, but we don't want a build ID when we are 3659 // producing an object file. On some of those system a plain -r (not 3660 // -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a 3661 // plain -r. I don't know how to turn off --build-id when using clang 3662 // other than passing a trailing --build-id=none. So that is what we 3663 // do, but only on systems likely to support it, which is to say, 3664 // systems that normally use gold or the GNU linker. 3665 func (b *Builder) disableBuildID(ldflags []string) []string { 3666 switch cfg.Goos { 3667 case "android", "dragonfly", "linux", "netbsd": 3668 ldflags = append(ldflags, "-Wl,--build-id=none") 3669 } 3670 return ldflags 3671 } 3672 3673 // An actionQueue is a priority queue of actions. 3674 type actionQueue []*Action 3675 3676 // Implement heap.Interface 3677 func (q *actionQueue) Len() int { return len(*q) } 3678 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 3679 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } 3680 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) } 3681 func (q *actionQueue) Pop() interface{} { 3682 n := len(*q) - 1 3683 x := (*q)[n] 3684 *q = (*q)[:n] 3685 return x 3686 } 3687 3688 func (q *actionQueue) push(a *Action) { 3689 heap.Push(q, a) 3690 } 3691 3692 func (q *actionQueue) pop() *Action { 3693 return heap.Pop(q).(*Action) 3694 } 3695 3696 func InstrumentInit() { 3697 if !cfg.BuildRace && !cfg.BuildMSan { 3698 return 3699 } 3700 if cfg.BuildRace && cfg.BuildMSan { 3701 fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0]) 3702 os.Exit(2) 3703 } 3704 if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") { 3705 fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) 3706 os.Exit(2) 3707 } 3708 if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" { 3709 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]) 3710 os.Exit(2) 3711 } 3712 if !cfg.BuildContext.CgoEnabled { 3713 fmt.Fprintf(os.Stderr, "go %s: -race requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0]) 3714 os.Exit(2) 3715 } 3716 if cfg.BuildRace { 3717 buildGcflags = append(buildGcflags, "-race") 3718 cfg.BuildLdflags = append(cfg.BuildLdflags, "-race") 3719 } else { 3720 buildGcflags = append(buildGcflags, "-msan") 3721 cfg.BuildLdflags = append(cfg.BuildLdflags, "-msan") 3722 } 3723 if cfg.BuildContext.InstallSuffix != "" { 3724 cfg.BuildContext.InstallSuffix += "_" 3725 } 3726 3727 if cfg.BuildRace { 3728 cfg.BuildContext.InstallSuffix += "race" 3729 cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "race") 3730 } else { 3731 cfg.BuildContext.InstallSuffix += "msan" 3732 cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "msan") 3733 } 3734 } 3735 3736 // ExecCmd is the command to use to run user binaries. 3737 // Normally it is empty, meaning run the binaries directly. 3738 // If cross-compiling and running on a remote system or 3739 // simulator, it is typically go_GOOS_GOARCH_exec, with 3740 // the target GOOS and GOARCH substituted. 3741 // The -exec flag overrides these defaults. 3742 var ExecCmd []string 3743 3744 // FindExecCmd derives the value of ExecCmd to use. 3745 // It returns that value and leaves ExecCmd set for direct use. 3746 func FindExecCmd() []string { 3747 if ExecCmd != nil { 3748 return ExecCmd 3749 } 3750 ExecCmd = []string{} // avoid work the second time 3751 if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH { 3752 return ExecCmd 3753 } 3754 path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch)) 3755 if err == nil { 3756 ExecCmd = []string{path} 3757 } 3758 return ExecCmd 3759 }