Skip to content

Commit 8c3005c

Browse files
committed
cmd/go: make build -a skip standard packages in Go releases
Today, 'go build -a my/pkg' and 'go install -a my/pkg' recompile not just my/pkg and all its dependencies that you wrote but also the standard library packages. Recompiling the standard library is problematic on some systems because the installed copy is not writable. The -a behavior means that you can't use 'go install -a all' or 'go install -a my/...' to rebuild everything after a Go release - the rebuild stops early when it cannot overwrite the installed standard library. During development work, however, you do want install -a to rebuild everything, because anything might have changed. Resolve the conflict by making the behavior of -a depend on whether we are using a released copy of Go or a devel copy. In the release copies, -a no longer applies to the standard library. In the devel copies, it still does. This is the latest in a long line of refinements to the "do I build this or not" logic. It is surely not the last. Fixes #8290. LGTM=r R=golang-codereviews, r, tracey.brendan CC=adg, golang-codereviews, iant https://golang.org/cl/151730045
1 parent e5afecb commit 8c3005c

File tree

5 files changed

+67
-2
lines changed

5 files changed

+67
-2
lines changed

src/cmd/go/build.go

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ and test commands:
5757
5858
-a
5959
force rebuilding of packages that are already up-to-date.
60+
In Go releases, does not apply to the standard library.
6061
-n
6162
print the commands but do not run them.
6263
-p n

src/cmd/go/doc.go

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ and test commands:
7676
7777
-a
7878
force rebuilding of packages that are already up-to-date.
79+
In Go releases, does not apply to the standard library.
7980
-n
8081
print the commands but do not run them.
8182
-p n

src/cmd/go/pkg.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"os"
1515
pathpkg "path"
1616
"path/filepath"
17+
"runtime"
1718
"sort"
1819
"strings"
1920
"time"
@@ -685,6 +686,12 @@ func computeStale(pkgs ...*Package) {
685686
}
686687
}
687688

689+
// The runtime version string takes one of two forms:
690+
// "go1.X[.Y]" for Go releases, and "devel +hash" at tip.
691+
// Determine whether we are in a released copy by
692+
// inspecting the version.
693+
var isGoRelease = !strings.HasPrefix(runtime.Version(), "go1")
694+
688695
// isStale reports whether package p needs to be rebuilt.
689696
func isStale(p *Package, topRoot map[string]bool) bool {
690697
if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
@@ -705,7 +712,16 @@ func isStale(p *Package, topRoot map[string]bool) bool {
705712
return false
706713
}
707714

708-
if buildA || p.target == "" || p.Stale {
715+
// If we are running a release copy of Go, do not rebuild the standard packages.
716+
// They may not be writable anyway, but they are certainly not changing.
717+
// This makes 'go build -a' skip the standard packages when using an official release.
718+
// See issue 4106 and issue 8290.
719+
pkgBuildA := buildA
720+
if p.Standard && isGoRelease {
721+
pkgBuildA = false
722+
}
723+
724+
if pkgBuildA || p.target == "" || p.Stale {
709725
return true
710726
}
711727

src/cmd/go/test.bash

+27-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# license that can be found in the LICENSE file.
55

66
set -e
7-
go build -o testgo
7+
go build -tags testgo -o testgo
88
go() {
99
echo TEST ERROR: ran go, not testgo: go "$@" >&2
1010
exit 2
@@ -71,6 +71,32 @@ if ! grep -q "/tool/.*/$linker" $d/err.out; then
7171
fi
7272
rm -r $d
7373

74+
TEST 'go build -a in dev branch'
75+
./testgo install math || ok=false # should be up to date already but just in case
76+
d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
77+
if ! TESTGO_IS_GO_RELEASE=0 ./testgo build -v -a math 2>$d/err.out; then
78+
cat $d/err.out
79+
ok=false
80+
elif ! grep -q runtime $d/err.out; then
81+
echo "testgo build -a math in dev branch DID NOT build runtime, but should have"
82+
cat $d/err.out
83+
ok=false
84+
fi
85+
rm -r $d
86+
87+
TEST 'go build -a in release branch'
88+
./testgo install math || ok=false # should be up to date already but just in case
89+
d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
90+
if ! TESTGO_IS_GO_RELEASE=1 ./testgo build -v -a math 2>$d/err.out; then
91+
cat $d/err.out
92+
ok=false
93+
elif grep -q runtime $d/err.out; then
94+
echo "testgo build -a math in dev branch DID build runtime, but should NOT have"
95+
cat $d/err.out
96+
ok=false
97+
fi
98+
rm -r $d
99+
74100
# Test local (./) imports.
75101
testlocal() {
76102
local="$1"

src/cmd/go/testgo.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2014 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// This file contains extra hooks for testing the go command.
6+
// It is compiled into the Go binary only when building the
7+
// test copy; it does not get compiled into the standard go
8+
// command, so these testing hooks are not present in the
9+
// go command that everyone uses.
10+
11+
// +build testgo
12+
13+
package main
14+
15+
import "os"
16+
17+
func init() {
18+
if v := os.Getenv("TESTGO_IS_GO_RELEASE"); v != "" {
19+
isGoRelease = v == "1"
20+
}
21+
}

0 commit comments

Comments
 (0)