Skip to content
Closed
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
15 changes: 13 additions & 2 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1363,16 +1363,27 @@ def _check_raw_dylib_macro(session: nox.Session):
max_minor = int(max_version.split(".")[1])

# Build the set of DLL names that default_lib_name_windows can produce
expected_dlls = {"python3", "python3_d"}
expected_dlls = {
"python3",
"python3_d",
"libpython3",
"libpython3_d",
}
for minor in range(min_minor, max_minor + 1):
expected_dlls.add(f"python3{minor}")
expected_dlls.add(f"python3{minor}_d")
expected_dlls.add(f"libpython3.{minor}")
expected_dlls.add(f"libpython3.{minor}_d")
if minor >= 13:
expected_dlls.add(f"python3{minor}t")
expected_dlls.add(f"python3{minor}t_d")
expected_dlls.add(f"libpython3.{minor}t")
expected_dlls.add(f"libpython3.{minor}t_d")
if minor >= 15:
expected_dlls.add("python3t")
expected_dlls.add("python3t_d")
expected_dlls.add("libpython3t")
expected_dlls.add("libpython3t_d")

# PyPy DLL names (libpypy3.X-c.dll)
pypy_min, pypy_max = _parse_supported_interpreter_version("pypy")
Expand All @@ -1383,7 +1394,7 @@ def _check_raw_dylib_macro(session: nox.Session):

# Parse the DLL name list in the extern_libpython!(@impl ...) invocation
lib_rs = (PYO3_DIR / "pyo3-ffi" / "src" / "impl_" / "macros.rs").read_text()
found_dlls = set(re.findall(r'"((?:python|libpypy)[^"]+)"', lib_rs))
found_dlls = set(re.findall(r'"((?:python|libpython|libpypy)[^"]+)"', lib_rs))

