cmd/go: accept main packages as dependencies in go.mod files #32504
Many Go programs today not only depend on other packages, but they depend on other programs themselves. In other words, a module (whether a program or a library), may depend on other
When Go Modules first came out, the same exact question came up here: #25922.
The answer was appropriate for Go 1.11 when Modules was still highly experimental, but it might be worth reconsidering when Go Modules becomes the official dependency manager for all Go code out there.
The reason being, the
Furthermore, a module should be able to depend on other Go code regardless of whether it's
It's also worth mentioning that other tools (such as https://github.com/myitcv/gobin) exist to make this workaround a little bit easier. But it's worth drawing a comparison of how other languages have an external binary for dependency management such as
I propose that Go provides first class support for modules that depend on
I suggest that the Go Modules system provides first class support for such programs by providing the following two functionalities:
The above two features would mean two changes to the Go toolchain:
Create a new block statment to separate
The reason for that is that when
Note that the module root for
If each go.mod file has its own version of a binary, then that must mean the Go workspace ($GOPATH/pkg or $GOPATH/bin) must be able to host multiple versions of the same binary.
More importantly, we should be able to have an explicit way to run a versioned binary such as:
go exec github.com/golang/protobuf/protoc-gen-go # or `go exec protoc-gen-go` if possible.
A quick hack would be to just have
However, sometimes we cannot execute a binary directly. For example,
This changes the behavior of
On the other hand, we should be able to distinguish a regular go-get, and go-install that is independent of the current directory's go.mod file. Maybe a user just wanted to install a binary that had nothing to do with the project they were in the CWD of. Therefore, we could include a new
One other solution for running a versioned binary is by simply allowing the
What this means is that if we run
Could you give some more detail on that? Generally we expect the output of
Similarly, putting the dependencies of tools in the
@bcmills here's an example: I start a new gRPC project and use
I make a
Now, I give this project to my coworker, and my coworker
In this process, there's no way to enforce what version of
What I'd love to see is that a Module can depend on a
How to enforce those "versioned binaries", is really up to everyone...but I'd love for a friendly and official way to do it because it's quite a common use case. My suggestion above is one of a few that I can think of.
That's a good point, but that's also the case with importing many
@marwan-at-work and I were exchanging some comments offline. This has come up on the golang-tools calls many times before, and @ianthehat has strong feelings on the direction in which all of this should head. My comments stem mainly from learnings from
I think you're after the
This topic has come up before in many different guises (incomplete list):
as well as being a regular-ish feature on the golang-tools calls/Slack.
So a key point is that the problem space also includes the "global"/system-wide tools. There need not be a single solution, rather just clarifying the wider scope.
My position (in the loosest sense) is heavily influenced by learnings from
With those high level goals in mind, is a rough list of more detailed requirements from my perspective. (Note "tool" is just the generic term I use for
The edit to refer to "discoverable" directories above is critical to allowing multiple versions of a tool to be installed on disk in the global setting, and to allow for variations in GOOS/GOARCH and build constraints for both global/local installs.
@rsc has, in the past, indicated that
For local tools, there is the question on whether to use the main module's
Alternative solutions to recording requirements in
The only point being this is an implementation detail to my mind, albeit it a significant/contentious one
Note, with the
Also to state the perhaps obvious point that the implementation detail behind the recording of main dependencies is orthogonal to the
Whilst, selfishly, I'm happily using
On a recent golang-tools call, @ianthehat made noises that
@ianthehat - is there any update on this point, or the discussion more generally?