Skip to content

Commit d13167d

Browse files
authored
Merge pull request #82 from PyO3/python-313t
Generate import libraries for free-threaded Python 3.13+ builds
2 parents ca5ab09 + c3a6098 commit d13167d

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

.github/workflows/dll.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
name: Collect pythonXY.dll
88
runs-on: windows-latest
99
steps:
10-
- uses: actions/setup-python@v5
10+
- uses: Quansight-Labs/setup-python@v5
1111
with:
1212
python-version: |
1313
pypy3.8
@@ -20,12 +20,13 @@ jobs:
2020
3.11
2121
3.12
2222
3.13
23+
3.13t
2324
allow-prereleases: true
2425
- name: Copy pythonXY.dll
2526
shell: bash
2627
run: |
2728
set -e
28-
for VER in 3.7 3.8 3.9 3.10 3.11 3.12 3.13; do
29+
for VER in 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.13t; do
2930
VER_NUM=$(echo $VER | sed 's/\.//')
3031
PREFIX=$(py -$VER -c "import sys; print(sys.base_prefix, end='')")
3132
cp "$PREFIX/python$VER_NUM.dll" .

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ Generating version-specific `python3y.dll` import libraries
9595
-----------------------------------------------------------
9696

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

100100
See the `ImportLibraryGenerator` builder API description for details.
101101

102102
Maintenance
103103
-----------
104104

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

107107
The upstream version of this file is located in the [CPython project][cpython]
108108
repository under the path `Misc/stable_abi.toml`.

src/lib.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
//! -----------------------------------------------------------
9292
//!
9393
//! As an advanced feature, `python3-dll-a` can generate Python version
94-
//! specific import libraries such as `python39.lib`.
94+
//! specific import libraries such as `python39.lib` or `python313t.lib`.
9595
//!
9696
//! See the [`ImportLibraryGenerator`] builder API description for details.
9797
@@ -137,6 +137,9 @@ pub enum PythonImplementation {
137137
/// Generates `python3.dll` or `pythonXY.dll` import library directly from the
138138
/// embedded Python ABI definitions data for the specified compile target.
139139
///
140+
/// ABI-tagged versioned Python DLLs such as `python313t.dll` are also supported
141+
/// via an optional ABI flags string parameter.
142+
///
140143
/// Example usage
141144
/// -------------
142145
///
@@ -164,6 +167,13 @@ pub enum PythonImplementation {
164167
/// .version(Some((3, 8)))
165168
/// .generate(Path::new("target/python3-lib"))
166169
/// .unwrap();
170+
///
171+
/// // Generate `python313t.lib` in "target/python3-lib"
172+
/// ImportLibraryGenerator::new("x86_64", "msvc")
173+
/// .version(Some((3, 13)))
174+
/// .abiflags(Some("t"))
175+
/// .generate(Path::new("target/python3-lib"))
176+
/// .unwrap();
167177
/// ```
168178
#[derive(Debug, Clone)]
169179
pub struct ImportLibraryGenerator {
@@ -175,6 +185,11 @@ pub struct ImportLibraryGenerator {
175185
version: Option<(u8, u8)>,
176186
/// Python interpreter implementation
177187
implementation: PythonImplementation,
188+
/// Optional Python ABI flags
189+
///
190+
/// For example, `"t"` stands for the free-threaded CPython v3.13 build
191+
/// aka CPython `3.13t`.
192+
abiflags: Option<String>,
178193
}
179194

180195
impl ImportLibraryGenerator {
@@ -186,11 +201,12 @@ impl ImportLibraryGenerator {
186201
/// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`)
187202
/// is passed in `env`.
188203
pub fn new(arch: &str, env: &str) -> Self {
189-
Self {
204+
ImportLibraryGenerator {
190205
arch: arch.to_string(),
191206
env: env.to_string(),
192207
version: None,
193208
implementation: PythonImplementation::CPython,
209+
abiflags: None,
194210
}
195211
}
196212

@@ -202,6 +218,19 @@ impl ImportLibraryGenerator {
202218
self
203219
}
204220

221+
/// Sets the ABI flags for the `pythonXY<abi>.dll` import library.
222+
///
223+
/// For example, `"t"` stands for the free-threaded CPython v3.13 build
224+
/// aka CPython `3.13t`.
225+
/// In this case, `python313t.dll` import library will be generated.
226+
///
227+
/// The untagged versioned `pythonXY.dll` import library
228+
/// is generated by default.
229+
pub fn abiflags(&mut self, flags: Option<&str>) -> &mut Self {
230+
self.abiflags = flags.map(ToOwned::to_owned);
231+
self
232+
}
233+
205234
/// Sets Python interpreter implementation
206235
pub fn implementation(&mut self, implementation: PythonImplementation) -> &mut Self {
207236
self.implementation = implementation;
@@ -256,7 +285,11 @@ impl ImportLibraryGenerator {
256285
Some((3, 10)) => ("python310.def", include_str!("python310.def")),
257286
Some((3, 11)) => ("python311.def", include_str!("python311.def")),
258287
Some((3, 12)) => ("python312.def", include_str!("python312.def")),
259-
Some((3, 13)) => ("python313.def", include_str!("python313.def")),
288+
Some((3, 13)) => match self.abiflags.as_deref() {
289+
Some("t") => ("python313t.def", include_str!("python313t.def")),
290+
None => ("python313.def", include_str!("python313.def")),
291+
_ => return Err(Error::new(ErrorKind::Other, "Unsupported Python ABI flags")),
292+
},
260293
_ => return Err(Error::new(ErrorKind::Other, "Unsupported Python version")),
261294
},
262295
PythonImplementation::PyPy => match self.version {
@@ -532,6 +565,15 @@ mod tests {
532565
.unwrap();
533566
}
534567

568+
// Free-threaded CPython v3.13+
569+
for minor in 13..=13 {
570+
ImportLibraryGenerator::new("x86_64", "gnu")
571+
.version(Some((3, minor)))
572+
.abiflags(Some("t"))
573+
.generate(&dir)
574+
.unwrap();
575+
}
576+
535577
// PyPy
536578
for minor in 7..=10 {
537579
ImportLibraryGenerator::new("x86_64", "gnu")
@@ -571,6 +613,15 @@ mod tests {
571613
.unwrap();
572614
}
573615

616+
// Free-threaded CPython v3.13+
617+
for minor in 13..=13 {
618+
ImportLibraryGenerator::new("x86_64", "msvc")
619+
.version(Some((3, minor)))
620+
.abiflags(Some("t"))
621+
.generate(&dir)
622+
.unwrap();
623+
}
624+
574625
// PyPy
575626
for minor in 7..=10 {
576627
ImportLibraryGenerator::new("x86_64", "msvc")

0 commit comments

Comments
 (0)