import (
"context"
"go/build"
- "path"
"path/filepath"
"strings"
}
p.Internal.ExeName = src[:len(src)-len(".go")]
} else {
- p.Internal.ExeName = path.Base(p.ImportPath)
+ p.Internal.ExeName = p.DefaultExecName()
}
a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p)
"os"
"os/exec"
"os/signal"
- "path"
"path/filepath"
"slices"
"sort"
return true
}
+func defaultExecName(importPath string) string {
+ var p load.Package
+ p.ImportPath = importPath
+ return p.DefaultExecName()
+}
+
func loadModTool(ctx context.Context, name string) string {
modload.InitWorkfile()
modload.LoadModFile(ctx)
matches := []string{}
for tool := range modload.MainModules.Tools() {
- if tool == name || path.Base(tool) == name {
+ if tool == name || defaultExecName(tool) == name {
matches = append(matches, tool)
}
}
pkgOpts := load.PackageOpts{MainOnly: true}
p := load.PackagesAndErrors(ctx, pkgOpts, []string{tool})[0]
p.Internal.OmitDebug = true
- p.Internal.ExeName = path.Base(p.ImportPath)
+ p.Internal.ExeName = p.DefaultExecName()
a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p)
a1.CacheExecutable = true
"fmt"
"os"
"os/exec"
- "path"
"strings"
"sync"
}
name := a.Package.Internal.ExeName
if name == "" {
- name = path.Base(a.Package.ImportPath)
+ name = a.Package.DefaultExecName()
}
outputID, _, err := c.PutExecutable(a.actionID, name+cfg.ExeSuffix, r)
r.Close()
stdout 'my name is: bar'$GOEXE
! stdout 'a.out'
+# Test tool package paths that end in v2
+# to ensure we use the second to last component.
+
+# Don't use v2 as the short name of the tool.
+! go tool v2
+stderr 'go: no such tool "v2"'
+
+# Use the second to last component as the short
+# name of the tool.
+go tool foo
+stdout 'my name is: foo'$GOEXE
+
+# go run should use the same name for the tool
+# We need to use a fresh cache, or we'd end up with an executable cache hit
+# from when we ran built the tool to run go tool above, and we'd just
+# reuse the name from the test case above.
+env GOCACHE=$WORK/cache2
+go run example.com/foo/v2
+stdout 'my name is: foo'$GOEXE
+
-- go.mod --
module example.com/foo
go 1.24
tool example.com/foo/bar
+tool example.com/foo/v2
+
+require example.com/foo/v2 v2.0.0
+
+replace example.com/foo/v2 => ./v2
-- bar/bar.go --
package main
func main() {
fmt.Println("my name is:", filepath.Base(os.Args[0]))
-}
\ No newline at end of file
+}
+-- v2/go.mod --
+module example.com/foo/v2
+
+go 1.24
+-- v2/main.go --
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+func main() {
+ fmt.Println("my name is:", filepath.Base(os.Args[0]))
+}