github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 "errors" 9 "fmt" 10 "go/build" 11 "os" 12 "os/exec" 13 "path" 14 "path/filepath" 15 "runtime" 16 "strings" 17 18 "cmd/go/internal/base" 19 "cmd/go/internal/cfg" 20 "cmd/go/internal/load" 21 "cmd/go/internal/search" 22 ) 23 24 var CmdBuild = &base.Command{ 25 UsageLine: "go build [-o output] [-i] [build flags] [packages]", 26 Short: "compile packages and dependencies", 27 Long: ` 28 Build compiles the packages named by the import paths, 29 along with their dependencies, but it does not install the results. 30 31 If the arguments to build are a list of .go files, build treats 32 them as a list of source files specifying a single package. 33 34 When compiling a single main package, build writes 35 the resulting executable to an output file named after 36 the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') 37 or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). 38 The '.exe' suffix is added when writing a Windows executable. 39 40 When compiling multiple packages or a single non-main package, 41 build compiles the packages but discards the resulting object, 42 serving only as a check that the packages can be built. 43 44 When compiling packages, build ignores files that end in '_test.go'. 45 46 The -o flag, only allowed when compiling a single package, 47 forces build to write the resulting executable or object 48 to the named output file, instead of the default behavior described 49 in the last two paragraphs. 50 51 The -i flag installs the packages that are dependencies of the target. 52 53 The build flags are shared by the build, clean, get, install, list, run, 54 and test commands: 55 56 -a 57 force rebuilding of packages that are already up-to-date. 58 -n 59 print the commands but do not run them. 60 -p n 61 the number of programs, such as build commands or 62 test binaries, that can be run in parallel. 63 The default is the number of CPUs available. 64 -race 65 enable data race detection. 66 Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. 67 -msan 68 enable interoperation with memory sanitizer. 69 Supported only on linux/amd64, linux/arm64 70 and only with Clang/LLVM as the host C compiler. 71 -v 72 print the names of packages as they are compiled. 73 -work 74 print the name of the temporary work directory and 75 do not delete it when exiting. 76 -x 77 print the commands. 78 79 -asmflags '[pattern=]arg list' 80 arguments to pass on each go tool asm invocation. 81 -buildmode mode 82 build mode to use. See 'go help buildmode' for more. 83 -compiler name 84 name of compiler to use, as in runtime.Compiler (gccgo or gc). 85 -gccgoflags '[pattern=]arg list' 86 arguments to pass on each gccgo compiler/linker invocation. 87 -gcflags '[pattern=]arg list' 88 arguments to pass on each go tool compile invocation. 89 -installsuffix suffix 90 a suffix to use in the name of the package installation directory, 91 in order to keep output separate from default builds. 92 If using the -race flag, the install suffix is automatically set to race 93 or, if set explicitly, has _race appended to it. Likewise for the -msan 94 flag. Using a -buildmode option that requires non-default compile flags 95 has a similar effect. 96 -ldflags '[pattern=]arg list' 97 arguments to pass on each go tool link invocation. 98 -linkshared 99 link against shared libraries previously created with 100 -buildmode=shared. 101 -mod mode 102 module download mode to use: readonly or vendor. 103 See 'go help modules' for more. 104 -pkgdir dir 105 install and load all packages from dir instead of the usual locations. 106 For example, when building with a non-standard configuration, 107 use -pkgdir to keep generated packages in a separate location. 108 -tags 'tag list' 109 a space-separated list of build tags to consider satisfied during the 110 build. For more information about build tags, see the description of 111 build constraints in the documentation for the go/build package. 112 -toolexec 'cmd args' 113 a program to use to invoke toolchain programs like vet and asm. 114 For example, instead of running asm, the go command will run 115 'cmd args /path/to/asm <arguments for asm>'. 116 117 The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a 118 space-separated list of arguments to pass to an underlying tool 119 during the build. To embed spaces in an element in the list, surround 120 it with either single or double quotes. The argument list may be 121 preceded by a package pattern and an equal sign, which restricts 122 the use of that argument list to the building of packages matching 123 that pattern (see 'go help packages' for a description of package 124 patterns). Without a pattern, the argument list applies only to the 125 packages named on the command line. The flags may be repeated 126 with different patterns in order to specify different arguments for 127 different sets of packages. If a package matches patterns given in 128 multiple flags, the latest match on the command line wins. 129 For example, 'go build -gcflags=-S fmt' prints the disassembly 130 only for package fmt, while 'go build -gcflags=all=-S fmt' 131 prints the disassembly for fmt and all its dependencies. 132 133 For more about specifying packages, see 'go help packages'. 134 For more about where packages and binaries are installed, 135 run 'go help gopath'. 136 For more about calling between Go and C/C++, run 'go help c'. 137 138 Note: Build adheres to certain conventions such as those described 139 by 'go help gopath'. Not all projects can follow these conventions, 140 however. Installations that have their own conventions or that use 141 a separate software build system may choose to use lower-level 142 invocations such as 'go tool compile' and 'go tool link' to avoid 143 some of the overheads and design decisions of the build tool. 144 145 See also: go install, go get, go clean. 146 `, 147 } 148 149 const concurrentGCBackendCompilationEnabledByDefault = true 150 151 func init() { 152 // break init cycle 153 CmdBuild.Run = runBuild 154 CmdInstall.Run = runInstall 155 156 CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "") 157 CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file") 158 159 CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "") 160 161 AddBuildFlags(CmdBuild) 162 AddBuildFlags(CmdInstall) 163 } 164 165 // Note that flags consulted by other parts of the code 166 // (for example, buildV) are in cmd/go/internal/cfg. 167 168 var ( 169 forcedAsmflags []string // internally-forced flags for cmd/asm 170 forcedGcflags []string // internally-forced flags for cmd/compile 171 forcedLdflags []string // internally-forced flags for cmd/link 172 forcedGccgoflags []string // internally-forced flags for gccgo 173 ) 174 175 var BuildToolchain toolchain = noToolchain{} 176 var ldBuildmode string 177 178 // buildCompiler implements flag.Var. 179 // It implements Set by updating both 180 // BuildToolchain and buildContext.Compiler. 181 type buildCompiler struct{} 182 183 func (c buildCompiler) Set(value string) error { 184 switch value { 185 case "gc": 186 BuildToolchain = gcToolchain{} 187 case "gccgo": 188 BuildToolchain = gccgoToolchain{} 189 default: 190 return fmt.Errorf("unknown compiler %q", value) 191 } 192 cfg.BuildToolchainName = value 193 cfg.BuildToolchainCompiler = BuildToolchain.compiler 194 cfg.BuildToolchainLinker = BuildToolchain.linker 195 cfg.BuildContext.Compiler = value 196 return nil 197 } 198 199 func (c buildCompiler) String() string { 200 return cfg.BuildContext.Compiler 201 } 202 203 func init() { 204 switch build.Default.Compiler { 205 case "gc", "gccgo": 206 buildCompiler{}.Set(build.Default.Compiler) 207 } 208 } 209 210 // addBuildFlags adds the flags common to the build, clean, get, 211 // install, list, run, and test commands. 212 func AddBuildFlags(cmd *base.Command) { 213 cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "") 214 cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "") 215 cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "") 216 cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "") 217 cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "") 218 219 cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "") 220 cmd.Flag.Var(buildCompiler{}, "compiler", "") 221 cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "") 222 cmd.Flag.Var(&load.BuildGcflags, "gcflags", "") 223 cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "") 224 cmd.Flag.StringVar(&cfg.BuildMod, "mod", "", "") 225 cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "") 226 cmd.Flag.Var(&load.BuildLdflags, "ldflags", "") 227 cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "") 228 cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "") 229 cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "") 230 cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "") 231 cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildContext.BuildTags), "tags", "") 232 cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "") 233 cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "") 234 235 // Undocumented, unstable debugging flags. 236 cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "") 237 } 238 239 // fileExtSplit expects a filename and returns the name 240 // and ext (without the dot). If the file has no 241 // extension, ext will be empty. 242 func fileExtSplit(file string) (name, ext string) { 243 dotExt := filepath.Ext(file) 244 name = file[:len(file)-len(dotExt)] 245 if dotExt != "" { 246 ext = dotExt[1:] 247 } 248 return 249 } 250 251 func pkgsMain(pkgs []*load.Package) (res []*load.Package) { 252 for _, p := range pkgs { 253 if p.Name == "main" { 254 res = append(res, p) 255 } 256 } 257 return res 258 } 259 260 func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) { 261 for _, p := range pkgs { 262 if p.Name != "main" { 263 res = append(res, p) 264 } 265 } 266 return res 267 } 268 269 func oneMainPkg(pkgs []*load.Package) []*load.Package { 270 if len(pkgs) != 1 || pkgs[0].Name != "main" { 271 base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode) 272 } 273 return pkgs 274 } 275 276 var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs } 277 278 var runtimeVersion = runtime.Version() 279 280 func runBuild(cmd *base.Command, args []string) { 281 BuildInit() 282 var b Builder 283 b.Init() 284 285 pkgs := load.PackagesForBuild(args) 286 287 if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" { 288 _, cfg.BuildO = path.Split(pkgs[0].ImportPath) 289 cfg.BuildO += cfg.ExeSuffix 290 } 291 292 // sanity check some often mis-used options 293 switch cfg.BuildContext.Compiler { 294 case "gccgo": 295 if load.BuildGcflags.Present() { 296 fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags") 297 } 298 if load.BuildLdflags.Present() { 299 fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags") 300 } 301 case "gc": 302 if load.BuildGccgoflags.Present() { 303 fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags") 304 } 305 } 306 307 depMode := ModeBuild 308 if cfg.BuildI { 309 depMode = ModeInstall 310 } 311 312 pkgs = omitTestOnly(pkgsFilter(load.Packages(args))) 313 314 // Special case -o /dev/null by not writing at all. 315 if cfg.BuildO == os.DevNull { 316 cfg.BuildO = "" 317 } 318 319 if cfg.BuildO != "" { 320 if len(pkgs) > 1 { 321 base.Fatalf("go build: cannot use -o with multiple packages") 322 } else if len(pkgs) == 0 { 323 base.Fatalf("no packages to build") 324 } 325 p := pkgs[0] 326 p.Target = cfg.BuildO 327 p.Stale = true // must build - not up to date 328 p.StaleReason = "build -o flag in use" 329 a := b.AutoAction(ModeInstall, depMode, p) 330 b.Do(a) 331 return 332 } 333 334 a := &Action{Mode: "go build"} 335 for _, p := range pkgs { 336 a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p)) 337 } 338 if cfg.BuildBuildmode == "shared" { 339 a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a) 340 } 341 b.Do(a) 342 } 343 344 var CmdInstall = &base.Command{ 345 UsageLine: "go install [-i] [build flags] [packages]", 346 Short: "compile and install packages and dependencies", 347 Long: ` 348 Install compiles and installs the packages named by the import paths. 349 350 The -i flag installs the dependencies of the named packages as well. 351 352 For more about the build flags, see 'go help build'. 353 For more about specifying packages, see 'go help packages'. 354 355 See also: go build, go get, go clean. 356 `, 357 } 358 359 // libname returns the filename to use for the shared library when using 360 // -buildmode=shared. The rules we use are: 361 // Use arguments for special 'meta' packages: 362 // std --> libstd.so 363 // std cmd --> libstd,cmd.so 364 // A single non-meta argument with trailing "/..." is special cased: 365 // foo/... --> libfoo.so 366 // (A relative path like "./..." expands the "." first) 367 // Use import paths for other cases, changing '/' to '-': 368 // somelib --> libsubdir-somelib.so 369 // ./ or ../ --> libsubdir-somelib.so 370 // gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so 371 // a/... b/... ---> liba/c,b/d.so - all matching import paths 372 // Name parts are joined with ','. 373 func libname(args []string, pkgs []*load.Package) (string, error) { 374 var libname string 375 appendName := func(arg string) { 376 if libname == "" { 377 libname = arg 378 } else { 379 libname += "," + arg 380 } 381 } 382 var haveNonMeta bool 383 for _, arg := range args { 384 if search.IsMetaPackage(arg) { 385 appendName(arg) 386 } else { 387 haveNonMeta = true 388 } 389 } 390 if len(libname) == 0 { // non-meta packages only. use import paths 391 if len(args) == 1 && strings.HasSuffix(args[0], "/...") { 392 // Special case of "foo/..." as mentioned above. 393 arg := strings.TrimSuffix(args[0], "/...") 394 if build.IsLocalImport(arg) { 395 cwd, _ := os.Getwd() 396 bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly) 397 if bp.ImportPath != "" && bp.ImportPath != "." { 398 arg = bp.ImportPath 399 } 400 } 401 appendName(strings.ReplaceAll(arg, "/", "-")) 402 } else { 403 for _, pkg := range pkgs { 404 appendName(strings.ReplaceAll(pkg.ImportPath, "/", "-")) 405 } 406 } 407 } else if haveNonMeta { // have both meta package and a non-meta one 408 return "", errors.New("mixing of meta and non-meta packages is not allowed") 409 } 410 // TODO(mwhudson): Needs to change for platforms that use different naming 411 // conventions... 412 return "lib" + libname + ".so", nil 413 } 414 415 func runInstall(cmd *base.Command, args []string) { 416 BuildInit() 417 InstallPackages(args, load.PackagesForBuild(args)) 418 } 419 420 // omitTestOnly returns pkgs with test-only packages removed. 421 func omitTestOnly(pkgs []*load.Package) []*load.Package { 422 var list []*load.Package 423 for _, p := range pkgs { 424 if len(p.GoFiles)+len(p.CgoFiles) == 0 && !p.Internal.CmdlinePkgLiteral { 425 // Package has no source files, 426 // perhaps due to build tags or perhaps due to only having *_test.go files. 427 // Also, it is only being processed as the result of a wildcard match 428 // like ./..., not because it was listed as a literal path on the command line. 429 // Ignore it. 430 continue 431 } 432 list = append(list, p) 433 } 434 return list 435 } 436 437 func InstallPackages(patterns []string, pkgs []*load.Package) { 438 if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) { 439 base.Fatalf("cannot install, GOBIN must be an absolute path") 440 } 441 442 pkgs = omitTestOnly(pkgsFilter(pkgs)) 443 for _, p := range pkgs { 444 if p.Target == "" { 445 switch { 446 case p.Standard && p.ImportPath == "unsafe": 447 // unsafe is a built-in package, has no target 448 case p.Name != "main" && p.Internal.Local && p.ConflictDir == "": 449 // Non-executables outside GOPATH need not have a target: 450 // we can use the cache to hold the built package archive for use in future builds. 451 // The ones inside GOPATH should have a target (in GOPATH/pkg) 452 // or else something is wrong and worth reporting (like a ConflictDir). 453 case p.Name != "main" && p.Module != nil: 454 // Non-executables have no target (except the cache) when building with modules. 455 case p.Internal.GobinSubdir: 456 base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName) 457 case p.Internal.CmdlineFiles: 458 base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName) 459 case p.ConflictDir != "": 460 base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir) 461 default: 462 base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+ 463 "\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir) 464 } 465 } 466 } 467 base.ExitIfErrors() 468 469 var b Builder 470 b.Init() 471 depMode := ModeBuild 472 if cfg.BuildI { 473 depMode = ModeInstall 474 } 475 a := &Action{Mode: "go install"} 476 var tools []*Action 477 for _, p := range pkgs { 478 // If p is a tool, delay the installation until the end of the build. 479 // This avoids installing assemblers/compilers that are being executed 480 // by other steps in the build. 481 a1 := b.AutoAction(ModeInstall, depMode, p) 482 if load.InstallTargetDir(p) == load.ToTool { 483 a.Deps = append(a.Deps, a1.Deps...) 484 a1.Deps = append(a1.Deps, a) 485 tools = append(tools, a1) 486 continue 487 } 488 a.Deps = append(a.Deps, a1) 489 } 490 if len(tools) > 0 { 491 a = &Action{ 492 Mode: "go install (tools)", 493 Deps: tools, 494 } 495 } 496 497 if cfg.BuildBuildmode == "shared" { 498 // Note: If buildmode=shared then only non-main packages 499 // are present in the pkgs list, so all the special case code about 500 // tools above did not apply, and a is just a simple Action 501 // with a list of Deps, one per package named in pkgs, 502 // the same as in runBuild. 503 a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a) 504 } 505 506 b.Do(a) 507 base.ExitIfErrors() 508 509 // Success. If this command is 'go install' with no arguments 510 // and the current directory (the implicit argument) is a command, 511 // remove any leftover command binary from a previous 'go build'. 512 // The binary is installed; it's not needed here anymore. 513 // And worse it might be a stale copy, which you don't want to find 514 // instead of the installed one if $PATH contains dot. 515 // One way to view this behavior is that it is as if 'go install' first 516 // runs 'go build' and the moves the generated file to the install dir. 517 // See issue 9645. 518 if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" { 519 // Compute file 'go build' would have created. 520 // If it exists and is an executable file, remove it. 521 _, targ := filepath.Split(pkgs[0].ImportPath) 522 targ += cfg.ExeSuffix 523 if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory 524 fi, err := os.Stat(targ) 525 if err == nil { 526 m := fi.Mode() 527 if m.IsRegular() { 528 if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit 529 os.Remove(targ) 530 } 531 } 532 } 533 } 534 } 535 } 536 537 // ExecCmd is the command to use to run user binaries. 538 // Normally it is empty, meaning run the binaries directly. 539 // If cross-compiling and running on a remote system or 540 // simulator, it is typically go_GOOS_GOARCH_exec, with 541 // the target GOOS and GOARCH substituted. 542 // The -exec flag overrides these defaults. 543 var ExecCmd []string 544 545 // FindExecCmd derives the value of ExecCmd to use. 546 // It returns that value and leaves ExecCmd set for direct use. 547 func FindExecCmd() []string { 548 if ExecCmd != nil { 549 return ExecCmd 550 } 551 ExecCmd = []string{} // avoid work the second time 552 if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH { 553 return ExecCmd 554 } 555 path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch)) 556 if err == nil { 557 ExecCmd = []string{path} 558 } 559 return ExecCmd 560 }