Skip to content
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

proposal: build tag for detecting go modules usage #37995

Open
pjebs opened this issue Mar 22, 2020 · 12 comments
Open

proposal: build tag for detecting go modules usage #37995

pjebs opened this issue Mar 22, 2020 · 12 comments
Labels
Milestone

Comments

@pjebs
Copy link
Contributor

@pjebs pjebs commented Mar 22, 2020

It would be nice if there was a build tag for detecting if go modules is being used.

I have created a package: https://github.com/rocketlaunchr/dbq. I went out of my way to put v2 in a separate v2 directory so that it would be compatible with go module users and non-go module users. This is supposedly preferred practice.

For v2, I want to introduce a dependency (https://github.com/cenkalti/backoff) that is at v4 but did not use the separate directory approach.

For my package, in order to support Go Modules and non-modules users, I need to use a build tag so that I can use github.com/cenkalti/backoff/v4 for go modules users and gopkg.in/cenkalti/backoff.v4 for non-go modules users.

@gopherbot gopherbot added this to the Proposal milestone Mar 22, 2020
@gopherbot gopherbot added the Proposal label Mar 22, 2020
@pjebs pjebs changed the title proposal: build tag for go modules proposal: build tag for detecting go modules usage Mar 22, 2020
@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 22, 2020

@dmitshur
Copy link
Member

@dmitshur dmitshur commented Mar 22, 2020

For my package, in order to support Go Modules and non-modules users, I need to use a build tag so that I can use github.com/cenkalti/backoff/v4 for go modules users and gopkg.in/cenkalti/backoff.v4 for non-go modules users.

It may not be necessary to use a build tag to achieve compatibility for both modes because of "minimal module-awareness for legacy operation" that was implemented in commit d4e2128 and issue #25069. Are you familiar with that behavior?

/cc @jayconrod @bcmills @matloob

@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 22, 2020

So how do I achieve my aim? As it stands adding /v4 to imports prevents compilation when go modules is not enabled.

@dmitshur on a separate matter did you get my email from about a week ago?

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Mar 23, 2020

Minimal module compatibility lets code built in GOPATH mode stay compatible in this situation. The Modules wiki has more information about this.

If a package has a go.mod file in some parent directory within GOPATH, it should import github.com/cenkalti/backoff/v4 (as is required in module mode). If a package does not have a go.mod file, it should import github.com/cenkalti/backoff without the /v4 suffix, matching the directory structure.

The path gopkg.in/cenkalti/backoff.v4 should not be used in either case, even though it's possible to use in GOPATH mode. The module declares its name as github.com/cenkalti/backoff/v4. Referring to a package by multiple names can lead to migration problems, duplicate packages, and conflicts. They will not be de-duplicated.

@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 23, 2020

github.com/cenkalti/backoff default branch is set to v4. When in gopath mode does it use master which is quite old?

@bcmills
Copy link
Member

@bcmills bcmills commented Mar 23, 2020

Yes. If you want to support GOPATH-mode users with this particular dependency, probably the simplest approach is to use go mod vendor to generate (and check in) a vendor directory for your project.

GOPATH-mode users would then build your dependencies from your vendor directory instead of whatever is in their GOPATH/src.

@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 23, 2020

Is there a way to use this solution just for 1 dependency?

@bcmills
Copy link
Member

@bcmills bcmills commented Mar 23, 2020

I don't think so, no — but users who are sensitive to extra dependencies should generally be building in module mode anyway.

@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 23, 2020

In the blog post: https://blog.golang.org/v2-go-modules they recommend the separate directory approach. They mention the downsides are maintaining 2 separate codebases (this is a big downside I am already facing). They say the benefits are compatibility with GOPATH mode. They didn't mention the issue I just faced.

Is this still the recommend approach?

For my package, I'd love to abandon the separate directory approach since it looks like supporting GOPATH is not viable (and never was). It's possibly too late now to abandon it because I may have GOPATH users already pointing to the v2 directory.

@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 23, 2020

Also what's wrong with a build tag for detecting GO MODULES enabled?

@jayconrod
Copy link
Contributor

@jayconrod jayconrod commented Mar 23, 2020

When in gopath mode does it use master which is quite old?

In GOPATH mode, go get will download the default branch. That's set to v4 for this repo, so GOPATH users will get something pretty recent.

In the blog post: https://blog.golang.org/v2-go-modules they recommend the separate directory approach. They mention the downsides are maintaining 2 separate codebases (this is a big downside I am already facing). They say the benefits are compatibility with GOPATH mode. They didn't mention the issue I just faced.

If you have GOPATH users that need to refer to anything other than the latest version of the default branch, then using separate directories is recommended. For example, if you have the module example.com/mod, and you rewrite your API in example.com/mod/v2, GOPATH users of example.com/mod will be broken unless you have both versions on the default branch with v2 in a subdirectory.

I don't know enough about backoff to judge its compatibility with GOPATH. Since it's at major version v4 on the default branch, not in a subdirectory, it should be imported as github.com/cenkalti/backoff/v4 in projects with a go.mod file and as github.com/cenkalti/backoff in projects without a go.mod file.

As @bcmills mentioned, you may be able to check in a vendor directory to work around compatibility issues with GOPATH users so they get the correct version. As another alternative, you could create a branch named go1 with code for GOPATH users. In GOPATH mode, go get will pick that instead of the default branch if it's present (see go help gopath-get.

Also what's wrong with a build tag for detecting GO MODULES enabled?

We'd rather not add features if there's already a way to solve a problem. There are some options here, and we'd like to be sure none of those can work before pursuing something new.

@pjebs
Copy link
Contributor Author

@pjebs pjebs commented Mar 26, 2020

@jayconrod

In GOPATH mode, go get will download the default branch. That's set to v4 for this repo, so GOPATH users will get something pretty recent.

That doesn't seem to be the case. go get seems to get master instead of the default branch: v4. NOTE: I'm using Go1.12 so maybe it's changed. (I can't use Go1.14)

As @bcmills mentioned, you may be able to check in a vendor directory to work around compatibility issues with GOPATH users so they get the correct version. As another alternative, you could create a branch named go1 with code for GOPATH users. In GOPATH mode, go get will pick that instead of the default branch if it's present (see go help gopath-get.

This is not viable. It's already a nuisance maintaining a v1 and v2 directory. I can't maintain another branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.