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