Skip to content

Commit 6f7542e

Browse files
author
Jay Conrod
committed
cmd/go: ignore build tags when 'go get' modifies build list
In module mode, 'go get' should not consider build constraints when loading packages in order to modify the module graph. With this change, 'go get' considers all build tags to be true except for "ignore" and malformed build constraint expressions. When 'go get' builds packages, it still applies build constraints for the target platform. Fixes #32345 Change-Id: I6dceae6f10a5185870537de730b36292271ad124 Reviewed-on: https://go-review.googlesource.com/c/go/+/179898 Reviewed-by: Bryan C. Mills <bcmills@google.com>
1 parent 64c134f commit 6f7542e

6 files changed

Lines changed: 94 additions & 32 deletions

File tree

src/cmd/go/internal/imports/tags.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import "cmd/go/internal/cfg"
88

99
var tags map[string]bool
1010

11+
// Tags returns a set of build tags that are true for the target platform.
12+
// It includes GOOS, GOARCH, the compiler, possibly "cgo",
13+
// release tags like "go1.13", and user-specified build tags.
1114
func Tags() map[string]bool {
1215
if tags == nil {
1316
tags = loadTags()
@@ -32,3 +35,15 @@ func loadTags() map[string]bool {
3235
}
3336
return tags
3437
}
38+
39+
var anyTags map[string]bool
40+
41+
// AnyTags returns a special set of build tags that satisfy nearly all
42+
// build tag expressions. Only "ignore" and malformed build tag requirements
43+
// are considered false.
44+
func AnyTags() map[string]bool {
45+
if anyTags == nil {
46+
anyTags = map[string]bool{"*": true}
47+
}
48+
return anyTags
49+
}

src/cmd/go/internal/modcmd/vendor.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ func matchMetadata(dir string, info os.FileInfo) bool {
166166
return false
167167
}
168168

169-
var anyTagsExceptIgnore = map[string]bool{"*": true}
170-
171169
// matchPotentialSourceFile reports whether info may be relevant to a build operation.
172170
func matchPotentialSourceFile(dir string, info os.FileInfo) bool {
173171
if strings.HasSuffix(info.Name(), "_test.go") {
@@ -181,7 +179,7 @@ func matchPotentialSourceFile(dir string, info os.FileInfo) bool {
181179
defer f.Close()
182180

183181
content, err := imports.ReadImports(f, false, nil)
184-
if err == nil && !imports.ShouldBuild(content, anyTagsExceptIgnore) {
182+
if err == nil && !imports.ShouldBuild(content, imports.AnyTags()) {
185183
// The file is explicitly tagged "ignore", so it can't affect the build.
186184
// Leave it out.
187185
return false

src/cmd/go/internal/modget/get.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"cmd/go/internal/base"
1010
"cmd/go/internal/cfg"
1111
"cmd/go/internal/get"
12+
"cmd/go/internal/imports"
1213
"cmd/go/internal/load"
1314
"cmd/go/internal/modfetch"
1415
"cmd/go/internal/modload"
@@ -446,9 +447,8 @@ func runGet(cmd *base.Command, args []string) {
446447
// Don't load packages if pkgPatterns is empty. Both
447448
// modload.ImportPathsQuiet and ModulePackages convert an empty list
448449
// of patterns to []string{"."}, which is not what we want.
449-
matches = modload.ImportPathsQuiet(pkgPatterns)
450+
matches = modload.ImportPathsQuiet(pkgPatterns, imports.AnyTags())
450451
seenPkgs = make(map[string]bool)
451-
install = make([]string, 0, len(pkgPatterns))
452452
for i, match := range matches {
453453
arg := pkgGets[i]
454454

@@ -462,7 +462,6 @@ func runGet(cmd *base.Command, args []string) {
462462
continue
463463
}
464464

465-
install = append(install, arg.path)
466465
allStd := true
467466
for _, pkg := range match.Pkgs {
468467
if !seenPkgs[pkg] {
@@ -513,7 +512,11 @@ func runGet(cmd *base.Command, args []string) {
513512
}
514513
prevBuildList = buildList
515514
}
516-
search.WarnUnmatched(matches) // don't warn on every iteration
515+
if !*getD {
516+
// Only print warnings after the last iteration,
517+
// and only if we aren't going to build.
518+
search.WarnUnmatched(matches)
519+
}
517520

518521
// Handle downgrades.
519522
var down []module.Version
@@ -606,16 +609,17 @@ func runGet(cmd *base.Command, args []string) {
606609

607610
// If -d was specified, we're done after the module work.
608611
// We've already downloaded modules by loading packages above.
609-
// Otherwise, we need to build and install the packages matched
610-
// by command line arguments.
611-
// Note that 'go get -u' without any arguments results in
612-
// len(install) == 1 if there's a package in the current directory.
613-
// search.CleanPatterns returns "." for empty args.
614-
if *getD || len(install) == 0 {
612+
// Otherwise, we need to build and install the packages matched by
613+
// command line arguments. This may be a different set of packages,
614+
// since we only build packages for the target platform.
615+
// Note that 'go get -u' without arguments is equivalent to
616+
// 'go get -u .', so we'll typically build the package in the current
617+
// directory.
618+
if *getD || len(pkgPatterns) == 0 {
615619
return
616620
}
617621
work.BuildInit()
618-
pkgs := load.PackagesForBuild(install)
622+
pkgs := load.PackagesForBuild(pkgPatterns)
619623
work.InstallPackages(install, pkgs)
620624
}
621625

src/cmd/go/internal/modload/load.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,19 @@ var buildList []module.Version
5151
var loaded *loader
5252

5353
// ImportPaths returns the set of packages matching the args (patterns),
54-
// adding modules to the build list as needed to satisfy new imports.
54+
// on the target platform. Modules may be added to the build list
55+
// to satisfy new imports.
5556
func ImportPaths(patterns []string) []*search.Match {
56-
matches := ImportPathsQuiet(patterns)
57+
matches := ImportPathsQuiet(patterns, imports.Tags())
5758
search.WarnUnmatched(matches)
5859
return matches
5960
}
6061

61-
// ImportPathsQuiet is like ImportPaths but does not warn about patterns with no matches.
62-
func ImportPathsQuiet(patterns []string) []*search.Match {
62+
// ImportPathsQuiet is like ImportPaths but does not warn about patterns with
63+
// no matches. It also lets the caller specify a set of build tags to match
64+
// packages. The build tags should typically be imports.Tags() or
65+
// imports.AnyTags(); a nil map has no special meaning.
66+
func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
6367
var fsDirs [][]string
6468
updateMatches := func(matches []*search.Match, iterating bool) {
6569
for i, m := range matches {
@@ -179,7 +183,7 @@ func ImportPathsQuiet(patterns []string) []*search.Match {
179183
})
180184
}
181185

182-
loaded = newLoader()
186+
loaded = newLoader(tags)
183187
loaded.load(func() []string {
184188
var roots []string
185189
updateMatches(matches, true)
@@ -258,12 +262,13 @@ func warnPattern(pattern string, list []string) []string {
258262
func ImportFromFiles(gofiles []string) {
259263
InitMod()
260264

261-
imports, testImports, err := imports.ScanFiles(gofiles, imports.Tags())
265+
tags := imports.Tags()
266+
imports, testImports, err := imports.ScanFiles(gofiles, tags)
262267
if err != nil {
263268
base.Fatalf("go: %v", err)
264269
}
265270

266-
loaded = newLoader()
271+
loaded = newLoader(tags)
267272
loaded.load(func() []string {
268273
var roots []string
269274
roots = append(roots, imports...)
@@ -312,7 +317,7 @@ func LoadBuildList() []module.Version {
312317
}
313318

314319
func ReloadBuildList() []module.Version {
315-
loaded = newLoader()
320+
loaded = newLoader(imports.Tags())
316321
loaded.load(func() []string { return nil })
317322
return buildList
318323
}
@@ -338,9 +343,8 @@ func LoadVendor() []string {
338343
func loadAll(testAll bool) []string {
339344
InitMod()
340345

341-
loaded = newLoader()
346+
loaded = newLoader(imports.AnyTags())
342347
loaded.isALL = true
343-
loaded.tags = anyTags
344348
loaded.testAll = testAll
345349
if !testAll {
346350
loaded.testRoots = true
@@ -359,15 +363,11 @@ func loadAll(testAll bool) []string {
359363
return paths
360364
}
361365

362-
// anyTags is a special tags map that satisfies nearly all build tag expressions.
363-
// Only "ignore" and malformed build tag requirements are considered false.
364-
var anyTags = map[string]bool{"*": true}
365-
366366
// TargetPackages returns the list of packages in the target (top-level) module
367367
// matching pattern, which may be relative to the working directory, under all
368368
// build tag settings.
369369
func TargetPackages(pattern string) []string {
370-
return matchPackages(pattern, anyTags, false, []module.Version{Target})
370+
return matchPackages(pattern, imports.AnyTags(), false, []module.Version{Target})
371371
}
372372

373373
// BuildList returns the module build list,
@@ -510,9 +510,9 @@ type loader struct {
510510
// LoadTests controls whether the loaders load tests of the root packages.
511511
var LoadTests bool
512512

513-
func newLoader() *loader {
513+
func newLoader(tags map[string]bool) *loader {
514514
ld := new(loader)
515-
ld.tags = imports.Tags()
515+
ld.tags = tags
516516
ld.testRoots = LoadTests
517517

518518
// Inside the "std" and "cmd" modules, we prefer to use the vendor directory

src/cmd/go/internal/modload/query.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strings"
1313
"sync"
1414

15+
"cmd/go/internal/imports"
1516
"cmd/go/internal/modfetch"
1617
"cmd/go/internal/module"
1718
"cmd/go/internal/search"
@@ -265,7 +266,7 @@ func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]Q
265266
if i := strings.Index(pattern, "..."); i >= 0 {
266267
base = pathpkg.Dir(pattern[:i+3])
267268
match = func(m module.Version, root string, isLocal bool) []string {
268-
return matchPackages(pattern, anyTags, false, []module.Version{m})
269+
return matchPackages(pattern, imports.AnyTags(), false, []module.Version{m})
269270
}
270271
} else {
271272
match = func(m module.Version, root string, isLocal bool) []string {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
env GO111MODULE=on
2+
3+
[short] skip
4+
5+
# get should add modules needed to build packages, even if those
6+
# dependencies are in sources excluded by build tags.
7+
# All build tags are considered true except "ignore".
8+
go mod init m
9+
go get -d .
10+
go list -m all
11+
stdout 'example.com/version v1.1.0'
12+
stdout 'rsc.io/quote v1.5.2'
13+
14+
[short] skip
15+
16+
# Packages that are only imported in excluded files should not be built.
17+
go get -x .
18+
stderr 'compile.* -p m '
19+
! stderr 'compile.* -p example.com/version '
20+
! stderr 'compile.* -p rsc.io/quote '
21+
22+
-- empty.go --
23+
package m
24+
25+
-- excluded.go --
26+
// +build windows,mips
27+
28+
package m
29+
30+
import _ "example.com/version"
31+
32+
-- tools.go --
33+
// +build tools
34+
35+
package tools
36+
37+
import _ "rsc.io/quote"
38+
39+
-- ignore.go --
40+
// +build ignore
41+
42+
package ignore
43+
44+
import _ "example.com/doesnotexist"

0 commit comments

Comments
 (0)