diff --git a/Cargo.toml b/Cargo.toml index f63bf32c5f9..58640ade613 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,9 @@ exclude = [ "/tests/ui", ] edition = "2021" +# this allows PyO3 to forward build-config from `pyo3-ffi` to avoid downstream crates +# needing to depend on `pyo3-ffi` directly to use `pyo3-build-config` functionality. +links = "pyo3-python" rust-version.workspace = true [dependencies] @@ -82,7 +85,7 @@ uuid = { version = "1.10.0", features = ["v4"] } parking_lot = { version = "0.12.3", features = ["arc_lock"] } [build-dependencies] -pyo3-build-config = { path = "pyo3-build-config", version = "=0.28.3", features = ["resolve-config"] } +pyo3-build-config = { path = "pyo3-build-config", version = "=0.28.3" } [features] default = ["macros"] @@ -106,16 +109,16 @@ multiple-pymethods = ["inventory", "pyo3-macros/multiple-pymethods"] extension-module = ["pyo3-ffi/extension-module"] # Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more. -abi3 = ["pyo3-build-config/abi3", "pyo3-ffi/abi3"] +abi3 = ["pyo3-ffi/abi3"] # With abi3, we can manually set the minimum Python version. -abi3-py38 = ["abi3-py39", "pyo3-build-config/abi3-py38", "pyo3-ffi/abi3-py38"] -abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39"] -abi3-py310 = ["abi3-py311", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310"] -abi3-py311 = ["abi3-py312", "pyo3-build-config/abi3-py311", "pyo3-ffi/abi3-py311"] -abi3-py312 = ["abi3-py313", "pyo3-build-config/abi3-py312", "pyo3-ffi/abi3-py312"] -abi3-py313 = ["abi3-py314", "pyo3-build-config/abi3-py313", "pyo3-ffi/abi3-py313"] -abi3-py314 = ["abi3", "pyo3-build-config/abi3-py314", "pyo3-ffi/abi3-py314"] +abi3-py38 = ["abi3-py39", "pyo3-ffi/abi3-py38"] +abi3-py39 = ["abi3-py310", "pyo3-ffi/abi3-py39"] +abi3-py310 = ["abi3-py311", "pyo3-ffi/abi3-py310"] +abi3-py311 = ["abi3-py312", "pyo3-ffi/abi3-py311"] +abi3-py312 = ["abi3-py313", "pyo3-ffi/abi3-py312"] +abi3-py313 = ["abi3-py314", "pyo3-ffi/abi3-py313"] +abi3-py314 = ["abi3", "pyo3-ffi/abi3-py314"] # deprecated: no longer needed, raw-dylib is used instead generate-import-lib = ["pyo3-ffi/generate-import-lib"] diff --git a/build.rs b/build.rs index 25e3f54e331..2f33c61dc35 100644 --- a/build.rs +++ b/build.rs @@ -43,6 +43,10 @@ fn configure_pyo3() -> Result<()> { print_feature_cfgs(); + // Forwards interpreter config under the links = "pyo3-python" configuration, + // which allows consumers of `pyo3-build-config` APIs to depend on pyo3 instead of pyo3-ffi. + interpreter_config.to_cargo_dep_env()?; + // Make `cargo test` etc work on macOS with Xcode bundled Python add_python_framework_link_args(); diff --git a/guide/src/building-and-distribution/multiple-python-versions.md b/guide/src/building-and-distribution/multiple-python-versions.md index c9c1c22c9a1..97d22780625 100644 --- a/guide/src/building-and-distribution/multiple-python-versions.md +++ b/guide/src/building-and-distribution/multiple-python-versions.md @@ -36,11 +36,11 @@ To see a full reference of all the `#[cfg]` flags provided, see the [`pyo3-build You can use the `#[cfg]` flags in just two steps: -1. Add `pyo3-build-config` with the [`resolve-config`](../features.md#resolve-config) feature enabled to your crate's build dependencies in `Cargo.toml`: +1. Add `pyo3-build-config` to your crate's build dependencies in `Cargo.toml`: ```toml [build-dependencies] - pyo3-build-config = { {{#PYO3_CRATE_VERSION}}, features = ["resolve-config"] } + pyo3-build-config = {{#PYO3_CRATE_VERSION}} ``` 2. Add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) file to your crate with the following contents: diff --git a/guide/src/features.md b/guide/src/features.md index 6accfd39c10..2b9ee9c4024 100644 --- a/guide/src/features.md +++ b/guide/src/features.md @@ -105,12 +105,6 @@ See [the `#[pyclass]` implementation details](class.md#implementation-details) f The `nightly` feature needs the nightly Rust compiler. This allows PyO3 to use the `auto_traits` and `negative_impls` features to fix the `Python::detach` function. -### `resolve-config` - -The `resolve-config` feature of the `pyo3-build-config` crate controls whether that crate's build script automatically resolves a Python interpreter / build configuration. -This feature is primarily useful when building PyO3 itself. -By default this feature is not enabled, meaning you can freely use `pyo3-build-config` as a standalone library to read or write PyO3 build configuration files or resolve metadata about a Python interpreter. - ## Optional Dependencies These features enable conversions between Python types and types from other Rust crates, enabling easy access to the rest of the Rust ecosystem. diff --git a/newsfragments/5862.changed.md b/newsfragments/5862.changed.md new file mode 100644 index 00000000000..b1ae875c1a6 --- /dev/null +++ b/newsfragments/5862.changed.md @@ -0,0 +1 @@ +Deprecate `pyo3-build-config/resolve-config` feature. diff --git a/pyo3-benches/Cargo.toml b/pyo3-benches/Cargo.toml index 4a3024819f9..b7a6f2df29a 100644 --- a/pyo3-benches/Cargo.toml +++ b/pyo3-benches/Cargo.toml @@ -20,7 +20,7 @@ rust_decimal = { version = "1.0.0", default-features = false } hashbrown = "0.16" [features] -abi3 = ["pyo3-build-config/abi3"] +abi3 = ["pyo3/abi3"] [[bench]] name = "bench_any" diff --git a/pyo3-build-config/Cargo.toml b/pyo3-build-config/Cargo.toml index 14632951863..6a4e24fe14d 100644 --- a/pyo3-build-config/Cargo.toml +++ b/pyo3-build-config/Cargo.toml @@ -20,8 +20,7 @@ target-lexicon = "0.13.3" [features] default = [] -# Attempt to resolve a Python interpreter config for building in the build -# script. If this feature isn't enabled, the build script no-ops. +# deprecated resolve-config = [] # deprecated @@ -29,16 +28,3 @@ extension-module = [] # deprecated: no longer needed, raw-dylib is used instead generate-import-lib = [] - -# These features are enabled by pyo3 when building Stable ABI extension modules. -abi3 = [] -abi3-py38 = ["abi3-py39"] -abi3-py39 = ["abi3-py310"] -abi3-py310 = ["abi3-py311"] -abi3-py311 = ["abi3-py312"] -abi3-py312 = ["abi3-py313"] -abi3-py313 = ["abi3-py314"] -abi3-py314 = ["abi3"] - -[package.metadata.docs.rs] -features = ["resolve-config"] diff --git a/pyo3-build-config/build.rs b/pyo3-build-config/build.rs deleted file mode 100644 index 78d193a8376..00000000000 --- a/pyo3-build-config/build.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Import some modules from this crate inline to generate the build config. -// Allow dead code because not all code in the modules is used in this build script. - -#[path = "src/impl_.rs"] -#[allow(dead_code, reason = "not all code is used in build.rs")] -mod impl_; - -#[path = "src/errors.rs"] -#[allow(dead_code, reason = "not all code is used in build.rs")] -mod errors; - -use std::{env, path::Path}; - -use errors::{Context, Result}; -use impl_::{make_interpreter_config, InterpreterConfig}; - -fn configure(interpreter_config: Option, name: &str) -> Result { - let target = Path::new(&env::var_os("OUT_DIR").unwrap()).join(name); - if let Some(config) = interpreter_config { - config - .to_writer(&mut std::fs::File::create(&target).with_context(|| { - format!("failed to write config file at {}", target.display()) - })?)?; - Ok(true) - } else { - std::fs::File::create(&target) - .with_context(|| format!("failed to create new file at {}", target.display()))?; - Ok(false) - } -} - -fn generate_build_configs() -> Result<()> { - // If PYO3_CONFIG_FILE is set, copy it into the crate. - let configured = configure( - InterpreterConfig::from_pyo3_config_file_env().transpose()?, - "pyo3-build-config-file.txt", - )?; - - if configured { - // Don't bother trying to find an interpreter on the host system - // if the user-provided config file is present. - configure(None, "pyo3-build-config.txt")?; - } else { - configure(Some(make_interpreter_config()?), "pyo3-build-config.txt")?; - } - Ok(()) -} - -fn main() { - if std::env::var("CARGO_FEATURE_RESOLVE_CONFIG").is_ok() { - if let Err(e) = generate_build_configs() { - eprintln!("error: {}", e.report()); - std::process::exit(1) - } - } else { - eprintln!("resolve-config feature not enabled; build script in no-op mode"); - } -} diff --git a/pyo3-build-config/src/impl_.rs b/pyo3-build-config/src/impl_.rs index 6a090d93b75..36ec7961ed1 100644 --- a/pyo3-build-config/src/impl_.rs +++ b/pyo3-build-config/src/impl_.rs @@ -1,6 +1,3 @@ -//! Main implementation module included in both the `pyo3-build-config` library crate -//! and its build script. - #[cfg(test)] use std::cell::RefCell; use std::{ @@ -61,9 +58,7 @@ pub fn cargo_env_var(var: &str) -> Option { /// Gets an external environment variable, and registers the build script to rerun if /// the variable changes. pub fn env_var(var: &str) -> Option { - if cfg!(feature = "resolve-config") { - println!("cargo:rerun-if-env-changed={var}"); - } + println!("cargo:rerun-if-env-changed={var}"); #[cfg(test)] { READ_ENV_VARS.with(|env_vars| { @@ -490,7 +485,8 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED")) #[doc(hidden)] pub fn from_cargo_dep_env() -> Option> { - cargo_env_var("DEP_PYTHON_PYO3_CONFIG") + cargo_env_var("DEP_PYTHON_PYO3_CONFIG") // from `pyo3-ffi` + .or_else(|| cargo_env_var("DEP_PYO3_PYTHON_PYO3_CONFIG")) // forwared by `pyo3` .map(|buf| InterpreterConfig::from_reader(&*unescape(&buf))) } @@ -583,7 +579,6 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED")) /// This requires knowledge of the final target, so cannot be done when the config file is /// inlined into `pyo3-build-config` at build time and instead needs to be done when /// resolving the build config for linking. - #[cfg(any(test, feature = "resolve-config"))] pub(crate) fn apply_default_lib_name_to_config_file(&mut self, target: &Triple) { if self.lib_name.is_none() { self.lib_name = Some(default_lib_name_for_target( @@ -1909,9 +1904,7 @@ pub fn make_cross_compile_config() -> Result> { Ok(interpreter_config) } -/// Generates an interpreter config which will be hard-coded into the pyo3-build-config crate. -/// Only used by `pyo3-build-config` build script. -#[allow(dead_code, unused_mut)] +/// Generates an interpreter config suitable for the build host. pub fn make_interpreter_config() -> Result { let host = Triple::host(); let abi3_version = get_abi3_version(); @@ -2874,17 +2867,17 @@ mod tests { } #[test] - #[cfg(all( - target_os = "linux", - target_arch = "x86_64", - feature = "resolve-config" - ))] + #[cfg(all(target_os = "linux", target_arch = "x86_64",))] fn parse_sysconfigdata() { // A best effort attempt to get test coverage for the sysconfigdata parsing. // Might not complete successfully depending on host installation; that's ok as long as // CI demonstrates this path is covered! - let interpreter_config = crate::get(); + let Ok(interpreter_config) = make_interpreter_config() else { + // Couldn't get an interpreter config, won't be able to test a matching sysconfigdata, + // never mind. (This is intended for coverage, don't mind if it fails if it doesn't run.) + return; + }; let lib_dir = match &interpreter_config.lib_dir { Some(lib_dir) => Path::new(lib_dir), @@ -2910,7 +2903,16 @@ mod tests { _ => return, }; let sysconfigdata = super::parse_sysconfigdata(sysconfigdata_path).unwrap(); - let parsed_config = InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(); + let mut parsed_config = InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(); + + // Workaround case where empty `PYTHONFRAMEWORKPREFIX` is returned as empty string instead of None, + // which causes the assert_eq! below to fail. + // + // TODO: probably should deprecate using this variable at all, seemingly only used in `add_python_framework_link_args` + // which is probably a strictly worse version of `add_libpython_rpath_link_args`. + if parsed_config.python_framework_prefix.as_deref() == Some("") { + parsed_config.python_framework_prefix = None; + } assert_eq!( parsed_config, diff --git a/pyo3-build-config/src/lib.rs b/pyo3-build-config/src/lib.rs index 4e705d2ca02..5990ce96bcc 100644 --- a/pyo3-build-config/src/lib.rs +++ b/pyo3-build-config/src/lib.rs @@ -10,12 +10,6 @@ mod errors; mod impl_; -#[cfg(feature = "resolve-config")] -use std::{ - io::Cursor, - path::{Path, PathBuf}, -}; - use std::{env, process::Command, str::FromStr, sync::OnceLock}; pub use impl_::{ @@ -40,9 +34,8 @@ use target_lexicon::OperatingSystem; /// | `#[cfg(GraalPy)]` | This marks code which is run when compiling for GraalPy. | /// /// For examples of how to use these attributes, -#[doc = concat!("[see PyO3's guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution/multiple_python_versions.html)")] +#[doc = concat!("[see PyO3's guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution/multiple-python-versions.html)")] /// . -#[cfg(feature = "resolve-config")] pub fn use_pyo3_cfgs() { print_expected_cfgs(); for cargo_command in get().build_script_outputs() { @@ -99,7 +92,6 @@ fn _add_extension_module_link_args( /// #[doc = concat!("[See PyO3's guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution#dynamically-embedding-the-python-interpreter)")] /// for more details. -#[cfg(feature = "resolve-config")] pub fn add_libpython_rpath_link_args() { let target = impl_::target_triple_from_env(); _add_libpython_rpath_link_args( @@ -109,7 +101,6 @@ pub fn add_libpython_rpath_link_args() { ) } -#[cfg(feature = "resolve-config")] fn _add_libpython_rpath_link_args( interpreter_config: &InterpreterConfig, is_linking_libpython: bool, @@ -130,7 +121,6 @@ fn _add_libpython_rpath_link_args( /// - macOS: `-Wl,-rpath,` /// /// All other platforms currently are no-ops. -#[cfg(feature = "resolve-config")] pub fn add_python_framework_link_args() { let target = impl_::target_triple_from_env(); _add_python_framework_link_args( @@ -141,7 +131,6 @@ pub fn add_python_framework_link_args() { ) } -#[cfg(feature = "resolve-config")] fn _add_python_framework_link_args( interpreter_config: &InterpreterConfig, triple: &Triple, @@ -158,72 +147,15 @@ fn _add_python_framework_link_args( /// Loads the configuration determined from the build environment. /// /// Because this will never change in a given compilation run, this is cached in a `OnceLock`. -#[cfg(feature = "resolve-config")] pub fn get() -> &'static InterpreterConfig { static CONFIG: OnceLock = OnceLock::new(); CONFIG.get_or_init(|| { - // Check if we are in a build script and cross compiling to a different target. - let cross_compile_config_path = resolve_cross_compile_config_path(); - let cross_compiling = cross_compile_config_path - .as_ref() - .map(|path| path.exists()) - .unwrap_or(false); - - #[allow( - clippy::const_is_empty, - reason = "CONFIG_FILE is generated in build.rs, content can vary" - )] - if let Some(interpreter_config) = InterpreterConfig::from_cargo_dep_env() { - interpreter_config - } else if let Some(interpreter_config) = config_from_pyo3_config_file_env() { - Ok(interpreter_config) - } else if cross_compiling { - InterpreterConfig::from_path(cross_compile_config_path.as_ref().unwrap()) - } else { - InterpreterConfig::from_reader(Cursor::new(HOST_CONFIG)) - } - .expect("failed to parse PyO3 config") - }) -} - -/// Build configuration provided by `PYO3_CONFIG_FILE`, inlined into the `pyo3-build-config` binary. -#[cfg(feature = "resolve-config")] -fn config_from_pyo3_config_file_env() -> Option { - #[doc(hidden)] - const CONFIG_FILE: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config-file.txt")); - - #[allow( - clippy::const_is_empty, - reason = "CONFIG_FILE is generated in build.rs, content can vary" - )] - if !CONFIG_FILE.is_empty() { - let config = InterpreterConfig::from_reader(Cursor::new(CONFIG_FILE)) - .expect("contents of CONFIG_FILE should always be valid (generated by pyo3-build-config's build.rs)"); - Some(config) - } else { - None - } -} - -/// Build configuration discovered by `pyo3-build-config` build script. Not aware of -/// cross-compilation settings. Not generated if `PYO3_CONFIG_FILE` is set. -#[doc(hidden)] -#[cfg(feature = "resolve-config")] -const HOST_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config.txt")); - -/// Returns the path where PyO3's build.rs writes its cross compile configuration. -/// -/// The config file will be named `$OUT_DIR//pyo3-build-config.txt`. -/// -/// Must be called from a build script, returns `None` if not. -#[doc(hidden)] -#[cfg(feature = "resolve-config")] -fn resolve_cross_compile_config_path() -> Option { - env::var_os("TARGET").map(|target| { - let mut path = PathBuf::from(env!("OUT_DIR")); - path.push(Path::new(&target)); - path.push("pyo3-build-config.txt"); - path + let Some(interpreter_config) = InterpreterConfig::from_cargo_dep_env() else { + panic!( + "`pyo3_build_config::get()` requires a direct dependency on `pyo3` or `pyo3-ffi`" + ) + }; + interpreter_config.expect("failed to parse PyO3 config") }) } @@ -304,9 +236,11 @@ pub fn print_expected_cfgs() { /// /// Please don't use these - they could change at any time. #[doc(hidden)] -#[cfg(feature = "resolve-config")] pub mod pyo3_build_script_impl { - use crate::errors::{Context, Result}; + use crate::{ + errors::Result, + impl_::{make_cross_compile_config, make_interpreter_config}, + }; use super::*; @@ -314,8 +248,7 @@ pub mod pyo3_build_script_impl { pub use crate::errors::*; } pub use crate::impl_::{ - cargo_env_var, env_var, is_linking_libpython_for_target, make_cross_compile_config, - target_triple_from_env, InterpreterConfig, PythonVersion, + cargo_env_var, env_var, is_linking_libpython_for_target, target_triple_from_env, }; pub enum BuildConfigSource { /// Config was provided by `PYO3_CONFIG_FILE`. @@ -332,52 +265,29 @@ pub mod pyo3_build_script_impl { } /// Gets the configuration for use from `pyo3-ffi`'s build script. - /// - /// Differs from `.get()` in three ways: - /// 1. The cargo_dep_env config is not yet available (exported by `pyo3-ffi`'s build script). - /// 1. If `PYO3_CONFIG_FILE` is set, lib name is fixed up and the windows import libs might be generated. - /// 2. The cross-compile config file is generated if necessary. - /// - /// Steps 2 and 3 are necessary because `pyo3-ffi`'s build script is the first code run which knows - /// the correct target triple. pub fn resolve_build_config(target: &Triple) -> Result { #[allow( clippy::const_is_empty, reason = "CONFIG_FILE is generated in build.rs, content can vary" )] - if let Some(mut interpreter_config) = config_from_pyo3_config_file_env() { + if let Some(mut interpreter_config) = + InterpreterConfig::from_pyo3_config_file_env().transpose()? + { interpreter_config.apply_default_lib_name_to_config_file(target); Ok(BuildConfig { interpreter_config, source: BuildConfigSource::ConfigFile, }) } else if let Some(interpreter_config) = make_cross_compile_config()? { - // This is a cross compile and need to write the config file. - let path = resolve_cross_compile_config_path() - .expect("resolve_build_config() must be called from a build script"); - let parent_dir = path.parent().ok_or_else(|| { - format!( - "failed to resolve parent directory of config file {}", - path.display() - ) - })?; - std::fs::create_dir_all(parent_dir).with_context(|| { - format!( - "failed to create config file directory {}", - parent_dir.display() - ) - })?; - interpreter_config.to_writer(&mut std::fs::File::create(&path).with_context( - || format!("failed to create config file at {}", path.display()), - )?)?; Ok(BuildConfig { interpreter_config, source: BuildConfigSource::CrossCompile, }) } else { - let interpreter_config = InterpreterConfig::from_reader(Cursor::new(HOST_CONFIG))?; + // No config file, and no cross compile config, so fall back to trying to find an interpreter on the host system. + let host_config = make_interpreter_config(); Ok(BuildConfig { - interpreter_config, + interpreter_config: host_config?, source: BuildConfigSource::Host, }) } @@ -482,7 +392,6 @@ mod tests { assert_eq!(std::str::from_utf8(&buf).unwrap(), ""); } - #[cfg(feature = "resolve-config")] #[test] fn python_framework_link_args() { let mut buf = Vec::new(); @@ -528,7 +437,6 @@ mod tests { } #[test] - #[cfg(feature = "resolve-config")] fn test_maximum_version_exceeded_formatting() { let interpreter_config = InterpreterConfig { implementation: PythonImplementation::CPython, diff --git a/pyo3-ffi-check/Cargo.toml b/pyo3-ffi-check/Cargo.toml index 2c1beb36190..c9eb83bfef9 100644 --- a/pyo3-ffi-check/Cargo.toml +++ b/pyo3-ffi-check/Cargo.toml @@ -7,6 +7,7 @@ publish = false [dependencies] pyo3-ffi-check-definitions = { path = "definitions" } pyo3-ffi-check-macro = { path = "macro" } +pyo3-ffi = { path = "../pyo3-ffi" } [build-dependencies] pyo3-build-config = { path = "../pyo3-build-config" } diff --git a/pyo3-ffi-check/build.rs b/pyo3-ffi-check/build.rs index cbaa336df24..5728c6b8f57 100644 --- a/pyo3-ffi-check/build.rs +++ b/pyo3-ffi-check/build.rs @@ -35,4 +35,9 @@ fn main() { // Because `pyo3-ffi` is a dependency, libpython is linked, this ensures `main.rs` can run. // Slightly needless (no symbols from libpython are actually called), but simple to do. pyo3_build_config::add_libpython_rpath_link_args(); + + // Forward config into this crate's compilation, so that `ffi-check` macro can consume it. + let pyo3_config_raw = + std::env::var("DEP_PYTHON_PYO3_CONFIG").expect("PYO3_CONFIG environment variable not set"); + println!("cargo:rustc-env=DEP_PYTHON_PYO3_CONFIG={pyo3_config_raw}"); } diff --git a/pyo3-ffi/Cargo.toml b/pyo3-ffi/Cargo.toml index 3e8116a9493..bb145a480c6 100644 --- a/pyo3-ffi/Cargo.toml +++ b/pyo3-ffi/Cargo.toml @@ -23,16 +23,16 @@ default = [] extension-module = ["pyo3-build-config/extension-module"] # Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more. -abi3 = ["pyo3-build-config/abi3"] +abi3 = [] # With abi3, we can manually set the minimum Python version. -abi3-py38 = ["abi3-py39", "pyo3-build-config/abi3-py38"] -abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39"] -abi3-py310 = ["abi3-py311", "pyo3-build-config/abi3-py310"] -abi3-py311 = ["abi3-py312", "pyo3-build-config/abi3-py311"] -abi3-py312 = ["abi3-py313", "pyo3-build-config/abi3-py312"] -abi3-py313 = ["abi3-py314", "pyo3-build-config/abi3-py313"] -abi3-py314 = ["abi3", "pyo3-build-config/abi3-py314"] +abi3-py38 = ["abi3-py39"] +abi3-py39 = ["abi3-py310"] +abi3-py310 = ["abi3-py311"] +abi3-py311 = ["abi3-py312"] +abi3-py312 = ["abi3-py313"] +abi3-py313 = ["abi3-py314"] +abi3-py314 = ["abi3"] # deprecated: no longer needed, raw-dylib is used instead generate-import-lib = ["pyo3-build-config/generate-import-lib"] diff --git a/pyo3-ffi/build.rs b/pyo3-ffi/build.rs index 127874ffa84..20cbefb01c1 100644 --- a/pyo3-ffi/build.rs +++ b/pyo3-ffi/build.rs @@ -3,9 +3,9 @@ use pyo3_build_config::{ pyo3_build_script_impl::{ cargo_env_var, env_var, errors::Result, is_linking_libpython_for_target, resolve_build_config, target_triple_from_env, BuildConfig, BuildConfigSource, - InterpreterConfig, MaximumVersionExceeded, PythonVersion, + MaximumVersionExceeded, }, - warn, PythonImplementation, + warn, InterpreterConfig, PythonImplementation, PythonVersion, }; /// Minimum Python version PyO3 supports.