golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.36k stars 17.71k forks source link

cmd/go: version information is not structured enough for use by developer tools #21207

Closed heschi closed 7 years ago

heschi commented 7 years ago

Developer tools need to know what version of Go is in use for a variety of reasons. Two examples that have come up very recently:

If you're using a released version, it's relatively straightforward to parse the output of go version: go version go1.8.3 linux/amd64 means you're running 1.8.3. But we also do release candidates, which say go1.8rc1, and then sometimes we build off dev tags and get something like go1.8.3.typealias. And then for even more fun, devel builds: go version devel +835dfef939 Wed Jul 26 13:29:59 2017 +0000 linux/amd64 which doesn't help at all.

I don't have a specific proposal, but there is a clear need for a structured way of determining at least the major/minor Go version in use, even for devel builds. More detailed information in some form could be valuable if, for example, we wanted Delve to be able to tell if a devel build contained a specific runtime change. That's probably overkill though.

dsnet commented 7 years ago

One possibility would be to put the release tags as a space-separated list printed by go env:

So perhaps:

$ go env
...
GOTAGS="go1.1 go1.2 go1.3 go1.4 go1.5 go1.6 go1.7 go1.8"

For special SDKs like App Engine, they would have the appengine tag in that list. This provides Gogland with the information they need to determine properties of the toolchain that they are working with.

dsnet commented 7 years ago

I was curious what ActiveGo does and their toolchain has the following version string:

ActiveGo 1803 [403309] provided by ActiveState Software, Inc.
Built Sun Jun 18 17:37:35 PDT 2017

go version go1.8.3 linux/amd64

Which, I'm guessing Gogland would also choke on.

dlsniper commented 7 years ago

The tags could be extracted from this file: https://github.com/golang/go/blob/835dfef939879b284d4c0f4e1726491f27e4f1ee/src/go/build/build.go#L295 but for example Delve would need to know that in the binary somehow.

As for the editors, for example, you might want to know if it's go 1.8.0 or go 1.8.3, as users of editors could then test different versions of Go and still be able to tell the difference between versions. Same goes for different beta / RC versions of go 1.9 for example.

Another case is when go tip might mean go 1.9 for the build tag which is based on the master branch and go tip of the debug branch that is also tracking go 1.9 and hence has the go 1.9 build tag.

dsnet commented 7 years ago

As for the editors, for example, you might want to know if it's go 1.8.0 or go 1.8.3, as users of editors could then test different versions of Go and still be able to tell the difference between versions. Same goes for different beta / RC versions of go 1.9 for example.

Just checking if the version string doesn't match is sufficient to tell if they are different versions, right? In terms of feature sets, is there a case where you want to distinguish between go1.8.0 and go1.8.3? Typically the point releases changes nothing other than minor bugs.

Thus, you could use the version string to tell if one version is exactly the same as another (or different). And use build tags to identify the set of core functionality the toolchain provides.

ianlancetaylor commented 7 years ago

While in theory 1.8.0 and 1.8.3 ought to be the same, in practice, who knows? If we are going to introduce this kind of mechanism, it should probably have a way to report minor versions as well.

dlsniper commented 7 years ago

is there a case where you want to distinguish between go1.8.0 and go1.8.3

One use-case is when users are using currently Go 1.8.0 in their production servers and are testing Go 1.8.3 for upgrade. At that point there would be two Go releases which have the same Go 1.8 label but the user wouldn't know which is which.

heschi commented 7 years ago

@dsnet Technically Gogland parses zversion.go, so probably wouldn't be confused by the ActiveState banner, but hopefully we can agree that that is not a well-structured API. Delve might get confused if their parsing logic is overly specific; I haven't looked.

@dlsniper I'm not proposing we change go version itself, and tools could still use that to display the most descriptive version information to humans. This proposal is intended for the tools themselves to make decisions on, and I wouldn't expect its output to be shown directly to users. So, for Gogland, I would expect the text in the GOROOT dropdown to show the output of "go version", perhaps lightly interpreted, but vendoring to be enabled based on this structured information.

Possibly I should file a separate bug to expose the build tags, since that has some intrinsic value of its own entirely separate from this discussion.

dlsniper commented 7 years ago

I'm not proposing we change go version itself

