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: should offer a way to abort compilation if a build tag constraint is not met #21673
Comments
It sounds like you already have a workable solution, albeit one that requires a small extra dependency. Since this bug report is against cmd/go, do you have a suggestion for how this could be done in the go tool? |
@ianlancetaylor Thank you for the quick reply. I noodled on that question a bit while working on the post, and I think there are three ideas that come to mind. I have two initial ideas that are very closely related, but only vary because I'm unsure which is more clear on what the behavior will be. I touched on briefly on the first idea in the blog post, which would be to add an // +build go1.9,abort In this case, if the This way you could also easily do this: // +build linux,amd64,abort darwin,amd64,abort Which would build successfully if this was That said I've baked my noodle on this approach a bit, and since writing the post last evening I've started to wonder if the The second thought I had, which I haven't confirmed is easy from a current code perspective, would be to have a marker at the end of a build tag to indicate that if it's not met we should fail the build: // +build go1.9:abort I'm not sure how I feel about this approach because I can't figure out how it'd work for build tags that we combine. A third approach, borrowing from Perl, would be to add a new keyword (e.g., |
Some notes:
|
@akavel Thank you for taking the time to reply. I think this problem is definitely complex, so I enjoy thinking about it more to see if there are other solutions. For your first point, you're absolutely right. I could reference the constant in those functions to make it fail to build. It's a great suggestion. 👍 I think there is one tradeoff still, and it's only that I still need to duplicate all of the functions that are referenced outside of that file. I was hoping to avoid that. Hmm. I think maybe the Would an example be that you want to abort if the build if it's not Linux or Windows? If you tried to put the abort flag in either of the files, would it fail the build? On Linux, I don't believe the content of the If you were using this mechanism I don't think you would be able to abort the build in either of those files, possibly because the OS is in the name. This would require a third file without an OS on the name. If we step back and assume the OS isn't on the file (i.e., we have a third file to control this abort logic), can we use I think the answer is no, we wouldn't. My current suggestion would fail to provide that because the comma separated tags (e.g., In other words, what if we treat the // if this isn't Go1.9+
// abort the build
// +build !go1.9,abort You could then also have: // if this isn't windows
// and this isn't linux
// abort the build
// +build !windows,!linux,abort You would absolutely have to put this in a third file, if you're going to have OS-specific files, but we could make that something expected and documented. |
As far as I can see @akavel 's suggestion addresses the core problem. |
With the release of
Go 1.9
, the monotonic time source withintime.Time
means we can now usetime.Time.Sub()
to keep track of how long things took (even across leap seconds). For me, this means the code that I had usinggo:linkname
to expose the monotonic time source can be removed from my project and be replaced withtime.Now()
.However, when removing my usage of this time source I realized that I had no easy way to enforce that consumers of my code build it against a Go runtime version that is safe for them. I can absolutely use build tags to to guard the functionality, but then the build fails because functions in that file are now undefined. The error the developer sees at build time indicates that some of my source code is missing, not that the Go runtime is too old.
If I do create a second file that has copies of the missing functions, that panic when invoked, the incompatibility isn't potentially discovered until runtime.
While I do talk about the runtime version in this example, I think this could be applied to every build tag offered by
go build
. This means that projects where the author has intentionally not targeted an architecture can have the build fail with a helpful error message. I may be making a wild assumption here, but it's possible this type of functionality may be helpful during theGo 1
=>Go 2
transition period too (assuming one will happen).To solve this problem in a concise way, I ended up writing a library that is released to the public domain that can help with this.[1] The downside is that it then requires you to add a small dependency to your project or copy the code in, which may not be deal depending on your needs.
I've also written a blog post[2] to document this problem, look at some of the solutions to the problem, and then provide an overview of the package I wrote. I'd be happy to add the blog post to the ExperienceReports wiki page but I'm not sure what the best title for the section would be. Should I use a section already there, or do you think I should create a new one with a name like
Runtime Compatibility Constraints
?[1] https://github.com/theckman/goconstraint
[2] https://medium.com/@theckman/version-constraints-and-go-c9309be15773
The text was updated successfully, but these errors were encountered: