go/packages: add Flags to Config
Add the Flags field to the Config struct in packages to provide a way for users to pass along additional information to the underlying query tool. Since users that need Flags will already know something about the build system they are using (and flags will vary depending on the underlying build system), they can pass through the flags that they need for that build system. For example, build tags should be passed through using the Flags field in go build, using "-tags=". Change-Id: Ia65bf0d003db2f6d9aaad6cd09c602f4bc5bf3e3 Reviewed-on: https://go-review.googlesource.com/125302 Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
9dbe528bbb
commit
8cc4e8a6f4
|
@ -214,9 +214,6 @@ application, but not by the metadata query, so, for example:
|
||||||
|
|
||||||
Questions & Tasks
|
Questions & Tasks
|
||||||
|
|
||||||
- Add this pass-through option for the underlying query tool:
|
|
||||||
Flags []string
|
|
||||||
|
|
||||||
- Add GOARCH/GOOS?
|
- Add GOARCH/GOOS?
|
||||||
They are not portable concepts, but could be made portable.
|
They are not portable concepts, but could be made portable.
|
||||||
Our goal has been to allow users to express themselves using the conventions
|
Our goal has been to allow users to express themselves using the conventions
|
||||||
|
@ -230,8 +227,6 @@ Questions & Tasks
|
||||||
However, this approach is low-level, unwieldy, and non-portable.
|
However, this approach is low-level, unwieldy, and non-portable.
|
||||||
GOOS and GOARCH seem important enough to warrant a dedicated option.
|
GOOS and GOARCH seem important enough to warrant a dedicated option.
|
||||||
|
|
||||||
- Build tags: where do they fit in? How does Bazel/Blaze handle them?
|
|
||||||
|
|
||||||
- How should we handle partial failures such as a mixture of good and
|
- How should we handle partial failures such as a mixture of good and
|
||||||
malformed patterns, existing and non-existent packages, succesful and
|
malformed patterns, existing and non-existent packages, succesful and
|
||||||
failed builds, import failures, import cycles, and so on, in a call to
|
failed builds, import failures, import cycles, and so on, in a call to
|
||||||
|
|
|
@ -96,7 +96,7 @@ func golistPackagesFallback(cfg *rawConfig, words ...string) ([]*rawPackage, err
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := golist(cfg, append([]string{"list", "-e", "-json", "--"}, deps...))
|
buf, err := golist(cfg, golistargs_fallback(cfg, deps))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ func golistPackagesFallback(cfg *rawConfig, words ...string) ([]*rawPackage, err
|
||||||
|
|
||||||
// getDeps runs an initial go list to determine all the dependency packages.
|
// getDeps runs an initial go list to determine all the dependency packages.
|
||||||
func getDeps(cfg *rawConfig, words ...string) (originalSet map[string]*jsonPackage, deps []string, err error) {
|
func getDeps(cfg *rawConfig, words ...string) (originalSet map[string]*jsonPackage, deps []string, err error) {
|
||||||
buf, err := golist(cfg, append([]string{"list", "-e", "-json", "--"}, words...))
|
buf, err := golist(cfg, golistargs_fallback(cfg, words))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -146,3 +146,11 @@ func getDeps(cfg *rawConfig, words ...string) (originalSet map[string]*jsonPacka
|
||||||
}
|
}
|
||||||
return originalSet, deps, nil
|
return originalSet, deps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func golistargs_fallback(cfg *rawConfig, words []string) []string {
|
||||||
|
fullargs := []string{"list", "-e", "-json"}
|
||||||
|
fullargs = append(fullargs, cfg.ExtraFlags...)
|
||||||
|
fullargs = append(fullargs, "--")
|
||||||
|
fullargs = append(fullargs, words...)
|
||||||
|
return fullargs
|
||||||
|
}
|
||||||
|
|
|
@ -78,6 +78,10 @@ type Config struct {
|
||||||
//
|
//
|
||||||
Env []string
|
Env []string
|
||||||
|
|
||||||
|
// Flags is a list of command-line flags to be passed through to
|
||||||
|
// the underlying query tool.
|
||||||
|
Flags []string
|
||||||
|
|
||||||
// Error is called for each error encountered during package loading.
|
// Error is called for each error encountered during package loading.
|
||||||
// It must be safe to call Error simultaneously from multiple goroutines.
|
// It must be safe to call Error simultaneously from multiple goroutines.
|
||||||
// In addition to calling Error, the loader will record each error
|
// In addition to calling Error, the loader will record each error
|
||||||
|
|
|
@ -37,6 +37,7 @@ var usesOldGolist = false
|
||||||
// import error) will result in a JSON blob with no name and a
|
// import error) will result in a JSON blob with no name and a
|
||||||
// nonexistent testmain file in GoFiles. Test that we handle this
|
// nonexistent testmain file in GoFiles. Test that we handle this
|
||||||
// gracefully.
|
// gracefully.
|
||||||
|
// - test more Flags.
|
||||||
//
|
//
|
||||||
// TypeCheck & WholeProgram modes:
|
// TypeCheck & WholeProgram modes:
|
||||||
// - Fset may be user-supplied or not.
|
// - Fset may be user-supplied or not.
|
||||||
|
@ -269,7 +270,7 @@ func imports(p *packages.Package) []string {
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOptionsDir(t *testing.T) {
|
func TestConfigDir(t *testing.T) {
|
||||||
tmp, cleanup := makeTree(t, map[string]string{
|
tmp, cleanup := makeTree(t, map[string]string{
|
||||||
"src/a/a.go": `package a; const Name = "a" `,
|
"src/a/a.go": `package a; const Name = "a" `,
|
||||||
"src/a/b/b.go": `package b; const Name = "a/b"`,
|
"src/a/b/b.go": `package b; const Name = "a/b"`,
|
||||||
|
@ -316,6 +317,64 @@ func TestOptionsDir(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigFlags(t *testing.T) {
|
||||||
|
// Test satisfying +build line tags, with -tags flag.
|
||||||
|
tmp, cleanup := makeTree(t, map[string]string{
|
||||||
|
// package a
|
||||||
|
"src/a/a.go": `package a; import _ "a/b"`,
|
||||||
|
"src/a/b.go": `// +build tag
|
||||||
|
|
||||||
|
package a`,
|
||||||
|
"src/a/c.go": `// +build tag tag2
|
||||||
|
|
||||||
|
package a`,
|
||||||
|
"src/a/d.go": `// +build tag,tag2
|
||||||
|
|
||||||
|
package a`,
|
||||||
|
// package a/b
|
||||||
|
"src/a/b/a.go": `package b`,
|
||||||
|
"src/a/b/b.go": `// +build tag
|
||||||
|
|
||||||
|
package b`,
|
||||||
|
})
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
for _, test := range []struct {
|
||||||
|
pattern string
|
||||||
|
tags []string
|
||||||
|
wantSrcs string
|
||||||
|
wantImportSrcs map[string]string
|
||||||
|
}{
|
||||||
|
{`a`, []string{}, "a.go", map[string]string{"a/b": "a.go"}},
|
||||||
|
{`a`, []string{`-tags=tag`}, "a.go b.go c.go", map[string]string{"a/b": "a.go b.go"}},
|
||||||
|
{`a`, []string{`-tags=tag2`}, "a.go c.go", map[string]string{"a/b": "a.go"}},
|
||||||
|
{`a`, []string{`-tags=tag tag2`}, "a.go b.go c.go d.go", map[string]string{"a/b": "a.go b.go"}},
|
||||||
|
} {
|
||||||
|
cfg := &packages.Config{
|
||||||
|
Mode: packages.LoadFiles,
|
||||||
|
Flags: test.tags,
|
||||||
|
Env: append(os.Environ(), "GOPATH="+tmp),
|
||||||
|
}
|
||||||
|
|
||||||
|
initial, err := packages.Load(cfg, test.pattern)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(initial) != 1 {
|
||||||
|
t.Errorf("test tags %v: pattern %s, expected 1 package, got %d packages.", test.tags, test.pattern, len(initial))
|
||||||
|
}
|
||||||
|
pkg := initial[0]
|
||||||
|
if srcs := strings.Join(srcs(pkg), " "); srcs != test.wantSrcs {
|
||||||
|
t.Errorf("test tags %v: srcs of package %s = [%s], want [%s]", test.tags, test.pattern, srcs, test.wantSrcs)
|
||||||
|
}
|
||||||
|
for path, ipkg := range pkg.Imports {
|
||||||
|
if srcs := strings.Join(srcs(ipkg), " "); srcs != test.wantImportSrcs[path] {
|
||||||
|
t.Errorf("build tags %v: srcs of imported package %s = [%s], want [%s]", test.tags, path, srcs, test.wantImportSrcs[path])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type errCollector struct {
|
type errCollector struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
errors []error
|
errors []error
|
||||||
|
|
|
@ -54,6 +54,7 @@ type rawConfig struct {
|
||||||
Context context.Context
|
Context context.Context
|
||||||
Dir string
|
Dir string
|
||||||
Env []string
|
Env []string
|
||||||
|
ExtraFlags []string
|
||||||
Export bool
|
Export bool
|
||||||
Tests bool
|
Tests bool
|
||||||
Deps bool
|
Deps bool
|
||||||
|
@ -64,6 +65,7 @@ func newRawConfig(cfg *Config) *rawConfig {
|
||||||
Context: cfg.Context,
|
Context: cfg.Context,
|
||||||
Dir: cfg.Dir,
|
Dir: cfg.Dir,
|
||||||
Env: cfg.Env,
|
Env: cfg.Env,
|
||||||
|
ExtraFlags: cfg.Flags,
|
||||||
Export: cfg.Mode > LoadImports && cfg.Mode < LoadAllSyntax,
|
Export: cfg.Mode > LoadImports && cfg.Mode < LoadAllSyntax,
|
||||||
Tests: cfg.Tests,
|
Tests: cfg.Tests,
|
||||||
Deps: cfg.Mode >= LoadImports,
|
Deps: cfg.Mode >= LoadImports,
|
||||||
|
@ -75,9 +77,11 @@ func newRawConfig(cfg *Config) *rawConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *rawConfig) Flags() []string {
|
func (cfg *rawConfig) Flags() []string {
|
||||||
return []string{
|
return append([]string{
|
||||||
fmt.Sprintf("-test=%t", cfg.Tests),
|
fmt.Sprintf("-test=%t", cfg.Tests),
|
||||||
fmt.Sprintf("-export=%t", cfg.Export),
|
fmt.Sprintf("-export=%t", cfg.Export),
|
||||||
fmt.Sprintf("-deps=%t", cfg.Deps),
|
fmt.Sprintf("-deps=%t", cfg.Deps),
|
||||||
}
|
},
|
||||||
|
cfg.ExtraFlags...,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue