-
-
Notifications
You must be signed in to change notification settings - Fork 661
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
Add go_cross_binary
rule for cross-compilation.
#3261
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
4c1d00c
to
b9f5ead
Compare
go/private/rules/cross.bzl
Outdated
old_default_info = ctx.attr.target[DefaultInfo] | ||
old_executable = old_default_info.files_to_run.executable | ||
if not old_executable: | ||
fail('target must have executable') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A go_binary
doesn't necessarily have executable
set, e.g. when it is build with linkmode
c-shared
.
If there is no executable, you can just forward all providers unchanged - no need for the symlink trick.
Could you also add a test verifying that we don't break non-standard linkmode
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have ideas on how to switch between a executable and non executable version of go_cross
. I see how go_binary
does it in wrappers.bzl. However, it seems to me like there’s no way for a go_cross_wrapper
macro to access the attributes of the go_binary
specified by the target
attribute. I could use native.existing_rule
but as far as I can tell that would only work if the rule the target
Label refers to is in the same package as the go_cross
rule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the diff to have a go_cross
wrapper macro that tries to find the target in the local package, but if it fails it suggests that the user explicitly call go_cross_executable
or go_cross_non_executable
. This feels a little gross to me, so let me know if you have a better suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for trying this out. It also feels rather invasive to me, so I would prefer a different solution.
Simple idea first: How common is it for go_cross
targets to be bazel run
? With platform
set, it would be relatively unlikely that the target platform matches host.
Next simplest idea: Unconditionally mark the rule as executable, but write and advertise a bash/bat script or simple Go binary that prints an error message when executed in case the link mode doesn't provide you with an actual executable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since one can specify a go_cross
rule without a platform and with just an sdk_version
, I decided to go for the second option. This way users can still bazel run
a go_cross
rule that just changes the sdk version.
go/private/rules/cross.bzl
Outdated
|
||
new_default_info = DefaultInfo( | ||
files = depset([new_executable]), | ||
runfiles = old_default_info.default_runfiles, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For better or worse, you should probably copy this ugly workaround here: https://github.com/bazelbuild/rules_go/blob/47676dfc37a012c109e036b551c07a7e2da3d68b/go/private/rules/binary.bzl#L133
go/private/rules/cross.bzl
Outdated
""", | ||
), | ||
"sdk_version": attr.string( | ||
doc = """GoSDK version to transition the given target to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doc = """GoSDK version to transition the given target to. | |
doc = """Go SDK version to transition the given target to. |
go/private/rules/cross.bzl
Outdated
"implementation": _go_cross_impl, | ||
"attrs": { | ||
"target": attr.label( | ||
doc = """Go binary to transition to the given platform and/or sdk_version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to use providers
to limit the rule to Go targets.
go/private/rules/cross.bzl
Outdated
), | ||
}, | ||
"cfg": go_cross_transition, | ||
"doc": """ """, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing?
go/private/rules/cross.bzl
Outdated
new_executable = ctx.actions.declare_file(ctx.attr.name) | ||
ctx.actions.symlink(output=new_executable, target_file=old_executable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im a bit confused by this as it reads as:
- declare a new binary executable file
- the new binary executable file is a symlink to the old executable
If you don't mind, I would love to get 1-2 line of comments on top of this explaining what's happening. 🙏
54f8c9e
to
ea53726
Compare
3dba311
to
dbae7c9
Compare
go/private/rules/cross.bzl
Outdated
# the underlying `go_binary` target is executable. | ||
error_script = _error_script(ctx) | ||
|
||
# See the implementaion of `go_binary` for an explanation of the need for default vs data runfiles here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# See the implementaion of `go_binary` for an explanation of the need for default vs data runfiles here. | |
# See the implementation of `go_binary` for an explanation of the need for default vs data runfiles here. |
- Adds a `go_cross` rule that wraps a `go_binary` to generate a cross-compiled version of the binary. - Supports compiling for a different platform, and/or a different golang SDK version. - Adds docs for the new `go_cross` rule. - Adds testing in `tests/core/cross` for the new `go_cross` rule. Signed-off-by: James Bartlett <[email protected]>
@achew22 This generally looks good to me. Are you also fine with the new API? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One really dumb high level question. Is go_cross
always going to wrap a go_binary
or can it wrap a go_test
(or other)? If it's really only ever intended to be used to wrap a go_binary
what would we think about calling it go_cross_binary
?
Other than that question, this looks more than good. Thanks so much for putting in so much hard work @JamesMBartlett! |
Does this PR include a strategy for setting the sdk for a go_tests? I would really love to see that, especially for testing a specific sdk version. |
@joeljeske See bc60909 |
Thanks! From what I can tell, running a go_test with a different SDK version requires passing different bazel cli flags, right? Given that go_cross enables transitioning a go_binary the SDK using attrs, do you think we should enable a similar behavior for go_test? It seems like it would be important to be able to run tests under the non-default sdk in the same invocation as building binaries. It would be important that one could use go_cross with a target of a test, or if one could set sdk version for a go_test directly. What do you think? |
I love the excitement around this feature, but let's leave the feature requests for different conversations. This PR is useful as it stands right now, we're just haggling over naming. Besides, I think the bikeshed should be blue -- it's obviously the best color. |
Very good, thank you! |
Signed-off-by: James Bartlett <[email protected]>
dbae7c9
to
18992d5
Compare
go_cross
rule for cross-compilation.go_cross_binary
rule for cross-compilation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ❤️ this PR. Thanks @JamesMBartlett. Leaving it for @fmeum to take one last look since he has a knack for the subtle.
I changed the name to |
Signed-off-by: James Bartlett <[email protected]>
Thanks again for the great contribution, @JamesMBartlett! |
Just curious, what's the advantage of |
Passing the Also, correct me if I'm wrong @fmeum but I believe |
Thank you for the explanation, that makes sense. I encountered two issues with rules_go's support of the
|
EDIT: on second thought, I don't think the cgo constraints are actually added to the toolchain so I don't think the above is the issue you're running into |
What type of PR is this?
Feature
What does this PR do? Why is it needed?
This PR adds a
go_cross_binary
rule, that allows cross compilinggo_binary
generated targets to different platforms and/or different versions of the go SDK. See #3202 for the desired use case this supports. Implementation details:go_cross_binary
rule wraps ago_binary
and transitions on//command_line_option:platforms
and@io_bazel_rules_go//go/toolchain:sdk_version
based on theplatform
andsdk_version
attrs of thego_cross_binary
rule.tests/core/cross
that ensures thatgo_cross_binary
targets get built for the correct platform and sdk_version.Which issues(s) does this PR fix?
Fixes #3202
Other notes for review
This is the second of two diffs to support the use case in #3202. The first is here #3260. So once the other one lands this will not include the first commit.
Working with my employer at the moment to sign the CLA.