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:
Suzy Mueller 2018-07-20 14:24:40 -04:00
Родитель 9dbe528bbb
Коммит 8cc4e8a6f4
5 изменённых файлов: 92 добавлений и 22 удалений

Просмотреть файл

@ -214,9 +214,6 @@ application, but not by the metadata query, so, for example:
Questions & Tasks
- Add this pass-through option for the underlying query tool:
Flags []string
- Add GOARCH/GOOS?
They are not portable concepts, but could be made portable.
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.
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
malformed patterns, existing and non-existent packages, succesful and
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
}
buf, err := golist(cfg, append([]string{"list", "-e", "-json", "--"}, deps...))
buf, err := golist(cfg, golistargs_fallback(cfg, deps))
if err != nil {
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.
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 {
return nil, nil, err
}
@ -146,3 +146,11 @@ func getDeps(cfg *rawConfig, words ...string) (originalSet map[string]*jsonPacka
}
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
// 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.
// It must be safe to call Error simultaneously from multiple goroutines.
// 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
// nonexistent testmain file in GoFiles. Test that we handle this
// gracefully.
// - test more Flags.
//
// TypeCheck & WholeProgram modes:
// - Fset may be user-supplied or not.
@ -269,7 +270,7 @@ func imports(p *packages.Package) []string {
return keys
}
func TestOptionsDir(t *testing.T) {
func TestConfigDir(t *testing.T) {
tmp, cleanup := makeTree(t, map[string]string{
"src/a/a.go": `package a; const Name = "a" `,
"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 {
mu sync.Mutex
errors []error

Просмотреть файл

@ -51,22 +51,24 @@ type rawPackage struct {
// rawConfig specifies details about what raw package information is needed
// and how the underlying build tool should load package data.
type rawConfig struct {
Context context.Context
Dir string
Env []string
Export bool
Tests bool
Deps bool
Context context.Context
Dir string
Env []string
ExtraFlags []string
Export bool
Tests bool
Deps bool
}
func newRawConfig(cfg *Config) *rawConfig {
rawCfg := &rawConfig{
Context: cfg.Context,
Dir: cfg.Dir,
Env: cfg.Env,
Export: cfg.Mode > LoadImports && cfg.Mode < LoadAllSyntax,
Tests: cfg.Tests,
Deps: cfg.Mode >= LoadImports,
Context: cfg.Context,
Dir: cfg.Dir,
Env: cfg.Env,
ExtraFlags: cfg.Flags,
Export: cfg.Mode > LoadImports && cfg.Mode < LoadAllSyntax,
Tests: cfg.Tests,
Deps: cfg.Mode >= LoadImports,
}
if rawCfg.Env == nil {
rawCfg.Env = os.Environ()
@ -75,9 +77,11 @@ func newRawConfig(cfg *Config) *rawConfig {
}
func (cfg *rawConfig) Flags() []string {
return []string{
return append([]string{
fmt.Sprintf("-test=%t", cfg.Tests),
fmt.Sprintf("-export=%t", cfg.Export),
fmt.Sprintf("-deps=%t", cfg.Deps),
}
},
cfg.ExtraFlags...,
)
}