cmd/internal/objabi,test: use correct GOEXPERIMENT build tags in test/run.go

Currently, run.go sets GOEXPERIMENT build tags based on the
*difference* from the baseline experiment configuration, rather than
the absolute experiment configuration. This differs from cmd/go. As a
result, if we set a baseline configuration and don't override it with
a GOEXPERIMENT setting, run.go won't set any GOEXPERIMENT build tags,
instead of setting the tags corresponding to the baseline
configuration.

Fix this by making compile -V=goexperiment produce the full
GOEXPERIMENT configuration, which run.go can then use to set exactly
the right set of build tags.

For #40724.

Change-Id: Ieda6ea62f1a1fabbe8d749d6d09c198fd5ca8377
Reviewed-on: https://go-review.googlesource.com/c/go/+/310171
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Austin Clements 2021-04-14 13:25:31 -04:00 committed by Russ Cox
parent cf2396c70e
commit d26fc68aa1
3 changed files with 35 additions and 25 deletions

View file

@ -108,8 +108,9 @@ func parseExperiments() goexperiment.Flags {
// expList returns the list of lower-cased experiment names for
// experiments that differ from base. base may be nil to indicate no
// experiments.
func expList(exp, base *goexperiment.Flags) []string {
// experiments. If all is true, then include all experiment flags,
// regardless of base.
func expList(exp, base *goexperiment.Flags, all bool) []string {
var list []string
rv := reflect.ValueOf(exp).Elem()
var rBase reflect.Value
@ -124,7 +125,7 @@ func expList(exp, base *goexperiment.Flags) []string {
if base != nil {
baseVal = rBase.Field(i).Bool()
}
if val != baseVal {
if all || val != baseVal {
if val {
list = append(list, name)
} else {
@ -140,11 +141,11 @@ func expList(exp, base *goexperiment.Flags) []string {
// GOEXPERIMENT is exactly what a user would set on the command line
// to get the set of enabled experiments.
func GOEXPERIMENT() string {
return strings.Join(expList(&Experiment, &experimentBaseline), ",")
return strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
}
// EnabledExperiments returns a list of enabled experiments, as
// lower-cased experiment names.
func EnabledExperiments() []string {
return expList(&Experiment, nil)
return expList(&Experiment, nil, false)
}

View file

@ -93,10 +93,16 @@ func (versionFlag) Set(s string) error {
p := ""
// If the enabled experiments differ from the defaults,
// include that difference.
if goexperiment := GOEXPERIMENT(); goexperiment != "" {
p = " X:" + goexperiment
if s == "goexperiment" {
// test/run.go uses this to discover the full set of
// experiment tags. Report everything.
p = " X:" + strings.Join(expList(&Experiment, nil, true), ",")
} else {
// If the enabled experiments differ from the defaults,
// include that difference.
if goexperiment := GOEXPERIMENT(); goexperiment != "" {
p = " X:" + goexperiment
}
}
// The go command invokes -V=full to get a unique identifier

View file

@ -376,6 +376,7 @@ type context struct {
GOARCH string
cgoEnabled bool
noOptEnv bool
expTags map[string]bool // Set lazily
}
// shouldTest looks for build tags in a source file and returns
@ -445,26 +446,28 @@ func (ctxt *context) match(name string) bool {
}
}
exp := os.Getenv("GOEXPERIMENT")
if exp == "" {
// If GOEXPERIMENT environment variable is unset, get the default value
// that is baked into the toolchain.
cmd := exec.Command(goTool(), "tool", "compile", "-V")
out, err := cmd.CombinedOutput()
if err == nil {
if strings.HasPrefix(name, "goexperiment.") {
// Query goexperiment tags from the toolchain.
if ctxt.expTags == nil {
ctxt.expTags = make(map[string]bool)
cmd := exec.Command(goTool(), "tool", "compile", "-V=goexperiment")
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("failed to get GOEXPERIMENT configuration:\n%s", out)
}
i := bytes.Index(out, []byte("X:"))
if i != -1 {
exp = string(out[i+2:])
}
}
}
if exp != "" {
experiments := strings.Split(exp, ",")
for _, e := range experiments {
if name == "goexperiment."+e {
return true
for _, exp := range strings.Split(string(out[i+2:]), ",") {
v := true
if strings.HasPrefix(exp, "no") {
v, exp = false, exp[2:]
}
ctxt.expTags["goexperiment."+exp] = v
}
}
}
return ctxt.expTags[name]
}
if name == "cgo" && ctxt.cgoEnabled {