From ae0dcc93fa81f133303a4342fb9645f4befafc42 Mon Sep 17 00:00:00 2001 From: messense Date: Tue, 10 May 2022 15:46:47 +0800 Subject: [PATCH] Add support for generating non-abi3 python import libraries for Windows targets --- Architecture.md | 4 ++-- Cargo.toml | 4 +++- examples/maturin-starter/Cargo.toml | 2 +- guide/src/building_and_distribution.md | 14 +++++++------- guide/src/features.md | 6 +++--- pyo3-build-config/src/impl_.rs | 12 +++++++++--- pyo3-build-config/src/import_lib.rs | 14 +++++++++----- pyo3-ffi/Cargo.toml | 4 +++- 8 files changed, 37 insertions(+), 23 deletions(-) diff --git a/Architecture.md b/Architecture.md index 5f676b19200..468a5bfff07 100644 --- a/Architecture.md +++ b/Architecture.md @@ -193,9 +193,9 @@ Some of the functionality of `pyo3-build-config`: `PYO3_CROSS_PYTHON_IMPLEMENTATION`) or system files. When cross compiling extension modules it is often possible to make it work without any additional user input. - - When an experimental feature `generate-abi3-import-lib` is enabled, the `pyo3-ffi` build script can + - When an experimental feature `generate-import-lib` is enabled, the `pyo3-ffi` build script can generate `python3.dll` import libraries for Windows targets automatically via an external - [`python3-dll-a`] crate. This enables the users to cross compile abi3 extensions for Windows without + [`python3-dll-a`] crate. This enables the users to cross compile Python extensions for Windows without having to install any Windows Python libraries. diff --git a/Cargo.toml b/Cargo.toml index 7ce281fc67e..182234f5076 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,7 +80,9 @@ abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39"] abi3-py310 = ["abi3", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310"] # Automatically generates `python3.dll` import libraries for Windows targets. -generate-abi3-import-lib = ["pyo3-ffi/generate-abi3-import-lib"] +generate-import-lib = ["pyo3-ffi/generate-import-lib"] +# Deprecated, replaced by `generate-import-lib` +generate-abi3-import-lib = ["generate-import-lib"] # Changes `Python::with_gil` and `Python::acquire_gil` to automatically initialize the # Python interpreter if needed. diff --git a/examples/maturin-starter/Cargo.toml b/examples/maturin-starter/Cargo.toml index 21e8c90cc54..64318dcfe87 100644 --- a/examples/maturin-starter/Cargo.toml +++ b/examples/maturin-starter/Cargo.toml @@ -11,6 +11,6 @@ crate-type = ["cdylib"] pyo3 = { path = "../../", features = ["extension-module"] } [features] -abi3 = ["pyo3/abi3-py37", "pyo3/generate-abi3-import-lib"] +abi3 = ["pyo3/abi3-py37", "pyo3/generate-import-lib"] [workspace] diff --git a/guide/src/building_and_distribution.md b/guide/src/building_and_distribution.md index 1e9079b2526..60332c9ac6d 100644 --- a/guide/src/building_and_distribution.md +++ b/guide/src/building_and_distribution.md @@ -163,7 +163,7 @@ PyO3 will still attempt to compile `abi3` extension modules after displaying a w On Unix-like systems this works unconditionally; on Windows you must also set the `RUSTFLAGS` environment variable to contain `-L native=/path/to/python/libs` so that the linker can find `python3.lib`. -If the `python3.dll` import library is not available, an experimental `generate-abi3-import-lib` crate +If the `python3.dll` import library is not available, an experimental `generate-import-lib` crate feature may be enabled, and the required library will be created and used by PyO3 automatically. *Note*: MSVC targets require LLVM binutils (`llvm-dlltool`) to be available in `PATH` for @@ -243,12 +243,12 @@ When cross-compiling, PyO3's build script cannot execute the target Python inter * `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python installation. This variable is only needed if PyO3 cannot determine the version to target from `abi3-py3*` features, or if `PYO3_CROSS_LIB_DIR` is not set, or if there are multiple versions of Python present in `PYO3_CROSS_LIB_DIR`. * `PYO3_CROSS_PYTHON_IMPLEMENTATION`: Python implementation name ("CPython" or "PyPy") of the target Python installation. CPython is assumed by default when this variable is not set, unless `PYO3_CROSS_LIB_DIR` is set for a Unix-like target and PyO3 can get the interpreter configuration from `_sysconfigdata*.py`. -An experimental `pyo3` crate feature `generate-abi3-import-lib` enables the user to cross-compile -"abi3" extension modules for Windows targets without setting the `PYO3_CROSS_LIB_DIR` environment +An experimental `pyo3` crate feature `generate-import-lib` enables the user to cross-compile +extension modules for Windows targets without setting the `PYO3_CROSS_LIB_DIR` environment variable or providing any Windows Python library files. It uses an external [`python3-dll-a`] crate -to generate import libraries for the Stable ABI Python DLL for MinGW-w64 and MSVC compile targets. -*Note*: MSVC targets require LLVM binutils to be available on the host system. -More specifically, `python3-dll-a` requires `llvm-dlltool` executable to be present in `PATH` when +to generate import libraries for the Python DLL for MinGW-w64 and MSVC compile targets. +*Note*: MSVC targets require LLVM binutils or MSVC build tools to be available on the host system. +More specifically, `python3-dll-a` requires `llvm-dlltool` or `lib.exe` executable to be present in `PATH` when targeting `*-pc-windows-msvc`. An example might look like the following (assuming your target's sysroot is at `/home/pyo3/cross/sysroot` and that your target is `armv7`): @@ -278,7 +278,7 @@ cargo build --target x86_64-pc-windows-gnu Any of the `abi3-py3*` features can be enabled instead of setting `PYO3_CROSS_PYTHON_VERSION` in the above examples. `PYO3_CROSS_LIB_DIR` can often be omitted when cross compiling extension modules for Unix and macOS targets, -or when cross compiling "abi3" extension modules for Windows and the experimental `generate-abi3-import-lib` +or when cross compiling extension modules for Windows and the experimental `generate-import-lib` crate feature is enabled. The following resources may also be useful for cross-compiling: diff --git a/guide/src/features.md b/guide/src/features.md index c67de97ec30..e704d093956 100644 --- a/guide/src/features.md +++ b/guide/src/features.md @@ -30,12 +30,12 @@ These features are extensions of the `abi3` feature to specify the exact minimum See the [building and distribution](building_and_distribution.md#minimum-python-version-for-abi3) section for further detail. -### `generate-abi3-import-lib` +### `generate-import-lib` -This experimental feature is used to generate import libraries for the Stable ABI Python DLL +This experimental feature is used to generate import libraries for Python DLL for MinGW-w64 and MSVC (cross-)compile targets. -Enabling it allows to (cross-)compile `abi3` extension modules to any Windows targets +Enabling it allows to (cross-)compile extension modules to any Windows targets without having to install the Windows Python distribution files for the target. See the [building and distribution](building_and_distribution.md#building-abi3-extensions-without-a-python-interpreter) diff --git a/pyo3-build-config/src/impl_.rs b/pyo3-build-config/src/impl_.rs index 17cb020c993..f578d62c165 100644 --- a/pyo3-build-config/src/impl_.rs +++ b/pyo3-build-config/src/impl_.rs @@ -1409,8 +1409,9 @@ fn default_cross_compile(cross_compile_config: &CrossCompileConfig) -> Result Result { // Auto generate python3.dll import libraries for Windows targets. #[cfg(feature = "python3-dll-a")] { - interpreter_config.lib_dir = self::import_lib::generate_abi3_import_lib(&host)?; + let py_version = if interpreter_config.abi3 { + None + } else { + Some(interpreter_config.version) + }; + interpreter_config.lib_dir = self::import_lib::generate_import_lib(&host, py_version)?; } Ok(interpreter_config) diff --git a/pyo3-build-config/src/import_lib.rs b/pyo3-build-config/src/import_lib.rs index ac88c5eefa5..ef941542a50 100644 --- a/pyo3-build-config/src/import_lib.rs +++ b/pyo3-build-config/src/import_lib.rs @@ -7,21 +7,24 @@ use python3_dll_a::ImportLibraryGenerator; use crate::errors::{Context, Result}; -use super::{Architecture, OperatingSystem, Triple}; +use super::{Architecture, OperatingSystem, PythonVersion, Triple}; -/// Generates the `python3.dll` import library for Windows targets. +/// Generates the `python3.dll` or `pythonXY.dll` import library for Windows targets. /// /// Places the generated import library into the build script output directory /// and returns the full library directory path. /// /// Does nothing if the target OS is not Windows. -pub(super) fn generate_abi3_import_lib(target: &Triple) -> Result> { +pub(super) fn generate_import_lib( + target: &Triple, + py_version: Option, +) -> Result> { if target.operating_system != OperatingSystem::Windows { return Ok(None); } - let out_dir = env::var_os("OUT_DIR") - .expect("generate_abi3_import_lib() must be called from a build script"); + let out_dir = + env::var_os("OUT_DIR").expect("generate_import_lib() must be called from a build script"); // Put the newly created import library into the build script output directory. let mut out_lib_dir = PathBuf::from(out_dir); @@ -37,6 +40,7 @@ pub(super) fn generate_abi3_import_lib(target: &Triple) -> Result let env = target.environment.to_string(); ImportLibraryGenerator::new(&arch, &env) + .version(py_version.map(|v| (v.major, v.minor))) .generate(&out_lib_dir) .context("failed to generate python3.dll import library")?; diff --git a/pyo3-ffi/Cargo.toml b/pyo3-ffi/Cargo.toml index 6691f29c1c8..176b0c8df29 100644 --- a/pyo3-ffi/Cargo.toml +++ b/pyo3-ffi/Cargo.toml @@ -33,7 +33,9 @@ abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39"] abi3-py310 = ["abi3", "pyo3-build-config/abi3-py310"] # Automatically generates `python3.dll` import libraries for Windows targets. -generate-abi3-import-lib = ["pyo3-build-config/python3-dll-a"] +generate-import-lib = ["pyo3-build-config/python3-dll-a"] +# Deprecated, replaced by `generate-import-lib` +generate-abi3-import-lib = ["generate-import-lib"] [build-dependencies]