]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: allow -o to point to a folder that writes multiple execs
authorDaniel Theophanes <kardianos@gmail.com>
Fri, 15 Mar 2019 06:42:57 +0000 (23:42 -0700)
committerDaniel Theophanes <kardianos@gmail.com>
Mon, 18 Mar 2019 16:13:50 +0000 (16:13 +0000)
If -o points to a directory that exists then allow multiple
executables to be written to that directory.

Fixes #14295

Change-Id: Ic951e637c70a2ada5e7534bae9a43901a39fe2c5
Reviewed-on: https://go-review.googlesource.com/c/go/+/167679
Run-TryBot: Daniel Theophanes <kardianos@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
src/cmd/go/alldocs.go
src/cmd/go/internal/work/build.go
src/cmd/go/testdata/script/build_multi_main.txt [new file with mode: 0644]

index 55371c12159c015ba4db46e99dea3792944815fa..141f13c63e5b0b96250c675afbb31189ab2220b6 100644 (file)
 //
 // When compiling packages, build ignores files that end in '_test.go'.
 //
-// The -o flag, only allowed when compiling a single package,
-// forces build to write the resulting executable or object
-// to the named output file, instead of the default behavior described
-// in the last two paragraphs.
+// The -o flag forces build to write the resulting executable or object
+// to the named output file or directory, instead of the default behavior described
+// in the last two paragraphs. If the named output is a directory that exists,
+// then any resulting executables will be written to that directory.
 //
 // The -i flag installs the packages that are dependencies of the target.
 //
index d89ee899f095b5abf6afcbd8d91f6aa1d24a48df..82ac7d692f0e8bd3117e92808e476cbe5be1e40b 100644 (file)
@@ -42,10 +42,10 @@ serving only as a check that the packages can be built.
 
 When compiling packages, build ignores files that end in '_test.go'.
 
-The -o flag, only allowed when compiling a single package,
-forces build to write the resulting executable or object
-to the named output file, instead of the default behavior described
-in the last two paragraphs.
+The -o flag forces build to write the resulting executable or object
+to the named output file or directory, instead of the default behavior described
+in the last two paragraphs. If the named output is a directory that exists,
+then any resulting executables will be written to that directory.
 
 The -i flag installs the packages that are dependencies of the target.
 
@@ -153,7 +153,7 @@ func init() {
        CmdInstall.Run = runInstall
 
        CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
-       CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file")
+       CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file or directory")
 
        CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "")
 
@@ -316,8 +316,29 @@ func runBuild(cmd *base.Command, args []string) {
        }
 
        if cfg.BuildO != "" {
+               // If the -o name exists and is a directory, then
+               // write all main packages to that directory.
+               // Otherwise require only a single package be built.
+               if bs, err := os.Stat(cfg.BuildO); err == nil && bs.IsDir() {
+                       a := &Action{Mode: "go build"}
+                       for _, p := range pkgs {
+                               if p.Name != "main" {
+                                       continue
+                               }
+                               p.Target = filepath.Join(cfg.BuildO, load.DefaultExecName(p))
+                               p.Target += cfg.ExeSuffix
+                               p.Stale = true
+                               p.StaleReason = "build -o flag in use"
+                               a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p))
+                       }
+                       if len(a.Deps) == 0 {
+                               base.Fatalf("go build: no main packages to build")
+                       }
+                       b.Do(a)
+                       return
+               }
                if len(pkgs) > 1 {
-                       base.Fatalf("go build: cannot use -o with multiple packages")
+                       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")
                }
diff --git a/src/cmd/go/testdata/script/build_multi_main.txt b/src/cmd/go/testdata/script/build_multi_main.txt
new file mode 100644 (file)
index 0000000..734e8d8
--- /dev/null
@@ -0,0 +1,27 @@
+# Verify build -o can output multiple executables to a directory.
+
+mkdir $WORK/bin
+go build -o $WORK/bin ./cmd/c1 ./cmd/c2
+! stderr 'multiple packages'
+
+! go build -o $WORK/bin ./pkg1 ./pkg1
+stderr 'no main packages'
+
+-- go.mod --
+module exmod
+
+-- cmd/c1/main.go --
+package main
+
+func main() {}
+
+-- cmd/c2/main.go --
+package main
+
+func main() {}
+
+-- pkg1/pkg1.go --
+package pkg1
+
+-- pkg2/pkg2.go --
+package pkg2