Skip to content

Commit 81eabed

Browse files
messensedavidhewitt
authored andcommitted
Fix generating import lib for python3.13t when abi3 feature is enabled (#4808)
1 parent 1cd0353 commit 81eabed

File tree

3 files changed

+86
-27
lines changed

3 files changed

+86
-27
lines changed

newsfragments/4808.fixed.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix generating import lib for python3.13t when `abi3` feature is enabled.

pyo3-build-config/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ rust-version = "1.63"
1313

1414
[dependencies]
1515
once_cell = "1"
16-
python3-dll-a = { version = "0.2.11", optional = true }
16+
python3-dll-a = { version = "0.2.12", optional = true }
1717
target-lexicon = "0.12.14"
1818

1919
[build-dependencies]
20-
python3-dll-a = { version = "0.2.11", optional = true }
20+
python3-dll-a = { version = "0.2.12", optional = true }
2121
target-lexicon = "0.12.14"
2222

2323
[features]

pyo3-build-config/src/impl_.rs

+83-25
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
497497
let mut lib_dir = None;
498498
let mut executable = None;
499499
let mut pointer_width = None;
500-
let mut build_flags = None;
500+
let mut build_flags: Option<BuildFlags> = None;
501501
let mut suppress_build_script_link_lines = None;
502502
let mut extra_build_script_lines = vec![];
503503

@@ -535,10 +535,12 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
535535
let version = version.ok_or("missing value for version")?;
536536
let implementation = implementation.unwrap_or(PythonImplementation::CPython);
537537
let abi3 = abi3.unwrap_or(false);
538+
let build_flags = build_flags.unwrap_or_default();
539+
let gil_disabled = build_flags.0.contains(&BuildFlag::Py_GIL_DISABLED);
538540
// Fixup lib_name if it's not set
539541
let lib_name = lib_name.or_else(|| {
540542
if let Ok(Ok(target)) = env::var("TARGET").map(|target| target.parse::<Triple>()) {
541-
default_lib_name_for_target(version, implementation, abi3, &target)
543+
default_lib_name_for_target(version, implementation, abi3, gil_disabled, &target)
542544
} else {
543545
None
544546
}
@@ -553,7 +555,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
553555
lib_dir,
554556
executable,
555557
pointer_width,
556-
build_flags: build_flags.unwrap_or_default(),
558+
build_flags,
557559
suppress_build_script_link_lines: suppress_build_script_link_lines.unwrap_or(false),
558560
extra_build_script_lines,
559561
})
@@ -565,7 +567,10 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
565567
// Auto generate python3.dll import libraries for Windows targets.
566568
if self.lib_dir.is_none() {
567569
let target = target_triple_from_env();
568-
let py_version = if self.implementation == PythonImplementation::CPython && self.abi3 {
570+
let py_version = if self.implementation == PythonImplementation::CPython
571+
&& self.abi3
572+
&& !self.is_free_threaded()
573+
{
569574
None
570575
} else {
571576
Some(self.version)
@@ -893,6 +898,9 @@ pub struct CrossCompileConfig {
893898

894899
/// The compile target triple (e.g. aarch64-unknown-linux-gnu)
895900
target: Triple,
901+
902+
/// Python ABI flags, used to detect free-threaded Python builds.
903+
abiflags: Option<String>,
896904
}
897905

898906
impl CrossCompileConfig {
@@ -907,7 +915,7 @@ impl CrossCompileConfig {
907915
) -> Result<Option<Self>> {
908916
if env_vars.any() || Self::is_cross_compiling_from_to(host, target) {
909917
let lib_dir = env_vars.lib_dir_path()?;
910-
let version = env_vars.parse_version()?;
918+
let (version, abiflags) = env_vars.parse_version()?;
911919
let implementation = env_vars.parse_implementation()?;
912920
let target = target.clone();
913921

@@ -916,6 +924,7 @@ impl CrossCompileConfig {
916924
version,
917925
implementation,
918926
target,
927+
abiflags,
919928
}))
920929
} else {
921930
Ok(None)
@@ -989,22 +998,25 @@ impl CrossCompileEnvVars {
989998
}
990999

9911000
/// Parses `PYO3_CROSS_PYTHON_VERSION` environment variable value
992-
/// into `PythonVersion`.
993-
fn parse_version(&self) -> Result<Option<PythonVersion>> {
994-
let version = self
995-
.pyo3_cross_python_version
996-
.as_ref()
997-
.map(|os_string| {
1001+
/// into `PythonVersion` and ABI flags.
1002+
fn parse_version(&self) -> Result<(Option<PythonVersion>, Option<String>)> {
1003+
match self.pyo3_cross_python_version.as_ref() {
1004+
Some(os_string) => {
9981005
let utf8_str = os_string
9991006
.to_str()
10001007
.ok_or("PYO3_CROSS_PYTHON_VERSION is not valid a UTF-8 string")?;
1001-
utf8_str
1008+
let (utf8_str, abiflags) = if let Some(version) = utf8_str.strip_suffix('t') {
1009+
(version, Some("t".to_string()))
1010+
} else {
1011+
(utf8_str, None)
1012+
};
1013+
let version = utf8_str
10021014
.parse()
1003-
.context("failed to parse PYO3_CROSS_PYTHON_VERSION")
1004-
})
1005-
.transpose()?;
1006-
1007-
Ok(version)
1015+
.context("failed to parse PYO3_CROSS_PYTHON_VERSION")?;
1016+
Ok((Some(version), abiflags))
1017+
}
1018+
None => Ok((None, None)),
1019+
}
10081020
}
10091021

10101022
/// Parses `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable value
@@ -1530,16 +1542,27 @@ fn default_cross_compile(cross_compile_config: &CrossCompileConfig) -> Result<In
15301542
let implementation = cross_compile_config
15311543
.implementation
15321544
.unwrap_or(PythonImplementation::CPython);
1545+
let gil_disabled = cross_compile_config.abiflags.as_deref() == Some("t");
15331546

1534-
let lib_name =
1535-
default_lib_name_for_target(version, implementation, abi3, &cross_compile_config.target);
1547+
let lib_name = default_lib_name_for_target(
1548+
version,
1549+
implementation,
1550+
abi3,
1551+
gil_disabled,
1552+
&cross_compile_config.target,
1553+
);
15361554

15371555
let mut lib_dir = cross_compile_config.lib_dir_string();
15381556

15391557
// Auto generate python3.dll import libraries for Windows targets.
15401558
#[cfg(feature = "python3-dll-a")]
15411559
if lib_dir.is_none() {
1542-
let py_version = if abi3 { None } else { Some(version) };
1560+
let py_version = if implementation == PythonImplementation::CPython && abi3 && !gil_disabled
1561+
{
1562+
None
1563+
} else {
1564+
Some(version)
1565+
};
15431566
lib_dir = self::import_lib::generate_import_lib(
15441567
&cross_compile_config.target,
15451568
cross_compile_config
@@ -1652,12 +1675,16 @@ fn default_lib_name_for_target(
16521675
version: PythonVersion,
16531676
implementation: PythonImplementation,
16541677
abi3: bool,
1678+
gil_disabled: bool,
16551679
target: &Triple,
16561680
) -> Option<String> {
16571681
if target.operating_system == OperatingSystem::Windows {
1658-
Some(default_lib_name_windows(version, implementation, abi3, false, false, false).unwrap())
1682+
Some(
1683+
default_lib_name_windows(version, implementation, abi3, false, false, gil_disabled)
1684+
.unwrap(),
1685+
)
16591686
} else if is_linking_libpython_for_target(target) {
1660-
Some(default_lib_name_unix(version, implementation, None, false).unwrap())
1687+
Some(default_lib_name_unix(version, implementation, None, gil_disabled).unwrap())
16611688
} else {
16621689
None
16631690
}
@@ -1906,7 +1933,14 @@ pub fn make_interpreter_config() -> Result<InterpreterConfig> {
19061933
// Auto generate python3.dll import libraries for Windows targets.
19071934
#[cfg(feature = "python3-dll-a")]
19081935
{
1909-
let py_version = if interpreter_config.abi3 {
1936+
let gil_disabled = interpreter_config
1937+
.build_flags
1938+
.0
1939+
.contains(&BuildFlag::Py_GIL_DISABLED);
1940+
let py_version = if interpreter_config.implementation == PythonImplementation::CPython
1941+
&& interpreter_config.abi3
1942+
&& !gil_disabled
1943+
{
19101944
None
19111945
} else {
19121946
Some(interpreter_config.version)
@@ -2706,7 +2740,7 @@ mod tests {
27062740

27072741
assert_eq!(
27082742
env_vars.parse_version().unwrap(),
2709-
Some(PythonVersion { major: 3, minor: 9 })
2743+
(Some(PythonVersion { major: 3, minor: 9 }), None),
27102744
);
27112745

27122746
let env_vars = CrossCompileEnvVars {
@@ -2716,7 +2750,25 @@ mod tests {
27162750
pyo3_cross_python_implementation: None,
27172751
};
27182752

2719-
assert_eq!(env_vars.parse_version().unwrap(), None);
2753+
assert_eq!(env_vars.parse_version().unwrap(), (None, None));
2754+
2755+
let env_vars = CrossCompileEnvVars {
2756+
pyo3_cross: None,
2757+
pyo3_cross_lib_dir: None,
2758+
pyo3_cross_python_version: Some("3.13t".into()),
2759+
pyo3_cross_python_implementation: None,
2760+
};
2761+
2762+
assert_eq!(
2763+
env_vars.parse_version().unwrap(),
2764+
(
2765+
Some(PythonVersion {
2766+
major: 3,
2767+
minor: 13
2768+
}),
2769+
Some("t".into())
2770+
),
2771+
);
27202772

27212773
let env_vars = CrossCompileEnvVars {
27222774
pyo3_cross: None,
@@ -2799,6 +2851,11 @@ mod tests {
27992851
version: Some(interpreter_config.version),
28002852
implementation: Some(interpreter_config.implementation),
28012853
target: triple!("x86_64-unknown-linux-gnu"),
2854+
abiflags: if interpreter_config.is_free_threaded() {
2855+
Some("t".into())
2856+
} else {
2857+
None
2858+
},
28022859
};
28032860

28042861
let sysconfigdata_path = match find_sysconfigdata(&cross) {
@@ -3074,6 +3131,7 @@ mod tests {
30743131
version: None,
30753132
implementation: None,
30763133
target: triple!("x86_64-unknown-linux-gnu"),
3134+
abiflags: None,
30773135
})
30783136
.unwrap_err();
30793137

0 commit comments

Comments
 (0)