var tags map[string]bool
+// Tags returns a set of build tags that are true for the target platform.
+// It includes GOOS, GOARCH, the compiler, possibly "cgo",
+// release tags like "go1.13", and user-specified build tags.
func Tags() map[string]bool {
if tags == nil {
tags = loadTags()
}
return tags
}
+
+var anyTags map[string]bool
+
+// AnyTags returns a special set of build tags that satisfy nearly all
+// build tag expressions. Only "ignore" and malformed build tag requirements
+// are considered false.
+func AnyTags() map[string]bool {
+ if anyTags == nil {
+ anyTags = map[string]bool{"*": true}
+ }
+ return anyTags
+}
return false
}
-var anyTagsExceptIgnore = map[string]bool{"*": true}
-
// matchPotentialSourceFile reports whether info may be relevant to a build operation.
func matchPotentialSourceFile(dir string, info os.FileInfo) bool {
if strings.HasSuffix(info.Name(), "_test.go") {
defer f.Close()
content, err := imports.ReadImports(f, false, nil)
- if err == nil && !imports.ShouldBuild(content, anyTagsExceptIgnore) {
+ if err == nil && !imports.ShouldBuild(content, imports.AnyTags()) {
// The file is explicitly tagged "ignore", so it can't affect the build.
// Leave it out.
return false
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/get"
+ "cmd/go/internal/imports"
"cmd/go/internal/load"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
// Don't load packages if pkgPatterns is empty. Both
// modload.ImportPathsQuiet and ModulePackages convert an empty list
// of patterns to []string{"."}, which is not what we want.
- matches = modload.ImportPathsQuiet(pkgPatterns)
+ matches = modload.ImportPathsQuiet(pkgPatterns, imports.AnyTags())
seenPkgs = make(map[string]bool)
- install = make([]string, 0, len(pkgPatterns))
for i, match := range matches {
arg := pkgGets[i]
continue
}
- install = append(install, arg.path)
allStd := true
for _, pkg := range match.Pkgs {
if !seenPkgs[pkg] {
}
prevBuildList = buildList
}
- search.WarnUnmatched(matches) // don't warn on every iteration
+ if !*getD {
+ // Only print warnings after the last iteration,
+ // and only if we aren't going to build.
+ search.WarnUnmatched(matches)
+ }
// Handle downgrades.
var down []module.Version
// If -d was specified, we're done after the module work.
// We've already downloaded modules by loading packages above.
- // Otherwise, we need to build and install the packages matched
- // by command line arguments.
- // Note that 'go get -u' without any arguments results in
- // len(install) == 1 if there's a package in the current directory.
- // search.CleanPatterns returns "." for empty args.
- if *getD || len(install) == 0 {
+ // Otherwise, we need to build and install the packages matched by
+ // command line arguments. This may be a different set of packages,
+ // since we only build packages for the target platform.
+ // Note that 'go get -u' without arguments is equivalent to
+ // 'go get -u .', so we'll typically build the package in the current
+ // directory.
+ if *getD || len(pkgPatterns) == 0 {
return
}
work.BuildInit()
- pkgs := load.PackagesForBuild(install)
+ pkgs := load.PackagesForBuild(pkgPatterns)
work.InstallPackages(install, pkgs)
}
var loaded *loader
// ImportPaths returns the set of packages matching the args (patterns),
-// adding modules to the build list as needed to satisfy new imports.
+// on the target platform. Modules may be added to the build list
+// to satisfy new imports.
func ImportPaths(patterns []string) []*search.Match {
- matches := ImportPathsQuiet(patterns)
+ matches := ImportPathsQuiet(patterns, imports.Tags())
search.WarnUnmatched(matches)
return matches
}
-// ImportPathsQuiet is like ImportPaths but does not warn about patterns with no matches.
-func ImportPathsQuiet(patterns []string) []*search.Match {
+// ImportPathsQuiet is like ImportPaths but does not warn about patterns with
+// no matches. It also lets the caller specify a set of build tags to match
+// packages. The build tags should typically be imports.Tags() or
+// imports.AnyTags(); a nil map has no special meaning.
+func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
var fsDirs [][]string
updateMatches := func(matches []*search.Match, iterating bool) {
for i, m := range matches {
})
}
- loaded = newLoader()
+ loaded = newLoader(tags)
loaded.load(func() []string {
var roots []string
updateMatches(matches, true)
func ImportFromFiles(gofiles []string) {
InitMod()
- imports, testImports, err := imports.ScanFiles(gofiles, imports.Tags())
+ tags := imports.Tags()
+ imports, testImports, err := imports.ScanFiles(gofiles, tags)
if err != nil {
base.Fatalf("go: %v", err)
}
- loaded = newLoader()
+ loaded = newLoader(tags)
loaded.load(func() []string {
var roots []string
roots = append(roots, imports...)
}
func ReloadBuildList() []module.Version {
- loaded = newLoader()
+ loaded = newLoader(imports.Tags())
loaded.load(func() []string { return nil })
return buildList
}
func loadAll(testAll bool) []string {
InitMod()
- loaded = newLoader()
+ loaded = newLoader(imports.AnyTags())
loaded.isALL = true
- loaded.tags = anyTags
loaded.testAll = testAll
if !testAll {
loaded.testRoots = true
return paths
}
-// anyTags is a special tags map that satisfies nearly all build tag expressions.
-// Only "ignore" and malformed build tag requirements are considered false.
-var anyTags = map[string]bool{"*": true}
-
// TargetPackages returns the list of packages in the target (top-level) module
// matching pattern, which may be relative to the working directory, under all
// build tag settings.
func TargetPackages(pattern string) []string {
- return matchPackages(pattern, anyTags, false, []module.Version{Target})
+ return matchPackages(pattern, imports.AnyTags(), false, []module.Version{Target})
}
// BuildList returns the module build list,
// LoadTests controls whether the loaders load tests of the root packages.
var LoadTests bool
-func newLoader() *loader {
+func newLoader(tags map[string]bool) *loader {
ld := new(loader)
- ld.tags = imports.Tags()
+ ld.tags = tags
ld.testRoots = LoadTests
// Inside the "std" and "cmd" modules, we prefer to use the vendor directory
"strings"
"sync"
+ "cmd/go/internal/imports"
"cmd/go/internal/modfetch"
"cmd/go/internal/module"
"cmd/go/internal/search"
if i := strings.Index(pattern, "..."); i >= 0 {
base = pathpkg.Dir(pattern[:i+3])
match = func(m module.Version, root string, isLocal bool) []string {
- return matchPackages(pattern, anyTags, false, []module.Version{m})
+ return matchPackages(pattern, imports.AnyTags(), false, []module.Version{m})
}
} else {
match = func(m module.Version, root string, isLocal bool) []string {
--- /dev/null
+env GO111MODULE=on
+
+[short] skip
+
+# get should add modules needed to build packages, even if those
+# dependencies are in sources excluded by build tags.
+# All build tags are considered true except "ignore".
+go mod init m
+go get -d .
+go list -m all
+stdout 'example.com/version v1.1.0'
+stdout 'rsc.io/quote v1.5.2'
+
+[short] skip
+
+# Packages that are only imported in excluded files should not be built.
+go get -x .
+stderr 'compile.* -p m '
+! stderr 'compile.* -p example.com/version '
+! stderr 'compile.* -p rsc.io/quote '
+
+-- empty.go --
+package m
+
+-- excluded.go --
+// +build windows,mips
+
+package m
+
+import _ "example.com/version"
+
+-- tools.go --
+// +build tools
+
+package tools
+
+import _ "rsc.io/quote"
+
+-- ignore.go --
+// +build ignore
+
+package ignore
+
+import _ "example.com/doesnotexist"