From 4ec78e6b1820a9369325a070f01f85612a8d84a0 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Fri, 5 Mar 2021 15:27:36 +0900 Subject: [PATCH 1/2] Warning when 'abi3' is used with PyPy --- CHANGELOG.md | 3 +++ build.rs | 72 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0724c49e..abb1feec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Packaging +- The `abi3` feature shows a warning when building for `PyPy`. [#1469](https://github.com/PyO3/pyo3/pull/1469) + ### Added - Add conversions between `OsStr`/`OsString`/`Path`/`PathBuf` and Python strings. [#1379](https://github.com/PyO3/pyo3/pull/1379) - Add #[pyo3(from_py_with = "...")]` attribute for function arguments and struct fields to override the default from-Python conversion. [#1411](https://github.com/PyO3/pyo3/pull/1411) diff --git a/build.rs b/build.rs index 2afb5802..eb3edf3a 100644 --- a/build.rs +++ b/build.rs @@ -23,6 +23,13 @@ macro_rules! bail { ($fmt: literal $(, $args: expr)+) => { return Err(format!($fmt $(,$args)+).into()); }; } +// Show warning. If needed, please extend this macro to support arguments. +macro_rules! warn { + ($msg: literal) => { + println!(concat!("cargo:warning=", $msg)); + }; +} + /// Information returned from python interpreter #[derive(Debug)] struct InterpreterConfig { @@ -34,13 +41,23 @@ struct InterpreterConfig { base_prefix: String, executable: PathBuf, calcsize_pointer: Option, + implementation: PythonInterpreterKind, } -#[derive(Debug, Clone)] +impl InterpreterConfig { + fn is_pypy(&self) -> bool { + self.implementation == PythonInterpreterKind::PyPy + } +} + +#[derive(Debug, Clone, PartialEq, PartialOrd)] struct PythonVersion { major: u8, minor: u8, - implementation: PythonInterpreterKind, +} + +impl PythonVersion { + const PY37: Self = PythonVersion { major: 3, minor: 7 }; } #[derive(Debug, Clone, PartialEq)] @@ -60,6 +77,10 @@ impl FromStr for PythonInterpreterKind { } } +fn is_abi3() -> bool { + env::var_os("CARGO_FEATURE_ABI3").is_some() +} + trait GetPrimitive { fn get_bool(&self, key: &str) -> Result; fn get_numeric(&self, key: &str) -> Result; @@ -266,16 +287,14 @@ impl BuildFlags { fn fixup(&mut self, interpreter_config: &InterpreterConfig) { if self.0.contains("Py_DEBUG") { self.0.insert("Py_REF_DEBUG"); - if interpreter_config.version.major == 3 && interpreter_config.version.minor <= 7 { + if interpreter_config.version <= PythonVersion::PY37 { // Py_DEBUG only implies Py_TRACE_REFS until Python 3.7 self.0.insert("Py_TRACE_REFS"); } } // WITH_THREAD is always on for Python 3.7, and for PyPy. - if (interpreter_config.version.implementation == PythonInterpreterKind::PyPy) - || (interpreter_config.version.major == 3 && interpreter_config.version.minor >= 7) - { + if interpreter_config.is_pypy() || interpreter_config.version >= PythonVersion::PY37 { self.0.insert("WITH_THREAD"); } } @@ -455,11 +474,7 @@ fn load_cross_compile_from_sysconfigdata( }; let calcsize_pointer = sysconfig_data.get_numeric("SIZEOF_VOID_P").ok(); - let python_version = PythonVersion { - major, - minor, - implementation: PythonInterpreterKind::CPython, - }; + let python_version = PythonVersion { major, minor }; let interpreter_config = InterpreterConfig { version: python_version, @@ -469,6 +484,7 @@ fn load_cross_compile_from_sysconfigdata( base_prefix: "".to_string(), executable: PathBuf::new(), calcsize_pointer, + implementation: PythonInterpreterKind::CPython, }; let build_flags = BuildFlags::from_config_map(&sysconfig_data); @@ -486,11 +502,7 @@ fn load_cross_compile_from_headers( let major = patchlevel_defines.get_numeric("PY_MAJOR_VERSION")?; let minor = patchlevel_defines.get_numeric("PY_MINOR_VERSION")?; - let python_version = PythonVersion { - major, - minor, - implementation: PythonInterpreterKind::CPython, - }; + let python_version = PythonVersion { major, minor }; let config_data = parse_header_defines(python_include_dir.join("pyconfig.h"))?; @@ -502,6 +514,7 @@ fn load_cross_compile_from_headers( base_prefix: "".to_string(), executable: PathBuf::new(), calcsize_pointer: None, + implementation: PythonInterpreterKind::CPython, }; let build_flags = BuildFlags::from_config_map(&config_data); @@ -531,11 +544,7 @@ fn windows_hardcoded_cross_compile( bail!("One of PYO3_CROSS_INCLUDE_DIR, PYO3_CROSS_PYTHON_VERSION, or an abi3-py3* feature must be specified when cross-compiling for Windows.") }; - let python_version = PythonVersion { - major, - minor, - implementation: PythonInterpreterKind::CPython, - }; + let python_version = PythonVersion { major, minor }; let interpreter_config = InterpreterConfig { version: python_version, @@ -545,6 +554,7 @@ fn windows_hardcoded_cross_compile( base_prefix: "".to_string(), executable: PathBuf::new(), calcsize_pointer: None, + implementation: PythonInterpreterKind::CPython, }; Ok((interpreter_config, BuildFlags::windows_hardcoded())) @@ -609,6 +619,7 @@ fn get_rustc_link_lib(config: &InterpreterConfig) -> String { let link_name = if env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() == "windows" { if env::var("CARGO_CFG_TARGET_ENV").unwrap().as_str() == "gnu" { // https://packages.msys2.org/base/mingw-w64-python + // TODO: ABI3? format!( "pythonXY:python{}.{}", config.version.major, config.version.minor @@ -618,7 +629,7 @@ fn get_rustc_link_lib(config: &InterpreterConfig) -> String { // See https://www.python.org/dev/peps/pep-0384/#linkage // // This contains only the limited ABI symbols. - if env::var_os("CARGO_FEATURE_ABI3").is_some() { + if is_abi3() { "pythonXY:python3".to_owned() } else { format!( @@ -628,7 +639,7 @@ fn get_rustc_link_lib(config: &InterpreterConfig) -> String { } } } else { - match config.version.implementation { + match config.implementation { PythonInterpreterKind::CPython => format!("python{}", config.ld_version), PythonInterpreterKind::PyPy => format!("pypy{}-c", config.version.major), } @@ -736,8 +747,8 @@ print("calcsize_pointer", struct.calcsize("P")) version: PythonVersion { major: map["version_major"].parse()?, minor: map["version_minor"].parse()?, - implementation: map["implementation"].parse()?, }, + implementation: map["implementation"].parse()?, libdir: map.get("libdir").cloned(), shared, ld_version: map["ld_version"].clone(), @@ -781,14 +792,21 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<()> { println!("cargo:rustc-cfg=Py_SHARED"); } - if interpreter_config.version.implementation == PythonInterpreterKind::PyPy { + let is_abi3 = is_abi3(); + + if interpreter_config.is_pypy() { println!("cargo:rustc-cfg=PyPy"); + if is_abi3 { + warn!( + "PyPy does not yet support abi3 and the resulting wheel would be version-specific. \ + See https://foss.heptapod.net/pypy/pypy/-/issues/3397 for more information." + ) + } }; - let minor = if env::var_os("CARGO_FEATURE_ABI3").is_some() { + let minor = if is_abi3 { println!("cargo:rustc-cfg=Py_LIMITED_API"); // Check any `abi3-py3*` feature is set. If not, use the interpreter version. - match get_abi3_minor_version() { Some(minor) if minor > interpreter_config.version.minor => bail!( "You cannot set a mininimum Python version 3.{} higher than the interpreter version 3.{}", From 6f8f958f341d08081d9b343b0749e85b76f77340 Mon Sep 17 00:00:00 2001 From: Yuji Kanagawa Date: Sat, 6 Mar 2021 18:03:17 +0900 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com> --- CHANGELOG.md | 3 --- build.rs | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abb1feec..0724c49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] -### Packaging -- The `abi3` feature shows a warning when building for `PyPy`. [#1469](https://github.com/PyO3/pyo3/pull/1469) - ### Added - Add conversions between `OsStr`/`OsString`/`Path`/`PathBuf` and Python strings. [#1379](https://github.com/PyO3/pyo3/pull/1379) - Add #[pyo3(from_py_with = "...")]` attribute for function arguments and struct fields to override the default from-Python conversion. [#1411](https://github.com/PyO3/pyo3/pull/1411) diff --git a/build.rs b/build.rs index eb3edf3a..7db5782a 100644 --- a/build.rs +++ b/build.rs @@ -798,7 +798,7 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<()> { println!("cargo:rustc-cfg=PyPy"); if is_abi3 { warn!( - "PyPy does not yet support abi3 and the resulting wheel would be version-specific. \ + "PyPy does not yet support abi3 so the resulting wheel will be version-specific. \ See https://foss.heptapod.net/pypy/pypy/-/issues/3397 for more information." ) }