Skip to content

Commit bf94fc3

Browse files
hyangahbradfitz
authored andcommitted
cmd/go: fix the default build output name for versioned binaries
`go build` has chosen the last element of the package import path as the default output name when -o option is given. That caused the output of a package build when the module root is the major version component such as 'v2'. A similar issue involving `go install` was fixed in https://golang.org/cl/128900. This CL refactors the logic added with the change and makes it available as internal/load.DefaultExecName. This CL makes 'go test' to choose the right default test binary name when the tested package is in the module root. (E.g., instead of v2.test, choose pkg.test for the test of 'path/pkg/v2') Fixes #27283. Change-Id: I6905754f0906db46e3ce069552715f45356913ae Reviewed-on: https://go-review.googlesource.com/c/go/+/140863 Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 0a04c04 commit bf94fc3

File tree

5 files changed

+64
-35
lines changed

5 files changed

+64
-35
lines changed

src/cmd/go/internal/load/pkg.go

+39-32
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,44 @@ var cgoSyscallExclude = map[string]bool{
11861186

11871187
var foldPath = make(map[string]string)
11881188

1189+
// DefaultExecName returns the default executable name of the given
1190+
// package.
1191+
func DefaultExecName(p *Package) string {
1192+
_, elem := filepath.Split(p.ImportPath)
1193+
if cfg.ModulesEnabled {
1194+
// NOTE(rsc): Using p.ImportPath instead of p.Dir
1195+
// makes sure we install a package in the root of a
1196+
// cached module directory as that package name
1197+
1198+
// Using p.ImportPath instead of p.Dir
1199+
// is probably correct all the time,
1200+
// even for non-module-enabled code,
1201+
// but I'm not brave enough to change the
1202+
// non-module behavior this late in the
1203+
// release cycle. Maybe for Go 1.12.
1204+
// See golang.org/issue/26869.
1205+
_, elem = pathpkg.Split(p.ImportPath)
1206+
1207+
// If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
1208+
// See golang.org/issue/24667.
1209+
isVersion := func(v string) bool {
1210+
if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
1211+
return false
1212+
}
1213+
for i := 2; i < len(v); i++ {
1214+
if c := v[i]; c < '0' || '9' < c {
1215+
return false
1216+
}
1217+
}
1218+
return true
1219+
}
1220+
if isVersion(elem) {
1221+
_, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
1222+
}
1223+
}
1224+
return elem
1225+
}
1226+
11891227
// load populates p using information from bp, err, which should
11901228
// be the result of calling build.Context.Import.
11911229
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
@@ -1226,38 +1264,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
12261264
p.Error = &PackageError{Err: e}
12271265
return
12281266
}
1229-
_, elem := filepath.Split(p.Dir)
1230-
if cfg.ModulesEnabled {
1231-
// NOTE(rsc): Using p.ImportPath instead of p.Dir
1232-
// makes sure we install a package in the root of a
1233-
// cached module directory as that package name
1234-
1235-
// Using p.ImportPath instead of p.Dir
1236-
// is probably correct all the time,
1237-
// even for non-module-enabled code,
1238-
// but I'm not brave enough to change the
1239-
// non-module behavior this late in the
1240-
// release cycle. Maybe for Go 1.12.
1241-
// See golang.org/issue/26869.
1242-
_, elem = pathpkg.Split(p.ImportPath)
1243-
1244-
// If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
1245-
// See golang.org/issue/24667.
1246-
isVersion := func(v string) bool {
1247-
if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
1248-
return false
1249-
}
1250-
for i := 2; i < len(v); i++ {
1251-
if c := v[i]; c < '0' || '9' < c {
1252-
return false
1253-
}
1254-
}
1255-
return true
1256-
}
1257-
if isVersion(elem) {
1258-
_, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
1259-
}
1260-
}
1267+
elem := DefaultExecName(p)
12611268
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
12621269
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
12631270
// Install cross-compiled binaries to subdirectories of bin.

src/cmd/go/internal/test/test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
811811
if p.ImportPath == "command-line-arguments" {
812812
elem = p.Name
813813
} else {
814-
_, elem = path.Split(p.ImportPath)
814+
elem = load.DefaultExecName(p)
815815
}
816816
testBinary := elem + ".test"
817817

src/cmd/go/internal/work/build.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"go/build"
1111
"os"
1212
"os/exec"
13-
"path"
13+
//"path"
1414
"path/filepath"
1515
"runtime"
1616
"strings"
@@ -285,7 +285,7 @@ func runBuild(cmd *base.Command, args []string) {
285285
pkgs := load.PackagesForBuild(args)
286286

287287
if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
288-
_, cfg.BuildO = path.Split(pkgs[0].ImportPath)
288+
cfg.BuildO = load.DefaultExecName(pkgs[0])
289289
cfg.BuildO += cfg.ExeSuffix
290290
}
291291

src/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt

+6
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@ import "rsc.io/quote"
1313
func main() {
1414
println(quote.Hello())
1515
}
16+
-- fortune_test.go --
17+
package main
18+
19+
import "testing"
20+
21+
func TestFortuneV2(t *testing.T) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
env GO111MODULE=on
2+
3+
go get -m rsc.io/fortune/v2
4+
5+
# The default executable name shouldn't be v2$exe
6+
go build rsc.io/fortune/v2
7+
! exists v2$exe
8+
exists fortune$exe
9+
10+
# The default test binary name shouldn't be v2.test$exe
11+
go test -c rsc.io/fortune/v2
12+
! exists v2.test$exe
13+
exists fortune.test$exe
14+
15+
-- go.mod --
16+
module scratch

0 commit comments

Comments
 (0)