-
Notifications
You must be signed in to change notification settings - Fork 770
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 abi3-py* features #1263
Add abi3-py* features #1263
Conversation
b517964
to
b94755c
Compare
Now I think that using the environmental variable is easier for users and tools... 🤔 |
Environment variables are definitely much easier to set. Also that way my build configuration won't be affected by thirdparty packages (any package I include in my dependencies could incorrectly enable these features). It's also kinda hard to understand how these features interact. If I set A single environment variable |
I believe that we need some place, likely in Cargo.toml or pyproject.toml, that specifies the minimum supported python version. pyo3 should have
I'd define it so that |
I could be wrong, but I don't think it's possible for pyo3's |
I think @konstin meant that maturin or some tools can read the metadata.
That makes sense. |
d3d2333
to
9895282
Compare
@@ -9,7 +9,10 @@ use std::{ | |||
str::FromStr, | |||
}; | |||
|
|||
const PY3_MIN_MINOR: u8 = 5; | |||
/// Minimum required Python version. | |||
const PY3_MIN_MINOR: u8 = 6; |
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.
Not related to this PR, but we dropped 3.5 support in #1250.
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.
This is cool, but I am quite concerned that changing the Python ABI dynamically (upwards) only works when building extension-module
on linux.
This kinda makes me worry that it shouldn't be set using features and an environment variable is better. That way maturin
and setuptools-rust
can set the environment variable when it's appropriate without breaking cargo test
etc.
/// Minimum required Python version. | ||
const PY3_MIN_MINOR: u8 = 6; | ||
/// Maximum Python version that can be used as minimum required Python version with abi3. | ||
const ABI3_MAX_MINOR: u8 = 9; |
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.
Binaries trying to link against a higher python version than the actual installed libpython
will fail because symbols will mismatch. So this new feature can only work for extension modules.
(And even worse, only extension modules on linux - because on windows they always link!)
This would mean that an extension module which uses the abi3-pyXY
features would further break cargo test
even after #1123 , and would also not be cross-platform.
build.rs
Outdated
} | ||
// Check any `abi3-py3*` feature is set. If not, use the interpreter version. | ||
(PY3_MIN_MINOR..=ABI3_MAX_MINOR) | ||
.find_map(|i| env::var_os(format!("CARGO_FEATURE_ABI3_PY3{}", i)).map(|_| i)) |
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:
.find_map(|i| env::var_os(format!("CARGO_FEATURE_ABI3_PY3{}", i)).map(|_| i)) | |
.find(|i| env::var_os(format!("CARGO_FEATURE_ABI3_PY3{}", i)).is_some()) |
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 catch 👍
|
👍 - maybe should we set the feature
Note that as well as windows, also tests will not link with I was hoping that after #1123 we would be able to run |
Sounds too restrictive to do so. |
Can this happen even with abi3? cc: @alex |
Yes, if you build an ABI3 wheel that targets 3.9 as the minimum version, it may fail when you try to load it against a 3.6 CPython. (Note that it'll only fail if you use a symbol that was recently added to the ABI3 ABI, if you target a higher minimu version but don't use any newer symbols, it'll probably just work.) |
Ah, it makes sense, thanks. Maybe we should prohibit setting a higher version. |
9895282
to
ca68209
Compare
ca68209
to
ae79b92
Compare
E.g., if you set `abi3-py36` feature, you can build `cp36-abi3-manylinux2020_x86_64.whl` using Python 3.8. | ||
|
||
To ensure ABI compatibility, we don't allow setting a minimum version higher than the system Python version. | ||
E.g., if you set `abi3-py38` and try to compile the crate with Python 3.8, it just fails. |
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.
E.g., if you set `abi3-py38` and try to compile the crate with Python 3.8, it just fails. | |
E.g., if you set `abi3-py39` and try to compile the crate with Python 3.8, it just fails. |
I think?
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.
Oops, nice catch, thanks.
I'm leaning towards setting this as a feature flag. |
ae79b92
to
93282e9
Compare
I think @konstin highlighted an interesting case where someone can in theory use this setup to build an abi3-py39 wheel without But I agree that in 99% of cases a higher version is a problem, because it means that tests (e.g) might unexpectedly fail to link. So I suggest that if we detect in I still want to push a concern with features vs environment-variables. Imagine we have a library
Now we want to use So the packaging tool makes a Python 3.6 wheel. However this is a bug: If instead maturin were to set an environment variable |
For now I don't think we need to support such a rare case. I'm willing to change the behavior if a user complains about, though.
I tried that and confirm that it just fails to compile (and noticed the bug of feature definitions...). I think env var is also good, but I also think that it would add additional works for tools. |
👍
I guess, but tools are great for doing lots of work for the user so I'm not sure that's such a big problem! 😄 Anyway I guess to learn more about this design the best way now might be to merge it? We can then try out the implementations in (We can give a little time between merging and releasing to experiment... or even release a pyo3 |
I finally got around to prototype what I had in mind: diff. The idea is that you always have to set a minimum version, as the code will have one implicitly anyway. This then makes it possible on maturin's side to build without checking for python interpreter (diff). This makes it possible to build for your minimum target version without the error prone process of finding python versions, with which I had a lot of trouble in maturin. It should also be faster since we avoid running python twice. (We could go even further and move pyo3's build script into a separate crate that is only built when abi3 is not used, but that's out of scope for now) |
@konstin |
Unfortunately not :/ Do you know why we do |
No, I don't explicitly understand the difference. Just found some notes but still investigating. |
If I recall (from experimentation last time I wondered this) I'll try and see if I can reproduce this in a minimal repro for rust upstream.
Unfortunately I think msvc linker needs to resolve all the symbols from somewhere at build time. Looks like there's an option we could try setting (similar to macos): https://docs.microsoft.com/en-us/cpp/build/reference/force-force-file-output?view=msvc-160 ... but it might just break stuff. |
Updated: I added |
FYI: How about releasing 0.13 after merging this PR? cc: @davidhewitt |
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'm happy to do the release. I made a ticket #1306 just to make sure we include everything we want in this release.
For this PR, I've made a final review with a few suggested improvements to finish it up. I'm still not totally sure if feature flags or an environment variable is better, but I think it's fine for us to merge this now and learn about it. It shouldn't be such an annoying breaking change if we decide to use an environment variable later.
@@ -820,7 +836,25 @@ fn check_target_architecture(interpreter_config: &InterpreterConfig) -> Result<( | |||
Ok(()) | |||
} | |||
|
|||
fn abi3_without_interpreter() -> Result<()> { |
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 think this is a good start, in the future I think we can replace this with something more flexible.
See this discussion with the PyOxidiser maintainer who suggested if PyOxidiser used PyO3 they would like the ability to set an environment variable with a path to a JSON file which configures PyO3: indygreg/PyOxidizer#324 (comment)
E.g., if you set `abi3-py38` and try to compile the crate with Python 3.6, it just fails. | ||
|
||
As an advanced feature, you can build PyO3 wheel without calling Python interpreter with | ||
the environment variable `PYO3_NO_INTERPRETER` set, but this only works on *NIX. |
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.
Maybe to match PYO3_PYTHON
, it's better to call this new environment variable PYO3_NO_HOST_PYTHON
?
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.
Sound nice 👍
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 decided to use a shorter PYO3_NO_PYTHON
.
Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
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.
LGTM! Just one remaining nit.
build.rs
Outdated
@@ -850,7 +850,7 @@ fn abi3_without_interpreter() -> Result<()> { | |||
|
|||
fn main() -> Result<()> { | |||
// If PYO3_NO_INTEPRETER is set with abi3, we can build PyO3 without calling Python (UNIX only). |
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.
// If PYO3_NO_INTEPRETER is set with abi3, we can build PyO3 without calling Python (UNIX only). | |
// If PYO3_NO_PYTHON is set with abi3, we can build PyO3 without calling Python (UNIX only). |
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!
2b3267a
to
4914372
Compare
Thank you for your kind reviews, now the docs are much better 😃 |
For #1195, but still needs some design enhancements.
This PR adds some feature flags that can be used to specify the minimum required version when building
abi3
wheel.E.g., you can build
cp36-abi3-manylinux1
wheel with Python3.8 if you useabi3-py36
feature.I still have some questions:
cp3-abi3
wheels? I think it's better for tools (maturin or setuptools-rust) to allow this renaming with some configuration. cc: @konstinFor folks who are not familiar with PEP425 (like me!), here's the link: https://www.python.org/dev/peps/pep-0425