@heschik sorry I was not clear about it, I don't propose this either. Also, see @zolotov's comment here: https://youtrack.jetbrains.com/issue/GO-4203#comment=27-2340685

Hope it helps :)

ianlancetaylor commented 7 years ago

See alternative proposal over at #21209.

odeke-em commented 7 years ago

I interrupt this discussion to inform us that this issue is a duplicate of older issue https://github.com/golang/go/issues/11972 :) I'll mention that issue's author @griesemer so that he can chime in, as this issue seems to have more discussions going on.

davecheney commented 7 years ago

I think build tags are the better solution to this.

On 29 Jul 2017, at 16:47, Emmanuel T Odeke notifications@github.com wrote:

I interrupt this discussion to inform us that this issue is a duplicate of older issue #11972 :) I'll mention that issue's author @griesemer so that he can chime in, as this issue seems to have more discussions going on.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

aarzilli commented 7 years ago

As far as I am concerned this could be solved by just documenting the output format of go version and runtime.Version(). For delve the problem wasn't writing the parser, it was figuring out the syntax. And yes, delve will absolutely choke on ActiveGo version string because the version is at the end.

Proposal #21209 doesn't really help because it doesn't give the syntax used for tags, nor does it say where ActiveGo should put its banner.

Having a major.minor version for development build isn't as important, because there isn't almost any reason to support development version from before the latest major.minor release.

heschi commented 7 years ago

For better or worse, discussion seems to have moved to #21209.

rsc commented 7 years ago

The discussion on #21209 closed, and I think this one should close too. The examples in the original report are not something we should extract from the version strng. See the discussion on #21209 for more.

zolotov commented 7 years ago

@rsc sorry, I do not fully understand, where required information should be extracted from then?

The discussion on #21209 closed, and I think this one should close too.

I find it strange that discussion #21209 was closed in favor of #21207 and #21207 is closing now because #21209 is closed.

rsc commented 7 years ago

Over in #21209, Chris wrote:

It seems that the takeaways from this thread are to focus on providing either build tags (go1.9) or capabilities (type-aliases, plugins) statically to allow tools to reliably toggle features. Closing this and moving discussion there.

Sorry, I thought that these more specific requests had been filed separately, but perhaps not. Certainly the title here - more structured version information in the version string - is not going to happen.

I was going to add a way to expose the build tags just now, but I realized that they are already accessible. To get build tags, you can use:

 go list -f '{{context.ReleaseTags}} {{context.BuildTags}}' runtime

or any other template walking over context (see go help list), such as

go list -f '{{join (context.ReleaseTags) ","}}' runtime

The package does not matter; you just have to list one, and runtime is as good as any.

So my suggestion would be to use that to get build tags and use knowledge of when a particular feature was released to decide to use it.

zolotov commented 7 years ago

@rsc ReleaseTags will work for us, thank you. Although, as I mentioned in #21209 I'd prefer to get the same information in textual and easy to parse form, like in generated zversion.go. Is this possible to put more structured version information or release tags information there?

rsc commented 7 years ago

Isn't the output of the go list commands above textual and easy to parse? I don't think IDEs should assume they know how the location of specific Go source code - gccgo doesn't even need to have standard library source code present, for example. But querying the go command is something we can keep working indefinitely.

zolotov commented 7 years ago

Isn't the output of the go list commands above textual and easy to parse? I

It requires running an external binary. As I said in #21209, it's less predictable and harder to cache and to track changes. Also, after indexing IDE actually knows the values of almost all constants in Go sources, running external tool for it looks like a double work.

I don't think IDEs should assume they know how the location of specific Go source code

This is what IDEs do, they assume locations of specific source code. For example, for navigation to anything or to infer type of an expression they need the knowledge where builtin types/vars/function are located. Or, where template helper-functions are defined (text/template/funcs.go#builtins) to suggest them in templates. The same is for version.

gccgo doesn't even need to have standard library source code present, for example.

The IDE requires sources at the moment. If someday we'll implement resolution algorithm against binaries, I think we will return to this question and likely will have to run the binary. Until then I would appreciate if at least major version of GOROOT or ReleaseTags would be easier to access.

rsc commented 7 years ago

For release builds you can of course read $GOROOT/VERSION. But for development trees I think the only thing that will be reliable is to use go list.