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