Skip to content

Commit 5b606a9

Browse files
committed
cmd/go: correct staleness for packages in modules
Packages in modules don't have a Target set for them, so the current logic for determining staleness always reports them as stale. Instead it should be reporting whether "go install" would do anything, and sholud be false after a go install. If a package does not have a Target, instead check to see whether we've cached its build artifact. Change-Id: Ie7bdb234944353f6c2727bd8bf939cc27ddf3f18 Reviewed-on: https://go-review.googlesource.com/c/go/+/444619 Run-TryBot: Michael Matloob <[email protected]> Reviewed-by: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Michael Matloob <[email protected]>
1 parent d5efd0d commit 5b606a9

File tree

3 files changed

+70
-66
lines changed

3 files changed

+70
-66
lines changed

src/cmd/go/internal/work/buildid.go

+54-63
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,19 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string,
418418
a.buildID = actionID + buildIDSeparator + mainpkg.buildID + buildIDSeparator + contentID
419419
}
420420

421-
// Check to see if target exists and matches the expected action ID.
422-
// If so, it's up to date and we can reuse it instead of rebuilding it.
423-
var buildID string
424-
if target != "" && !cfg.BuildA {
425-
buildID, _ = buildid.ReadFile(target)
421+
// If user requested -a, we force a rebuild, so don't use the cache.
422+
if cfg.BuildA {
423+
if p := a.Package; p != nil && !p.Stale {
424+
p.Stale = true
425+
p.StaleReason = "build -a flag in use"
426+
}
427+
// Begin saving output for later writing to cache.
428+
a.output = []byte{}
429+
return false
430+
}
431+
432+
if target != "" {
433+
buildID, _ := buildid.ReadFile(target)
426434
if strings.HasPrefix(buildID, actionID+buildIDSeparator) {
427435
a.buildID = buildID
428436
if a.json != nil {
@@ -433,18 +441,13 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string,
433441
a.Target = "DO NOT USE - " + a.Mode
434442
return true
435443
}
436-
}
437-
438-
// Special case for building a main package: if the only thing we
439-
// want the package for is to link a binary, and the binary is
440-
// already up-to-date, then to avoid a rebuild, report the package
441-
// as up-to-date as well. See "Build IDs" comment above.
442-
// TODO(rsc): Rewrite this code to use a TryCache func on the link action.
443-
if target != "" && !cfg.BuildA && !b.NeedExport && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" {
444-
buildID, err := buildid.ReadFile(target)
445-
if err == nil {
446-
id := strings.Split(buildID, buildIDSeparator)
447-
if len(id) == 4 && id[1] == actionID {
444+
// Special case for building a main package: if the only thing we
445+
// want the package for is to link a binary, and the binary is
446+
// already up-to-date, then to avoid a rebuild, report the package
447+
// as up-to-date as well. See "Build IDs" comment above.
448+
// TODO(rsc): Rewrite this code to use a TryCache func on the link action.
449+
if !b.NeedExport && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" {
450+
if id := strings.Split(buildID, buildIDSeparator); len(id) == 4 && id[1] == actionID {
448451
// Temporarily assume a.buildID is the package build ID
449452
// stored in the installed binary, and see if that makes
450453
// the upcoming link action ID a match. If so, report that
@@ -488,7 +491,7 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string,
488491
// then to avoid the link step, report the link as up-to-date.
489492
// We avoid the nested build ID problem in the previous special case
490493
// by recording the test results in the cache under the action ID half.
491-
if !cfg.BuildA && len(a.triggers) == 1 && a.triggers[0].TryCache != nil && a.triggers[0].TryCache(b, a.triggers[0]) {
494+
if len(a.triggers) == 1 && a.triggers[0].TryCache != nil && a.triggers[0].TryCache(b, a.triggers[0]) {
492495
// Best effort attempt to display output from the compile and link steps.
493496
// If it doesn't work, it doesn't work: reusing the test result is more
494497
// important than reprinting diagnostic information.
@@ -505,63 +508,51 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string,
505508
return true
506509
}
507510

508-
if b.IsCmdList {
509-
// Invoked during go list to compute and record staleness.
510-
if p := a.Package; p != nil && !p.Stale {
511-
p.Stale = true
512-
if cfg.BuildA {
513-
p.StaleReason = "build -a flag in use"
514-
} else {
515-
p.StaleReason = "build ID mismatch"
516-
for _, p1 := range p.Internal.Imports {
517-
if p1.Stale && p1.StaleReason != "" {
518-
if strings.HasPrefix(p1.StaleReason, "stale dependency: ") {
519-
p.StaleReason = p1.StaleReason
520-
break
521-
}
522-
if strings.HasPrefix(p.StaleReason, "build ID mismatch") {
523-
p.StaleReason = "stale dependency: " + p1.ImportPath
524-
}
525-
}
511+
// Check to see if the action output is cached.
512+
if c := cache.Default(); c != nil {
513+
if file, _, err := c.GetFile(actionHash); err == nil {
514+
if buildID, err := buildid.ReadFile(file); err == nil {
515+
if printOutput {
516+
showStdout(b, c, a.actionID, "stdout")
517+
}
518+
a.built = file
519+
a.Target = "DO NOT USE - using cache"
520+
a.buildID = buildID
521+
if a.json != nil {
522+
a.json.BuildID = a.buildID
526523
}
524+
if p := a.Package; p != nil && target != "" {
525+
p.Stale = true
526+
// Clearer than explaining that something else is stale.
527+
p.StaleReason = "not installed but available in build cache"
528+
}
529+
return true
527530
}
528531
}
529-
530-
// Fall through to update a.buildID from the build artifact cache,
531-
// which will affect the computation of buildIDs for targets
532-
// higher up in the dependency graph.
533532
}
534533

535-
// Check the build artifact cache.
536-
// We treat hits in this cache as being "stale" for the purposes of go list
537-
// (in effect, "stale" means whether p.Target is up-to-date),
538-
// but we're still happy to use results from the build artifact cache.
539-
if c := cache.Default(); c != nil {
540-
if !cfg.BuildA {
541-
if file, _, err := c.GetFile(actionHash); err == nil {
542-
if buildID, err := buildid.ReadFile(file); err == nil {
543-
if printOutput {
544-
showStdout(b, c, a.actionID, "stdout")
534+
// If we've reached this point, we can't use the cache for the action.
535+
if p := a.Package; p != nil && !p.Stale {
536+
p.Stale = true
537+
p.StaleReason = "build ID mismatch"
538+
if b.IsCmdList {
539+
// Since we may end up printing StaleReason, include more detail.
540+
for _, p1 := range p.Internal.Imports {
541+
if p1.Stale && p1.StaleReason != "" {
542+
if strings.HasPrefix(p1.StaleReason, "stale dependency: ") {
543+
p.StaleReason = p1.StaleReason
544+
break
545545
}
546-
a.built = file
547-
a.Target = "DO NOT USE - using cache"
548-
a.buildID = buildID
549-
if a.json != nil {
550-
a.json.BuildID = a.buildID
546+
if strings.HasPrefix(p.StaleReason, "build ID mismatch") {
547+
p.StaleReason = "stale dependency: " + p1.ImportPath
551548
}
552-
if p := a.Package; p != nil {
553-
// Clearer than explaining that something else is stale.
554-
p.StaleReason = "not installed but available in build cache"
555-
}
556-
return true
557549
}
558550
}
559551
}
560-
561-
// Begin saving output for later writing to cache.
562-
a.output = []byte{}
563552
}
564553

554+
// Begin saving output for later writing to cache.
555+
a.output = []byte{}
565556
return false
566557
}
567558

src/cmd/go/testdata/script/mod_get_commit.txt

+1-3
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache
1919
go build -x golang.org/x/text/language
2020
stderr 'compile|cp|gccgo .*language\.a$'
2121

22-
# BUG: after the build, the package should not be stale, as 'go install' would
23-
# not do anything further.
2422
go list -f '{{.Stale}}' golang.org/x/text/language
25-
stdout ^true
23+
stdout ^false
2624

2725
# install after build should not run the compiler again.
2826
go install -x golang.org/x/text/language
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[short] skip
2+
3+
env GOCACHE=$WORK/cache
4+
go list -f '{{.Stale}}' .
5+
stdout true
6+
go install .
7+
go list -f '{{.Stale}}' .
8+
stdout false
9+
10+
-- go.mod --
11+
module example.com/mod
12+
13+
go 1.20
14+
-- m.go --
15+
package m

0 commit comments

Comments
 (0)