Merge pull request #1263 from PyO3/abi3-min-python
Add abi3-py* features
This commit is contained in:
commit
9aa70f7c89
|
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
|
||||
### Added
|
||||
- Add support for building for CPython limited API. This required a few minor changes to runtime behaviour of of pyo3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152)
|
||||
- Add feature flags `abi3-py*` to set the minimum Python version when using the limited API. [#1263]((https://github.com/PyO3/pyo3/pull/1263))
|
||||
- Add argument names to `TypeError` messages generated by pymethod wrappers. [#1212](https://github.com/PyO3/pyo3/pull/1212)
|
||||
- Add FFI definitions for PEP 587 "Python Initialization Configuration". [#1247](https://github.com/PyO3/pyo3/pull/1247)
|
||||
- Add `PyEval_SetProfile` and `PyEval_SetTrace` to FFI. [#1255](https://github.com/PyO3/pyo3/pull/1255)
|
||||
|
|
|
@ -36,9 +36,13 @@ rustversion = "1.0"
|
|||
[features]
|
||||
default = ["macros"]
|
||||
macros = ["ctor", "indoc", "inventory", "paste", "pyo3cls", "unindent"]
|
||||
# Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for
|
||||
# more.
|
||||
# Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more.
|
||||
abi3 = []
|
||||
# With abi3, we can manually set the minimum Python version.
|
||||
abi3-py36 = ["abi3-py37"]
|
||||
abi3-py37 = ["abi3-py38"]
|
||||
abi3-py38 = ["abi3-py39"]
|
||||
abi3-py39 = ["abi3"]
|
||||
|
||||
# Optimizes PyObject to Vec conversion and so on.
|
||||
nightly = []
|
||||
|
|
45
build.rs
45
build.rs
|
@ -9,7 +9,10 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
|
||||
const PY3_MIN_MINOR: u8 = 5;
|
||||
/// 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;
|
||||
const CFG_KEY: &str = "py_sys_config";
|
||||
|
||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
@ -784,12 +787,25 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<String> {
|
|||
bail!("Python 2 is not supported");
|
||||
}
|
||||
|
||||
if env::var_os("CARGO_FEATURE_ABI3").is_some() {
|
||||
let minor = if env::var_os("CARGO_FEATURE_ABI3").is_some() {
|
||||
println!("cargo:rustc-cfg=Py_LIMITED_API");
|
||||
}
|
||||
// Check any `abi3-py3*` feature is set. If not, use the interpreter version.
|
||||
let abi3_minor = (PY3_MIN_MINOR..=ABI3_MAX_MINOR)
|
||||
.find(|i| env::var_os(format!("CARGO_FEATURE_ABI3_PY3{}", i)).is_some());
|
||||
match (abi3_minor, interpreter_config.version.minor) {
|
||||
(Some(abi3_minor), Some(interpreter_minor)) if abi3_minor > interpreter_minor => bail!(
|
||||
"You cannot set a mininimum Python version {} higher than the interpreter version {}",
|
||||
abi3_minor,
|
||||
interpreter_minor
|
||||
),
|
||||
_ => abi3_minor.or(interpreter_config.version.minor),
|
||||
}
|
||||
} else {
|
||||
interpreter_config.version.minor
|
||||
};
|
||||
|
||||
if let Some(minor) = interpreter_config.version.minor {
|
||||
for i in 6..=minor {
|
||||
if let Some(minor) = minor {
|
||||
for i in PY3_MIN_MINOR..=minor {
|
||||
println!("cargo:rustc-cfg=Py_3_{}", i);
|
||||
flags += format!("CFG_Py_3_{},", i).as_ref();
|
||||
}
|
||||
|
@ -834,7 +850,26 @@ fn check_target_architecture(interpreter_config: &InterpreterConfig) -> Result<(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn abi3_without_interpreter() -> Result<()> {
|
||||
println!("cargo:rustc-cfg=Py_LIMITED_API");
|
||||
let mut flags = "FLAG_WITH_THREAD=1".to_string();
|
||||
for minor in PY3_MIN_MINOR..=ABI3_MAX_MINOR {
|
||||
println!("cargo:rustc-cfg=Py_3_{}", minor);
|
||||
flags += &format!(",CFG_Py_3_{}", minor);
|
||||
}
|
||||
println!("cargo:rustc-cfg=py_sys_config=\"WITH_THREAD\"");
|
||||
println!("cargo:python_flags={}", flags);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// If PYO3_NO_PYTHON is set with abi3, we can build PyO3 without calling Python (UNIX only).
|
||||
// We only check for the abi3-py3{ABI3_MAX_MINOR} because lower versions depend on it.
|
||||
if env::var_os("PYO3_NO_PYTHON").is_some()
|
||||
&& env::var_os(format!("CARGO_FEATURE_ABI3_PY3{}", ABI3_MAX_MINOR)).is_some()
|
||||
{
|
||||
return abi3_without_interpreter();
|
||||
}
|
||||
// 1. Setup cfg variables so we can do conditional compilation in this library based on the
|
||||
// python interpeter's compilation flags. This is necessary for e.g. matching the right unicode
|
||||
// and threading interfaces. First check if we're cross compiling, if so, we cannot run the
|
||||
|
|
|
@ -58,6 +58,16 @@ pyo3 = { version = "...", features = ["abi3"]}
|
|||
|
||||
3. Ensure that the `.whl` is correctly marked as `abi3`. For projects using `setuptools`, this is accomplished by passing `--py-limited-api=cp3x` (where `x` is the minimum Python version supported by the wheel, e.g. `--py-limited-api=cp35` for Python 3.5) to `setup.py bdist_wheel`.
|
||||
|
||||
### Minimum Python version for `abi3`
|
||||
|
||||
Because a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py36`, `abi3-py37`, `abi-py38` etc. to set the minimum required Python version for your `abi3` wheel.
|
||||
For example, if you set the `abi3-py36` feature, your extension wheel can be used on all Python 3 versions from Python 3.6 and up. `maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp36-abi3-manylinux2020_x86_64.whl`.
|
||||
If you set more that one of these api version feature flags the highest version always wins. For example, with both `abi3-py36` and `abi3-py38` set, PyO3 would build a wheel which supports Python 3.8 and up.
|
||||
PyO3 is only able to link your extension module to api3 version up to and including your host Python version. E.g., if you set `abi3-py38` and try to compile the crate with a host of Python 3.6, the build will fail.
|
||||
|
||||
As an advanced feature, you can build PyO3 wheel without calling Python interpreter with
|
||||
the environment variable `PYO3_NO_PYTHON` set, but this only works on *NIX.
|
||||
|
||||
## Cross Compiling
|
||||
|
||||
Cross compiling PyO3 modules is relatively straightforward and requires a few pieces of software:
|
||||
|
@ -107,4 +117,3 @@ For an example of how to build python extensions using Bazel, see https://github
|
|||
|
||||
[maturin]: https://github.com/PyO3/maturin
|
||||
[setuptools-rust]: https://github.com/PyO3/setuptools-rust
|
||||
|
||||
|
|
Loading…
Reference in a new issue