// run through go run and go test respectively.
// -pgo file
// specify the file path of a profile for profile-guided optimization (PGO).
+// Special name "auto" lets the go command select a file named
+// "default.pgo" in the main package's directory if that file exists.
// Special name "off" turns off PGO.
// -pkgdir dir
// install and load all packages from dir instead of the usual locations.
// We need to test whether the path is an actual Go file and not a
// package path or pattern ending in '.go' (see golang.org/issue/34653).
if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
- return []*Package{GoFilesPackage(ctx, opts, patterns)}
+ pkgs := []*Package{GoFilesPackage(ctx, opts, patterns)}
+ setPGOProfilePath(pkgs)
+ return pkgs
}
}
}
// their dependencies).
setToolFlags(pkgs...)
+ setPGOProfilePath(pkgs)
+
return pkgs
}
+// setPGOProfilePath sets cfg.BuildPGOFile to the PGO profile path.
+// In -pgo=auto mode, it finds the default PGO profile.
+func setPGOProfilePath(pkgs []*Package) {
+ switch cfg.BuildPGO {
+ case "":
+ fallthrough // default to "off"
+ case "off":
+ return
+
+ case "auto":
+ // Locate PGO profile from the main package.
+
+ setError := func(p *Package) {
+ if p.Error == nil {
+ p.Error = &PackageError{Err: errors.New("-pgo=auto requires exactly one main package")}
+ }
+ }
+
+ var mainpkg *Package
+ for _, p := range pkgs {
+ if p.Name == "main" {
+ if mainpkg != nil {
+ setError(p)
+ setError(mainpkg)
+ continue
+ }
+ mainpkg = p
+ }
+ }
+ if mainpkg == nil {
+ // No main package, no default.pgo to look for.
+ return
+ }
+ file := filepath.Join(mainpkg.Dir, "default.pgo")
+ if fi, err := os.Stat(file); err == nil && !fi.IsDir() {
+ cfg.BuildPGOFile = file
+ }
+
+ default:
+ // Profile specified from the command line.
+ // Make it absolute path, as the compiler runs on various directories.
+ if p, err := filepath.Abs(cfg.BuildPGO); err != nil {
+ base.Fatalf("fail to get absolute path of PGO file %s: %v", cfg.BuildPGO, err)
+ } else {
+ cfg.BuildPGOFile = p
+ }
+ }
+}
+
// CheckPackageErrors prints errors encountered loading pkgs and their
// dependencies, then exits with a non-zero status if any errors were found.
func CheckPackageErrors(pkgs []*Package) {
run through go run and go test respectively.
-pgo file
specify the file path of a profile for profile-guided optimization (PGO).
+ Special name "auto" lets the go command select a file named
+ "default.pgo" in the main package's directory if that file exists.
Special name "off" turns off PGO.
-pkgdir dir
install and load all packages from dir instead of the usual locations.
if cfg.BuildRace && cfg.BuildCoverMode != "atomic" {
base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, cfg.BuildCoverMode)
}
-
- setPGOProfilePath()
}
// fuzzInstrumentFlags returns compiler flags that enable fuzzing instrumation
}
return nil
}
-
-func setPGOProfilePath() {
- switch cfg.BuildPGO {
- case "":
- fallthrough // default to "auto"
- case "off":
- // Nothing to do.
- case "auto":
- base.Fatalf("-pgo=auto is not implemented")
- default:
- // make it absolute path, as the compiler runs on various directories.
- if p, err := filepath.Abs(cfg.BuildPGO); err != nil {
- base.Fatalf("fail to get absolute path of PGO file %s: %v", cfg.BuildPGO, err)
- } else {
- cfg.BuildPGOFile = p
- }
- }
-}
--- /dev/null
+# Test go build -pgo=auto flag.
+
+# use default.pgo for a single main package
+go build -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+# check that pgo applied to dependencies
+stderr 'compile.*-p test/dep.*-pgoprofile=.*default\.pgo'
+
+# use default.pgo for ... with a single main package
+go build -n -pgo=auto ./a/...
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+# error with multiple packages
+! go build -n -pgo=auto ./b/...
+stderr '-pgo=auto requires exactly one main package'
+
+# build succeeds without PGO when default.pgo file is absent
+go build -n -pgo=auto -o nopgo.exe ./nopgo
+stderr 'compile.*nopgo.go'
+! stderr '-pgoprofile'
+
+# other build-related commands
+go install -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+go run -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
+
+go test -n -pgo=auto ./a/a1
+stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go.*a1_test.go'
+stderr 'compile.*-pgoprofile=.*default\.pgo.*external_test.go'
+
+# go list commands should succeed as usual
+go list -pgo=auto ./a/a1
+
+go list -test -pgo=auto ./a/a1
+
+go list -deps -pgo=auto ./a/a1
+
+-- go.mod --
+module test
+go 1.20
+-- a/a1/a1.go --
+package main
+import _ "test/dep"
+func main() {}
+-- a/a1/a1_test.go --
+package main
+import "testing"
+func TestA(*testing.T) {}
+-- a/a1/external_test.go --
+package main_test
+import "testing"
+func TestExternal(*testing.T) {}
+-- a/a1/default.pgo --
+-- b/b1/b1.go --
+package main
+func main() {}
+-- b/b1/default.pgo --
+-- b/b2/b2.go --
+package main
+func main() {}
+-- b/b2/default.pgo --
+-- nopgo/nopgo.go --
+package main
+func main() {}
+-- dep/dep.go --
+package dep