Skip to content

Instantly share code, notes, and snippets.

@perillo
Created April 21, 2021 14:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save perillo/a1381d24eaf9ce4f98d428f6ee83f0b5 to your computer and use it in GitHub Desktop.
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
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)
}
@perillo
Copy link
Author

perillo commented Apr 21, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment