diff --git a/test-crates/pyo3-bin-msvc-debuginfo/.gitignore b/test-crates/pyo3-bin-msvc-debuginfo/.gitignore new file mode 100644 index 000000000..c1e2f2938 --- /dev/null +++ b/test-crates/pyo3-bin-msvc-debuginfo/.gitignore @@ -0,0 +1,2 @@ +*.py[cdo] +*.pdb diff --git a/test-crates/pyo3-bin-msvc-debuginfo/Cargo.lock b/test-crates/pyo3-bin-msvc-debuginfo/Cargo.lock new file mode 100644 index 000000000..382d53f05 --- /dev/null +++ b/test-crates/pyo3-bin-msvc-debuginfo/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "pyo3-mixed" +version = "0.1.0" diff --git a/test-crates/pyo3-bin-msvc-debuginfo/Cargo.toml b/test-crates/pyo3-bin-msvc-debuginfo/Cargo.toml new file mode 100644 index 000000000..9f63a8acf --- /dev/null +++ b/test-crates/pyo3-bin-msvc-debuginfo/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pyo3-mixed" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "pyo3-bin" # keep the name with a dash to test `.pdb` file name +path = "src/main.rs" diff --git a/test-crates/pyo3-bin-msvc-debuginfo/check_installed/check_installed.py b/test-crates/pyo3-bin-msvc-debuginfo/check_installed/check_installed.py new file mode 100644 index 000000000..28b7886d1 --- /dev/null +++ b/test-crates/pyo3-bin-msvc-debuginfo/check_installed/check_installed.py @@ -0,0 +1,31 @@ +import sys +import platform +from pathlib import Path + + +class MaturinTestError(Exception): + pass + + +def main(): + # e.g. `venv\Scripts` + scripts_dir = Path(sys.executable).parent + + # set by `bin.name = "pyo3-bin"` in `Cargo.toml` + exe_binding_path = scripts_dir / "pyo3-bin.exe" + if not exe_binding_path.exists(): + raise MaturinTestError(f"{exe_binding_path} does not exist") + + # the pdb file of `foo-bar.exe` is `foo_bar.pdb` + exe_binding_debuginfo_path = scripts_dir / "pyo3_bin.pdb" + if not exe_binding_debuginfo_path.exists(): + raise MaturinTestError(f"{exe_binding_debuginfo_path} does not exist") + + +if __name__ == "__main__": + if not platform.system() == "Windows": + raise MaturinTestError("This test is only supported on MSVC") + + main() + + print("SUCCESS") diff --git a/test-crates/pyo3-bin-msvc-debuginfo/pyproject.toml b/test-crates/pyo3-bin-msvc-debuginfo/pyproject.toml new file mode 100644 index 000000000..147625782 --- /dev/null +++ b/test-crates/pyo3-bin-msvc-debuginfo/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["maturin>=1.7,<2.0"] +build-backend = "maturin" + +[project] +name = "pyo3-mixed" +requires-python = ">=3.8" +classifiers = [ + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dynamic = ["version"] + +[tool.maturin] +bindings = "bin" diff --git a/test-crates/pyo3-bin-msvc-debuginfo/src/main.rs b/test-crates/pyo3-bin-msvc-debuginfo/src/main.rs new file mode 100644 index 000000000..e7a11a969 --- /dev/null +++ b/test-crates/pyo3-bin-msvc-debuginfo/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/.gitignore b/test-crates/pyo3-mixed-msvc-debuginfo/.gitignore new file mode 100644 index 000000000..c1e2f2938 --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/.gitignore @@ -0,0 +1,2 @@ +*.py[cdo] +*.pdb diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/Cargo.lock b/test-crates/pyo3-mixed-msvc-debuginfo/Cargo.lock new file mode 100644 index 000000000..2fffc244e --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/Cargo.lock @@ -0,0 +1,171 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" + +[[package]] +name = "portable-atomic" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ee168e30649f7f234c3d49ef5a7a6cbf5134289bc46c29ff3155fa3221c225" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "once_cell", + "portable-atomic", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e61cef80755fe9e46bb8a0b8f20752ca7676dcc07a5277d8b7768c6172e529b3" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ce096073ec5405f5ee2b8b31f03a68e02aa10d5d4f565eca04acc41931fa1c" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2440c6d12bc8f3ae39f1e775266fa5122fd0c8891ce7520fa6048e683ad3de28" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be962f0e06da8f8465729ea2cb71a416d2257dff56cbe40a70d3e62a93ae5d1" +dependencies = [ + "heck", + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "pyo3-mixed" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/Cargo.toml b/test-crates/pyo3-mixed-msvc-debuginfo/Cargo.toml new file mode 100644 index 000000000..817cdfedd --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "pyo3-mixed" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "pyo3_mixed" +crate-type = ["cdylib"] + +[dependencies] +pyo3 = "0.22.0" diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/check_installed/check_installed.py b/test-crates/pyo3-mixed-msvc-debuginfo/check_installed/check_installed.py new file mode 100644 index 000000000..6e04bf725 --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/check_installed/check_installed.py @@ -0,0 +1,36 @@ +import platform +from pathlib import Path +import sysconfig + +import pyo3_mixed + + +class MaturinTestError(Exception): + pass + + +def main(): + # e.g. `...\test-crates\pyo3-mixed-msvc-debuginfo\python\pyo3_mixed\__init__.py` + init_py_path = Path(pyo3_mixed.__file__) + + ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") + + # set by `module-name = "pyo3_mixed._pyo3_lib"` in `pyproject.toml` + # e.g. `_pyo3_lib.cp310-win_amd64.pyd` + lib_pyd_path = init_py_path.with_name(f"_pyo3_lib{ext_suffix}") + if not lib_pyd_path.exists(): + raise MaturinTestError(f"{lib_pyd_path} does not exist") + + # set by `lib.name = "pyo3_mixed"` in `Cargo.toml` + lib_debuginfo_path = init_py_path.with_name("pyo3_mixed.pdb") + if not lib_debuginfo_path.exists(): + raise MaturinTestError(f"{lib_debuginfo_path} does not exist") + + +if __name__ == "__main__": + if not platform.system() == "Windows": + raise MaturinTestError("This test is only supported on MSVC") + + main() + + print("SUCCESS") diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/pyproject.toml b/test-crates/pyo3-mixed-msvc-debuginfo/pyproject.toml new file mode 100644 index 000000000..4ce343c73 --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/pyproject.toml @@ -0,0 +1,19 @@ +[build-system] +requires = ["maturin>=1.7,<2.0"] +build-backend = "maturin" + +[project] +name = "pyo3-mixed" +requires-python = ">=3.8" +classifiers = [ + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +dynamic = ["version"] + +[tool.maturin] +python-source = "python" +# keep the pyd name different from the rust lib name to test `.pdb` file name +module-name = "pyo3_mixed._pyo3_lib" +features = ["pyo3/extension-module"] diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/python/pyo3_mixed/__init__.py b/test-crates/pyo3-mixed-msvc-debuginfo/python/pyo3_mixed/__init__.py new file mode 100644 index 000000000..a66cd14cf --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/python/pyo3_mixed/__init__.py @@ -0,0 +1,8 @@ +from ._pyo3_lib import sum_as_string +from . import _pyo3_lib + +__all__ = ["sum_as_string"] + +__doc__ = _pyo3_lib.__doc__ +if hasattr(_pyo3_lib, "__all__"): + __all__ = _pyo3_lib.__all__ diff --git a/test-crates/pyo3-mixed-msvc-debuginfo/src/lib.rs b/test-crates/pyo3-mixed-msvc-debuginfo/src/lib.rs new file mode 100644 index 000000000..7e7c97469 --- /dev/null +++ b/test-crates/pyo3-mixed-msvc-debuginfo/src/lib.rs @@ -0,0 +1,15 @@ +use pyo3::prelude::*; + +/// A Python module implemented in Rust. +#[pymodule] +// keep the name the same as `module-name = "pyo3_mixed._pyo3_lib"` in `pyproject.toml` +#[pyo3(name = "_pyo3_lib")] +mod pyo3_lib { + use super::*; + + /// Formats the sum of two numbers as string. + #[pyfunction] + fn sum_as_string(a: usize, b: usize) -> PyResult { + Ok((a + b).to_string()) + } +} diff --git a/tests/common/other.rs b/tests/common/other.rs index 2ab2136a6..d63981e6d 100644 --- a/tests/common/other.rs +++ b/tests/common/other.rs @@ -191,7 +191,11 @@ pub fn test_source_distribution( Ok(()) } -fn build_wheel_files(package: impl AsRef, unique_name: &str) -> Result> { +fn build_wheel_files( + package: impl AsRef, + unique_name: &str, + with_debuginfo: bool, +) -> Result> { let manifest_path = package.as_ref().join("Cargo.toml"); let wheel_directory = Path::new("test-crates").join("wheels").join(unique_name); @@ -204,6 +208,7 @@ fn build_wheel_files(package: impl AsRef, unique_name: &str) -> Result, unique_name: &str, ) -> Result<()> { - let mut wheel = build_wheel_files(package, unique_name)?; + let mut wheel = build_wheel_files(package, unique_name, false)?; let mut mtimes = BTreeSet::::new(); for idx in 0..wheel.len() { @@ -240,8 +245,9 @@ pub fn check_wheel_files( package: impl AsRef, expected_files: Vec<&str>, unique_name: &str, + with_debuginfo: bool, ) -> Result<()> { - let wheel = build_wheel_files(package, unique_name)?; + let wheel = build_wheel_files(package, unique_name, with_debuginfo)?; let drop_platform_specific_files = |file: &&str| -> bool { !matches!(Path::new(file).extension(), Some(ext) if ext == "pyc" || ext == "pyd" || ext == "so") }; diff --git a/tests/run.rs b/tests/run.rs index adc5fa996..0bc6ad4aa 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -251,6 +251,30 @@ fn develop_pyo3_ffi_pure(#[case] backend: TestInstallBackend, #[case] name: &str )); } +#[test] +#[cfg_attr(not(target_env = "msvc"), ignore)] // msvc debuginfo is only supported on `msvc` +fn develop_pyo3_mixed_msvc_debuginfo() { + handle_result(develop::test_develop( + "test-crates/pyo3-mixed-msvc-debuginfo", + None, + "develop-pyo3-mixed-msvc-debuginfo", + false, + TestInstallBackend::Pip, + )); +} + +#[test] +#[cfg_attr(not(target_env = "msvc"), ignore)] // msvc debuginfo is only supported on `msvc` +fn develop_pyo3_bin_msvc_debuginfo() { + handle_result(develop::test_develop( + "test-crates/pyo3-bin-msvc-debuginfo", + None, // `bindings=bin` is already set in `pyproject.toml` + "develop-pyo3-bin-msvc-debuginfo", + false, + TestInstallBackend::Pip, + )); +} + #[test] fn integration_pyo3_bin() { let python_implementation = test_python_implementation().unwrap(); @@ -819,6 +843,41 @@ fn pyo3_mixed_include_exclude_wheel_files() { "README.md", ], "wheel-files-pyo3-mixed-include-exclude", + false, + )) +} + +#[test] +#[cfg_attr(not(target_env = "msvc"), ignore)] // msvc debuginfo is only supported on `msvc` +fn pyo3_mixed_msvc_debuginfo_wheel_files() { + handle_result(other::check_wheel_files( + "test-crates/pyo3-mixed-msvc-debuginfo", + vec![ + "pyo3_mixed-0.1.0.dist-info/METADATA", + "pyo3_mixed-0.1.0.dist-info/RECORD", + "pyo3_mixed-0.1.0.dist-info/WHEEL", + "pyo3_mixed/__init__.py", + "pyo3_mixed/pyo3_mixed.pdb", + ], + "wheel-files-pyo3-mixed-msvc-debuginfo", + true, + )) +} + +#[test] +#[cfg_attr(not(target_env = "msvc"), ignore)] // msvc debuginfo is only supported on `msvc` +fn pyo3_bin_msvc_debuginfo_wheel_files() { + handle_result(other::check_wheel_files( + "test-crates/pyo3-bin-msvc-debuginfo", + vec![ + "pyo3_mixed-0.1.0.dist-info/METADATA", + "pyo3_mixed-0.1.0.dist-info/RECORD", + "pyo3_mixed-0.1.0.dist-info/WHEEL", + "pyo3_mixed-0.1.0.data/scripts/pyo3-bin.exe", + "pyo3_mixed-0.1.0.data/scripts/pyo3_bin.pdb", + ], + "wheel-files-pyo3-bin-msvc-debuginfo", + true, )) }