Merge pull request #1469 from PyO3/deny-pypy-and-abi3

Show warning when abi3 is used with PyPy
This commit is contained in:
David Hewitt 2021-03-06 23:09:38 +00:00 committed by GitHub
commit 4c80ce93c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 45 additions and 27 deletions

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 so the resulting wheel will 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.{}",