Commit 0b5fbf70 authored by Russ Cox's avatar Russ Cox

cmd/go: add Package.StaleReason for debugging with go list

It comes up every few months that we can't understand why
the go command is rebuilding some package.
Add diagnostics so that the go command can explain itself
if asked.

For #2775, #3506, #12074.

Change-Id: I1c73b492589b49886bf31a8f9d05514adbd6ed70
Reviewed-on: https://go-review.googlesource.com/22432Reviewed-by: default avatarRob Pike <r@golang.org>
parent 525ae3f8
...@@ -568,6 +568,7 @@ syntax of package template. The default output is equivalent to -f ...@@ -568,6 +568,7 @@ syntax of package template. The default output is equivalent to -f
Goroot bool // is this package in the Go root? Goroot bool // is this package in the Go root?
Standard bool // is this package part of the standard Go library? Standard bool // is this package part of the standard Go library?
Stale bool // would 'go install' do anything for this package? Stale bool // would 'go install' do anything for this package?
StaleReason string // explanation for Stale==true
Root string // Go root or Go path dir containing this package Root string // Go root or Go path dir containing this package
// Source files // Source files
......
...@@ -465,6 +465,7 @@ func runBuild(cmd *Command, args []string) { ...@@ -465,6 +465,7 @@ func runBuild(cmd *Command, args []string) {
p := pkgs[0] p := pkgs[0]
p.target = *buildO p.target = *buildO
p.Stale = true // must build - not up to date p.Stale = true // must build - not up to date
p.StaleReason = "build -o flag in use"
a := b.action(modeInstall, depMode, p) a := b.action(modeInstall, depMode, p)
b.do(a) b.do(a)
return return
...@@ -836,6 +837,7 @@ func goFilesPackage(gofiles []string) *Package { ...@@ -836,6 +837,7 @@ func goFilesPackage(gofiles []string) *Package {
pkg.Target = pkg.target pkg.Target = pkg.target
pkg.Stale = true pkg.Stale = true
pkg.StaleReason = "files named on command line"
computeStale(pkg) computeStale(pkg)
return pkg return pkg
......
...@@ -524,32 +524,43 @@ func (tg *testgoData) wantArchive(path string) { ...@@ -524,32 +524,43 @@ func (tg *testgoData) wantArchive(path string) {
} }
} }
// isStale returns whether pkg is stale. // isStale reports whether pkg is stale, and why
func (tg *testgoData) isStale(pkg string) bool { func (tg *testgoData) isStale(pkg string) (bool, string) {
tg.run("list", "-f", "{{.Stale}}", pkg) tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
switch v := strings.TrimSpace(tg.getStdout()); v { v := strings.TrimSpace(tg.getStdout())
case "true": f := strings.SplitN(v, ":", 2)
return true if len(f) == 2 {
case "false": switch f[0] {
return false case "true":
default: return true, f[1]
tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v) case "false":
panic("unreachable") return false, f[1]
}
} }
tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
panic("unreachable")
} }
// wantStale fails with msg if pkg is not stale. // wantStale fails with msg if pkg is not stale.
func (tg *testgoData) wantStale(pkg, msg string) { func (tg *testgoData) wantStale(pkg, reason, msg string) {
if !tg.isStale(pkg) { stale, why := tg.isStale(pkg)
if !stale {
tg.t.Fatal(msg) tg.t.Fatal(msg)
} }
if reason == "" && why != "" || !strings.Contains(why, reason) {
tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
}
} }
// wantNotStale fails with msg if pkg is stale. // wantNotStale fails with msg if pkg is stale.
func (tg *testgoData) wantNotStale(pkg, msg string) { func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
if tg.isStale(pkg) { stale, why := tg.isStale(pkg)
if stale {
tg.t.Fatal(msg) tg.t.Fatal(msg)
} }
if reason == "" && why != "" || !strings.Contains(why, reason) {
tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
}
} }
// cleanup cleans up a test that runs testgo. // cleanup cleans up a test that runs testgo.
...@@ -708,7 +719,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { ...@@ -708,7 +719,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg.tempFile("d1/src/p1/p1.go", `package p1`) tg.tempFile("d1/src/p1/p1.go", `package p1`)
tg.setenv("GOPATH", tg.path("d1")) tg.setenv("GOPATH", tg.path("d1"))
tg.run("install", "-a", "p1") tg.run("install", "-a", "p1")
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly")
tg.sleep() tg.sleep()
// Changing mtime and content of runtime/internal/sys/sys.go // Changing mtime and content of runtime/internal/sys/sys.go
...@@ -717,28 +728,28 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { ...@@ -717,28 +728,28 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go" sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go"
restore := addNL(sys) restore := addNL(sys)
defer restore() defer restore()
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after updating runtime/internal/sys/sys.go") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating runtime/internal/sys/sys.go")
restore() restore()
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after restoring runtime/internal/sys/sys.go") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after restoring runtime/internal/sys/sys.go")
// But changing runtime/internal/sys/zversion.go should have an effect: // But changing runtime/internal/sys/zversion.go should have an effect:
// that's how we tell when we flip from one release to another. // that's how we tell when we flip from one release to another.
zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go" zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go"
restore = addNL(zversion) restore = addNL(zversion)
defer restore() defer restore()
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to new release") tg.wantStale("p1", "build ID mismatch", "./testgo list claims p1 is NOT stale, incorrectly, after changing to new release")
restore() restore()
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after changing back to old release") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
addNL(zversion) addNL(zversion)
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing again to new release") tg.wantStale("p1", "build ID mismatch", "./testgo list claims p1 is NOT stale, incorrectly, after changing again to new release")
tg.run("install", "p1") tg.run("install", "p1")
tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with new release") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
// Restore to "old" release. // Restore to "old" release.
restore() restore()
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to old release after new build") tg.wantStale("p1", "build ID mismatch", "./testgo list claims p1 is NOT stale, incorrectly, after changing to old release after new build")
tg.run("install", "p1") tg.run("install", "p1")
tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with old release") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
// Everything is out of date. Rebuild to leave things in a better state. // Everything is out of date. Rebuild to leave things in a better state.
tg.run("install", "std") tg.run("install", "std")
...@@ -821,8 +832,8 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) { ...@@ -821,8 +832,8 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
sep := string(filepath.ListSeparator) sep := string(filepath.ListSeparator)
tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2")) tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2"))
tg.run("install", "p1") tg.run("install", "p1")
tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly")
tg.wantNotStale("p2", "./testgo list claims p2 is stale, incorrectly") tg.wantNotStale("p2", "", "./testgo list claims p2 is stale, incorrectly")
tg.sleep() tg.sleep()
if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil { if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -831,12 +842,12 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) { ...@@ -831,12 +842,12 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
} else { } else {
tg.must(f.Close()) tg.must(f.Close())
} }
tg.wantStale("p2", "./testgo list claims p2 is NOT stale, incorrectly") tg.wantStale("p2", "newer source file", "./testgo list claims p2 is NOT stale, incorrectly")
tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly") tg.wantStale("p1", "stale dependency", "./testgo list claims p1 is NOT stale, incorrectly")
tg.run("install", "p1") tg.run("install", "p1")
tg.wantNotStale("p2", "./testgo list claims p2 is stale after reinstall, incorrectly") tg.wantNotStale("p2", "", "./testgo list claims p2 is stale after reinstall, incorrectly")
tg.wantNotStale("p1", "./testgo list claims p1 is stale after reinstall, incorrectly") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after reinstall, incorrectly")
} }
func TestGoInstallDetectsRemovedFiles(t *testing.T) { func TestGoInstallDetectsRemovedFiles(t *testing.T) {
...@@ -850,13 +861,13 @@ func TestGoInstallDetectsRemovedFiles(t *testing.T) { ...@@ -850,13 +861,13 @@ func TestGoInstallDetectsRemovedFiles(t *testing.T) {
package mypkg`) package mypkg`)
tg.setenv("GOPATH", tg.path(".")) tg.setenv("GOPATH", tg.path("."))
tg.run("install", "mypkg") tg.run("install", "mypkg")
tg.wantNotStale("mypkg", "./testgo list mypkg claims mypkg is stale, incorrectly") tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale, incorrectly")
// z.go was not part of the build; removing it is okay. // z.go was not part of the build; removing it is okay.
tg.must(os.Remove(tg.path("src/mypkg/z.go"))) tg.must(os.Remove(tg.path("src/mypkg/z.go")))
tg.wantNotStale("mypkg", "./testgo list mypkg claims mypkg is stale after removing z.go; should not be stale") tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale after removing z.go; should not be stale")
// y.go was part of the package; removing it should be detected. // y.go was part of the package; removing it should be detected.
tg.must(os.Remove(tg.path("src/mypkg/y.go"))) tg.must(os.Remove(tg.path("src/mypkg/y.go")))
tg.wantStale("mypkg", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale") tg.wantStale("mypkg", "build ID mismatch", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale")
} }
func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) { func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) {
...@@ -919,13 +930,13 @@ func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) { ...@@ -919,13 +930,13 @@ func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) {
package main`) package main`)
tg.setenv("GOPATH", tg.path(".")) tg.setenv("GOPATH", tg.path("."))
tg.run("install", "mycmd") tg.run("install", "mycmd")
tg.wantNotStale("mycmd", "./testgo list mypkg claims mycmd is stale, incorrectly") tg.wantNotStale("mycmd", "", "./testgo list mypkg claims mycmd is stale, incorrectly")
// z.go was not part of the build; removing it is okay. // z.go was not part of the build; removing it is okay.
tg.must(os.Remove(tg.path("src/mycmd/z.go"))) tg.must(os.Remove(tg.path("src/mycmd/z.go")))
tg.wantNotStale("mycmd", "./testgo list mycmd claims mycmd is stale after removing z.go; should not be stale") tg.wantNotStale("mycmd", "", "./testgo list mycmd claims mycmd is stale after removing z.go; should not be stale")
// y.go was part of the package; removing it should be detected. // y.go was part of the package; removing it should be detected.
tg.must(os.Remove(tg.path("src/mycmd/y.go"))) tg.must(os.Remove(tg.path("src/mycmd/y.go")))
tg.wantStale("mycmd", "./testgo list mycmd claims mycmd is NOT stale after removing y.go; should be stale") tg.wantStale("mycmd", "build ID mismatch", "./testgo list mycmd claims mycmd is NOT stale after removing y.go; should be stale")
} }
func testLocalRun(tg *testgoData, exepath, local, match string) { func testLocalRun(tg *testgoData, exepath, local, match string) {
...@@ -1317,7 +1328,7 @@ func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) { ...@@ -1317,7 +1328,7 @@ func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
tg.sleep() tg.sleep()
tg.run("test", "main_test") tg.run("test", "main_test")
tg.run("install", "main_test") tg.run("install", "main_test")
tg.wantNotStale("main_test", "after go install, main listed as stale") tg.wantNotStale("main_test", "", "after go install, main listed as stale")
tg.run("test", "main_test") tg.run("test", "main_test")
} }
...@@ -1327,9 +1338,9 @@ func TestPackageNotStaleWithTrailingSlash(t *testing.T) { ...@@ -1327,9 +1338,9 @@ func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
defer tg.cleanup() defer tg.cleanup()
goroot := runtime.GOROOT() goroot := runtime.GOROOT()
tg.setenv("GOROOT", goroot+"/") tg.setenv("GOROOT", goroot+"/")
tg.wantNotStale("runtime", "with trailing slash in GOROOT, runtime listed as stale") tg.wantNotStale("runtime", "", "with trailing slash in GOROOT, runtime listed as stale")
tg.wantNotStale("os", "with trailing slash in GOROOT, os listed as stale") tg.wantNotStale("os", "", "with trailing slash in GOROOT, os listed as stale")
tg.wantNotStale("io", "with trailing slash in GOROOT, io listed as stale") tg.wantNotStale("io", "", "with trailing slash in GOROOT, io listed as stale")
} }
// With $GOBIN set, binaries get installed to $GOBIN. // With $GOBIN set, binaries get installed to $GOBIN.
......
...@@ -41,6 +41,7 @@ syntax of package template. The default output is equivalent to -f ...@@ -41,6 +41,7 @@ syntax of package template. The default output is equivalent to -f
Goroot bool // is this package in the Go root? Goroot bool // is this package in the Go root?
Standard bool // is this package part of the standard Go library? Standard bool // is this package part of the standard Go library?
Stale bool // would 'go install' do anything for this package? Stale bool // would 'go install' do anything for this package?
StaleReason string // explanation for Stale==true
Root string // Go root or Go path dir containing this package Root string // Go root or Go path dir containing this package
// Source files // Source files
......
...@@ -39,6 +39,7 @@ type Package struct { ...@@ -39,6 +39,7 @@ type Package struct {
Goroot bool `json:",omitempty"` // is this package found in the Go root? Goroot bool `json:",omitempty"` // is this package found in the Go root?
Standard bool `json:",omitempty"` // is this package part of the standard Go library? Standard bool `json:",omitempty"` // is this package part of the standard Go library?
Stale bool `json:",omitempty"` // would 'go install' do anything for this package? Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
StaleReason string `json:",omitempty"` // why is Stale true?
Root string `json:",omitempty"` // Go root or Go path dir containing this package Root string `json:",omitempty"` // Go root or Go path dir containing this package
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
...@@ -1085,7 +1086,7 @@ func packageList(roots []*Package) []*Package { ...@@ -1085,7 +1086,7 @@ func packageList(roots []*Package) []*Package {
// at the named pkgs (command-line arguments). // at the named pkgs (command-line arguments).
func computeStale(pkgs ...*Package) { func computeStale(pkgs ...*Package) {
for _, p := range packageList(pkgs) { for _, p := range packageList(pkgs) {
p.Stale = isStale(p) p.Stale, p.StaleReason = isStale(p)
} }
} }
...@@ -1356,14 +1357,15 @@ var isGoRelease = strings.HasPrefix(runtime.Version(), "go1") ...@@ -1356,14 +1357,15 @@ var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
// standard library, even in release versions. This makes // standard library, even in release versions. This makes
// 'go build -tags netgo' work, among other things. // 'go build -tags netgo' work, among other things.
// isStale reports whether package p needs to be rebuilt. // isStale reports whether package p needs to be rebuilt,
func isStale(p *Package) bool { // along with the reason why.
func isStale(p *Package) (bool, string) {
if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") { if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
// fake, builtin package // fake, builtin package
return false return false, "builtin package"
} }
if p.Error != nil { if p.Error != nil {
return true return true, "errors loading package"
} }
// A package without Go sources means we only found // A package without Go sources means we only found
...@@ -1373,23 +1375,26 @@ func isStale(p *Package) bool { ...@@ -1373,23 +1375,26 @@ func isStale(p *Package) bool {
// only useful with the specific version of the toolchain that // only useful with the specific version of the toolchain that
// created them. // created them.
if len(p.gofiles) == 0 && !p.usesSwig() { if len(p.gofiles) == 0 && !p.usesSwig() {
return false return false, "no source files"
} }
// If the -a flag is given, rebuild everything. // If the -a flag is given, rebuild everything.
if buildA { if buildA {
return true return true, "build -a flag in use"
} }
// If there's no install target or it's already marked stale, we have to rebuild. // If there's no install target or it's already marked stale, we have to rebuild.
if p.target == "" || p.Stale { if p.target == "" {
return true return true, "no install target"
}
if p.Stale {
return true, p.StaleReason
} }
// Package is stale if completely unbuilt. // Package is stale if completely unbuilt.
fi, err := os.Stat(p.target) fi, err := os.Stat(p.target)
if err != nil { if err != nil {
return true return true, "cannot stat install target"
} }
// Package is stale if the expected build ID differs from the // Package is stale if the expected build ID differs from the
...@@ -1402,13 +1407,13 @@ func isStale(p *Package) bool { ...@@ -1402,13 +1407,13 @@ func isStale(p *Package) bool {
// See issue 8290 and issue 10702. // See issue 8290 and issue 10702.
targetBuildID, err := readBuildID(p) targetBuildID, err := readBuildID(p)
if err == nil && targetBuildID != p.buildID { if err == nil && targetBuildID != p.buildID {
return true return true, "build ID mismatch"
} }
// Package is stale if a dependency is. // Package is stale if a dependency is.
for _, p1 := range p.deps { for _, p1 := range p.deps {
if p1.Stale { if p1.Stale {
return true return true, "stale dependency"
} }
} }
...@@ -1431,7 +1436,7 @@ func isStale(p *Package) bool { ...@@ -1431,7 +1436,7 @@ func isStale(p *Package) bool {
// install is to run make.bash, which will remove the old package archives // install is to run make.bash, which will remove the old package archives
// before rebuilding.) // before rebuilding.)
if p.Standard && isGoRelease { if p.Standard && isGoRelease {
return false return false, "standard package in Go release distribution"
} }
// Time-based staleness. // Time-based staleness.
...@@ -1446,7 +1451,7 @@ func isStale(p *Package) bool { ...@@ -1446,7 +1451,7 @@ func isStale(p *Package) bool {
// Package is stale if a dependency is, or if a dependency is newer. // Package is stale if a dependency is, or if a dependency is newer.
for _, p1 := range p.deps { for _, p1 := range p.deps {
if p1.target != "" && olderThan(p1.target) { if p1.target != "" && olderThan(p1.target) {
return true return true, "newer dependency"
} }
} }
...@@ -1465,10 +1470,10 @@ func isStale(p *Package) bool { ...@@ -1465,10 +1470,10 @@ func isStale(p *Package) bool {
// taken care of above (at least when the installed Go is a released version). // taken care of above (at least when the installed Go is a released version).
if p.Root != goroot { if p.Root != goroot {
if olderThan(buildToolchain.compiler()) { if olderThan(buildToolchain.compiler()) {
return true return true, "newer compiler"
} }
if p.build.IsCommand() && olderThan(buildToolchain.linker()) { if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
return true return true, "newer linker"
} }
} }
...@@ -1513,11 +1518,11 @@ func isStale(p *Package) bool { ...@@ -1513,11 +1518,11 @@ func isStale(p *Package) bool {
srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles) srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
for _, src := range srcs { for _, src := range srcs {
if olderThan(filepath.Join(p.Dir, src)) { if olderThan(filepath.Join(p.Dir, src)) {
return true return true, "newer source file"
} }
} }
return false return false, ""
} }
// computeBuildID computes the build ID for p, leaving it in p.buildID. // computeBuildID computes the build ID for p, leaving it in p.buildID.
......
...@@ -512,7 +512,8 @@ func runTest(cmd *Command, args []string) { ...@@ -512,7 +512,8 @@ func runTest(cmd *Command, args []string) {
continue continue
} }
p.Stale = true // rebuild p.Stale = true // rebuild
p.fake = true // do not warn about rebuild p.StaleReason = "rebuild for coverage"
p.fake = true // do not warn about rebuild
p.coverMode = testCoverMode p.coverMode = testCoverMode
var coverFiles []string var coverFiles []string
coverFiles = append(coverFiles, p.GoFiles...) coverFiles = append(coverFiles, p.GoFiles...)
...@@ -749,6 +750,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, ...@@ -749,6 +750,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
ptest.fake = true ptest.fake = true
ptest.forceLibrary = true ptest.forceLibrary = true
ptest.Stale = true ptest.Stale = true
ptest.StaleReason = "rebuild for test"
ptest.build = new(build.Package) ptest.build = new(build.Package)
*ptest.build = *p.build *ptest.build = *p.build
m := map[string][]token.Position{} m := map[string][]token.Position{}
...@@ -1027,6 +1029,7 @@ func recompileForTest(pmain, preal, ptest *Package, testDir string) { ...@@ -1027,6 +1029,7 @@ func recompileForTest(pmain, preal, ptest *Package, testDir string) {
p.target = "" p.target = ""
p.fake = true p.fake = true
p.Stale = true p.Stale = true
p.StaleReason = "depends on package being tested"
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment