From dbbb56e82ac846d64d9b2a961d27d7561ddea80d Mon Sep 17 00:00:00 2001 From: messense Date: Thu, 26 May 2022 11:39:49 +0800 Subject: [PATCH] Add bindings detection to bin targets --- Changelog.md | 1 + src/build_context.rs | 61 ++++- src/build_options.rs | 111 +++++--- src/compile.rs | 9 +- src/main.rs | 4 +- test-crates/pyo3-bin/Cargo.lock | 249 ++++++++++++++++++ test-crates/pyo3-bin/Cargo.toml | 9 + .../check_installed/check_installed.py | 22 ++ test-crates/pyo3-bin/src/main.rs | 12 + tests/run.rs | 10 + 10 files changed, 432 insertions(+), 56 deletions(-) create mode 100644 test-crates/pyo3-bin/Cargo.lock create mode 100644 test-crates/pyo3-bin/Cargo.toml create mode 100644 test-crates/pyo3-bin/check_installed/check_installed.py create mode 100644 test-crates/pyo3-bin/src/main.rs diff --git a/Changelog.md b/Changelog.md index 21e7475e9..02e8277fb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fix python interpreter detection on arm64 Windows in [#940](https://github.com/PyO3/maturin/pull/940) * Fallback to `py -X.Y` when `pythonX.Y` cannot be found on Windows in [#943](https://github.com/PyO3/maturin/pull/943) * Auto-detect Python Installs from Microsoft Store in [#944](https://github.com/PyO3/maturin/pull/944) +* Add bindings detection to bin targets in [#938](https://github.com/PyO3/maturin/pull/938) ## [0.12.17] - 2022-05-18 diff --git a/src/build_context.rs b/src/build_context.rs index c2df703db..da1875fdc 100644 --- a/src/build_context.rs +++ b/src/build_context.rs @@ -24,7 +24,9 @@ pub enum BridgeModel { /// A native module with c bindings, i.e. `#[no_mangle] extern "C" ` Cffi, /// A rust binary to be shipped a python package - Bin, + /// The String is the name of the bindings + /// providing crate, e.g. pyo3, the number is the minimum minor python version + Bin(Option<(String, usize)>), /// A native module with pyo3 or rust-cpython bindings. The String is the name of the bindings /// providing crate, e.g. pyo3, the number is the minimum minor python version Bindings(String, usize), @@ -46,17 +48,24 @@ impl BridgeModel { /// Test whether this is using a specific bindings crate pub fn is_bindings(&self, name: &str) -> bool { match self { + BridgeModel::Bin(Some((value, _))) => value == name, BridgeModel::Bindings(value, _) => value == name, _ => false, } } + + /// Test whether this is bin bindings + pub fn is_bin(&self) -> bool { + matches!(self, BridgeModel::Bin(_)) + } } impl Display for BridgeModel { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { BridgeModel::Cffi => write!(f, "cffi"), - BridgeModel::Bin => write!(f, "bin"), + BridgeModel::Bin(Some((name, _))) => write!(f, "{} bin", name), + BridgeModel::Bin(None) => write!(f, "bin"), BridgeModel::Bindings(name, _) => write!(f, "{}", name), BridgeModel::BindingsAbi3(..) => write!(f, "pyo3"), } @@ -213,7 +222,8 @@ impl BuildContext { let wheels = match &self.bridge { BridgeModel::Cffi => self.build_cffi_wheel()?, - BridgeModel::Bin => self.build_bin_wheel()?, + BridgeModel::Bin(None) => self.build_bin_wheel(None)?, + BridgeModel::Bin(Some(..)) => self.build_bin_wheels(&self.interpreter)?, BridgeModel::Bindings(..) => self.build_binding_wheels(&self.interpreter)?, BridgeModel::BindingsAbi3(major, minor) => { let cpythons: Vec<_> = self @@ -309,7 +319,7 @@ impl BuildContext { .collect(); others.sort(); - if matches!(self.bridge, BridgeModel::Bin) && !musllinux.is_empty() { + if self.bridge.is_bin() && !musllinux.is_empty() { return get_policy_and_libs(artifact, Some(musllinux[0]), &self.target); } @@ -669,13 +679,22 @@ impl BuildContext { fn write_bin_wheel( &self, + python_interpreter: Option<&PythonInterpreter>, artifact: &Path, platform_tags: &[PlatformTag], ext_libs: &[Library], ) -> Result { - let (tag, tags) = self - .target - .get_universal_tags(platform_tags, self.universal2)?; + let (tag, tags) = match (&self.bridge, python_interpreter) { + (BridgeModel::Bin(None), _) => self + .target + .get_universal_tags(platform_tags, self.universal2)?, + (BridgeModel::Bin(Some(..)), Some(python_interpreter)) => { + let tag = + python_interpreter.get_tag(&self.target, platform_tags, self.universal2)?; + (tag.clone(), vec![tag]) + } + _ => unreachable!(), + }; if !self.metadata21.scripts.is_empty() { bail!("Defining entrypoints and working with a binary doesn't mix well"); @@ -708,9 +727,12 @@ impl BuildContext { /// Builds a wheel that contains a binary /// /// Runs [auditwheel_rs()] if not deactivated - pub fn build_bin_wheel(&self) -> Result> { + pub fn build_bin_wheel( + &self, + python_interpreter: Option<&PythonInterpreter>, + ) -> Result> { let mut wheels = Vec::new(); - let artifacts = compile(self, None, &self.bridge) + let artifacts = compile(self, python_interpreter, &self.bridge) .context("Failed to build a native library through cargo")?; let artifact = artifacts @@ -725,12 +747,31 @@ impl BuildContext { self.platform_tag.clone() }; - let (wheel_path, tag) = self.write_bin_wheel(&artifact, &platform_tags, &external_libs)?; + let (wheel_path, tag) = self.write_bin_wheel( + python_interpreter, + &artifact, + &platform_tags, + &external_libs, + )?; println!("📦 Built wheel to {}", wheel_path.display()); wheels.push((wheel_path, tag)); Ok(wheels) } + + /// Builds a wheel that contains a binary + /// + /// Runs [auditwheel_rs()] if not deactivated + pub fn build_bin_wheels( + &self, + interpreters: &[PythonInterpreter], + ) -> Result> { + let mut wheels = Vec::new(); + for python_interpreter in interpreters { + wheels.extend(self.build_bin_wheel(Some(python_interpreter))?); + } + Ok(wheels) + } } /// Calculate the sha256 of a file diff --git a/src/build_options.rs b/src/build_options.rs index 34fd80556..332297ea2 100644 --- a/src/build_options.rs +++ b/src/build_options.rs @@ -264,7 +264,7 @@ impl BuildOptions { }), )?; - if bridge != BridgeModel::Bin && module_name.contains('-') { + if !bridge.is_bin() && module_name.contains('-') { bail!( "The module name must not contains a minus \ (Make sure you have set an appropriate [lib] name in your Cargo.toml)" @@ -349,7 +349,7 @@ impl BuildOptions { } } else { // Defaults to musllinux_1_2 for musl target if it's not bin bindings - if target.is_musl_target() && !matches!(bridge, BridgeModel::Bin) { + if target.is_musl_target() && !bridge.is_bin() { Some(PlatformTag::Musllinux { x: 1, y: 2 }) } else { None @@ -371,8 +371,8 @@ impl BuildOptions { } match bridge { - BridgeModel::Bin => { - // Only support two different kind of platform tags when compiling to musl target + BridgeModel::Bin(None) => { + // Only support two different kind of platform tags when compiling to musl target without any binding crates if platform_tags.iter().any(|tag| tag.is_musllinux()) && !target.is_musl_target() { bail!( "Cannot mix musllinux and manylinux platform tags when compiling to {}", @@ -550,6 +550,28 @@ fn is_generating_import_lib(cargo_metadata: &Metadata) -> Result { Ok(false) } +/// Tries to determine the bindings type from dependency +fn find_bindings( + deps: &HashMap<&str, &Node>, + packages: &HashMap<&str, &cargo_metadata::Package>, +) -> Option<(String, usize)> { + if deps.get("pyo3").is_some() { + let ver = &packages["pyo3"].version; + let minor = + pyo3_minimum_python_minor_version(ver.major, ver.minor).unwrap_or(MINIMUM_PYTHON_MINOR); + Some(("pyo3".to_string(), minor)) + } else if deps.get("pyo3-ffi").is_some() { + let ver = &packages["pyo3-ffi"].version; + let minor = pyo3_ffi_minimum_python_minor_version(ver.major, ver.minor) + .unwrap_or(MINIMUM_PYTHON_MINOR); + Some(("pyo3-ffi".to_string(), minor)) + } else if deps.contains_key("cpython") { + Some(("rust-cpython".to_string(), MINIMUM_PYTHON_MINOR)) + } else { + None + } +} + /// Tries to determine the [BridgeModel] for the target crate pub fn find_bridge(cargo_metadata: &Metadata, bridge: Option<&str>) -> Result { let resolve = cargo_metadata @@ -574,13 +596,21 @@ pub fn find_bridge(cargo_metadata: &Metadata, bridge: Option<&str>) -> Result
= root_package + .targets + .iter() + .flat_map(|target| target.crate_types.iter()) + .map(String::as_str) + .collect(); let bridge = if let Some(bindings) = bridge { if bindings == "cffi" { BridgeModel::Cffi } else if bindings == "bin" { - println!("🔗 Found bin bindings"); - BridgeModel::Bin + BridgeModel::Bin(find_bindings(&deps, &packages)) } else { if !deps.contains_key(bindings) { bail!( @@ -591,41 +621,26 @@ pub fn find_bridge(cargo_metadata: &Metadata, bridge: Option<&str>) -> Result
= package - .targets - .iter() - .flat_map(|target| target.crate_types.iter()) - .map(String::as_str) - .collect(); - - if targets.contains(&"cdylib") { - BridgeModel::Cffi - } else if targets.contains(&"bin") { - BridgeModel::Bin + } else if let Some((bindings, minor)) = find_bindings(&deps, &packages) { + if !targets.contains(&"cdylib") && targets.contains(&"bin") { + BridgeModel::Bin(Some((bindings, minor))) } else { - bail!("Couldn't detect the binding type; Please specify them with --bindings/-b") + BridgeModel::Bindings(bindings, minor) } + } else if targets.contains(&"cdylib") { + BridgeModel::Cffi + } else if targets.contains(&"bin") { + BridgeModel::Bin(find_bindings(&deps, &packages)) + } else { + bail!("Couldn't detect the binding type; Please specify them with --bindings/-b") }; + if !(bridge.is_bindings("pyo3") || bridge.is_bindings("pyo3-ffi")) { + println!("🔗 Found {} bindings", bridge); + } + for &lib in PYO3_BINDING_CRATES.iter() { - if bridge.is_bindings(lib) { + if !bridge.is_bin() && bridge.is_bindings(lib) { let pyo3_node = deps[lib]; if !pyo3_node.features.contains(&"extension-module".to_string()) { let version = cargo_metadata[&pyo3_node.id].version.to_string(); @@ -771,7 +786,7 @@ pub fn find_interpreter( generate_import_lib: bool, ) -> Result> { match bridge { - BridgeModel::Bindings(binding_name, _) => { + BridgeModel::Bindings(binding_name, _) | BridgeModel::Bin(Some((binding_name, _))) => { let mut native_interpreters = false; let mut interpreters = Vec::new(); if let Some(config_file) = env::var_os("PYO3_CONFIG_FILE") { @@ -893,7 +908,7 @@ pub fn find_interpreter( println!("🐍 Using {} to generate the cffi bindings", interpreter); Ok(vec![interpreter]) } - BridgeModel::Bin => Ok(vec![]), + BridgeModel::Bin(None) => Ok(vec![]), BridgeModel::BindingsAbi3(major, minor) => { let interpreter = if !interpreter.is_empty() { PythonInterpreter::check_executables(interpreter, target, bridge) @@ -1125,12 +1140,28 @@ mod test { assert_eq!( find_bridge(&hello_world, Some("bin")).unwrap(), - BridgeModel::Bin + BridgeModel::Bin(None) + ); + assert_eq!( + find_bridge(&hello_world, None).unwrap(), + BridgeModel::Bin(None) ); - assert_eq!(find_bridge(&hello_world, None).unwrap(), BridgeModel::Bin); assert!(find_bridge(&hello_world, Some("rust-cpython")).is_err()); assert!(find_bridge(&hello_world, Some("pyo3")).is_err()); + + let pyo3_bin = MetadataCommand::new() + .manifest_path(&Path::new("test-crates/pyo3-bin").join("Cargo.toml")) + .exec() + .unwrap(); + assert!(matches!( + find_bridge(&pyo3_bin, Some("bin")).unwrap(), + BridgeModel::Bin(Some((..))) + )); + assert!(matches!( + find_bridge(&pyo3_bin, None).unwrap(), + BridgeModel::Bin(Some(..)) + )); } #[test] diff --git a/src/compile.rs b/src/compile.rs index c65589399..f9efb77be 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -36,9 +36,10 @@ fn compile_universal2( python_interpreter: Option<&PythonInterpreter>, bindings_crate: &BridgeModel, ) -> Result> { - let build_type = match bindings_crate { - BridgeModel::Bin => "bin", - _ => "cdylib", + let build_type = if bindings_crate.is_bin() { + "bin" + } else { + "cdylib" }; let mut aarch64_context = context.clone(); aarch64_context.cargo_extra_args.extend(vec![ @@ -137,7 +138,7 @@ fn compile_target( // We need to pass --bins / --lib to set the rustc extra args later // TODO: What do we do when there are multiple bin targets? match bindings_crate { - BridgeModel::Bin => shared_args.push("--bins"), + BridgeModel::Bin(..) => shared_args.push("--bins"), BridgeModel::Cffi | BridgeModel::Bindings(..) | BridgeModel::BindingsAbi3(..) => { shared_args.push("--lib"); // https://github.com/rust-lang/rust/issues/59302#issue-422994250 diff --git a/src/main.rs b/src/main.rs index b41a89bc1..5f0eb6264 100644 --- a/src/main.rs +++ b/src/main.rs @@ -261,7 +261,7 @@ fn pep517(subcommand: Pep517Command) -> Result<()> { // Since afaik all other PEP 517 backends also return linux tagged wheels, we do so too let tags = match context.bridge { - BridgeModel::Bindings(..) => { + BridgeModel::Bindings(..) | BridgeModel::Bin(Some(..)) => { vec![context.interpreter[0].get_tag( &context.target, &[PlatformTag::Linux], @@ -274,7 +274,7 @@ fn pep517(subcommand: Pep517Command) -> Result<()> { .get_platform_tag(&[PlatformTag::Linux], context.universal2)?; vec![format!("cp{}{}-abi3-{}", major, minor, platform)] } - BridgeModel::Bin | BridgeModel::Cffi => { + BridgeModel::Bin(None) | BridgeModel::Cffi => { context .target .get_universal_tags(&[PlatformTag::Linux], context.universal2)? diff --git a/test-crates/pyo3-bin/Cargo.lock b/test-crates/pyo3-bin/Cargo.lock new file mode 100644 index 000000000..14dfa26ec --- /dev/null +++ b/test-crates/pyo3-bin/Cargo.lock @@ -0,0 +1,249 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "indoc" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e" + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "proc-macro2" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6302e85060011447471887705bb7838f14aba43fcb06957d823739a496b3dc" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-bin" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "pyo3-build-config" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b65b546c35d8a3b1b2f0ddbac7c6a569d759f357f2b9df884f5d6b719152c8" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c275a07127c1aca33031a563e384ffdd485aee34ef131116fcd58e3430d1742b" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284fc4485bfbcc9850a6d661d627783f18d19c2ab55880b021671c4ba83e90f7" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53bda0f58f73f5c5429693c96ed57f7abdb38fdfc28ae06da4101a257adb7faf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "syn" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + +[[package]] +name = "unindent" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52fee519a3e570f7df377a06a1a7775cdbfb7aa460be7e08de2b1f0e69973a44" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/test-crates/pyo3-bin/Cargo.toml b/test-crates/pyo3-bin/Cargo.toml new file mode 100644 index 000000000..6a8fcd011 --- /dev/null +++ b/test-crates/pyo3-bin/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pyo3-bin" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +pyo3 = { version = "0.16.5", features = ["auto-initialize"] } diff --git a/test-crates/pyo3-bin/check_installed/check_installed.py b/test-crates/pyo3-bin/check_installed/check_installed.py new file mode 100644 index 000000000..d3f99c958 --- /dev/null +++ b/test-crates/pyo3-bin/check_installed/check_installed.py @@ -0,0 +1,22 @@ +import os +import platform +import sys +from subprocess import check_output + + +def main(): + if platform.system().lower() == "windows": + # Add sys.base_prefix which contains python3y.dll to PATH + # otherwise running `pyo3-bin` might return exit code 3221225781 + path = os.environ["PATH"] + path = path + os.pathsep + sys.base_prefix + os.environ["PATH"] = path + + output = check_output(["pyo3-bin"]).decode("utf-8").strip() + if not output == "Hello, world!": + raise Exception(output) + print("SUCCESS") + + +if __name__ == "__main__": + main() diff --git a/test-crates/pyo3-bin/src/main.rs b/test-crates/pyo3-bin/src/main.rs new file mode 100644 index 000000000..9972bffee --- /dev/null +++ b/test-crates/pyo3-bin/src/main.rs @@ -0,0 +1,12 @@ +use pyo3::prelude::*; + +fn main() -> PyResult<()> { + Python::with_gil(|py| { + let builtins = PyModule::import(py, "builtins")?; + let total: i32 = builtins.getattr("sum")?.call1((vec![1, 2, 3],))?.extract()?; + assert_eq!(total, 6); + println!("Hello, world!"); + Ok(()) + }) +} + diff --git a/tests/run.rs b/tests/run.rs index 5ab72f748..2588d38e1 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -112,6 +112,16 @@ fn editable_pyo3_ffi_pure() { )); } +#[test] +fn integration_pyo3_bin() { + handle_result(integration::test_integration( + "test-crates/pyo3-bin", + None, + "integration_pyo3_bin", + false, + )); +} + #[test] fn integration_pyo3_pure() { handle_result(integration::test_integration(