Skip to content

Commit

Permalink
cmd/go: allow -o to point to a folder that writes multiple execs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
kardianos committed Mar 18, 2019
1 parent 6ca51f7 commit b48bda9
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 10 deletions.
8 changes: 4 additions & 4 deletions src/cmd/go/alldocs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 27 additions & 6 deletions src/cmd/go/internal/work/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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, "")

Expand Down Expand Up @@ -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")
}
Expand Down
27 changes: 27 additions & 0 deletions src/cmd/go/testdata/script/build_multi_main.txt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b48bda9

Please sign in to comment.