// A ppfValue is a single <pattern>=<flags> per-package flag value.
type ppfValue struct {
- match func(*Package) bool // compiled pattern
+ match func(*modload.State, *Package) bool // compiled pattern
flags []string
}
func (f *PerPackageFlag) set(v, cwd string) error {
f.raw = v
f.present = true
- match := func(p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern
+ match := func(_ *modload.State, p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern
// For backwards compatibility with earlier flag splitting, ignore spaces around flags.
v = strings.TrimSpace(v)
if v == "" {
return fmt.Errorf("parameter may not start with quote character %c", v[0])
}
pattern := strings.TrimSpace(v[:i])
- match = MatchPackage(modload.LoaderState, pattern, cwd)
+ match = MatchPackage(pattern, cwd)
v = v[i+1:]
}
flags, err := quoted.Split(v)
}
// For returns the flags to use for the given package.
-func (f *PerPackageFlag) For(p *Package) []string {
+//
+// The module loader state is used by the matcher to know if certain
+// patterns match packages within the state's MainModules.
+func (f *PerPackageFlag) For(s *modload.State, p *Package) []string {
flags := []string{}
for _, v := range f.values {
- if v.match(p) {
+ if v.match(s, p) {
flags = v.flags
}
}
package load
import (
+ "cmd/go/internal/modload"
"fmt"
"path/filepath"
"reflect"
}
for _, p := range tt.pkgs {
dir := nativeDir(p.dir)
- flags := ppFlags.For(&Package{PackagePublic: PackagePublic{ImportPath: p.path, Dir: dir}, Internal: PackageInternal{CmdlinePkg: p.cmdline}})
+ flags := ppFlags.For(modload.NewState(), &Package{PackagePublic: PackagePublic{ImportPath: p.path, Dir: dir}, Internal: PackageInternal{CmdlinePkg: p.cmdline}})
if !reflect.DeepEqual(flags, p.flags) {
t.Errorf("For(%v, %v, %v) = %v, want %v", p.path, dir, p.cmdline, flags, p.flags)
}
// can produce better error messages if it starts with the original paths.
// The initial load of p loads all the non-test imports and rewrites
// the vendored paths, so nothing should ever call p.vendored(p.Imports).
-func (p *Package) Resolve(loaderstate *modload.State, imports []string) []string {
+func (p *Package) Resolve(s *modload.State, imports []string) []string {
if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] {
panic("internal error: p.Resolve(p.Imports) called")
}
seen := make(map[string]bool)
var all []string
for _, path := range imports {
- path = ResolveImportPath(loaderstate, p, path)
+ path = ResolveImportPath(s, p, path)
if !seen[path] {
seen[path] = true
all = append(all, path)
// First, there is Go 1.5 vendoring (golang.org/s/go15vendor).
// If vendor expansion doesn't trigger, then the path is also subject to
// Go 1.11 module legacy conversion (golang.org/issue/25069).
-func ResolveImportPath(loaderstate *modload.State, parent *Package, path string) (found string) {
+func ResolveImportPath(s *modload.State, parent *Package, path string) (found string) {
var parentPath, parentDir, parentRoot string
parentIsStd := false
if parent != nil {
parentRoot = parent.Root
parentIsStd = parent.Standard
}
- return resolveImportPath(loaderstate, path, parentPath, parentDir, parentRoot, parentIsStd)
+ return resolveImportPath(s, path, parentPath, parentDir, parentRoot, parentIsStd)
}
-func resolveImportPath(loaderstate *modload.State, path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {
+func resolveImportPath(s *modload.State, path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {
if cfg.ModulesEnabled {
- if _, p, e := modload.Lookup(loaderstate, parentPath, parentIsStd, path); e == nil {
+ if _, p, e := modload.Lookup(s, parentPath, parentIsStd, path); e == nil {
return p
}
return path
// The linker loads implicit dependencies.
if p.Name == "main" && !p.Internal.ForceLibrary {
- ldDeps, err := LinkerDeps(p)
+ ldDeps, err := LinkerDeps(loaderstate, p)
if err != nil {
setError(err)
return
}
// LinkerDeps returns the list of linker-induced dependencies for main package p.
-func LinkerDeps(p *Package) ([]string, error) {
+func LinkerDeps(s *modload.State, p *Package) ([]string, error) {
// Everything links runtime.
deps := []string{"runtime"}
// External linking mode forces an import of runtime/cgo.
- if what := externalLinkingReason(p); what != "" && cfg.BuildContext.Compiler != "gccgo" {
+ if what := externalLinkingReason(s, p); what != "" && cfg.BuildContext.Compiler != "gccgo" {
if !cfg.BuildContext.CgoEnabled {
return nil, fmt.Errorf("%s requires external (cgo) linking, but cgo is not enabled", what)
}
// externalLinkingReason reports the reason external linking is required
// even for programs that do not use cgo, or the empty string if external
// linking is not required.
-func externalLinkingReason(p *Package) (what string) {
+func externalLinkingReason(s *modload.State, p *Package) (what string) {
// Some targets must use external linking even inside GOROOT.
if platform.MustLinkExternal(cfg.Goos, cfg.Goarch, false) {
return cfg.Goos + "/" + cfg.Goarch
// Using -ldflags=-linkmode=external forces external linking.
// If there are multiple -linkmode options, the last one wins.
if p != nil {
- ldflags := BuildLdflags.For(p)
+ ldflags := BuildLdflags.For(s, p)
for i := len(ldflags) - 1; i >= 0; i-- {
a := ldflags[i]
if a == "-linkmode=external" ||
// in LoadImport instead.
func LoadImportWithFlags(loaderstate *modload.State, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
p, err := loadImport(loaderstate, context.TODO(), PackageOpts{}, nil, path, srcDir, parent, stk, importPos, mode)
- setToolFlags(p)
+ setToolFlags(loaderstate, p)
return p, err
}
// It's then guaranteed to not return an error
func LoadPackageWithFlags(loaderstate *modload.State, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
p := LoadPackage(loaderstate, context.TODO(), PackageOpts{}, path, srcDir, stk, importPos, mode)
- setToolFlags(p)
+ setToolFlags(loaderstate, p)
return p
}
// compute the effective flags for all loaded packages
// (not just the ones matching the patterns but also
// their dependencies).
- setToolFlags(pkgs...)
+ setToolFlags(loaderstate, pkgs...)
setPGOProfilePath(pkgs)
return e.importPath
}
-func setToolFlags(pkgs ...*Package) {
+func setToolFlags(loaderstate *modload.State, pkgs ...*Package) {
for _, p := range PackageList(pkgs) {
- p.Internal.Asmflags = BuildAsmflags.For(p)
- p.Internal.Gcflags = BuildGcflags.For(p)
- p.Internal.Ldflags = BuildLdflags.For(p)
- p.Internal.Gccgoflags = BuildGccgoflags.For(p)
+ p.Internal.Asmflags = BuildAsmflags.For(loaderstate, p)
+ p.Internal.Gcflags = BuildGcflags.For(loaderstate, p)
+ p.Internal.Ldflags = BuildLdflags.For(loaderstate, p)
+ p.Internal.Gccgoflags = BuildGccgoflags.For(loaderstate, p)
}
}
pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
pkg.Incomplete = true
}
- setToolFlags(pkg)
+ setToolFlags(loaderstate, pkg)
return pkg
}
}
// EnsureImport ensures that package p imports the named package.
-func EnsureImport(loaderstate *modload.State, p *Package, pkg string) {
+func EnsureImport(s *modload.State, p *Package, pkg string) {
for _, d := range p.Internal.Imports {
if d.Name == pkg {
return
}
}
- p1, err := LoadImportWithFlags(loaderstate, pkg, p.Dir, p, &ImportStack{}, nil, 0)
+ p1, err := LoadImportWithFlags(s, pkg, p.Dir, p, &ImportStack{}, nil, 0)
if err != nil {
base.Fatalf("load %s: %v", pkg, err)
}
// "go test -cover"). It walks through the packages being built (and
// dependencies) and marks them for coverage instrumentation when
// appropriate, and possibly adding additional deps where needed.
-func PrepareForCoverageBuild(loaderstate *modload.State, pkgs []*Package) {
- var match []func(*Package) bool
+func PrepareForCoverageBuild(s *modload.State, pkgs []*Package) {
+ var match []func(*modload.State, *Package) bool
- matchMainModAndCommandLine := func(p *Package) bool {
+ matchMainModAndCommandLine := func(_ *modload.State, p *Package) bool {
// note that p.Standard implies p.Module == nil below.
return p.Internal.CmdlineFiles || p.Internal.CmdlinePkg || (p.Module != nil && p.Module.Main)
}
if len(cfg.BuildCoverPkg) != 0 {
// If -coverpkg has been specified, then we instrument only
// the specific packages selected by the user-specified pattern(s).
- match = make([]func(*Package) bool, len(cfg.BuildCoverPkg))
+ match = make([]func(*modload.State, *Package) bool, len(cfg.BuildCoverPkg))
for i := range cfg.BuildCoverPkg {
- match[i] = MatchPackage(loaderstate, cfg.BuildCoverPkg[i], base.Cwd())
+ match[i] = MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
}
} else {
// Without -coverpkg, instrument only packages in the main module
// (if any), as well as packages/files specifically named on the
// command line.
- match = []func(*Package) bool{matchMainModAndCommandLine}
+ match = []func(*modload.State, *Package) bool{matchMainModAndCommandLine}
}
// Visit the packages being built or installed, along with all of
// their dependencies, and mark them to be instrumented, taking
// into account the matchers we've set up in the sequence above.
- SelectCoverPackages(loaderstate, PackageList(pkgs), match, "build")
+ SelectCoverPackages(s, PackageList(pkgs), match, "build")
}
-func SelectCoverPackages(loaderstate *modload.State, roots []*Package, match []func(*Package) bool, op string) []*Package {
+func SelectCoverPackages(s *modload.State, roots []*Package, match []func(*modload.State, *Package) bool, op string) []*Package {
var warntag string
var includeMain bool
switch op {
for _, p := range roots {
haveMatch := false
for i := range match {
- if match[i](p) {
+ if match[i](s, p) {
matched[i] = true
haveMatch = true
}
// Force import of sync/atomic into package if atomic mode.
if cfg.BuildCoverMode == "atomic" {
- EnsureImport(loaderstate, p, "sync/atomic")
+ EnsureImport(s, p, "sync/atomic")
}
}
)
// MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd.
-func MatchPackage(loaderstate *modload.State, pattern, cwd string) func(*Package) bool {
+func MatchPackage(pattern, cwd string) func(*modload.State, *Package) bool {
switch {
case search.IsRelativePath(pattern):
// Split pattern into leading pattern-free directory path
}
dir = filepath.Join(cwd, dir)
if pattern == "" {
- return func(p *Package) bool { return p.Dir == dir }
+ return func(_ *modload.State, p *Package) bool { return p.Dir == dir }
}
matchPath := pkgpattern.MatchPattern(pattern)
- return func(p *Package) bool {
+ return func(_ *modload.State, p *Package) bool {
// Compute relative path to dir and see if it matches the pattern.
rel, err := filepath.Rel(dir, p.Dir)
if err != nil {
// This is slightly inaccurate: it matches every package, which isn't the same
// as matching the "all" package pattern.
// TODO(matloob): Should we make this more accurate? Does anyone depend on this behavior?
- return func(p *Package) bool { return true }
+ return func(_ *modload.State, p *Package) bool { return true }
case pattern == "std":
- return func(p *Package) bool { return p.Standard }
+ return func(_ *modload.State, p *Package) bool { return p.Standard }
case pattern == "cmd":
- return func(p *Package) bool { return p.Standard && strings.HasPrefix(p.ImportPath, "cmd/") }
- case pattern == "tool" && modload.Enabled(loaderstate):
- return func(p *Package) bool {
- return loaderstate.MainModules.Tools()[p.ImportPath]
- }
- case pattern == "work" && modload.Enabled(loaderstate):
- return func(p *Package) bool {
- return p.Module != nil && loaderstate.MainModules.Contains(p.Module.Path)
- }
-
+ return func(_ *modload.State, p *Package) bool { return p.Standard && strings.HasPrefix(p.ImportPath, "cmd/") }
default:
- matchPath := pkgpattern.MatchPattern(pattern)
- return func(p *Package) bool { return matchPath(p.ImportPath) }
+ return func(s *modload.State, p *Package) bool {
+ switch {
+ case pattern == "tool" && modload.Enabled(s):
+ return s.MainModules.Tools()[p.ImportPath]
+ case pattern == "work" && modload.Enabled(s):
+ return p.Module != nil && s.MainModules.Contains(p.Module.Path)
+ default:
+ matchPath := pkgpattern.MatchPattern(pattern)
+ return matchPath(p.ImportPath)
+ }
+ }
}
}
if cover != nil {
deps = append(deps, "internal/coverage/cfile")
}
- ldDeps, err := LinkerDeps(p)
+ ldDeps, err := LinkerDeps(loaderstate, p)
if err != nil && pmain.Error == nil {
pmain.Error = &PackageError{Err: err}
}
allTestImports = append(allTestImports, pmain.Internal.Imports...)
allTestImports = append(allTestImports, imports...)
allTestImports = append(allTestImports, ximports...)
- setToolFlags(allTestImports...)
+ setToolFlags(loaderstate, allTestImports...)
// Do initial scan for metadata needed for writing _testmain.go
// Use that metadata to update the list of imports for package main.
var writeCoverMetaAct *work.Action
if cfg.BuildCoverPkg != nil {
- match := make([]func(*load.Package) bool, len(cfg.BuildCoverPkg))
+ match := make([]func(*modload.State, *load.Package) bool, len(cfg.BuildCoverPkg))
for i := range cfg.BuildCoverPkg {
- match[i] = load.MatchPackage(modload.LoaderState, cfg.BuildCoverPkg[i], base.Cwd())
+ match[i] = load.MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
}
// Select for coverage all dependencies matching the -coverpkg
// at shlibpath. For the native toolchain this list is stored, newline separated, in
// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
// .go_export section.
-func readpkglist(loaderstate *modload.State, shlibpath string) (pkgs []*load.Package) {
+func readpkglist(s *modload.State, shlibpath string) (pkgs []*load.Package) {
var stk load.ImportStack
if cfg.BuildToolchainName == "gccgo" {
f, err := elf.Open(shlibpath)
for _, line := range bytes.Split(data, []byte{'\n'}) {
if path, found := bytes.CutPrefix(line, pkgpath); found {
path = bytes.TrimSuffix(path, []byte{';'})
- pkgs = append(pkgs, load.LoadPackageWithFlags(loaderstate, string(path), base.Cwd(), &stk, nil, 0))
+ pkgs = append(pkgs, load.LoadPackageWithFlags(s, string(path), base.Cwd(), &stk, nil, 0))
}
}
} else {
scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
for scanner.Scan() {
t := scanner.Text()
- pkgs = append(pkgs, load.LoadPackageWithFlags(loaderstate, t, base.Cwd(), &stk, nil, 0))
+ pkgs = append(pkgs, load.LoadPackageWithFlags(s, t, base.Cwd(), &stk, nil, 0))
}
}
return
}
// AutoAction returns the "right" action for go build or go install of p.
-func (b *Builder) AutoAction(loaderstate *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
+func (b *Builder) AutoAction(s *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
if p.Name == "main" {
- return b.LinkAction(loaderstate, mode, depMode, p)
+ return b.LinkAction(s, mode, depMode, p)
}
return b.CompileAction(mode, depMode, p)
}
// It depends on the action for compiling p.
// If the caller may be causing p to be installed, it is up to the caller
// to make sure that the install depends on (runs after) vet.
-func (b *Builder) VetAction(loaderstate *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
- a := b.vetAction(loaderstate, mode, depMode, p)
+func (b *Builder) VetAction(s *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
+ a := b.vetAction(s, mode, depMode, p)
a.VetxOnly = false
return a
}
-func (b *Builder) vetAction(loaderstate *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
+func (b *Builder) vetAction(s *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
// Construct vet action.
a := b.cacheAction("vet", p, func() *Action {
a1 := b.CompileAction(mode|ModeVetOnly, depMode, p)
deps = []*Action{a1}
}
for _, p1 := range p.Internal.Imports {
- deps = append(deps, b.vetAction(loaderstate, mode, depMode, p1))
+ deps = append(deps, b.vetAction(s, mode, depMode, p1))
}
a := &Action{
// LinkAction returns the action for linking p into an executable
// and possibly installing the result (according to mode).
// depMode is the action (build or install) to use when compiling dependencies.
-func (b *Builder) LinkAction(loaderstate *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
+func (b *Builder) LinkAction(s *modload.State, mode, depMode BuildMode, p *load.Package) *Action {
// Construct link action.
a := b.cacheAction("link", p, func() *Action {
a := &Action{
}
a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
a.built = a.Target
- b.addTransitiveLinkDeps(loaderstate, a, a1, "")
+ b.addTransitiveLinkDeps(s, a, a1, "")
// Sequence the build of the main package (a1) strictly after the build
// of all other dependencies that go into the link. It is likely to be after
// makes sure those are present in a.Deps.
// If shlib is non-empty, then a corresponds to the build and installation of shlib,
// so any rebuild of shlib should not be added as a dependency.
-func (b *Builder) addTransitiveLinkDeps(loaderstate *modload.State, a, a1 *Action, shlib string) {
+func (b *Builder) addTransitiveLinkDeps(s *modload.State, a, a1 *Action, shlib string) {
// Expand Deps to include all built packages, for the linker.
// Use breadth-first search to find rebuilt-for-test packages
// before the standard ones.
// we'll end up building an overall library or executable that depends at runtime
// on other libraries that are out-of-date, which is clearly not good either.
// We call it ModeBuggyInstall to make clear that this is not right.
- a.Deps = append(a.Deps, b.linkSharedAction(loaderstate, ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
+ a.Deps = append(a.Deps, b.linkSharedAction(s, ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
}
}
}
// buildmodeShared takes the "go build" action a1 into the building of a shared library of a1.Deps.
// That is, the input a1 represents "go build pkgs" and the result represents "go build -buildmode=shared pkgs".
-func (b *Builder) buildmodeShared(loaderstate *modload.State, mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action {
+func (b *Builder) buildmodeShared(s *modload.State, mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action {
name, err := libname(args, pkgs)
if err != nil {
base.Fatalf("%v", err)
}
- return b.linkSharedAction(loaderstate, mode, depMode, name, a1)
+ return b.linkSharedAction(s, mode, depMode, name, a1)
}
// linkSharedAction takes a grouping action a1 corresponding to a list of built packages
// and returns an action that links them together into a shared library with the name shlib.
// If a1 is nil, shlib should be an absolute path to an existing shared library,
// and then linkSharedAction reads that library to find out the package list.
-func (b *Builder) linkSharedAction(loaderstate *modload.State, mode, depMode BuildMode, shlib string, a1 *Action) *Action {
+func (b *Builder) linkSharedAction(s *modload.State, mode, depMode BuildMode, shlib string, a1 *Action) *Action {
fullShlib := shlib
shlib = filepath.Base(shlib)
a := b.cacheAction("build-shlib "+shlib, nil, func() *Action {
if a1 == nil {
// TODO(rsc): Need to find some other place to store config,
// not in pkg directory. See golang.org/issue/22196.
- pkgs := readpkglist(loaderstate, fullShlib)
+ pkgs := readpkglist(s, fullShlib)
a1 = &Action{
Mode: "shlib packages",
}
// we let them use the flags specified for the command-line arguments.
p := &load.Package{}
p.Internal.CmdlinePkg = true
- p.Internal.Ldflags = load.BuildLdflags.For(p)
- p.Internal.Gccgoflags = load.BuildGccgoflags.For(p)
+ p.Internal.Ldflags = load.BuildLdflags.For(s, p)
+ p.Internal.Gccgoflags = load.BuildGccgoflags.For(s, p)
// Add implicit dependencies to pkgs list.
// Currently buildmode=shared forces external linking mode, and
}
}
var stk load.ImportStack
- p := load.LoadPackageWithFlags(loaderstate, pkg, base.Cwd(), &stk, nil, 0)
+ p := load.LoadPackageWithFlags(s, pkg, base.Cwd(), &stk, nil, 0)
if p.Error != nil {
base.Fatalf("load %s: %v", pkg, p.Error)
}
// The linker step still needs all the usual linker deps.
// (For example, the linker always opens runtime.a.)
- ldDeps, err := load.LinkerDeps(nil)
+ ldDeps, err := load.LinkerDeps(s, nil)
if err != nil {
base.Error(err)
}
add(a, dep, true)
}
}
- b.addTransitiveLinkDeps(loaderstate, a, a1, shlib)
+ b.addTransitiveLinkDeps(s, a, a1, shlib)
return a
})