github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/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 cmd.Flag.Var(&load.DebugDeprecatedImportcfg, "debug-deprecated-importcfg", "") 233 } 234 235 // fileExtSplit expects a filename and returns the name 236 // and ext (without the dot). If the file has no 237 // extension, ext will be empty. 238 func fileExtSplit(file string) (name, ext string) { 239 dotExt := filepath.Ext(file) 240 name = file[:len(file)-len(dotExt)] 241 if dotExt != "" { 242 ext = dotExt[1:] 243 } 244 return 245 } 246 247 func pkgsMain(pkgs []*load.Package) (res []*load.Package) { 248 for _, p := range pkgs { 249 if p.Name == "main" { 250 res = append(res, p) 251 } 252 } 253 return res 254 } 255 256 func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) { 257 for _, p := range pkgs { 258 if p.Name != "main" { 259 res = append(res, p) 260 } 261 } 262 return res 263 } 264 265 func oneMainPkg(pkgs []*load.Package) []*load.Package { 266 if len(pkgs) != 1 || pkgs[0].Name != "main" { 267 base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode) 268 } 269 return pkgs 270 } 271 272 var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs } 273 274 var runtimeVersion = runtime.Version() 275 276 func runBuild(cmd *base.Command, args []string) { 277 BuildInit() 278 var b Builder 279 b.Init() 280 281 pkgs := load.PackagesForBuild(args) 282 283 if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" { 284 _, cfg.BuildO = path.Split(pkgs[0].ImportPath) 285 cfg.BuildO += cfg.ExeSuffix 286 } 287 288 // Special case -o /dev/null by not writing at all. 289 if cfg.BuildO == os.DevNull { 290 cfg.BuildO = "" 291 } 292 293 // sanity check some often mis-used options 294 switch cfg.BuildContext.Compiler { 295 case "gccgo": 296 if load.BuildGcflags.Present() { 297 fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags") 298 } 299 if load.BuildLdflags.Present() { 300 fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags") 301 } 302 case "gc": 303 if load.BuildGccgoflags.Present() { 304 fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags") 305 } 306 } 307 308 depMode := ModeBuild 309 if cfg.BuildI { 310 depMode = ModeInstall 311 } 312 313 pkgs = pkgsFilter(load.Packages(args)) 314 315 if cfg.BuildO != "" { 316 if len(pkgs) > 1 { 317 base.Fatalf("go build: cannot use -o with multiple packages") 318 } else if len(pkgs) == 0 { 319 base.Fatalf("no packages to build") 320 } 321 p := pkgs[0] 322 p.Target = cfg.BuildO 323 p.Stale = true // must build - not up to date 324 p.StaleReason = "build -o flag in use" 325 a := b.AutoAction(ModeInstall, depMode, p) 326 b.Do(a) 327 return 328 } 329 330 a := &Action{Mode: "go build"} 331 for _, p := range pkgs { 332 a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p)) 333 } 334 if cfg.BuildBuildmode == "shared" { 335 a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a) 336 } 337 b.Do(a) 338 } 339 340 var CmdInstall = &base.Command{ 341 UsageLine: "install [-i] [build flags] [packages]", 342 Short: "compile and install packages and dependencies", 343 Long: ` 344 Install compiles and installs the packages named by the import paths. 345 346 The -i flag installs the dependencies of the named packages as well. 347 348 For more about the build flags, see 'go help build'. 349 For more about specifying packages, see 'go help packages'. 350 351 See also: go build, go get, go clean. 352 `, 353 } 354 355 // libname returns the filename to use for the shared library when using 356 // -buildmode=shared. The rules we use are: 357 // Use arguments for special 'meta' packages: 358 // std --> libstd.so 359 // std cmd --> libstd,cmd.so 360 // A single non-meta argument with trailing "/..." is special cased: 361 // foo/... --> libfoo.so 362 // (A relative path like "./..." expands the "." first) 363 // Use import paths for other cases, changing '/' to '-': 364 // somelib --> libsubdir-somelib.so 365 // ./ or ../ --> libsubdir-somelib.so 366 // gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so 367 // a/... b/... ---> liba/c,b/d.so - all matching import paths 368 // Name parts are joined with ','. 369 func libname(args []string, pkgs []*load.Package) (string, error) { 370 var libname string 371 appendName := func(arg string) { 372 if libname == "" { 373 libname = arg 374 } else { 375 libname += "," + arg 376 } 377 } 378 var haveNonMeta bool 379 for _, arg := range args { 380 if load.IsMetaPackage(arg) { 381 appendName(arg) 382 } else { 383 haveNonMeta = true 384 } 385 } 386 if len(libname) == 0 { // non-meta packages only. use import paths 387 if len(args) == 1 && strings.HasSuffix(args[0], "/...") { 388 // Special case of "foo/..." as mentioned above. 389 arg := strings.TrimSuffix(args[0], "/...") 390 if build.IsLocalImport(arg) { 391 cwd, _ := os.Getwd() 392 bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly) 393 if bp.ImportPath != "" && bp.ImportPath != "." { 394 arg = bp.ImportPath 395 } 396 } 397 appendName(strings.Replace(arg, "/", "-", -1)) 398 } else { 399 for _, pkg := range pkgs { 400 appendName(strings.Replace(pkg.ImportPath, "/", "-", -1)) 401 } 402 } 403 } else if haveNonMeta { // have both meta package and a non-meta one 404 return "", errors.New("mixing of meta and non-meta packages is not allowed") 405 } 406 // TODO(mwhudson): Needs to change for platforms that use different naming 407 // conventions... 408 return "lib" + libname + ".so", nil 409 } 410 411 func runInstall(cmd *base.Command, args []string) { 412 BuildInit() 413 InstallPackages(args, false) 414 } 415 416 func InstallPackages(args []string, forGet bool) { 417 if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) { 418 base.Fatalf("cannot install, GOBIN must be an absolute path") 419 } 420 421 pkgs := pkgsFilter(load.PackagesForBuild(args)) 422 423 for _, p := range pkgs { 424 if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { 425 switch { 426 case p.Internal.GobinSubdir: 427 base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName) 428 case p.Internal.CmdlineFiles: 429 base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName) 430 case p.ConflictDir != "": 431 base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir) 432 default: 433 base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+ 434 "\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir) 435 } 436 } 437 } 438 base.ExitIfErrors() 439 440 var b Builder 441 b.Init() 442 depMode := ModeBuild 443 if cfg.BuildI { 444 depMode = ModeInstall 445 } 446 a := &Action{Mode: "go install"} 447 var tools []*Action 448 for _, p := range pkgs { 449 // During 'go get', don't attempt (and fail) to install packages with only tests. 450 // TODO(rsc): It's not clear why 'go get' should be different from 'go install' here. See #20760. 451 if forGet && len(p.GoFiles)+len(p.CgoFiles) == 0 && len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { 452 continue 453 } 454 // If p is a tool, delay the installation until the end of the build. 455 // This avoids installing assemblers/compilers that are being executed 456 // by other steps in the build. 457 a1 := b.AutoAction(ModeInstall, depMode, p) 458 if load.InstallTargetDir(p) == load.ToTool { 459 a.Deps = append(a.Deps, a1.Deps...) 460 a1.Deps = append(a1.Deps, a) 461 tools = append(tools, a1) 462 continue 463 } 464 a.Deps = append(a.Deps, a1) 465 } 466 if len(tools) > 0 { 467 a = &Action{ 468 Mode: "go install (tools)", 469 Deps: tools, 470 } 471 } 472 473 if cfg.BuildBuildmode == "shared" { 474 // Note: If buildmode=shared then only non-main packages 475 // are present in the pkgs list, so all the special case code about 476 // tools above did not apply, and a is just a simple Action 477 // with a list of Deps, one per package named in pkgs, 478 // the same as in runBuild. 479 a = b.buildmodeShared(ModeInstall, ModeInstall, args, pkgs, a) 480 } 481 482 b.Do(a) 483 base.ExitIfErrors() 484 485 // Success. If this command is 'go install' with no arguments 486 // and the current directory (the implicit argument) is a command, 487 // remove any leftover command binary from a previous 'go build'. 488 // The binary is installed; it's not needed here anymore. 489 // And worse it might be a stale copy, which you don't want to find 490 // instead of the installed one if $PATH contains dot. 491 // One way to view this behavior is that it is as if 'go install' first 492 // runs 'go build' and the moves the generated file to the install dir. 493 // See issue 9645. 494 if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" { 495 // Compute file 'go build' would have created. 496 // If it exists and is an executable file, remove it. 497 _, targ := filepath.Split(pkgs[0].ImportPath) 498 targ += cfg.ExeSuffix 499 if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory 500 fi, err := os.Stat(targ) 501 if err == nil { 502 m := fi.Mode() 503 if m.IsRegular() { 504 if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit 505 os.Remove(targ) 506 } 507 } 508 } 509 } 510 } 511 } 512 513 // ExecCmd is the command to use to run user binaries. 514 // Normally it is empty, meaning run the binaries directly. 515 // If cross-compiling and running on a remote system or 516 // simulator, it is typically go_GOOS_GOARCH_exec, with 517 // the target GOOS and GOARCH substituted. 518 // The -exec flag overrides these defaults. 519 var ExecCmd []string 520 521 // FindExecCmd derives the value of ExecCmd to use. 522 // It returns that value and leaves ExecCmd set for direct use. 523 func FindExecCmd() []string { 524 if ExecCmd != nil { 525 return ExecCmd 526 } 527 ExecCmd = []string{} // avoid work the second time 528 if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH { 529 return ExecCmd 530 } 531 path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch)) 532 if err == nil { 533 ExecCmd = []string{path} 534 } 535 return ExecCmd 536 }