-
Notifications
You must be signed in to change notification settings - Fork 554
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
feat: make variable substitution for py_wheel abi, python_tag args #1113
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,3 +54,20 @@ directory_writer = rule( | |
), | ||
}, | ||
) | ||
|
||
def _make_variable_tags_impl(ctx): # buildifier: disable=unused-variable | ||
rickeylev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# This example is contrived. In a real usage, this rule would | ||
# look at flags or dependencies to determine what values to use. | ||
# If all you're doing is setting constant values, then you can simply | ||
# set them in the py_wheel() call. | ||
vars = {} | ||
vars["ABI"] = "cp38" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have an example of what you're using it for yourself? I'm just thinking that a less contrived example would better demonstrate why you'd want to do this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above. |
||
vars["PYTHON_TAG"] = "cp38" | ||
vars["VERSION"] = "0.99.0" | ||
return [platform_common.TemplateVariableInfo(vars)] | ||
|
||
make_variable_tags = rule( | ||
attrs = {}, | ||
doc = """Make variable tags to pass to a py_wheel rule.""", | ||
implementation = _make_variable_tags_impl, | ||
) |
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.
nit: this seems like a strange example to me, would you actually expect users to write a custom rule and understand toolchains just to set these?
https://bazel.build/reference/be/make-variables#custom_variables
I think that's referring to us, so if users need a thing spelled
$(ABI)
I'd expect something in rules_python to provide it.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.
Yeah, I agree it'd be best if the rules just told us this directly and users didn't have to write a custom rule. That said...
We could factor out a helper rule so a user doesn't need to write something a custom rule and use TemplateVariableInfo themselves, e.g.:
But I'm not sure what value that really has -- it'd be easier to just set those values in the py_wheel() call. If you want to customize how it determines e.g. abi, then you're back to writing a custom rule.
Second, the more I learn about these tags, the more complicated it is to know the right value. We can get most of the way there for most users, though, I think.
PyInfo.uses_shared_libraries is probably the biggest indicator -- if there are no shared libraries, we can probably just set python_tag=py3, abi=none, platform=any as the defaults. This logic would have to live in py_wheel (more specifically, something that consumes the libraries to get that info).
If there are shared libraries, then it gets complicated.
For python tag, we need to use the major.minor python version. We can know this by look at the multi-python flags or the --python3_version flag.
For abi, we need the toolchain to tell us the abi value somehow. Normally this comes from sysconfig. A hack would be to call it in an action; this would work as long as host==target.
For platform tag, this one is complicated from what I'm told. I think a simple mapping of e.g. (linux, x86) -> "linux_x86_64" would go a long way (we even suggest such in the docs). I don't know how we'd know to use "manylinux", though -- from what I'm told, it's a specific docker image with specific versions of things used. It really sounds like it'd be modeled as a separate platform in Bazel-land with its own cc toolchain etc.
Some refs I found:
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 don't believe you can infer the abi/python_tag from the toolchain that works for all use cases. It depends on how and what you are packaging into the wheel.
For instance, we're using pybind11 to create bindings around c++ libraries. These bindings are major.minor locked since pybind11 uses features outside the stable C API. Build a wheel with python3.8 and you can't use it with python3.10. End result, we need to set
cp38
on wheels that package our python3.8 bindings.There is work going on to improve that state of affairs (e.g. python/cpython#93012), so at some point, we will need to use, e.g.
cp38
for older versions and perhapsabi3
when built with some later version of py3 where pybind11 can guarantee c python stability. In this case you have no way of being able to infer the correct abi tag from the toolchain without knowing what is going on with pybind11.Internally, we're using a custom rule to introspect the currently resolved toolchain to determine an
abi
tag that is appropriate for our pybind11 wheels. That then gets fed intopy_wheel
. With this pipeline, we can build python versions for multiple python toolchains without having to hardcode any toolchain information into the bazel BUILD files. You just specify your py3XY toolchain on the command line (via--extra-toolchains
) and the rest just works.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.
NB: It'd be super useful if python toolchains exposed their major.minor.patch version somehow.
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.
Aye, I think the non-shared library case could get automagic handling. Problems in the shared library cases.
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.
Nice!
Hm, yeah, the toolchains aren't enough -- we would need e.g. the pybind rules (or whatever extension-building rules) to also communicate their abi needs. Then something like py_wheel could look at it them to figure out what to use. Which may not always have a single answer, which is ok. Actually, I wonder if an aspect would help here...aight i'm just thinking out loud now.