New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
heschik opened this Issue Jul 28, 2017 · 20 comments

Comments

Projects
None yet
9 participants
@heschik
Contributor

heschik commented Jul 28, 2017

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:

  • Gogland needs to know what language features to enable, such as vendoring and type aliases.
  • Delve needs to know details of the runtime, such as where to find the G pointer in a thread's registers, as well as what flags it can pass to the build system to generate good debug information.

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.

@heschik heschik added the Debugging label Jul 28, 2017

@dsnet

This comment has been minimized.

Show comment
Hide comment
@dsnet

dsnet Jul 28, 2017

Member

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.

Member

dsnet commented Jul 28, 2017

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.

@ianlancetaylor ianlancetaylor added this to the Go1.10 milestone Jul 28, 2017

@dsnet

This comment has been minimized.

Show comment
Hide comment
@dsnet

dsnet Jul 28, 2017

Member

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.

Member

dsnet commented Jul 28, 2017

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

This comment has been minimized.

Show comment
Hide comment
@dlsniper

dlsniper Jul 28, 2017

Contributor

The tags could be extracted from this file:

c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.9"}
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.

Contributor

dlsniper commented Jul 28, 2017

The tags could be extracted from this file:

c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.9"}
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

This comment has been minimized.

Show comment
Hide comment
@dsnet

dsnet Jul 28, 2017

Member

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.

Member

dsnet commented Jul 28, 2017

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

This comment has been minimized.

Show comment
Hide comment
@ianlancetaylor

ianlancetaylor Jul 28, 2017

Contributor

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.

Contributor

ianlancetaylor commented Jul 28, 2017

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

This comment has been minimized.

Show comment
Hide comment
@dlsniper

dlsniper Jul 28, 2017

Contributor

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.

Contributor

dlsniper commented Jul 28, 2017

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.

@heschik

This comment has been minimized.

Show comment
Hide comment
@heschik

heschik Jul 28, 2017

Contributor

@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.

Contributor

heschik commented Jul 28, 2017

@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

This comment has been minimized.

Show comment
Hide comment
@dlsniper

dlsniper Jul 28, 2017

Contributor

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 :)

Contributor

dlsniper commented Jul 28, 2017

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

This comment has been minimized.

Show comment
Hide comment
@ianlancetaylor

ianlancetaylor Jul 28, 2017

Contributor

See alternative proposal over at #21209.

Contributor

ianlancetaylor commented Jul 28, 2017

See alternative proposal over at #21209.

@odeke-em

This comment has been minimized.

Show comment
Hide comment
@odeke-em

odeke-em Jul 29, 2017

Member

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.

Member

odeke-em commented Jul 29, 2017

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.

@davecheney

This comment has been minimized.

Show comment
Hide comment
@davecheney

davecheney Jul 30, 2017

Contributor
Contributor

davecheney commented Jul 30, 2017

@aarzilli

This comment has been minimized.

Show comment
Hide comment
@aarzilli

aarzilli Jul 30, 2017

Contributor

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.

Contributor

aarzilli commented Jul 30, 2017

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.

@heschik

This comment has been minimized.

Show comment
Hide comment
@heschik

heschik Aug 1, 2017

Contributor

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

Contributor

heschik commented Aug 1, 2017

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

@rsc

This comment has been minimized.

Show comment
Hide comment
@rsc

rsc Oct 25, 2017

Contributor

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.

Contributor

rsc commented Oct 25, 2017

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.

@rsc rsc closed this Oct 25, 2017

@zolotov

This comment has been minimized.

Show comment
Hide comment
@zolotov

zolotov Oct 25, 2017

Contributor

@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.

Contributor

zolotov commented Oct 25, 2017

@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

This comment has been minimized.

Show comment
Hide comment
@rsc

rsc Oct 25, 2017

Contributor

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.

Contributor

rsc commented Oct 25, 2017

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

This comment has been minimized.

Show comment
Hide comment
@zolotov

zolotov Oct 25, 2017

Contributor

@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?

Contributor

zolotov commented Oct 25, 2017

@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

This comment has been minimized.

Show comment
Hide comment
@rsc

rsc Oct 25, 2017

Contributor

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.

Contributor

rsc commented Oct 25, 2017

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

This comment has been minimized.

Show comment
Hide comment
@zolotov

zolotov Oct 25, 2017

Contributor

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.

Contributor

zolotov commented Oct 25, 2017

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

This comment has been minimized.

Show comment
Hide comment
@rsc

rsc Oct 25, 2017

Contributor

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.

Contributor

rsc commented Oct 25, 2017

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment