Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/dll.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
name: Collect pythonXY.dll
runs-on: windows-latest
steps:
- uses: actions/setup-python@v5
- uses: Quansight-Labs/setup-python@v5
with:
python-version: |
pypy3.8
Expand All @@ -20,12 +20,13 @@ jobs:
3.11
3.12
3.13
3.13t
allow-prereleases: true
- name: Copy pythonXY.dll
shell: bash
run: |
set -e
for VER in 3.7 3.8 3.9 3.10 3.11 3.12 3.13; do
for VER in 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.13t; do
VER_NUM=$(echo $VER | sed 's/\.//')
PREFIX=$(py -$VER -c "import sys; print(sys.base_prefix, end='')")
cp "$PREFIX/python$VER_NUM.dll" .
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ Generating version-specific `python3y.dll` import libraries
-----------------------------------------------------------

As an advanced feature, `python3-dll-a` can generate Python version
specific import libraries such as `python39.lib`.
specific import libraries such as `python39.lib` or `python313t.lib`.

See the `ImportLibraryGenerator` builder API description for details.

Maintenance
-----------

This crate embeds Module-Defitions based on the `stable_abi.toml` file from CPython.
This crate embeds Module-Definitions based on the `stable_abi.toml` file from CPython.

The upstream version of this file is located in the [CPython project][cpython]
repository under the path `Misc/stable_abi.toml`.
Expand Down
57 changes: 54 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
//! -----------------------------------------------------------
//!
//! As an advanced feature, `python3-dll-a` can generate Python version
//! specific import libraries such as `python39.lib`.
//! specific import libraries such as `python39.lib` or `python313t.lib`.
//!
//! See the [`ImportLibraryGenerator`] builder API description for details.

Expand Down Expand Up @@ -137,6 +137,9 @@ pub enum PythonImplementation {
/// Generates `python3.dll` or `pythonXY.dll` import library directly from the
/// embedded Python ABI definitions data for the specified compile target.
///
/// ABI-tagged versioned Python DLLs such as `python313t.dll` are also supported
/// via an optional ABI flags string parameter.
///
/// Example usage
/// -------------
///
Expand Down Expand Up @@ -164,6 +167,13 @@ pub enum PythonImplementation {
/// .version(Some((3, 8)))
/// .generate(Path::new("target/python3-lib"))
/// .unwrap();
///
/// // Generate `python313t.lib` in "target/python3-lib"
/// ImportLibraryGenerator::new("x86_64", "msvc")
/// .version(Some((3, 13)))
/// .abiflags(Some("t"))
/// .generate(Path::new("target/python3-lib"))
/// .unwrap();
/// ```
#[derive(Debug, Clone)]
pub struct ImportLibraryGenerator {
Expand All @@ -175,6 +185,11 @@ pub struct ImportLibraryGenerator {
version: Option<(u8, u8)>,
/// Python interpreter implementation
implementation: PythonImplementation,
/// Optional Python ABI flags
///
/// For example, `"t"` stands for the free-threaded CPython v3.13 build
/// aka CPython `3.13t`.
abiflags: Option<String>,
}

impl ImportLibraryGenerator {
Expand All @@ -186,11 +201,12 @@ impl ImportLibraryGenerator {
/// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`)
/// is passed in `env`.
pub fn new(arch: &str, env: &str) -> Self {
Self {
ImportLibraryGenerator {
arch: arch.to_string(),
env: env.to_string(),
version: None,
implementation: PythonImplementation::CPython,
abiflags: None,
}
}

Expand All @@ -202,6 +218,19 @@ impl ImportLibraryGenerator {
self
}

/// Sets the ABI flags for the `pythonXY<abi>.dll` import library.
///
/// For example, `"t"` stands for the free-threaded CPython v3.13 build
/// aka CPython `3.13t`.
/// In this case, `python313t.dll` import library will be generated.
///
/// The untagged versioned `pythonXY.dll` import library
/// is generated by default.
pub fn abiflags(&mut self, flags: Option<&str>) -> &mut Self {
self.abiflags = flags.map(ToOwned::to_owned);
self
}

/// Sets Python interpreter implementation
pub fn implementation(&mut self, implementation: PythonImplementation) -> &mut Self {
self.implementation = implementation;
Expand Down Expand Up @@ -256,7 +285,11 @@ impl ImportLibraryGenerator {
Some((3, 10)) => ("python310.def", include_str!("python310.def")),
Some((3, 11)) => ("python311.def", include_str!("python311.def")),
Some((3, 12)) => ("python312.def", include_str!("python312.def")),
Some((3, 13)) => ("python313.def", include_str!("python313.def")),
Some((3, 13)) => match self.abiflags.as_deref() {
Some("t") => ("python313t.def", include_str!("python313t.def")),
None => ("python313.def", include_str!("python313.def")),
_ => return Err(Error::new(ErrorKind::Other, "Unsupported Python ABI flags")),
},
_ => return Err(Error::new(ErrorKind::Other, "Unsupported Python version")),
},
PythonImplementation::PyPy => match self.version {
Expand Down Expand Up @@ -532,6 +565,15 @@ mod tests {
.unwrap();
}

// Free-threaded CPython v3.13+
for minor in 13..=13 {
ImportLibraryGenerator::new("x86_64", "gnu")
.version(Some((3, minor)))
.abiflags(Some("t"))
.generate(&dir)
.unwrap();
}

// PyPy
for minor in 7..=10 {
ImportLibraryGenerator::new("x86_64", "gnu")
Expand Down Expand Up @@ -571,6 +613,15 @@ mod tests {
.unwrap();
}

// Free-threaded CPython v3.13+
for minor in 13..=13 {
ImportLibraryGenerator::new("x86_64", "msvc")
.version(Some((3, minor)))
.abiflags(Some("t"))
.generate(&dir)
.unwrap();
}

// PyPy
for minor in 7..=10 {
ImportLibraryGenerator::new("x86_64", "msvc")
Expand Down