diff --git a/Cargo.lock b/Cargo.lock index cf19b6c4b..08b74888c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5450,6 +5450,7 @@ dependencies = [ "uv-static", "uv-types", "uv-warnings", + "uv-workspace", "walkdir", ] diff --git a/crates/uv-dispatch/src/lib.rs b/crates/uv-dispatch/src/lib.rs index 606836a06..0205ca969 100644 --- a/crates/uv-dispatch/src/lib.rs +++ b/crates/uv-dispatch/src/lib.rs @@ -311,6 +311,7 @@ impl BuildContext for BuildDispatch<'_> { self.index_locations, self.config_settings, self.config_settings_package, + self.extra_build_dependencies(), self.cache(), venv, tags, @@ -460,7 +461,7 @@ impl BuildContext for BuildDispatch<'_> { self.workspace_cache(), config_settings, self.build_isolation, - &self.extra_build_requires.extra_build_dependencies, + self.extra_build_dependencies(), &build_stack, build_kind, self.build_extra_env_vars.clone(), diff --git a/crates/uv-distribution/src/index/built_wheel_index.rs b/crates/uv-distribution/src/index/built_wheel_index.rs index 90ce5deed..d877c2509 100644 --- a/crates/uv-distribution/src/index/built_wheel_index.rs +++ b/crates/uv-distribution/src/index/built_wheel_index.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; + use uv_cache::{Cache, CacheBucket, CacheShard, WheelCache}; use uv_cache_info::CacheInfo; use uv_cache_key::cache_digest; @@ -9,6 +10,7 @@ use uv_distribution_types::{ use uv_normalize::PackageName; use uv_platform_tags::Tags; use uv_types::HashStrategy; +use uv_workspace::pyproject::ExtraBuildDependencies; use crate::Error; use crate::index::cached_wheel::CachedWheel; @@ -22,6 +24,7 @@ pub struct BuiltWheelIndex<'a> { hasher: &'a HashStrategy, config_settings: &'a ConfigSettings, config_settings_package: &'a PackageConfigSettings, + extra_build_dependencies: &'a ExtraBuildDependencies, } impl<'a> BuiltWheelIndex<'a> { @@ -32,6 +35,7 @@ impl<'a> BuiltWheelIndex<'a> { hasher: &'a HashStrategy, config_settings: &'a ConfigSettings, config_settings_package: &'a PackageConfigSettings, + extra_build_dependencies: &'a ExtraBuildDependencies, ) -> Self { Self { cache, @@ -39,6 +43,7 @@ impl<'a> BuiltWheelIndex<'a> { hasher, config_settings, config_settings_package, + extra_build_dependencies, } } @@ -69,10 +74,11 @@ impl<'a> BuiltWheelIndex<'a> { // If there are build settings, we need to scope to a cache shard. let config_settings = self.config_settings_for(&source_dist.name); - let cache_shard = if config_settings.is_empty() { + let extra_build_deps = self.extra_build_dependencies_for(&source_dist.name); + let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() { cache_shard } else { - cache_shard.shard(cache_digest(&config_settings)) + cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps))) }; Ok(self.find(&cache_shard)) @@ -107,10 +113,11 @@ impl<'a> BuiltWheelIndex<'a> { // If there are build settings, we need to scope to a cache shard. let config_settings = self.config_settings_for(&source_dist.name); - let cache_shard = if config_settings.is_empty() { + let extra_build_deps = self.extra_build_dependencies_for(&source_dist.name); + let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() { cache_shard } else { - cache_shard.shard(cache_digest(&config_settings)) + cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps))) }; Ok(self @@ -156,10 +163,11 @@ impl<'a> BuiltWheelIndex<'a> { // If there are build settings, we need to scope to a cache shard. let config_settings = self.config_settings_for(&source_dist.name); - let cache_shard = if config_settings.is_empty() { + let extra_build_deps = self.extra_build_dependencies_for(&source_dist.name); + let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() { cache_shard } else { - cache_shard.shard(cache_digest(&config_settings)) + cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps))) }; Ok(self @@ -183,10 +191,11 @@ impl<'a> BuiltWheelIndex<'a> { // If there are build settings, we need to scope to a cache shard. let config_settings = self.config_settings_for(&source_dist.name); - let cache_shard = if config_settings.is_empty() { + let extra_build_deps = self.extra_build_dependencies_for(&source_dist.name); + let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() { cache_shard } else { - cache_shard.shard(cache_digest(&config_settings)) + cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps))) }; self.find(&cache_shard) @@ -257,4 +266,15 @@ impl<'a> BuiltWheelIndex<'a> { Cow::Borrowed(self.config_settings) } } + + /// Determine the extra build dependencies for the given package name. + fn extra_build_dependencies_for( + &self, + name: &PackageName, + ) -> &[uv_pep508::Requirement] { + self.extra_build_dependencies + .get(name) + .map(Vec::as_slice) + .unwrap_or(&[]) + } } diff --git a/crates/uv-distribution/src/source/mod.rs b/crates/uv-distribution/src/source/mod.rs index 6e1dbb228..d516c6d0d 100644 --- a/crates/uv-distribution/src/source/mod.rs +++ b/crates/uv-distribution/src/source/mod.rs @@ -413,7 +413,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { self.build_context .extra_build_dependencies() .get(name) - .map(|v| v.as_slice()) + .map(Vec::as_slice) }) .unwrap_or(&[]) } diff --git a/crates/uv-installer/Cargo.toml b/crates/uv-installer/Cargo.toml index a78dec23b..d0f43e770 100644 --- a/crates/uv-installer/Cargo.toml +++ b/crates/uv-installer/Cargo.toml @@ -35,6 +35,7 @@ uv-redacted = { workspace = true } uv-static = { workspace = true } uv-types = { workspace = true } uv-warnings = { workspace = true } +uv-workspace = { workspace = true } anyhow = { workspace = true } async-channel = { workspace = true } diff --git a/crates/uv-installer/src/plan.rs b/crates/uv-installer/src/plan.rs index 69e10befc..ddabf3386 100644 --- a/crates/uv-installer/src/plan.rs +++ b/crates/uv-installer/src/plan.rs @@ -1,5 +1,6 @@ -use anyhow::{Result, bail}; use std::sync::Arc; + +use anyhow::{Result, bail}; use tracing::{debug, warn}; use uv_cache::{Cache, CacheBucket, WheelCache}; @@ -17,6 +18,7 @@ use uv_platform_tags::Tags; use uv_pypi_types::VerbatimParsedUrl; use uv_python::PythonEnvironment; use uv_types::HashStrategy; +use uv_workspace::pyproject::ExtraBuildDependencies; use crate::SitePackages; use crate::satisfies::RequirementSatisfaction; @@ -53,6 +55,7 @@ impl<'a> Planner<'a> { index_locations: &IndexLocations, config_settings: &ConfigSettings, config_settings_package: &PackageConfigSettings, + extra_build_dependencies: &ExtraBuildDependencies, cache: &Cache, venv: &PythonEnvironment, tags: &Tags, @@ -66,6 +69,7 @@ impl<'a> Planner<'a> { hasher, config_settings, config_settings_package, + extra_build_dependencies, ); let mut cached = vec![]; diff --git a/crates/uv-types/src/traits.rs b/crates/uv-types/src/traits.rs index 68e6583ae..6966c850a 100644 --- a/crates/uv-types/src/traits.rs +++ b/crates/uv-types/src/traits.rs @@ -19,6 +19,7 @@ use uv_git::GitResolver; use uv_pep508::PackageName; use uv_python::{Interpreter, PythonEnvironment}; use uv_workspace::WorkspaceCache; +use uv_workspace::pyproject::ExtraBuildDependencies; use crate::BuildArena; @@ -104,7 +105,7 @@ pub trait BuildContext { fn workspace_cache(&self) -> &WorkspaceCache; /// Get the extra build dependencies. - fn extra_build_dependencies(&self) -> &uv_workspace::pyproject::ExtraBuildDependencies; + fn extra_build_dependencies(&self) -> &ExtraBuildDependencies; /// Resolve the given requirements into a ready-to-install set of package versions. fn resolve<'a>( diff --git a/crates/uv/src/commands/pip/operations.rs b/crates/uv/src/commands/pip/operations.rs index b5879ecf6..3e940112e 100644 --- a/crates/uv/src/commands/pip/operations.rs +++ b/crates/uv/src/commands/pip/operations.rs @@ -1,12 +1,13 @@ //! Common operations shared across the `pip` API and subcommands. -use anyhow::{Context, anyhow}; -use itertools::Itertools; -use owo_colors::OwoColorize; use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::fmt::Write; use std::path::PathBuf; use std::sync::Arc; + +use anyhow::{Context, anyhow}; +use itertools::Itertools; +use owo_colors::OwoColorize; use tracing::debug; use uv_cache::Cache; @@ -468,6 +469,7 @@ pub(crate) async fn install( index_urls, config_settings, config_settings_package, + build_dispatch.extra_build_dependencies(), cache, venv, tags, diff --git a/crates/uv/tests/it/sync.rs b/crates/uv/tests/it/sync.rs index b304733d9..cb17c7fff 100644 --- a/crates/uv/tests/it/sync.rs +++ b/crates/uv/tests/it/sync.rs @@ -1662,6 +1662,19 @@ fn sync_extra_build_dependencies() -> Result<()> { + child==0.1.0 (from file://[TEMP_DIR]/child) "); + context.venv().arg("--clear").assert().success(); + uv_snapshot!(context.filters(), context.sync(), @r" + success: true + exit_code: 0 + ----- stdout ----- + + ----- stderr ----- + warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning. + Resolved [N] packages in [TIME] + Installed [N] packages in [TIME] + + child==0.1.0 (from file://[TEMP_DIR]/child) + "); + // Adding `extra-build-dependencies` with the wrong name should fail the build // (the cache is invalidated when extra build dependencies change) pyproject_toml.write_str(indoc! {r#"