add PythonABI and new builder structs for pyo3-build-config InterpreterConfig#5924
add PythonABI and new builder structs for pyo3-build-config InterpreterConfig#5924ngoldbaum wants to merge 41 commits into
Conversation
2e92e57 to
4f2177f
Compare
#3110) Towards #3064. This is purely refactoring, there should be no functional changes as a result of this. Currently the build metadata special-cases ABI3 builds or more generally assumes stable ABI builds and ABI3 builds are the same thing. With PEP 803 and the new abi3t ABI in Python 3.15, that is no longer the case. This replaces the old `ABI3Version` enum with a new struct combining two enums: ```rust /// struct describing ABI layout to use for build #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct StableAbi { /// The "kind" of stable ABI. Either abi3 or abi3t currently. pub kind: StableAbiKind, /// The minimum Python version to build for. pub version: StableAbiVersion, } /// Python version to use as the abi3/abi3t target. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum StableAbiVersion { /// Stable ABI wheels will have a minimum Python version matching the /// version of the current Python interpreter CurrentPython, /// Stable ABI wheels will have a fixed user-specified minimum Python /// version Version(u8, u8), } /// The "kind" of stable ABI. Either abi3 or abi3t currently. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum StableAbiKind { /// The original stable ABI, supporting Python 3.2 and up Abi3, } ``` `StableAbiVersion` is just the old `Abi3Version` enum renamed since the concept of a minimum supported version is shared by abi3t. I have [a branch](main...ngoldbaum:maturin:abi3t) that adds an `Abi3t` variant for `StableAbiKind`. My goal with this PR is to make reviewing the subsequent PR adding abi3t support easier. Also see PyO3/pyo3#5924 where I made a similar change in PyO3. Here in Maturin I needed different types but in principle I could make the two implementations use shared code. I'm not sure if that's actually useful for anything in practice. --------- Co-authored-by: messense <messense@icloud.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
davidhewitt
left a comment
There was a problem hiding this comment.
Thanks, some hazy thoughts here, not sure if I'm being helpful throwing these out there.
51ff27b to
dc5c1d1
Compare
Icxolu
left a comment
There was a problem hiding this comment.
I haven't worked too much inside the build code, so I'm not sure that I can help much here, but I gave this a brief read and left some comments.
I do like the builder pattern. I think it's nice to have a different type between the abi configuring phase and the usage phase (even tho it does not protect us from forgetting to configure something)
davidhewitt
left a comment
There was a problem hiding this comment.
I have taken a look through some parts, I think I have a couple of pieces that I'd like clarifying in this PR:
- I can't decide if we want to separate "host version" from target abi version. That seemed like it might help in #5960, but maybe it adds complexity for no practical benefit.
- I think it'd be helpful to introduce the possibility to configure for abi3t in this PR through a config file, even if the full end-to-end build with abi3t is not done here (we could maybe just halt the build if abi3t is selected for now). I think that'd make it easier to see the full end state possible states we're heading towards, plus help understand where "stable abi" vs "abi3 and abi3t" are the right names.
aea6287 to
e819b62
Compare
|
I just pushed a big commit that restores the I also added a new It ends up being an even bigger refactor! But I think we're getting close now. I also didn't end up adding abi3t yet because this got kinda big. I'm going to try rebasing #5807 on top of this next week and then I can add a stub abi3t implementation here. In the meantime, I'd very much appreciate feedback on the new approach. |
6931ee2 to
d1d5d13
Compare
|
@davidhewitt @Icxolu this is ready for another pass. |
|
@davidhewitt @Icxolu I think this is ready for another pass whenever you have some capacity. I'm also happy to try to minimize the diff more. Most of it is in the new |
Icxolu
left a comment
There was a problem hiding this comment.
I think this is moving in the right direction. I really like that we now clearly use target_abi as the source of truth for the emitted abi related cfgs. I left some thoughts below, nothing mandatory, just some ideas that crossed my mind while reading through this.
(I've haven't really looked through the many test changes, I assume that it's basically mechanical changes to use the builders)
| /// Gets the minimum supported Python version from PyO3 `abi3t-py*` features. | ||
| /// | ||
| /// Must be called from a PyO3 crate build script. | ||
| pub fn get_abi3t_version() -> Option<PythonVersion> { |
There was a problem hiding this comment.
I wonder if this should be combined with is_abi3t above. Basically is_abi3t should be equivalent to get_abi3t_version().is_some(), no? (also applies to is_abi3 and get_abi3_version)
Also should the MINIMUM_SUPPORTED_VERSION be different for abi3 and abi3t?
| apply_build_env_to_config( | ||
| InterpreterConfig::from_path(path) | ||
| .context("failed to parse contents of PYO3_CONFIG_FILE")?, | ||
| ) |
There was a problem hiding this comment.
I wonder if this should be a method on InterpreterConfig instead of a free function.
| let target_abi = | ||
| PythonAbiBuilder::from_sysconfig(implementation, version, abi3_version, gil_disabled)? | ||
| .finalize(); | ||
|
|
There was a problem hiding this comment.
As this already specifies everything abi related directly, I think this should be directly on PythonAbi instead of the builder.
| @@ -179,40 +231,50 @@ impl InterpreterConfig { | |||
| #[doc(hidden)] | |||
| pub fn build_script_outputs(&self) -> Vec<String> { | |||
There was a problem hiding this comment.
Nice, I think this is very clear now!
| /// Generates "default" interpreter configuration when compiling "abi3" extensions | ||
| /// without a working Python interpreter. | ||
| /// | ||
| /// `version` specifies the minimum supported Stable ABI CPython version. | ||
| /// | ||
| /// This should work for most CPython extension modules when compiling on | ||
| /// Windows, macOS and Linux. | ||
| /// | ||
| /// Must be called from a PyO3 crate build script. | ||
| fn default_abi3_config(host: &Triple, version: PythonVersion) -> Result<InterpreterConfig> { |
There was a problem hiding this comment.
Shouldn't this be moved into the function above?
| /// The Python implementation flavor. | ||
| /// | ||
| /// Serialized to `implementation`. | ||
| pub implementation: PythonImplementation, |
There was a problem hiding this comment.
Should we maybe have accessor methods, to prevent modifying an already finalized abi?
|
@davidhewitt and I had a 1-1 sync to discuss this PR and #5807. We decided to close this PR in favor of #5807 to avoid splitting work. @davidhewitt also offered to put in a PR that will upstream just the InterpreterConfig builder structs, along with deprecating constructing an InterpreterConfig directly. |
Towards #5786.
Refactor
pyo3_build_config::impl_::InterpreterConfigto use an enum to represent the kinds of stable ABI instead of booleanabi3flag. Also replace names that contain "abi3" with "stable_abi".This is extracted from a branch that enables abi3t builds and Python 3.15 stable ABI support, where I add a third enum variant to represent abi3t. My goal here is to make upstreaming that change simpler. PEP 803 was accepted over the weekend so a new ABI is definitely happening.
I also personally find the enum clearer to understand and easier to read code that uses it instead of the boolean flag.