Created
April 21, 2021 14:54
-
-
Save perillo/a1381d24eaf9ce4f98d428f6ee83f0b5 to your computer and use it in GitHub Desktop.
Patch to make go build more consistent, when the -o flag is specified and is a directory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go | |
index a75ace7d4e..c6108a2d0f 100644 | |
--- a/src/cmd/go/internal/work/build.go | |
+++ b/src/cmd/go/internal/work/build.go | |
@@ -369,13 +369,6 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { | |
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args) | |
load.CheckPackageErrors(pkgs) | |
- explicitO := len(cfg.BuildO) > 0 | |
- | |
- if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" { | |
- cfg.BuildO = pkgs[0].DefaultExecName() | |
- cfg.BuildO += cfg.ExeSuffix | |
- } | |
- | |
// sanity check some often mis-used options | |
switch cfg.BuildContext.Compiler { | |
case "gccgo": | |
@@ -399,61 +392,82 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { | |
pkgs = omitTestOnly(pkgsFilter(pkgs)) | |
- // Special case -o /dev/null by not writing at all. | |
- if cfg.BuildO == os.DevNull { | |
- cfg.BuildO = "" | |
- } | |
- | |
- if cfg.BuildO != "" { | |
- // If the -o name exists and is a directory or | |
- // ends with a slash or backslash, then | |
- // write all main packages to that directory. | |
- // Otherwise require only a single package be built. | |
- if fi, err := os.Stat(cfg.BuildO); (err == nil && fi.IsDir()) || | |
- strings.HasSuffix(cfg.BuildO, "/") || | |
- strings.HasSuffix(cfg.BuildO, string(os.PathSeparator)) { | |
- if !explicitO { | |
- base.Fatalf("go build: build output %q already exists and is a directory", cfg.BuildO) | |
- } | |
- a := &Action{Mode: "go build"} | |
- for _, p := range pkgs { | |
- if p.Name != "main" { | |
- continue | |
- } | |
+ if cfg.BuildO == "" { | |
+ cfg.BuildO = "." | |
+ } | |
+ buildToDir := func() bool { | |
+ fi, err := os.Stat(cfg.BuildO) | |
+ switch { | |
+ case err == nil && fi.IsDir(): | |
+ return true | |
+ case strings.HasSuffix(cfg.BuildO, "/"): | |
+ return true | |
+ case strings.HasSuffix(cfg.BuildO, string(os.PathSeparator)): | |
+ return true | |
+ } | |
+ | |
+ return false | |
+ } | |
+ buildDiscard := func() bool { | |
+ return cfg.BuildO == os.DevNull | |
+ } | |
- p.Target = filepath.Join(cfg.BuildO, p.DefaultExecName()) | |
- p.Target += cfg.ExeSuffix | |
- p.Stale = true | |
- p.StaleReason = "build -o flag in use" | |
- a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p)) | |
+ a := &Action{Mode: "go build"} | |
+ switch { | |
+ case buildDiscard(): | |
+ // Don't write anything at all. | |
+ for _, p := range pkgs { | |
+ if p.Name != "main" { | |
+ continue | |
} | |
- if len(a.Deps) == 0 { | |
- base.Fatalf("go build: no main packages to build") | |
+ | |
+ a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p)) | |
+ } | |
+ case buildToDir(): | |
+ // Write all main packages to the specified directory. | |
+ for _, p := range pkgs { | |
+ if p.Name != "main" { | |
+ continue | |
} | |
- b.Do(ctx, a) | |
- return | |
+ | |
+ p.Target = filepath.Join(cfg.BuildO, p.DefaultExecName()) | |
+ p.Target += cfg.ExeSuffix | |
+ p.Stale = true | |
+ p.StaleReason = "build -o flag in use" | |
+ | |
+ a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p)) | |
} | |
+ default: | |
+ // Require only a single package be built. | |
if len(pkgs) > 1 { | |
base.Fatalf("go build: cannot write multiple packages to non-directory %s", cfg.BuildO) | |
} else if len(pkgs) == 0 { | |
base.Fatalf("no packages to build") | |
} | |
+ | |
p := pkgs[0] | |
p.Target = cfg.BuildO | |
p.Stale = true // must build - not up to date | |
p.StaleReason = "build -o flag in use" | |
+ | |
a := b.AutoAction(ModeInstall, depMode, p) | |
b.Do(ctx, a) | |
+ | |
return | |
} | |
- a := &Action{Mode: "go build"} | |
+ // Build and discard all the non main packages. | |
for _, p := range pkgs { | |
+ if p.Name == "main" { | |
+ continue | |
+ } | |
+ | |
a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p)) | |
} | |
if cfg.BuildBuildmode == "shared" { | |
a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a) | |
} | |
+ | |
b.Do(ctx, a) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See golang/go#37378