Warning when 'abi3' is used with PyPy

This commit is contained in:
kngwyu 2021-03-05 15:27:36 +09:00
parent 21b26fcf3a
commit 4ec78e6b18
2 changed files with 48 additions and 27 deletions

View File

@ -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)

View File

@ -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<u32>,
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<bool>;
fn get_numeric<T: FromStr>(&self, key: &str) -> Result<T>;
@ -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.{}",