Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased
### Fixed
- Pass `--filter-platform` to `cargo metadata` so offline builds don't require dependencies exclusive to foreign targets. [#610](https://github.com/PyO3/setuptools-rust/pull/610)

## 1.13.0 (2026-06-27)
### Added
- Add `generated-files` option to `RustExtension` to copy files from the build script output directory to the wheel. [#574](https://github.com/PyO3/setuptools-rust/pull/574)
Expand Down
17 changes: 16 additions & 1 deletion setuptools_rust/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from .command import RustCommand
from .extension import Binding, RustBin, RustExtension, Strip
from .rustc_info import (
_is_custom_target,
get_rust_host,
get_rust_version,
get_rustc_cfgs,
Expand Down Expand Up @@ -129,6 +130,17 @@ def run_for_extension(self, ext: RustExtension) -> None:
dylib_paths, artifact_dir = self.build_extension(ext)
self.install_extension(ext, dylib_paths, artifact_dir)

def _metadata_filter_platforms(self, ext: RustExtension) -> Tuple[str, ...]:
"""Target triples of the platforms being built."""
target = self.target
if target is _Platform.CARGO_DEFAULT:
return (get_rust_host(ext.env),)
elif target is _Platform.UNIVERSAL2:
return _UNIVERSAL2_TARGETS
elif _is_custom_target(target):
return () # Custom target specs cannot be passed to --filter-platform
return target

def build_extension(
self, ext: RustExtension
) -> Tuple[List["_BuiltModule"], Optional[Path]]:
Expand All @@ -148,7 +160,10 @@ def build_extension(
debug = self._is_debug_build(ext)
use_cargo_crate_type = _check_cargo_supports_crate_type_option(ext.env)

package_id = ext.metadata(quiet=quiet)["resolve"]["root"]
package_id = ext.metadata(
quiet=quiet,
filter_platforms=self._metadata_filter_platforms(ext),
)["resolve"]["root"]
if package_id is None:
raise FileError(
f"manifest for Rust extention `{ext.name}` at path `{ext.path}` is a virtual manifest (a workspace root without a package).\n\n"
Expand Down
23 changes: 20 additions & 3 deletions setuptools_rust/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,16 +256,31 @@ def install_script(self, module_name: str, exe_path: str) -> None:
with open(file, "w") as f:
f.write(_SCRIPT_TEMPLATE.format(executable=repr(executable)))

def metadata(self, *, quiet: bool) -> "CargoMetadata":
def metadata(
self,
*,
quiet: bool,
filter_platforms: Sequence[str] = (),
) -> "CargoMetadata":
"""Returns cargo metadata for this extension package.

``filter_platforms`` restricts the dependency resolution to the given
target triples (``cargo metadata --filter-platform``).

Cached - will only execute cargo on first invocation.
"""

return self._metadata(os.environ.get("CARGO", "cargo"), quiet)
return self._metadata(
os.environ.get("CARGO", "cargo"), quiet, tuple(filter_platforms)
)

@lru_cache()
def _metadata(self, cargo: str, quiet: bool) -> "CargoMetadata":
def _metadata(
self,
cargo: str,
quiet: bool,
filter_platforms: "tuple[str, ...]" = (),
) -> "CargoMetadata":
metadata_command = [
cargo,
"metadata",
Expand All @@ -274,6 +289,8 @@ def _metadata(self, cargo: str, quiet: bool) -> "CargoMetadata":
"--format-version",
"1",
]
for platform in filter_platforms:
metadata_command.append(f"--filter-platform={platform}")
if self.cargo_manifest_args:
metadata_command.extend(self.cargo_manifest_args)

Expand Down
9 changes: 9 additions & 0 deletions tests/test_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pytest import CaptureFixture, MonkeyPatch

from setuptools_rust.extension import RustBin, RustExtension
from setuptools_rust.rustc_info import get_rust_host

SETUPTOOLS_RUST_DIR = Path(__file__).parent.parent

Expand Down Expand Up @@ -33,6 +34,14 @@ def test_metadata_contents(hello_world_bin: RustBin) -> None:
assert "target_directory" in metadata


def test_metadata_filter_platforms(hello_world_bin: RustBin) -> None:
metadata = hello_world_bin.metadata(
quiet=False, filter_platforms=(get_rust_host(None),)
)
assert "target_directory" in metadata
assert metadata["resolve"]["root"] is not None


def test_metadata_cargo_log(
capfd: CaptureFixture, monkeypatch: MonkeyPatch, hello_world_bin: RustBin
) -> None:
Expand Down