From 535b25b0226300d654d687691dca5ab4c982a8e3 Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Wed, 21 Oct 2026 12:14:28 -0600 Subject: [PATCH] Honor SETUPTOOLS_EXT_SUFFIX for limited-API builds --- CHANGELOG.md | 3 +++ setuptools_rust/build.py | 4 +++- tests/test_build.py | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 901972e6..73c4fae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## Unreleased +### Fixed +- Honor `SETUPTOOLS_EXT_SUFFIX` when replacing extension suffixes for limited-API builds. + ### Packaging - Drop support for Python 3.9. - Bump `setuptools` minimum version to 83.0. diff --git a/setuptools_rust/build.py b/setuptools_rust/build.py index 0cbf64ca..7f839dd4 100644 --- a/setuptools_rust/build.py +++ b/setuptools_rust/build.py @@ -491,7 +491,9 @@ def get_dylib_ext_path(self, ext: RustExtension, target_fname: str) -> str: if _is_py_limited_api(ext.py_limited_api, self._py_limited_api()): abi3_suffix = get_abi3_suffix() if abi3_suffix is not None: - so_ext = get_config_var("EXT_SUFFIX") + so_ext = os.getenv("SETUPTOOLS_EXT_SUFFIX") or get_config_var( + "EXT_SUFFIX" + ) assert isinstance(so_ext, str) ext_path = ext_path[: -len(so_ext)] + get_abi3_suffix() diff --git a/tests/test_build.py b/tests/test_build.py index 49d831b1..10265b98 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -1,7 +1,13 @@ +import sysconfig +from pathlib import Path from unittest import mock +import pytest +from setuptools import Distribution + from setuptools_rust._utils import Env -from setuptools_rust.build import _override_cargo_default_target +from setuptools_rust.build import _override_cargo_default_target, build_rust +from setuptools_rust.extension import RustExtension NO_ENV = Env(None) @@ -35,3 +41,35 @@ def test_adjusted_local_rust_target_macos(): assert ( _override_cargo_default_target("macosx-", NO_ENV) == "x86_64-apple-darwin" ) + + +@pytest.mark.parametrize( + "ext_suffix", + [None, "", ".so", ".custom.so", ".custom.extension.suffix.longer.than.default.so"], +) +@pytest.mark.parametrize( + "abi3_suffix", + [ + None, + ".abi3.so", + ".abi3-aarch64-linux-gnu.so", + ".abi3t-aarch64-linux-gnu.so", + ".pyd", + ], +) +def test_get_dylib_ext_path_suffix_override(monkeypatch, ext_suffix, abi3_suffix): + if ext_suffix is None: + monkeypatch.delenv("SETUPTOOLS_EXT_SUFFIX", raising=False) + else: + monkeypatch.setenv("SETUPTOOLS_EXT_SUFFIX", ext_suffix) + ext = RustExtension("package.rust") + command = build_rust(Distribution()) + command.plat_name = sysconfig.get_platform() + build_ext = command.get_finalized_command("build_ext") + path = Path(build_ext.get_ext_fullpath(ext.name)) + expected = path.with_name("rust" + abi3_suffix) if abi3_suffix else path + with ( + mock.patch.object(command, "_py_limited_api", return_value="cp39"), + mock.patch("setuptools_rust.build.get_abi3_suffix", return_value=abi3_suffix), + ): + assert Path(command.get_dylib_ext_path(ext, ext.name)) == expected