var foldPath = make(map[string]string)
-// DefaultExecName returns the default executable name
-// for a package with the import path importPath.
+// exeFromImportPath returns an executable name
+// 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
// consisting of two or more path elements. If the last element is
// a vN path element specifying the major version, then the
// second last element of the import path is used instead.
-func DefaultExecName(importPath string) string {
- _, elem := pathpkg.Split(importPath)
+func (p *Package) exeFromImportPath() string {
+ _, elem := pathpkg.Split(p.ImportPath)
if cfg.ModulesEnabled {
// If this is example.com/mycmd/v2, it's more useful to
// install it as mycmd than as v2. See golang.org/issue/24667.
- if elem != importPath && isVersionElement(elem) {
- _, elem = pathpkg.Split(pathpkg.Dir(importPath))
+ if elem != p.ImportPath && isVersionElement(elem) {
+ _, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
}
}
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
// be the result of calling build.Context.Import.
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
p.Error = &PackageError{Err: e}
return
}
- elem := DefaultExecName(p.ImportPath)
+ elem := p.DefaultExecName()
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
// Install cross-compiled binaries to subdirectories of bin.
pkg.Match = gofiles
if pkg.Name == "main" {
- _, elem := filepath.Split(gofiles[0])
- exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix
- if cfg.BuildO == "" {
- cfg.BuildO = exe
- }
+ exe := pkg.DefaultExecName() + cfg.ExeSuffix
+
if cfg.GOBIN != "" {
pkg.Target = filepath.Join(cfg.GOBIN, exe)
} else if cfg.ModulesEnabled {
"testing"
)
-func TestDefaultExecName(t *testing.T) {
+func TestPkgDefaultExecName(t *testing.T) {
oldModulesEnabled := cfg.ModulesEnabled
defer func() { cfg.ModulesEnabled = oldModulesEnabled }()
for _, tt := range []struct {
in string
+ files []string
wantMod string
wantGopath string
}{
- {"example.com/mycmd", "mycmd", "mycmd"},
- {"example.com/mycmd/v0", "v0", "v0"},
- {"example.com/mycmd/v1", "v1", "v1"},
- {"example.com/mycmd/v2", "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.
- {"mycmd", "mycmd", "mycmd"},
- {"mycmd/v0", "v0", "v0"},
- {"mycmd/v1", "v1", "v1"},
- {"mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
- {"v0", "v0", "v0"},
- {"v1", "v1", "v1"},
- {"v2", "v2", "v2"},
+ {"example.com/mycmd", []string{}, "mycmd", "mycmd"},
+ {"example.com/mycmd/v0", []string{}, "v0", "v0"},
+ {"example.com/mycmd/v1", []string{}, "v1", "v1"},
+ {"example.com/mycmd/v2", []string{}, "mycmd", "v2"}, // 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", []string{}, "mycmd", "mycmd"},
+ {"mycmd/v0", []string{}, "v0", "v0"},
+ {"mycmd/v1", []string{}, "v1", "v1"},
+ {"mycmd/v2", []string{}, "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
+ {"v0", []string{}, "v0", "v0"},
+ {"v1", []string{}, "v1", "v1"},
+ {"v2", []string{}, "v2", "v2"},
+ {"command-line-arguments", []string{"output.go", "foo.go"}, "output", "output"},
} {
{
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 {
- 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
- 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 {
- 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)
}
}
}
explicitO := len(cfg.BuildO) > 0
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
}
if p.Name != "main" {
continue
}
- p.Target = filepath.Join(cfg.BuildO, load.DefaultExecName(p.ImportPath))
+
+ p.Target = filepath.Join(cfg.BuildO, p.DefaultExecName())
p.Target += cfg.ExeSuffix
p.Stale = true
p.StaleReason = "build -o flag in use"
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
// Compute file 'go build' would have created.
// If it exists and is an executable file, remove it.
- targ := load.DefaultExecName(pkgs[0].ImportPath)
+ targ := pkgs[0].DefaultExecName()
targ += cfg.ExeSuffix
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
fi, err := os.Stat(targ)