Given all those considerations, the current straightforward if obscure
approach seems OKish to me.
But it does raise the question in my mind as to whether the
go/packages API should be seen as a transparent layer on top of the go
tool, or as a general way to specify the inspection of Go code without
regard to implementation tool.
> The go tool provides a number of other knobs to specify the configuration that users would might to pass through. These include the environment variables GOROOT, GOFLAGS, and GOMOD; and the flags -race, -msan, -gcflags -ldflags, and -mod.
I don't really understand how most of those flags would be useful to
pass to go/packages. Most of them relate to runtime behaviour, not to
compile-time information, and AFAICS the go/packages API does not
provide any runtime behaviour.
For example, why would it be useful to pass the -race flag other than
to set the race-detector build tag? Why -ldflags when we're not doing
any linking?
ISTM that the old go/build behaviour (build.Config.BuildFlags) was OK
here. I suspect that hardly anyone used build.Config.BuildFlags, and
even though there might technically be some redundancy there, if you
mess with BuildFlags, you need to know what you're doing.
FWIW in a fork of go/build that I did for my godeps tool
(
https://godoc.org/github.com/rogpeppe/godeps/build), I found the
go/build approach insufficient, as I specifically needed to include
dependencies for all architectures.
I added a MatchTag field to Context:
type Context {
// ... other fields
// MatchTag, if specified, is called to determine whether a given
// tag should be considered to match for the purposes of importing.
// If neg is false, it should report whether the tag matches,
// otherwise it should report whether the tag does not match.
// A MatchTag that always returns true is equivalent to
// specifying UseAllFiles=true.
//
// If MatchTag is nil, Context.DefaultMatchTag will be called to
// to decide if a tag matches.
MatchTag func(tag string, neg bool) bool
// The build and release tags specify build constraints
// that should be considered satisfied when processing +build lines.
// Clients creating a new context may customize BuildTags, which
// defaults to empty, but it is usually an error to customize
ReleaseTags,
// which defaults to the list of Go releases the current
release is compatible with.
// In addition to the BuildTags and ReleaseTags, build constraints
// consider the values of GOARCH and GOOS as satisfied tags.
//
// Both these fields are considered only by DefaultMatchTag and
// will be ignored if MatchTag is non-nil.
BuildTags []string
ReleaseTags []string
}
Then the godeps tool does:
ctx.MatchTag = func(tag string, neg bool) bool {
if build.KnownOS(tag) || build.KnownArch(tag) {
return true
}
// Fall back to default settings for all other tags.
return ctx.DefaultMatchTag(tag) != neg
}
to select all OS's and architectures, but exclude other tags such as
"js" and "ignore", which was the best general heuristic I came up with
for generating plausible dependency graphs.
I suspect that many possible clients of go/packages might want
something similar. It often doesn't matter whether a program compiles,
just that all the source files that the tool cares about are held in
the tree.
The requirements are quite different for a use such as godef, which
doesn't work if unless consider one set of valid tags at a time (it
would actually be really nice to provide the set of possible results
when different OSs, architecture or other tags apply, but that might
be computationally quite expensive).
On 25 September 2018 at 20:23, 'Bryan C. Mills' via golang-tools
>
https://groups.google.com/d/msgid/golang-tools/CAKWVi_S7R7-TK%2BoPsRwqY-_sCZXaq1nEHe6NQVyRm2pwibi8Wg%40mail.gmail.com.