mirror of
https://github.com/golang/go
synced 2024-11-18 22:34:45 -07:00
cmd/go: set expected filename when building a local package with -o is pointing to a folder
In the local package build process, when -o is pointing to an existing folder, the object
the filename is generated from files listed on the command line like when the -o is
not pointing to a folder instead of using the `importPath` that is going to be `command-line-arguments`
Fixes #34535
Change-Id: I09a7609c17a2ccdd83da32f01247c0ef473dea1e
GitHub-Last-Rev: b3224226a3
GitHub-Pull-Request: golang/go#34562
Reviewed-on: https://go-review.googlesource.com/c/go/+/197544
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
parent
43a4c61e12
commit
3ce29b44bb
@ -1391,26 +1391,51 @@ var cgoSyscallExclude = map[string]bool{
|
|||||||
|
|
||||||
var foldPath = make(map[string]string)
|
var foldPath = make(map[string]string)
|
||||||
|
|
||||||
// DefaultExecName returns the default executable name
|
// exeFromImportPath returns an executable name
|
||||||
// for a package with the import path importPath.
|
// for a package using the import path.
|
||||||
//
|
//
|
||||||
// The default executable name is the last element of the import path.
|
// The executable name is the last element of the import path.
|
||||||
// In module-aware mode, an additional rule is used on import paths
|
// In module-aware mode, an additional rule is used on import paths
|
||||||
// consisting of two or more path elements. If the last element is
|
// consisting of two or more path elements. If the last element is
|
||||||
// a vN path element specifying the major version, then the
|
// a vN path element specifying the major version, then the
|
||||||
// second last element of the import path is used instead.
|
// second last element of the import path is used instead.
|
||||||
func DefaultExecName(importPath string) string {
|
func (p *Package) exeFromImportPath() string {
|
||||||
_, elem := pathpkg.Split(importPath)
|
_, elem := pathpkg.Split(p.ImportPath)
|
||||||
if cfg.ModulesEnabled {
|
if cfg.ModulesEnabled {
|
||||||
// If this is example.com/mycmd/v2, it's more useful to
|
// If this is example.com/mycmd/v2, it's more useful to
|
||||||
// install it as mycmd than as v2. See golang.org/issue/24667.
|
// install it as mycmd than as v2. See golang.org/issue/24667.
|
||||||
if elem != importPath && isVersionElement(elem) {
|
if elem != p.ImportPath && isVersionElement(elem) {
|
||||||
_, elem = pathpkg.Split(pathpkg.Dir(importPath))
|
_, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return elem
|
return elem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exeFromFiles returns an executable name for a package
|
||||||
|
// using the first element in GoFiles or CgoFiles collections without the prefix.
|
||||||
|
//
|
||||||
|
// Returns empty string in case of empty collection.
|
||||||
|
func (p *Package) exeFromFiles() string {
|
||||||
|
var src string
|
||||||
|
if len(p.GoFiles) > 0 {
|
||||||
|
src = p.GoFiles[0]
|
||||||
|
} else if len(p.CgoFiles) > 0 {
|
||||||
|
src = p.CgoFiles[0]
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
_, elem := filepath.Split(src)
|
||||||
|
return elem[:len(elem)-len(".go")]
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultExecName returns the default executable name for a package
|
||||||
|
func (p *Package) DefaultExecName() string {
|
||||||
|
if p.Internal.CmdlineFiles {
|
||||||
|
return p.exeFromFiles()
|
||||||
|
}
|
||||||
|
return p.exeFromImportPath()
|
||||||
|
}
|
||||||
|
|
||||||
// load populates p using information from bp, err, which should
|
// load populates p using information from bp, err, which should
|
||||||
// be the result of calling build.Context.Import.
|
// be the result of calling build.Context.Import.
|
||||||
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||||
@ -1451,7 +1476,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
|||||||
p.Error = &PackageError{Err: e}
|
p.Error = &PackageError{Err: e}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
elem := DefaultExecName(p.ImportPath)
|
elem := p.DefaultExecName()
|
||||||
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
|
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
|
||||||
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
|
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
|
||||||
// Install cross-compiled binaries to subdirectories of bin.
|
// Install cross-compiled binaries to subdirectories of bin.
|
||||||
@ -2140,11 +2165,8 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||||||
pkg.Match = gofiles
|
pkg.Match = gofiles
|
||||||
|
|
||||||
if pkg.Name == "main" {
|
if pkg.Name == "main" {
|
||||||
_, elem := filepath.Split(gofiles[0])
|
exe := pkg.DefaultExecName() + cfg.ExeSuffix
|
||||||
exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix
|
|
||||||
if cfg.BuildO == "" {
|
|
||||||
cfg.BuildO = exe
|
|
||||||
}
|
|
||||||
if cfg.GOBIN != "" {
|
if cfg.GOBIN != "" {
|
||||||
pkg.Target = filepath.Join(cfg.GOBIN, exe)
|
pkg.Target = filepath.Join(cfg.GOBIN, exe)
|
||||||
} else if cfg.ModulesEnabled {
|
} else if cfg.ModulesEnabled {
|
||||||
|
@ -5,39 +5,49 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDefaultExecName(t *testing.T) {
|
func TestPkgDefaultExecName(t *testing.T) {
|
||||||
oldModulesEnabled := cfg.ModulesEnabled
|
oldModulesEnabled := cfg.ModulesEnabled
|
||||||
defer func() { cfg.ModulesEnabled = oldModulesEnabled }()
|
defer func() { cfg.ModulesEnabled = oldModulesEnabled }()
|
||||||
for _, tt := range []struct {
|
for _, tt := range []struct {
|
||||||
in string
|
in string
|
||||||
|
files []string
|
||||||
wantMod string
|
wantMod string
|
||||||
wantGopath string
|
wantGopath string
|
||||||
}{
|
}{
|
||||||
{"example.com/mycmd", "mycmd", "mycmd"},
|
{"example.com/mycmd", []string{}, "mycmd", "mycmd"},
|
||||||
{"example.com/mycmd/v0", "v0", "v0"},
|
{"example.com/mycmd/v0", []string{}, "v0", "v0"},
|
||||||
{"example.com/mycmd/v1", "v1", "v1"},
|
{"example.com/mycmd/v1", []string{}, "v1", "v1"},
|
||||||
{"example.com/mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
|
{"example.com/mycmd/v2", []string{}, "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
|
||||||
{"example.com/mycmd/v3", "mycmd", "v3"}, // Semantic import versioning, use second last element in module mode.
|
{"example.com/mycmd/v3", []string{}, "mycmd", "v3"}, // Semantic import versioning, use second last element in module mode.
|
||||||
{"mycmd", "mycmd", "mycmd"},
|
{"mycmd", []string{}, "mycmd", "mycmd"},
|
||||||
{"mycmd/v0", "v0", "v0"},
|
{"mycmd/v0", []string{}, "v0", "v0"},
|
||||||
{"mycmd/v1", "v1", "v1"},
|
{"mycmd/v1", []string{}, "v1", "v1"},
|
||||||
{"mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
|
{"mycmd/v2", []string{}, "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
|
||||||
{"v0", "v0", "v0"},
|
{"v0", []string{}, "v0", "v0"},
|
||||||
{"v1", "v1", "v1"},
|
{"v1", []string{}, "v1", "v1"},
|
||||||
{"v2", "v2", "v2"},
|
{"v2", []string{}, "v2", "v2"},
|
||||||
|
{"command-line-arguments", []string{"output.go", "foo.go"}, "output", "output"},
|
||||||
} {
|
} {
|
||||||
{
|
{
|
||||||
cfg.ModulesEnabled = true
|
cfg.ModulesEnabled = true
|
||||||
gotMod := DefaultExecName(tt.in)
|
pkg := new(Package)
|
||||||
|
pkg.ImportPath = tt.in
|
||||||
|
pkg.GoFiles = tt.files
|
||||||
|
pkg.Internal.CmdlineFiles = len(tt.files) > 0
|
||||||
|
gotMod := pkg.DefaultExecName()
|
||||||
if gotMod != tt.wantMod {
|
if gotMod != tt.wantMod {
|
||||||
t.Errorf("DefaultExecName(%q) in module mode = %v; want %v", tt.in, gotMod, tt.wantMod)
|
t.Errorf("pkg.DefaultExecName with ImportPath = %q in module mode = %v; want %v", tt.in, gotMod, tt.wantMod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
cfg.ModulesEnabled = false
|
cfg.ModulesEnabled = false
|
||||||
gotGopath := DefaultExecName(tt.in)
|
pkg := new(Package)
|
||||||
|
pkg.ImportPath = tt.in
|
||||||
|
pkg.GoFiles = tt.files
|
||||||
|
pkg.Internal.CmdlineFiles = len(tt.files) > 0
|
||||||
|
gotGopath := pkg.DefaultExecName()
|
||||||
if gotGopath != tt.wantGopath {
|
if gotGopath != tt.wantGopath {
|
||||||
t.Errorf("DefaultExecName(%q) in gopath mode = %v; want %v", tt.in, gotGopath, tt.wantGopath)
|
t.Errorf("pkg.DefaultExecName with ImportPath = %q in gopath mode = %v; want %v", tt.in, gotGopath, tt.wantGopath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,7 +829,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
|
|||||||
if p.ImportPath == "command-line-arguments" {
|
if p.ImportPath == "command-line-arguments" {
|
||||||
elem = p.Name
|
elem = p.Name
|
||||||
} else {
|
} else {
|
||||||
elem = load.DefaultExecName(p.ImportPath)
|
elem = p.DefaultExecName()
|
||||||
}
|
}
|
||||||
testBinary := elem + ".test"
|
testBinary := elem + ".test"
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ func runBuild(cmd *base.Command, args []string) {
|
|||||||
explicitO := len(cfg.BuildO) > 0
|
explicitO := len(cfg.BuildO) > 0
|
||||||
|
|
||||||
if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
|
if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
|
||||||
cfg.BuildO = load.DefaultExecName(pkgs[0].ImportPath)
|
cfg.BuildO = pkgs[0].DefaultExecName()
|
||||||
cfg.BuildO += cfg.ExeSuffix
|
cfg.BuildO += cfg.ExeSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +373,8 @@ func runBuild(cmd *base.Command, args []string) {
|
|||||||
if p.Name != "main" {
|
if p.Name != "main" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p.Target = filepath.Join(cfg.BuildO, load.DefaultExecName(p.ImportPath))
|
|
||||||
|
p.Target = filepath.Join(cfg.BuildO, p.DefaultExecName())
|
||||||
p.Target += cfg.ExeSuffix
|
p.Target += cfg.ExeSuffix
|
||||||
p.Stale = true
|
p.Stale = true
|
||||||
p.StaleReason = "build -o flag in use"
|
p.StaleReason = "build -o flag in use"
|
||||||
@ -595,7 +596,7 @@ func InstallPackages(patterns []string, pkgs []*load.Package) {
|
|||||||
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
|
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
|
||||||
// Compute file 'go build' would have created.
|
// Compute file 'go build' would have created.
|
||||||
// If it exists and is an executable file, remove it.
|
// If it exists and is an executable file, remove it.
|
||||||
targ := load.DefaultExecName(pkgs[0].ImportPath)
|
targ := pkgs[0].DefaultExecName()
|
||||||
targ += cfg.ExeSuffix
|
targ += cfg.ExeSuffix
|
||||||
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
|
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
|
||||||
fi, err := os.Stat(targ)
|
fi, err := os.Stat(targ)
|
||||||
|
10
src/cmd/go/testdata/script/build_multi_main.txt
vendored
10
src/cmd/go/testdata/script/build_multi_main.txt
vendored
@ -10,6 +10,11 @@ stderr 'no main packages'
|
|||||||
! go build ./cmd/c1
|
! go build ./cmd/c1
|
||||||
stderr 'already exists and is a directory'
|
stderr 'already exists and is a directory'
|
||||||
|
|
||||||
|
# Verify build -o output correctly local packages
|
||||||
|
mkdir $WORK/local
|
||||||
|
go build -o $WORK/local ./exec.go
|
||||||
|
exists $WORK/local/exec$GOEXE
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module exmod
|
module exmod
|
||||||
|
|
||||||
@ -29,5 +34,10 @@ package pkg1
|
|||||||
-- pkg2/pkg2.go --
|
-- pkg2/pkg2.go --
|
||||||
package pkg2
|
package pkg2
|
||||||
|
|
||||||
|
-- exec.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
-- c1$GOEXE/keep.txt --
|
-- c1$GOEXE/keep.txt --
|
||||||
Create c1 directory.
|
Create c1 directory.
|
||||||
|
Loading…
Reference in New Issue
Block a user