missing = expected_dlls - found_dlls
extra = found_dlls - expected_dlls
Expand Down
40 changes: 29 additions & 11 deletions pyo3-build-config/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2302,7 +2302,12 @@ const WINDOWS_STABLE_ABI_DEBUG_LIB_NAME: &str = "python3_d";
#[allow(dead_code)]
fn default_lib_name_for_target(abi: PythonAbi, target: &Triple) -> String {
if target.operating_system == OperatingSystem::Windows {
default_lib_name_windows(abi, false, false).unwrap()
default_lib_name_windows(
abi,
matches!(target.environment, Environment::Gnu | Environment::GnuLlvm),
false,
)
.unwrap()
} else {
default_lib_name_unix(
abi,
Expand All @@ -2314,6 +2319,10 @@ fn default_lib_name_for_target(abi: PythonAbi, target: &Triple) -> String {
}

fn default_lib_name_windows(abi: PythonAbi, mingw: bool, debug: bool) -> Result<String> {
// set `lib` prefix for mingw, as its python abi library is shipped prefixed. also mingw
// library has the version separated by dot
let (lib_prefix, separator) = if mingw { ("lib", ".") } else { ("", "") };

if abi.implementation.is_pypy() {
// PyPy on Windows ships `libpypy3.X-c.dll` (e.g. `libpypy3.11-c.dll`),
// not CPython's `pythonXY.dll`. With raw-dylib linking we need the real
Expand All @@ -2326,7 +2335,7 @@ fn default_lib_name_windows(abi: PythonAbi, mingw: bool, debug: bool) -> Result<
// CPython bug: linking against python3_d.dll raises error
// https://github.com/python/cpython/issues/101614
Ok(format!(
"python{}{}_d",
"{lib_prefix}python{}{separator}{}_d",
abi.version.major, abi.version.minor
))
} else if abi.kind == PythonAbiKind::Stable(StableAbi::Abi3)
Expand All @@ -2340,34 +2349,43 @@ fn default_lib_name_windows(abi: PythonAbi, mingw: bool, debug: bool) -> Result<
if abi.kind == PythonAbiKind::Stable(StableAbi::Abi3t) {
lib_name = lib_name.replace("python3", "python3t");
}
Ok(lib_name)
Ok(format!("{lib_prefix}{lib_name}"))
} else if mingw {
ensure!(
!abi.kind.is_free_threaded(),
"MinGW free-threaded builds are not currently tested or supported"
);
// https://packages.msys2.org/base/mingw-w64-python
Ok(format!("python{}.{}", abi.version.major, abi.version.minor))
Ok(format!(
"{lib_prefix}python{}.{}",
abi.version.major, abi.version.minor
))
} else if abi.kind().is_free_threaded() {
#[expect(deprecated, reason = "using constant internally")]
{
ensure!(abi.version() >= PythonVersion::PY313, "Cannot compile extensions for the free-threaded build on Python versions earlier than 3.13, found {}.{}", abi.version.major, abi.version.minor);
}
if debug {
Ok(format!(
"python{}{}t_d",
"{lib_prefix}python{}{separator}{}t_d",
abi.version.major, abi.version.minor
))
} else {
Ok(format!("python{}{}t", abi.version.major, abi.version.minor))
Ok(format!(
"{lib_prefix}python{}{separator}{}t",
abi.version.major, abi.version.minor
))
}
} else if debug {
Ok(format!(
"python{}{}_d",
"{lib_prefix}python{}{separator}{}_d",
abi.version.major, abi.version.minor
))
} else {
Ok(format!("python{}{}", abi.version.major, abi.version.minor))
Ok(format!(
"{lib_prefix}python{}{separator}{}",
abi.version.major, abi.version.minor
))
}
}

Expand Down Expand Up @@ -3091,7 +3109,7 @@ mod tests {
let implementation = PythonImplementation::CPython;
let version = PythonVersion::PY39;
let config = InterpreterConfigBuilder::new(implementation, version)
.lib_name("python39".to_string())
.lib_name("libpython3.9".to_string())
.lib_dir("/usr/lib/mingw".to_string())
.finalize()
.unwrap();
Expand Down Expand Up @@ -3290,7 +3308,7 @@ mod tests {
false,
)
.unwrap(),
"python3.9",
"libpython3.9",
);
assert_eq!(
super::default_lib_name_windows(
Expand All @@ -3302,7 +3320,7 @@ mod tests {
false,
)
.unwrap(),
"python3",
"libpython3",
);
assert_eq!(
super::default_lib_name_windows(
Expand Down
8 changes: 8 additions & 0 deletions pyo3-build-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,21 @@ pub fn print_expected_cfgs() {
"python3_d".to_string(),
"python3t".to_string(),
"python3t_d".to_string(),
"libpython3".to_string(),
"libpython3_d".to_string(),
"libpython3t".to_string(),
"libpython3t_d".to_string(),
];
for i in impl_::MINIMUM_SUPPORTED_VERSION.minor..=impl_::STABLE_ABI_MAX_MINOR + 1 {
dll_names.push(format!("python3{i}"));
dll_names.push(format!("python3{i}_d"));
dll_names.push(format!("libpython3.{i}"));
dll_names.push(format!("libpython3.{i}_d"));
if i >= 13 {
dll_names.push(format!("python3{i}t"));
dll_names.push(format!("python3{i}t_d"));
dll_names.push(format!("libpython3.{i}t"));
dll_names.push(format!("libpython3.{i}t_d"));
}
}
// PyPy DLL names (libpypy3.X-c.dll)
Expand Down
24 changes: 12 additions & 12 deletions pyo3-ffi/src/impl_/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,21 +257,21 @@ macro_rules! extern_libpython {
($abi:literal { $($body:tt)* }) => {
extern_libpython!(@impl $abi { $($body)* }
// abi3
"python3", "python3_d",
"python3", "python3_d", "libpython3", "libpython3_d",
// abi3t
"python3t", "python3t_d",
"python3t", "python3t_d", "libpython3t", "libpython3t_d",
// Python 3.9 - 3.15
"python39", "python39_d",
"python310", "python310_d",
"python311", "python311_d",
"python312", "python312_d",
"python313", "python313_d",
"python314", "python314_d",
"python315", "python315_d",
"python39", "python39_d", "libpython3.9", "libpython3.9_d",
"python310", "python310_d", "libpython3.10", "libpython3.10_d",
"python311", "python311_d", "libpython3.11", "libpython3.11_d",
"python312", "python312_d", "libpython3.12", "libpython3.12_d",
"python313", "python313_d", "libpython3.13", "libpython3.13_d",
"python314", "python314_d", "libpython3.14", "libpython3.14_d",
"python315", "python315_d", "libpython3.15", "libpython3.15_d",
// free-threaded builds (3.13+)
"python313t", "python313t_d",
"python314t", "python314t_d",
"python315t", "python315t_d",
"python313t", "python313t_d", "libpython3.13t", "libpython3.13t_d",
"python314t", "python314t_d", "libpython3.14t", "libpython3.14t_d",
"python315t", "python315t_d", "libpython3.15t", "libpython3.15t_d",
// PyPy (DLL is libpypy3.X-c.dll, not pythonXY.dll)
"libpypy3.11-c",
);
Expand Down
Loading