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