Add `--python-platform` to `uv run` and `uv tool` (#15515)

## Summary

Closes https://github.com/astral-sh/uv/issues/11120.
This commit is contained in:
Charlie Marsh 2025-08-28 20:51:39 -04:00 committed by GitHub
parent af856fb883
commit 4168d9b320
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 428 additions and 57 deletions

View File

@ -3308,6 +3308,23 @@ pub struct RunArgs {
/// If uv reaches the maximum recursion depth, it will exit with an error. /// If uv reaches the maximum recursion depth, it will exit with an error.
#[arg(long, hide = true, env = EnvVars::UV_RUN_MAX_RECURSION_DEPTH)] #[arg(long, hide = true, env = EnvVars::UV_RUN_MAX_RECURSION_DEPTH)]
pub max_recursion_depth: Option<u32>, pub max_recursion_depth: Option<u32>,
/// The platform for which requirements should be installed.
///
/// Represented as a "target triple", a string that describes the target platform in terms of
/// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
/// `aarch64-apple-darwin`.
///
/// When targeting macOS (Darwin), the default minimum version is `12.0`. Use
/// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `13.0`.
///
/// WARNING: When specified, uv will select wheels that are compatible with the _target_
/// platform; as a result, the installed distributions may not be compatible with the _current_
/// platform. Conversely, any distributions that are built from source may be incompatible with
/// the _target_ platform, as they will be built for the _current_ platform. The
/// `--python-platform` option is intended for advanced use cases.
#[arg(long)]
pub python_platform: Option<TargetTriple>,
} }
#[derive(Args)] #[derive(Args)]
@ -4565,6 +4582,23 @@ pub struct ToolRunArgs {
#[arg(long, env = EnvVars::UV_SHOW_RESOLUTION, value_parser = clap::builder::BoolishValueParser::new(), hide = true)] #[arg(long, env = EnvVars::UV_SHOW_RESOLUTION, value_parser = clap::builder::BoolishValueParser::new(), hide = true)]
pub show_resolution: bool, pub show_resolution: bool,
/// The platform for which requirements should be installed.
///
/// Represented as a "target triple", a string that describes the target platform in terms of
/// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
/// `aarch64-apple-darwin`.
///
/// When targeting macOS (Darwin), the default minimum version is `12.0`. Use
/// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `13.0`.
///
/// WARNING: When specified, uv will select wheels that are compatible with the _target_
/// platform; as a result, the installed distributions may not be compatible with the _current_
/// platform. Conversely, any distributions that are built from source may be incompatible with
/// the _target_ platform, as they will be built for the _current_ platform. The
/// `--python-platform` option is intended for advanced use cases.
#[arg(long)]
pub python_platform: Option<TargetTriple>,
#[arg(long, hide = true)] #[arg(long, hide = true)]
pub generate_shell_completion: Option<clap_complete_command::Shell>, pub generate_shell_completion: Option<clap_complete_command::Shell>,
} }
@ -4669,6 +4703,23 @@ pub struct ToolInstallArgs {
value_parser = parse_maybe_string, value_parser = parse_maybe_string,
)] )]
pub python: Option<Maybe<String>>, pub python: Option<Maybe<String>>,
/// The platform for which requirements should be installed.
///
/// Represented as a "target triple", a string that describes the target platform in terms of
/// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
/// `aarch64-apple-darwin`.
///
/// When targeting macOS (Darwin), the default minimum version is `12.0`. Use
/// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `13.0`.
///
/// WARNING: When specified, uv will select wheels that are compatible with the _target_
/// platform; as a result, the installed distributions may not be compatible with the _current_
/// platform. Conversely, any distributions that are built from source may be incompatible with
/// the _target_ platform, as they will be built for the _current_ platform. The
/// `--python-platform` option is intended for advanced use cases.
#[arg(long)]
pub python_platform: Option<TargetTriple>,
} }
#[derive(Args)] #[derive(Args)]
@ -4750,6 +4801,23 @@ pub struct ToolUpgradeArgs {
)] )]
pub python: Option<Maybe<String>>, pub python: Option<Maybe<String>>,
/// The platform for which requirements should be installed.
///
/// Represented as a "target triple", a string that describes the target platform in terms of
/// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
/// `aarch64-apple-darwin`.
///
/// When targeting macOS (Darwin), the default minimum version is `12.0`. Use
/// `MACOSX_DEPLOYMENT_TARGET` to specify a different minimum version, e.g., `13.0`.
///
/// WARNING: When specified, uv will select wheels that are compatible with the _target_
/// platform; as a result, the installed distributions may not be compatible with the _current_
/// platform. Conversely, any distributions that are built from source may be incompatible with
/// the _target_ platform, as they will be built for the _current_ platform. The
/// `--python-platform` option is intended for advanced use cases.
#[arg(long)]
pub python_platform: Option<TargetTriple>,
// The following is equivalent to flattening `ResolverInstallerArgs`, with the `--upgrade`, and // The following is equivalent to flattening `ResolverInstallerArgs`, with the `--upgrade`, and
// `--upgrade-package` options hidden, and the `--no-upgrade` option removed. // `--upgrade-package` options hidden, and the `--no-upgrade` option removed.
/// Allow package upgrades, ignoring pinned versions in any existing output file. Implies /// Allow package upgrades, ignoring pinned versions in any existing output file. Implies

View File

@ -308,14 +308,6 @@ impl RequirementSatisfaction {
return Self::CacheInvalid; return Self::CacheInvalid;
} }
} }
// If the distribution isn't compatible with the current platform, it is a mismatch.
if let Ok(Some(wheel_tags)) = distribution.read_tags() {
if !wheel_tags.is_compatible(tags) {
debug!("Platform tags mismatch for {name}: {distribution}");
return Self::Mismatch;
}
}
} }
} }

View File

@ -12,7 +12,7 @@ use crate::settings::{NetworkSettings, ResolverInstallerSettings};
use uv_cache::{Cache, CacheBucket}; use uv_cache::{Cache, CacheBucket};
use uv_cache_key::{cache_digest, hash_digest}; use uv_cache_key::{cache_digest, hash_digest};
use uv_configuration::{Concurrency, Constraints}; use uv_configuration::{Concurrency, Constraints, TargetTriple};
use uv_distribution_types::{Name, Resolution}; use uv_distribution_types::{Name, Resolution};
use uv_fs::PythonExt; use uv_fs::PythonExt;
use uv_preview::Preview; use uv_preview::Preview;
@ -111,6 +111,7 @@ impl CachedEnvironment {
spec: EnvironmentSpecification<'_>, spec: EnvironmentSpecification<'_>,
build_constraints: Constraints, build_constraints: Constraints,
interpreter: &Interpreter, interpreter: &Interpreter,
python_platform: Option<&TargetTriple>,
settings: &ResolverInstallerSettings, settings: &ResolverInstallerSettings,
network_settings: &NetworkSettings, network_settings: &NetworkSettings,
state: &PlatformState, state: &PlatformState,
@ -129,6 +130,7 @@ impl CachedEnvironment {
resolve_environment( resolve_environment(
spec, spec,
&interpreter, &interpreter,
python_platform,
build_constraints.clone(), build_constraints.clone(),
&settings.resolver, &settings.resolver,
network_settings, network_settings,

View File

@ -13,7 +13,7 @@ use uv_cache_key::cache_digest;
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder}; use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
use uv_configuration::{ use uv_configuration::{
Concurrency, Constraints, DependencyGroupsWithDefaults, DryRun, ExtrasSpecification, Reinstall, Concurrency, Constraints, DependencyGroupsWithDefaults, DryRun, ExtrasSpecification, Reinstall,
Upgrade, TargetTriple, Upgrade,
}; };
use uv_dispatch::{BuildDispatch, SharedState}; use uv_dispatch::{BuildDispatch, SharedState};
use uv_distribution::{DistributionDatabase, LoweredExtraBuildDependencies, LoweredRequirement}; use uv_distribution::{DistributionDatabase, LoweredExtraBuildDependencies, LoweredRequirement};
@ -1849,6 +1849,7 @@ impl<'lock> EnvironmentSpecification<'lock> {
pub(crate) async fn resolve_environment( pub(crate) async fn resolve_environment(
spec: EnvironmentSpecification<'_>, spec: EnvironmentSpecification<'_>,
interpreter: &Interpreter, interpreter: &Interpreter,
python_platform: Option<&TargetTriple>,
build_constraints: Constraints, build_constraints: Constraints,
settings: &ResolverSettings, settings: &ResolverSettings,
network_settings: &NetworkSettings, network_settings: &NetworkSettings,
@ -1899,8 +1900,8 @@ pub(crate) async fn resolve_environment(
.allow_insecure_host(network_settings.allow_insecure_host.clone()); .allow_insecure_host(network_settings.allow_insecure_host.clone());
// Determine the tags, markers, and interpreter to use for resolution. // Determine the tags, markers, and interpreter to use for resolution.
let tags = interpreter.tags()?; let tags = pip::resolution_tags(None, python_platform, interpreter)?;
let marker_env = interpreter.resolver_marker_environment(); let marker_env = pip::resolution_markers(None, python_platform, interpreter);
let python_requirement = PythonRequirement::from_interpreter(interpreter); let python_requirement = PythonRequirement::from_interpreter(interpreter);
index_locations.cache_index_credentials(); index_locations.cache_index_credentials();
@ -1973,7 +1974,7 @@ pub(crate) async fn resolve_environment(
let entries = client let entries = client
.fetch_all(index_locations.flat_indexes().map(Index::url)) .fetch_all(index_locations.flat_indexes().map(Index::url))
.await?; .await?;
FlatIndex::from_entries(entries, Some(tags), &hasher, build_options) FlatIndex::from_entries(entries, Some(&tags), &hasher, build_options)
}; };
let workspace_cache = WorkspaceCache::default(); let workspace_cache = WorkspaceCache::default();
@ -2024,7 +2025,7 @@ pub(crate) async fn resolve_environment(
&hasher, &hasher,
&reinstall, &reinstall,
&upgrade, &upgrade,
Some(tags), Some(&tags),
ResolverEnvironment::specific(marker_env), ResolverEnvironment::specific(marker_env),
python_requirement, python_requirement,
interpreter.markers(), interpreter.markers(),
@ -2207,6 +2208,7 @@ pub(crate) async fn update_environment(
venv: PythonEnvironment, venv: PythonEnvironment,
spec: RequirementsSpecification, spec: RequirementsSpecification,
modifications: Modifications, modifications: Modifications,
python_platform: Option<&TargetTriple>,
build_constraints: Constraints, build_constraints: Constraints,
extra_build_requires: ExtraBuildRequires, extra_build_requires: ExtraBuildRequires,
settings: &ResolverInstallerSettings, settings: &ResolverInstallerSettings,
@ -2268,8 +2270,8 @@ pub(crate) async fn update_environment(
// Determine markers and tags to use for resolution. // Determine markers and tags to use for resolution.
let interpreter = venv.interpreter(); let interpreter = venv.interpreter();
let marker_env = venv.interpreter().resolver_marker_environment(); let marker_env = pip::resolution_markers(None, python_platform, interpreter);
let tags = venv.interpreter().tags()?; let tags = pip::resolution_tags(None, python_platform, interpreter)?;
// Check if the current environment satisfies the requirements // Check if the current environment satisfies the requirements
let site_packages = SitePackages::from_environment(&venv)?; let site_packages = SitePackages::from_environment(&venv)?;
@ -2283,7 +2285,7 @@ pub(crate) async fn update_environment(
&constraints, &constraints,
&overrides, &overrides,
&marker_env, &marker_env,
tags, &tags,
config_setting, config_setting,
config_settings_package, config_settings_package,
&extra_build_requires, &extra_build_requires,
@ -2354,7 +2356,6 @@ pub(crate) async fn update_environment(
let preferences = Vec::default(); let preferences = Vec::default();
// Determine the tags to use for resolution. // Determine the tags to use for resolution.
let tags = venv.interpreter().tags()?;
let python_requirement = PythonRequirement::from_interpreter(interpreter); let python_requirement = PythonRequirement::from_interpreter(interpreter);
// Resolve the flat indexes from `--find-links`. // Resolve the flat indexes from `--find-links`.
@ -2363,7 +2364,7 @@ pub(crate) async fn update_environment(
let entries = client let entries = client
.fetch_all(index_locations.flat_indexes().map(Index::url)) .fetch_all(index_locations.flat_indexes().map(Index::url))
.await?; .await?;
FlatIndex::from_entries(entries, Some(tags), &hasher, build_options) FlatIndex::from_entries(entries, Some(&tags), &hasher, build_options)
}; };
// Create a build dispatch. // Create a build dispatch.
@ -2407,7 +2408,7 @@ pub(crate) async fn update_environment(
&hasher, &hasher,
reinstall, reinstall,
upgrade, upgrade,
Some(tags), Some(&tags),
ResolverEnvironment::specific(marker_env.clone()), ResolverEnvironment::specific(marker_env.clone()),
python_requirement, python_requirement,
venv.interpreter().markers(), venv.interpreter().markers(),
@ -2437,7 +2438,7 @@ pub(crate) async fn update_environment(
*link_mode, *link_mode,
*compile_bytecode, *compile_bytecode,
&hasher, &hasher,
tags, &tags,
&client, &client,
state.in_flight(), state.in_flight(),
concurrency, concurrency,

View File

@ -19,7 +19,7 @@ use uv_cli::ExternalCommand;
use uv_client::BaseClientBuilder; use uv_client::BaseClientBuilder;
use uv_configuration::{ use uv_configuration::{
Concurrency, Constraints, DependencyGroups, DryRun, EditableMode, ExtrasSpecification, Concurrency, Constraints, DependencyGroups, DryRun, EditableMode, ExtrasSpecification,
InstallOptions, InstallOptions, TargetTriple,
}; };
use uv_distribution::LoweredExtraBuildDependencies; use uv_distribution::LoweredExtraBuildDependencies;
use uv_distribution_types::Requirement; use uv_distribution_types::Requirement;
@ -96,6 +96,7 @@ pub(crate) async fn run(
editable: EditableMode, editable: EditableMode,
modifications: Modifications, modifications: Modifications,
python: Option<String>, python: Option<String>,
python_platform: Option<TargetTriple>,
install_mirrors: PythonInstallMirrors, install_mirrors: PythonInstallMirrors,
settings: ResolverInstallerSettings, settings: ResolverInstallerSettings,
network_settings: NetworkSettings, network_settings: NetworkSettings,
@ -319,7 +320,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
editable, editable,
install_options, install_options,
modifications, modifications,
None, python_platform.as_ref(),
(&settings).into(), (&settings).into(),
&network_settings, &network_settings,
&sync_state, &sync_state,
@ -421,6 +422,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
environment, environment,
spec, spec,
modifications, modifications,
python_platform.as_ref(),
build_constraints.unwrap_or_default(), build_constraints.unwrap_or_default(),
script_extra_build_requires, script_extra_build_requires,
&settings, &settings,
@ -837,7 +839,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
editable, editable,
install_options, install_options,
modifications, modifications,
None, python_platform.as_ref(),
(&settings).into(), (&settings).into(),
&network_settings, &network_settings,
&sync_state, &sync_state,
@ -998,6 +1000,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
spec, spec,
build_constraints.unwrap_or_default(), build_constraints.unwrap_or_default(),
&base_interpreter, &base_interpreter,
python_platform.as_ref(),
&settings, &settings,
&network_settings, &network_settings,
&sync_state, &sync_state,

View File

@ -253,6 +253,7 @@ pub(crate) async fn sync(
environment.clone(), environment.clone(),
spec, spec,
modifications, modifications,
python_platform.as_ref(),
build_constraints.unwrap_or_default(), build_constraints.unwrap_or_default(),
script_extra_build_requires, script_extra_build_requires,
&settings, &settings,

View File

@ -8,11 +8,13 @@ use tracing::{debug, trace};
use uv_cache::{Cache, Refresh}; use uv_cache::{Cache, Refresh};
use uv_cache_info::Timestamp; use uv_cache_info::Timestamp;
use uv_client::BaseClientBuilder; use uv_client::BaseClientBuilder;
use uv_configuration::{Concurrency, Constraints, DryRun, Reinstall, Upgrade}; use uv_configuration::{Concurrency, Constraints, DryRun, Reinstall, TargetTriple, Upgrade};
use uv_distribution::LoweredExtraBuildDependencies;
use uv_distribution_types::{ use uv_distribution_types::{
ExtraBuildRequires, NameRequirementSpecification, Requirement, RequirementSource, ExtraBuildRequires, NameRequirementSpecification, Requirement, RequirementSource,
UnresolvedRequirementSpecification, UnresolvedRequirementSpecification,
}; };
use uv_installer::{SatisfiesResult, SitePackages};
use uv_normalize::PackageName; use uv_normalize::PackageName;
use uv_pep440::{VersionSpecifier, VersionSpecifiers}; use uv_pep440::{VersionSpecifier, VersionSpecifiers};
use uv_pep508::MarkerTree; use uv_pep508::MarkerTree;
@ -29,6 +31,7 @@ use uv_workspace::WorkspaceCache;
use crate::commands::ExitStatus; use crate::commands::ExitStatus;
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger}; use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger};
use crate::commands::pip::operations::{self, Modifications}; use crate::commands::pip::operations::{self, Modifications};
use crate::commands::pip::{resolution_markers, resolution_tags};
use crate::commands::project::{ use crate::commands::project::{
EnvironmentSpecification, PlatformState, ProjectError, resolve_environment, resolve_names, EnvironmentSpecification, PlatformState, ProjectError, resolve_environment, resolve_names,
sync_environment, update_environment, sync_environment, update_environment,
@ -53,6 +56,7 @@ pub(crate) async fn install(
build_constraints: &[RequirementsSource], build_constraints: &[RequirementsSource],
entrypoints: &[PackageName], entrypoints: &[PackageName],
python: Option<String>, python: Option<String>,
python_platform: Option<TargetTriple>,
install_mirrors: PythonInstallMirrors, install_mirrors: PythonInstallMirrors,
force: bool, force: bool,
options: ResolverInstallerOptions, options: ResolverInstallerOptions,
@ -374,31 +378,62 @@ pub(crate) async fn install(
}); });
// If the requested and receipt requirements are the same... // If the requested and receipt requirements are the same...
if existing_environment if let Some(environment) = existing_environment.as_ref().filter(|_| {
.as_ref()
.filter(|_| {
// And the user didn't request a reinstall or upgrade... // And the user didn't request a reinstall or upgrade...
!request.is_latest() !request.is_latest() && settings.reinstall.is_none() && settings.resolver.upgrade.is_none()
&& settings.reinstall.is_none() }) {
&& settings.resolver.upgrade.is_none()
})
.is_some()
{
if let Some(tool_receipt) = existing_tool_receipt.as_ref() { if let Some(tool_receipt) = existing_tool_receipt.as_ref() {
if requirements == tool_receipt.requirements() if requirements == tool_receipt.requirements()
&& constraints == tool_receipt.constraints() && constraints == tool_receipt.constraints()
&& overrides == tool_receipt.overrides() && overrides == tool_receipt.overrides()
&& build_constraints == tool_receipt.build_constraints() && build_constraints == tool_receipt.build_constraints()
{ {
let ResolverInstallerSettings {
resolver:
ResolverSettings {
config_setting,
config_settings_package,
extra_build_dependencies,
extra_build_variables,
..
},
..
} = &settings;
// Lower the extra build dependencies, if any.
let extra_build_requires = LoweredExtraBuildDependencies::from_non_lowered(
extra_build_dependencies.clone(),
)
.into_inner();
// Determine the markers and tags to use for the resolution.
let markers = resolution_markers(None, python_platform.as_ref(), &interpreter);
let tags = resolution_tags(None, python_platform.as_ref(), &interpreter)?;
// Check if the installed packages meet the requirements.
let site_packages = SitePackages::from_environment(environment)?;
if matches!(
site_packages.satisfies_requirements(
requirements.iter(),
constraints.iter(),
overrides.iter(),
&markers,
&tags,
config_setting,
config_settings_package,
&extra_build_requires,
extra_build_variables,
),
Ok(SatisfiesResult::Fresh { .. })
) {
// Then we're done! Though we might need to update the receipt.
if *tool_receipt.options() != options { if *tool_receipt.options() != options {
// ...but the options differ, we need to update the receipt.
installed_tools.add_tool_receipt( installed_tools.add_tool_receipt(
package_name, package_name,
tool_receipt.clone().with_options(options), tool_receipt.clone().with_options(options),
)?; )?;
} }
// We're done, though we might need to update the receipt.
writeln!( writeln!(
printer.stderr(), printer.stderr(),
"`{}` is already installed", "`{}` is already installed",
@ -409,6 +444,7 @@ pub(crate) async fn install(
} }
} }
} }
}
// Create a `RequirementsSpecification` from the resolved requirements, to avoid re-resolving. // Create a `RequirementsSpecification` from the resolved requirements, to avoid re-resolving.
let spec = RequirementsSpecification { let spec = RequirementsSpecification {
@ -439,6 +475,7 @@ pub(crate) async fn install(
environment, environment,
spec, spec,
Modifications::Exact, Modifications::Exact,
python_platform.as_ref(),
Constraints::from_requirements(build_constraints.iter().cloned()), Constraints::from_requirements(build_constraints.iter().cloned()),
ExtraBuildRequires::default(), ExtraBuildRequires::default(),
&settings, &settings,
@ -480,6 +517,7 @@ pub(crate) async fn install(
let resolution = resolve_environment( let resolution = resolve_environment(
spec.clone(), spec.clone(),
&interpreter, &interpreter,
python_platform.as_ref(),
Constraints::from_requirements(build_constraints.iter().cloned()), Constraints::from_requirements(build_constraints.iter().cloned()),
&settings.resolver, &settings.resolver,
&network_settings, &network_settings,
@ -534,6 +572,7 @@ pub(crate) async fn install(
match resolve_environment( match resolve_environment(
spec, spec,
&interpreter, &interpreter,
python_platform.as_ref(),
Constraints::from_requirements(build_constraints.iter().cloned()), Constraints::from_requirements(build_constraints.iter().cloned()),
&settings.resolver, &settings.resolver,
&network_settings, &network_settings,

View File

@ -18,6 +18,7 @@ use uv_cli::ExternalCommand;
use uv_client::BaseClientBuilder; use uv_client::BaseClientBuilder;
use uv_configuration::Concurrency; use uv_configuration::Concurrency;
use uv_configuration::Constraints; use uv_configuration::Constraints;
use uv_configuration::TargetTriple;
use uv_distribution::LoweredExtraBuildDependencies; use uv_distribution::LoweredExtraBuildDependencies;
use uv_distribution_types::InstalledDist; use uv_distribution_types::InstalledDist;
use uv_distribution_types::{ use uv_distribution_types::{
@ -45,6 +46,7 @@ use uv_workspace::WorkspaceCache;
use crate::child::run_to_completion; use crate::child::run_to_completion;
use crate::commands::ExitStatus; use crate::commands::ExitStatus;
use crate::commands::pip;
use crate::commands::pip::loggers::{ use crate::commands::pip::loggers::{
DefaultInstallLogger, DefaultResolveLogger, SummaryInstallLogger, SummaryResolveLogger, DefaultInstallLogger, DefaultResolveLogger, SummaryInstallLogger, SummaryResolveLogger,
}; };
@ -89,6 +91,7 @@ pub(crate) async fn run(
build_constraints: &[RequirementsSource], build_constraints: &[RequirementsSource],
show_resolution: bool, show_resolution: bool,
python: Option<String>, python: Option<String>,
python_platform: Option<TargetTriple>,
install_mirrors: PythonInstallMirrors, install_mirrors: PythonInstallMirrors,
options: ResolverInstallerOptions, options: ResolverInstallerOptions,
settings: ResolverInstallerSettings, settings: ResolverInstallerSettings,
@ -267,6 +270,7 @@ pub(crate) async fn run(
build_constraints, build_constraints,
show_resolution, show_resolution,
python.as_deref(), python.as_deref(),
python_platform,
install_mirrors, install_mirrors,
options, options,
&settings, &settings,
@ -677,6 +681,7 @@ async fn get_or_create_environment(
build_constraints: &[RequirementsSource], build_constraints: &[RequirementsSource],
show_resolution: bool, show_resolution: bool,
python: Option<&str>, python: Option<&str>,
python_platform: Option<TargetTriple>,
install_mirrors: PythonInstallMirrors, install_mirrors: PythonInstallMirrors,
options: ResolverInstallerOptions, options: ResolverInstallerOptions,
settings: &ResolverInstallerSettings, settings: &ResolverInstallerSettings,
@ -966,8 +971,9 @@ async fn get_or_create_environment(
.into_inner(); .into_inner();
// Determine the markers and tags to use for the resolution. // Determine the markers and tags to use for the resolution.
let markers = interpreter.resolver_marker_environment(); let markers =
let tags = interpreter.tags()?; pip::resolution_markers(None, python_platform.as_ref(), &interpreter);
let tags = pip::resolution_tags(None, python_platform.as_ref(), &interpreter)?;
// Check if the installed packages meet the requirements. // Check if the installed packages meet the requirements.
let site_packages = SitePackages::from_environment(&environment)?; let site_packages = SitePackages::from_environment(&environment)?;
@ -977,7 +983,7 @@ async fn get_or_create_environment(
constraints.iter(), constraints.iter(),
overrides.iter(), overrides.iter(),
&markers, &markers,
tags, &tags,
config_setting, config_setting,
config_settings_package, config_settings_package,
&extra_build_requires, &extra_build_requires,
@ -1025,6 +1031,7 @@ async fn get_or_create_environment(
spec.clone(), spec.clone(),
build_constraints.clone(), build_constraints.clone(),
&interpreter, &interpreter,
python_platform.as_ref(),
settings, settings,
network_settings, network_settings,
&state, &state,
@ -1084,6 +1091,7 @@ async fn get_or_create_environment(
spec, spec,
build_constraints, build_constraints,
&interpreter, &interpreter,
python_platform.as_ref(),
settings, settings,
network_settings, network_settings,
&state, &state,

View File

@ -8,7 +8,7 @@ use tracing::{debug, trace};
use uv_cache::Cache; use uv_cache::Cache;
use uv_client::BaseClientBuilder; use uv_client::BaseClientBuilder;
use uv_configuration::{Concurrency, Constraints, DryRun}; use uv_configuration::{Concurrency, Constraints, DryRun, TargetTriple};
use uv_distribution_types::{ExtraBuildRequires, Requirement}; use uv_distribution_types::{ExtraBuildRequires, Requirement};
use uv_fs::CWD; use uv_fs::CWD;
use uv_normalize::PackageName; use uv_normalize::PackageName;
@ -40,6 +40,7 @@ use crate::settings::{NetworkSettings, ResolverInstallerSettings};
pub(crate) async fn upgrade( pub(crate) async fn upgrade(
names: Vec<String>, names: Vec<String>,
python: Option<String>, python: Option<String>,
python_platform: Option<TargetTriple>,
install_mirrors: PythonInstallMirrors, install_mirrors: PythonInstallMirrors,
args: ResolverInstallerOptions, args: ResolverInstallerOptions,
filesystem: ResolverInstallerOptions, filesystem: ResolverInstallerOptions,
@ -125,6 +126,7 @@ pub(crate) async fn upgrade(
name, name,
constraints, constraints,
interpreter.as_ref(), interpreter.as_ref(),
python_platform.as_ref(),
printer, printer,
&installed_tools, &installed_tools,
&args, &args,
@ -210,6 +212,7 @@ async fn upgrade_tool(
name: &PackageName, name: &PackageName,
constraints: &[Requirement], constraints: &[Requirement],
interpreter: Option<&Interpreter>, interpreter: Option<&Interpreter>,
python_platform: Option<&TargetTriple>,
printer: Printer, printer: Printer,
installed_tools: &InstalledTools, installed_tools: &InstalledTools,
args: &ResolverInstallerOptions, args: &ResolverInstallerOptions,
@ -296,6 +299,7 @@ async fn upgrade_tool(
let resolution = resolve_environment( let resolution = resolve_environment(
spec.into(), spec.into(),
interpreter, interpreter,
python_platform,
build_constraints.clone(), build_constraints.clone(),
&settings.resolver, &settings.resolver,
network_settings, network_settings,
@ -339,6 +343,7 @@ async fn upgrade_tool(
environment, environment,
spec, spec,
Modifications::Exact, Modifications::Exact,
python_platform,
build_constraints, build_constraints,
ExtraBuildRequires::default(), ExtraBuildRequires::default(),
&settings, &settings,

View File

@ -1198,6 +1198,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
&build_constraints, &build_constraints,
args.show_resolution || globals.verbose > 0, args.show_resolution || globals.verbose > 0,
args.python, args.python,
args.python_platform,
args.install_mirrors, args.install_mirrors,
args.options, args.options,
args.settings, args.settings,
@ -1286,6 +1287,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
&build_constraints, &build_constraints,
&entrypoints, &entrypoints,
args.python, args.python,
args.python_platform,
args.install_mirrors, args.install_mirrors,
args.force, args.force,
args.options, args.options,
@ -1334,6 +1336,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
Box::pin(commands::tool_upgrade( Box::pin(commands::tool_upgrade(
args.names, args.names,
args.python, args.python,
args.python_platform,
args.install_mirrors, args.install_mirrors,
args.args, args.args,
args.filesystem, args.filesystem,
@ -1779,6 +1782,7 @@ async fn run_project(
args.editable, args.editable,
args.modifications, args.modifications,
args.python, args.python,
args.python_platform,
args.install_mirrors, args.install_mirrors,
args.settings, args.settings,
globals.network_settings, globals.network_settings,

View File

@ -337,6 +337,7 @@ pub(crate) struct RunSettings {
pub(crate) active: Option<bool>, pub(crate) active: Option<bool>,
pub(crate) no_sync: bool, pub(crate) no_sync: bool,
pub(crate) python: Option<String>, pub(crate) python: Option<String>,
pub(crate) python_platform: Option<TargetTriple>,
pub(crate) install_mirrors: PythonInstallMirrors, pub(crate) install_mirrors: PythonInstallMirrors,
pub(crate) refresh: Refresh, pub(crate) refresh: Refresh,
pub(crate) settings: ResolverInstallerSettings, pub(crate) settings: ResolverInstallerSettings,
@ -391,6 +392,7 @@ impl RunSettings {
package, package,
no_project, no_project,
python, python,
python_platform,
show_resolution, show_resolution,
env_file, env_file,
no_env_file, no_env_file,
@ -450,6 +452,7 @@ impl RunSettings {
no_sync, no_sync,
active: flag(active, no_active, "active"), active: flag(active, no_active, "active"),
python: python.and_then(Maybe::into_option), python: python.and_then(Maybe::into_option),
python_platform,
refresh: Refresh::from(refresh), refresh: Refresh::from(refresh),
settings: ResolverInstallerSettings::combine( settings: ResolverInstallerSettings::combine(
resolver_installer_options(installer, build), resolver_installer_options(installer, build),
@ -477,6 +480,7 @@ pub(crate) struct ToolRunSettings {
pub(crate) isolated: bool, pub(crate) isolated: bool,
pub(crate) show_resolution: bool, pub(crate) show_resolution: bool,
pub(crate) python: Option<String>, pub(crate) python: Option<String>,
pub(crate) python_platform: Option<TargetTriple>,
pub(crate) install_mirrors: PythonInstallMirrors, pub(crate) install_mirrors: PythonInstallMirrors,
pub(crate) refresh: Refresh, pub(crate) refresh: Refresh,
pub(crate) options: ResolverInstallerOptions, pub(crate) options: ResolverInstallerOptions,
@ -510,6 +514,7 @@ impl ToolRunSettings {
build, build,
refresh, refresh,
python, python,
python_platform,
generate_shell_completion: _, generate_shell_completion: _,
} = args; } = args;
@ -585,6 +590,7 @@ impl ToolRunSettings {
isolated, isolated,
show_resolution, show_resolution,
python: python.and_then(Maybe::into_option), python: python.and_then(Maybe::into_option),
python_platform,
refresh: Refresh::from(refresh), refresh: Refresh::from(refresh),
settings, settings,
options, options,
@ -608,6 +614,7 @@ pub(crate) struct ToolInstallSettings {
pub(crate) overrides: Vec<PathBuf>, pub(crate) overrides: Vec<PathBuf>,
pub(crate) build_constraints: Vec<PathBuf>, pub(crate) build_constraints: Vec<PathBuf>,
pub(crate) python: Option<String>, pub(crate) python: Option<String>,
pub(crate) python_platform: Option<TargetTriple>,
pub(crate) refresh: Refresh, pub(crate) refresh: Refresh,
pub(crate) options: ResolverInstallerOptions, pub(crate) options: ResolverInstallerOptions,
pub(crate) settings: ResolverInstallerSettings, pub(crate) settings: ResolverInstallerSettings,
@ -636,6 +643,7 @@ impl ToolInstallSettings {
build, build,
refresh, refresh,
python, python,
python_platform,
} = args; } = args;
let options = let options =
@ -686,6 +694,7 @@ impl ToolInstallSettings {
.filter_map(Maybe::into_option) .filter_map(Maybe::into_option)
.collect(), .collect(),
python: python.and_then(Maybe::into_option), python: python.and_then(Maybe::into_option),
python_platform,
force, force,
editable, editable,
refresh: Refresh::from(refresh), refresh: Refresh::from(refresh),
@ -701,6 +710,7 @@ impl ToolInstallSettings {
pub(crate) struct ToolUpgradeSettings { pub(crate) struct ToolUpgradeSettings {
pub(crate) names: Vec<String>, pub(crate) names: Vec<String>,
pub(crate) python: Option<String>, pub(crate) python: Option<String>,
pub(crate) python_platform: Option<TargetTriple>,
pub(crate) install_mirrors: PythonInstallMirrors, pub(crate) install_mirrors: PythonInstallMirrors,
pub(crate) args: ResolverInstallerOptions, pub(crate) args: ResolverInstallerOptions,
pub(crate) filesystem: ResolverInstallerOptions, pub(crate) filesystem: ResolverInstallerOptions,
@ -712,6 +722,7 @@ impl ToolUpgradeSettings {
let ToolUpgradeArgs { let ToolUpgradeArgs {
name, name,
python, python,
python_platform,
upgrade, upgrade,
upgrade_package, upgrade_package,
index_args, index_args,
@ -789,6 +800,7 @@ impl ToolUpgradeSettings {
Self { Self {
names: if all { vec![] } else { name }, names: if all { vec![] } else { name },
python: python.and_then(Maybe::into_option), python: python.and_then(Maybe::into_option),
python_platform,
args, args,
filesystem: top_level, filesystem: top_level,
install_mirrors, install_mirrors,

View File

@ -3464,6 +3464,7 @@ fn resolve_tool() -> anyhow::Result<()> {
overrides: [], overrides: [],
build_constraints: [], build_constraints: [],
python: None, python: None,
python_platform: None,
refresh: None( refresh: None(
Timestamp( Timestamp(
SystemTime { SystemTime {

View File

@ -3968,3 +3968,58 @@ fn tool_install_with_executables_from_no_entrypoints() {
Installed 1 executable: flask Installed 1 executable: flask
"###); "###);
} }
#[test]
fn tool_install_python_platform() {
let context = TestContext::new("3.12")
.with_filtered_counts()
.with_filtered_exe_suffix();
let tool_dir = context.temp_dir.child("tools");
let bin_dir = context.temp_dir.child("bin");
// Install `black` for macos.
uv_snapshot!(context.filters(), context.tool_install()
.arg("black")
.arg("--python-platform")
.arg("macos")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
.env(EnvVars::PATH, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved [N] packages in [TIME]
Prepared [N] packages in [TIME]
Installed [N] packages in [TIME]
+ black==24.3.0
+ click==8.1.7
+ mypy-extensions==1.0.0
+ packaging==24.0
+ pathspec==0.12.1
+ platformdirs==4.2.0
Installed 2 executables: black, blackd
");
// Install `black` for Linux.
uv_snapshot!(context.filters(), context.tool_install()
.arg("black")
.arg("--python-platform")
.arg("linux")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
.env(EnvVars::PATH, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved [N] packages in [TIME]
Prepared [N] packages in [TIME]
Uninstalled [N] packages in [TIME]
Installed [N] packages in [TIME]
~ black==24.3.0
Installed 2 executables: black, blackd
");
}

View File

@ -233,7 +233,52 @@ uv run [OPTIONS] [COMMAND]
<p>If the interpreter request is satisfied by a discovered environment, the environment will be <p>If the interpreter request is satisfied by a discovered environment, the environment will be
used.</p> used.</p>
<p>See <a href="#uv-python">uv python</a> to view supported request formats.</p> <p>See <a href="#uv-python">uv python</a> to view supported request formats.</p>
<p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-run--quiet"><a href="#uv-run--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p> <p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-run--python-platform"><a href="#uv-run--python-platform"><code>--python-platform</code></a> <i>python-platform</i></dt><dd><p>The platform for which requirements should be installed.</p>
<p>Represented as a &quot;target triple&quot;, a string that describes the target platform in terms of its CPU, vendor, and operating system name, like <code>x86_64-unknown-linux-gnu</code> or <code>aarch64-apple-darwin</code>.</p>
<p>When targeting macOS (Darwin), the default minimum version is <code>12.0</code>. Use <code>MACOSX_DEPLOYMENT_TARGET</code> to specify a different minimum version, e.g., <code>13.0</code>.</p>
<p>WARNING: When specified, uv will select wheels that are compatible with the <em>target</em> platform; as a result, the installed distributions may not be compatible with the <em>current</em> platform. Conversely, any distributions that are built from source may be incompatible with the <em>target</em> platform, as they will be built for the <em>current</em> platform. The <code>--python-platform</code> option is intended for advanced use cases.</p>
<p>Possible values:</p>
<ul>
<li><code>windows</code>: An alias for <code>x86_64-pc-windows-msvc</code>, the default target for Windows</li>
<li><code>linux</code>: An alias for <code>x86_64-unknown-linux-gnu</code>, the default target for Linux</li>
<li><code>macos</code>: An alias for <code>aarch64-apple-darwin</code>, the default target for macOS</li>
<li><code>x86_64-pc-windows-msvc</code>: A 64-bit x86 Windows target</li>
<li><code>aarch64-pc-windows-msvc</code>: An ARM64 Windows target</li>
<li><code>i686-pc-windows-msvc</code>: A 32-bit x86 Windows target</li>
<li><code>x86_64-unknown-linux-gnu</code>: An x86 Linux target. Equivalent to <code>x86_64-manylinux_2_28</code></li>
<li><code>aarch64-apple-darwin</code>: An ARM-based macOS target, as seen on Apple Silicon devices</li>
<li><code>x86_64-apple-darwin</code>: An x86 macOS target</li>
<li><code>aarch64-unknown-linux-gnu</code>: An ARM64 Linux target. Equivalent to <code>aarch64-manylinux_2_28</code></li>
<li><code>aarch64-unknown-linux-musl</code>: An ARM64 Linux target</li>
<li><code>x86_64-unknown-linux-musl</code>: An <code>x86_64</code> Linux target</li>
<li><code>x86_64-manylinux2014</code>: An <code>x86_64</code> target for the <code>manylinux2014</code> platform. Equivalent to <code>x86_64-manylinux_2_17</code></li>
<li><code>x86_64-manylinux_2_17</code>: An <code>x86_64</code> target for the <code>manylinux_2_17</code> platform</li>
<li><code>x86_64-manylinux_2_28</code>: An <code>x86_64</code> target for the <code>manylinux_2_28</code> platform</li>
<li><code>x86_64-manylinux_2_31</code>: An <code>x86_64</code> target for the <code>manylinux_2_31</code> platform</li>
<li><code>x86_64-manylinux_2_32</code>: An <code>x86_64</code> target for the <code>manylinux_2_32</code> platform</li>
<li><code>x86_64-manylinux_2_33</code>: An <code>x86_64</code> target for the <code>manylinux_2_33</code> platform</li>
<li><code>x86_64-manylinux_2_34</code>: An <code>x86_64</code> target for the <code>manylinux_2_34</code> platform</li>
<li><code>x86_64-manylinux_2_35</code>: An <code>x86_64</code> target for the <code>manylinux_2_35</code> platform</li>
<li><code>x86_64-manylinux_2_36</code>: An <code>x86_64</code> target for the <code>manylinux_2_36</code> platform</li>
<li><code>x86_64-manylinux_2_37</code>: An <code>x86_64</code> target for the <code>manylinux_2_37</code> platform</li>
<li><code>x86_64-manylinux_2_38</code>: An <code>x86_64</code> target for the <code>manylinux_2_38</code> platform</li>
<li><code>x86_64-manylinux_2_39</code>: An <code>x86_64</code> target for the <code>manylinux_2_39</code> platform</li>
<li><code>x86_64-manylinux_2_40</code>: An <code>x86_64</code> target for the <code>manylinux_2_40</code> platform</li>
<li><code>aarch64-manylinux2014</code>: An ARM64 target for the <code>manylinux2014</code> platform. Equivalent to <code>aarch64-manylinux_2_17</code></li>
<li><code>aarch64-manylinux_2_17</code>: An ARM64 target for the <code>manylinux_2_17</code> platform</li>
<li><code>aarch64-manylinux_2_28</code>: An ARM64 target for the <code>manylinux_2_28</code> platform</li>
<li><code>aarch64-manylinux_2_31</code>: An ARM64 target for the <code>manylinux_2_31</code> platform</li>
<li><code>aarch64-manylinux_2_32</code>: An ARM64 target for the <code>manylinux_2_32</code> platform</li>
<li><code>aarch64-manylinux_2_33</code>: An ARM64 target for the <code>manylinux_2_33</code> platform</li>
<li><code>aarch64-manylinux_2_34</code>: An ARM64 target for the <code>manylinux_2_34</code> platform</li>
<li><code>aarch64-manylinux_2_35</code>: An ARM64 target for the <code>manylinux_2_35</code> platform</li>
<li><code>aarch64-manylinux_2_36</code>: An ARM64 target for the <code>manylinux_2_36</code> platform</li>
<li><code>aarch64-manylinux_2_37</code>: An ARM64 target for the <code>manylinux_2_37</code> platform</li>
<li><code>aarch64-manylinux_2_38</code>: An ARM64 target for the <code>manylinux_2_38</code> platform</li>
<li><code>aarch64-manylinux_2_39</code>: An ARM64 target for the <code>manylinux_2_39</code> platform</li>
<li><code>aarch64-manylinux_2_40</code>: An ARM64 target for the <code>manylinux_2_40</code> platform</li>
<li><code>wasm32-pyodide2024</code>: A wasm32 target using the Pyodide 2024 platform. Meant for use with Python 3.12</li>
</ul></dd><dt id="uv-run--quiet"><a href="#uv-run--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p> <p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p>
</dd><dt id="uv-run--refresh"><a href="#uv-run--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p> </dd><dt id="uv-run--refresh"><a href="#uv-run--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p>
</dd><dt id="uv-run--refresh-package"><a href="#uv-run--refresh-package"><code>--refresh-package</code></a> <i>refresh-package</i></dt><dd><p>Refresh cached data for a specific package</p> </dd><dt id="uv-run--refresh-package"><a href="#uv-run--refresh-package"><code>--refresh-package</code></a> <i>refresh-package</i></dt><dd><p>Refresh cached data for a specific package</p>
@ -2103,7 +2148,52 @@ uv tool run [OPTIONS] [COMMAND]
<p>This setting has no effect when used in the <code>uv pip</code> interface.</p> <p>This setting has no effect when used in the <code>uv pip</code> interface.</p>
<p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-tool-run--python"><a href="#uv-tool-run--python"><code>--python</code></a>, <code>-p</code> <i>python</i></dt><dd><p>The Python interpreter to use to build the run environment.</p> <p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-tool-run--python"><a href="#uv-tool-run--python"><code>--python</code></a>, <code>-p</code> <i>python</i></dt><dd><p>The Python interpreter to use to build the run environment.</p>
<p>See <a href="#uv-python">uv python</a> for details on Python discovery and supported request formats.</p> <p>See <a href="#uv-python">uv python</a> for details on Python discovery and supported request formats.</p>
<p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-tool-run--quiet"><a href="#uv-tool-run--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p> <p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-tool-run--python-platform"><a href="#uv-tool-run--python-platform"><code>--python-platform</code></a> <i>python-platform</i></dt><dd><p>The platform for which requirements should be installed.</p>
<p>Represented as a &quot;target triple&quot;, a string that describes the target platform in terms of its CPU, vendor, and operating system name, like <code>x86_64-unknown-linux-gnu</code> or <code>aarch64-apple-darwin</code>.</p>
<p>When targeting macOS (Darwin), the default minimum version is <code>12.0</code>. Use <code>MACOSX_DEPLOYMENT_TARGET</code> to specify a different minimum version, e.g., <code>13.0</code>.</p>
<p>WARNING: When specified, uv will select wheels that are compatible with the <em>target</em> platform; as a result, the installed distributions may not be compatible with the <em>current</em> platform. Conversely, any distributions that are built from source may be incompatible with the <em>target</em> platform, as they will be built for the <em>current</em> platform. The <code>--python-platform</code> option is intended for advanced use cases.</p>
<p>Possible values:</p>
<ul>
<li><code>windows</code>: An alias for <code>x86_64-pc-windows-msvc</code>, the default target for Windows</li>
<li><code>linux</code>: An alias for <code>x86_64-unknown-linux-gnu</code>, the default target for Linux</li>
<li><code>macos</code>: An alias for <code>aarch64-apple-darwin</code>, the default target for macOS</li>
<li><code>x86_64-pc-windows-msvc</code>: A 64-bit x86 Windows target</li>
<li><code>aarch64-pc-windows-msvc</code>: An ARM64 Windows target</li>
<li><code>i686-pc-windows-msvc</code>: A 32-bit x86 Windows target</li>
<li><code>x86_64-unknown-linux-gnu</code>: An x86 Linux target. Equivalent to <code>x86_64-manylinux_2_28</code></li>
<li><code>aarch64-apple-darwin</code>: An ARM-based macOS target, as seen on Apple Silicon devices</li>
<li><code>x86_64-apple-darwin</code>: An x86 macOS target</li>
<li><code>aarch64-unknown-linux-gnu</code>: An ARM64 Linux target. Equivalent to <code>aarch64-manylinux_2_28</code></li>
<li><code>aarch64-unknown-linux-musl</code>: An ARM64 Linux target</li>
<li><code>x86_64-unknown-linux-musl</code>: An <code>x86_64</code> Linux target</li>
<li><code>x86_64-manylinux2014</code>: An <code>x86_64</code> target for the <code>manylinux2014</code> platform. Equivalent to <code>x86_64-manylinux_2_17</code></li>
<li><code>x86_64-manylinux_2_17</code>: An <code>x86_64</code> target for the <code>manylinux_2_17</code> platform</li>
<li><code>x86_64-manylinux_2_28</code>: An <code>x86_64</code> target for the <code>manylinux_2_28</code> platform</li>
<li><code>x86_64-manylinux_2_31</code>: An <code>x86_64</code> target for the <code>manylinux_2_31</code> platform</li>
<li><code>x86_64-manylinux_2_32</code>: An <code>x86_64</code> target for the <code>manylinux_2_32</code> platform</li>
<li><code>x86_64-manylinux_2_33</code>: An <code>x86_64</code> target for the <code>manylinux_2_33</code> platform</li>
<li><code>x86_64-manylinux_2_34</code>: An <code>x86_64</code> target for the <code>manylinux_2_34</code> platform</li>
<li><code>x86_64-manylinux_2_35</code>: An <code>x86_64</code> target for the <code>manylinux_2_35</code> platform</li>
<li><code>x86_64-manylinux_2_36</code>: An <code>x86_64</code> target for the <code>manylinux_2_36</code> platform</li>
<li><code>x86_64-manylinux_2_37</code>: An <code>x86_64</code> target for the <code>manylinux_2_37</code> platform</li>
<li><code>x86_64-manylinux_2_38</code>: An <code>x86_64</code> target for the <code>manylinux_2_38</code> platform</li>
<li><code>x86_64-manylinux_2_39</code>: An <code>x86_64</code> target for the <code>manylinux_2_39</code> platform</li>
<li><code>x86_64-manylinux_2_40</code>: An <code>x86_64</code> target for the <code>manylinux_2_40</code> platform</li>
<li><code>aarch64-manylinux2014</code>: An ARM64 target for the <code>manylinux2014</code> platform. Equivalent to <code>aarch64-manylinux_2_17</code></li>
<li><code>aarch64-manylinux_2_17</code>: An ARM64 target for the <code>manylinux_2_17</code> platform</li>
<li><code>aarch64-manylinux_2_28</code>: An ARM64 target for the <code>manylinux_2_28</code> platform</li>
<li><code>aarch64-manylinux_2_31</code>: An ARM64 target for the <code>manylinux_2_31</code> platform</li>
<li><code>aarch64-manylinux_2_32</code>: An ARM64 target for the <code>manylinux_2_32</code> platform</li>
<li><code>aarch64-manylinux_2_33</code>: An ARM64 target for the <code>manylinux_2_33</code> platform</li>
<li><code>aarch64-manylinux_2_34</code>: An ARM64 target for the <code>manylinux_2_34</code> platform</li>
<li><code>aarch64-manylinux_2_35</code>: An ARM64 target for the <code>manylinux_2_35</code> platform</li>
<li><code>aarch64-manylinux_2_36</code>: An ARM64 target for the <code>manylinux_2_36</code> platform</li>
<li><code>aarch64-manylinux_2_37</code>: An ARM64 target for the <code>manylinux_2_37</code> platform</li>
<li><code>aarch64-manylinux_2_38</code>: An ARM64 target for the <code>manylinux_2_38</code> platform</li>
<li><code>aarch64-manylinux_2_39</code>: An ARM64 target for the <code>manylinux_2_39</code> platform</li>
<li><code>aarch64-manylinux_2_40</code>: An ARM64 target for the <code>manylinux_2_40</code> platform</li>
<li><code>wasm32-pyodide2024</code>: A wasm32 target using the Pyodide 2024 platform. Meant for use with Python 3.12</li>
</ul></dd><dt id="uv-tool-run--quiet"><a href="#uv-tool-run--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p> <p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p>
</dd><dt id="uv-tool-run--refresh"><a href="#uv-tool-run--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p> </dd><dt id="uv-tool-run--refresh"><a href="#uv-tool-run--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p>
</dd><dt id="uv-tool-run--refresh-package"><a href="#uv-tool-run--refresh-package"><code>--refresh-package</code></a> <i>refresh-package</i></dt><dd><p>Refresh cached data for a specific package</p> </dd><dt id="uv-tool-run--refresh-package"><a href="#uv-tool-run--refresh-package"><code>--refresh-package</code></a> <i>refresh-package</i></dt><dd><p>Refresh cached data for a specific package</p>
@ -2277,7 +2367,52 @@ uv tool install [OPTIONS] <PACKAGE>
<p>This setting has no effect when used in the <code>uv pip</code> interface.</p> <p>This setting has no effect when used in the <code>uv pip</code> interface.</p>
<p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-tool-install--python"><a href="#uv-tool-install--python"><code>--python</code></a>, <code>-p</code> <i>python</i></dt><dd><p>The Python interpreter to use to build the tool environment.</p> <p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-tool-install--python"><a href="#uv-tool-install--python"><code>--python</code></a>, <code>-p</code> <i>python</i></dt><dd><p>The Python interpreter to use to build the tool environment.</p>
<p>See <a href="#uv-python">uv python</a> for details on Python discovery and supported request formats.</p> <p>See <a href="#uv-python">uv python</a> for details on Python discovery and supported request formats.</p>
<p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-tool-install--quiet"><a href="#uv-tool-install--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p> <p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-tool-install--python-platform"><a href="#uv-tool-install--python-platform"><code>--python-platform</code></a> <i>python-platform</i></dt><dd><p>The platform for which requirements should be installed.</p>
<p>Represented as a &quot;target triple&quot;, a string that describes the target platform in terms of its CPU, vendor, and operating system name, like <code>x86_64-unknown-linux-gnu</code> or <code>aarch64-apple-darwin</code>.</p>
<p>When targeting macOS (Darwin), the default minimum version is <code>12.0</code>. Use <code>MACOSX_DEPLOYMENT_TARGET</code> to specify a different minimum version, e.g., <code>13.0</code>.</p>
<p>WARNING: When specified, uv will select wheels that are compatible with the <em>target</em> platform; as a result, the installed distributions may not be compatible with the <em>current</em> platform. Conversely, any distributions that are built from source may be incompatible with the <em>target</em> platform, as they will be built for the <em>current</em> platform. The <code>--python-platform</code> option is intended for advanced use cases.</p>
<p>Possible values:</p>
<ul>
<li><code>windows</code>: An alias for <code>x86_64-pc-windows-msvc</code>, the default target for Windows</li>
<li><code>linux</code>: An alias for <code>x86_64-unknown-linux-gnu</code>, the default target for Linux</li>
<li><code>macos</code>: An alias for <code>aarch64-apple-darwin</code>, the default target for macOS</li>
<li><code>x86_64-pc-windows-msvc</code>: A 64-bit x86 Windows target</li>
<li><code>aarch64-pc-windows-msvc</code>: An ARM64 Windows target</li>
<li><code>i686-pc-windows-msvc</code>: A 32-bit x86 Windows target</li>
<li><code>x86_64-unknown-linux-gnu</code>: An x86 Linux target. Equivalent to <code>x86_64-manylinux_2_28</code></li>
<li><code>aarch64-apple-darwin</code>: An ARM-based macOS target, as seen on Apple Silicon devices</li>
<li><code>x86_64-apple-darwin</code>: An x86 macOS target</li>
<li><code>aarch64-unknown-linux-gnu</code>: An ARM64 Linux target. Equivalent to <code>aarch64-manylinux_2_28</code></li>
<li><code>aarch64-unknown-linux-musl</code>: An ARM64 Linux target</li>
<li><code>x86_64-unknown-linux-musl</code>: An <code>x86_64</code> Linux target</li>
<li><code>x86_64-manylinux2014</code>: An <code>x86_64</code> target for the <code>manylinux2014</code> platform. Equivalent to <code>x86_64-manylinux_2_17</code></li>
<li><code>x86_64-manylinux_2_17</code>: An <code>x86_64</code> target for the <code>manylinux_2_17</code> platform</li>
<li><code>x86_64-manylinux_2_28</code>: An <code>x86_64</code> target for the <code>manylinux_2_28</code> platform</li>
<li><code>x86_64-manylinux_2_31</code>: An <code>x86_64</code> target for the <code>manylinux_2_31</code> platform</li>
<li><code>x86_64-manylinux_2_32</code>: An <code>x86_64</code> target for the <code>manylinux_2_32</code> platform</li>
<li><code>x86_64-manylinux_2_33</code>: An <code>x86_64</code> target for the <code>manylinux_2_33</code> platform</li>
<li><code>x86_64-manylinux_2_34</code>: An <code>x86_64</code> target for the <code>manylinux_2_34</code> platform</li>
<li><code>x86_64-manylinux_2_35</code>: An <code>x86_64</code> target for the <code>manylinux_2_35</code> platform</li>
<li><code>x86_64-manylinux_2_36</code>: An <code>x86_64</code> target for the <code>manylinux_2_36</code> platform</li>
<li><code>x86_64-manylinux_2_37</code>: An <code>x86_64</code> target for the <code>manylinux_2_37</code> platform</li>
<li><code>x86_64-manylinux_2_38</code>: An <code>x86_64</code> target for the <code>manylinux_2_38</code> platform</li>
<li><code>x86_64-manylinux_2_39</code>: An <code>x86_64</code> target for the <code>manylinux_2_39</code> platform</li>
<li><code>x86_64-manylinux_2_40</code>: An <code>x86_64</code> target for the <code>manylinux_2_40</code> platform</li>
<li><code>aarch64-manylinux2014</code>: An ARM64 target for the <code>manylinux2014</code> platform. Equivalent to <code>aarch64-manylinux_2_17</code></li>
<li><code>aarch64-manylinux_2_17</code>: An ARM64 target for the <code>manylinux_2_17</code> platform</li>
<li><code>aarch64-manylinux_2_28</code>: An ARM64 target for the <code>manylinux_2_28</code> platform</li>
<li><code>aarch64-manylinux_2_31</code>: An ARM64 target for the <code>manylinux_2_31</code> platform</li>
<li><code>aarch64-manylinux_2_32</code>: An ARM64 target for the <code>manylinux_2_32</code> platform</li>
<li><code>aarch64-manylinux_2_33</code>: An ARM64 target for the <code>manylinux_2_33</code> platform</li>
<li><code>aarch64-manylinux_2_34</code>: An ARM64 target for the <code>manylinux_2_34</code> platform</li>
<li><code>aarch64-manylinux_2_35</code>: An ARM64 target for the <code>manylinux_2_35</code> platform</li>
<li><code>aarch64-manylinux_2_36</code>: An ARM64 target for the <code>manylinux_2_36</code> platform</li>
<li><code>aarch64-manylinux_2_37</code>: An ARM64 target for the <code>manylinux_2_37</code> platform</li>
<li><code>aarch64-manylinux_2_38</code>: An ARM64 target for the <code>manylinux_2_38</code> platform</li>
<li><code>aarch64-manylinux_2_39</code>: An ARM64 target for the <code>manylinux_2_39</code> platform</li>
<li><code>aarch64-manylinux_2_40</code>: An ARM64 target for the <code>manylinux_2_40</code> platform</li>
<li><code>wasm32-pyodide2024</code>: A wasm32 target using the Pyodide 2024 platform. Meant for use with Python 3.12</li>
</ul></dd><dt id="uv-tool-install--quiet"><a href="#uv-tool-install--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p> <p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p>
</dd><dt id="uv-tool-install--refresh"><a href="#uv-tool-install--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p> </dd><dt id="uv-tool-install--refresh"><a href="#uv-tool-install--refresh"><code>--refresh</code></a></dt><dd><p>Refresh all cached data</p>
</dd><dt id="uv-tool-install--refresh-package"><a href="#uv-tool-install--refresh-package"><code>--refresh-package</code></a> <i>refresh-package</i></dt><dd><p>Refresh cached data for a specific package</p> </dd><dt id="uv-tool-install--refresh-package"><a href="#uv-tool-install--refresh-package"><code>--refresh-package</code></a> <i>refresh-package</i></dt><dd><p>Refresh cached data for a specific package</p>
@ -2442,7 +2577,52 @@ uv tool upgrade [OPTIONS] <NAME>...
<p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-tool-upgrade--python"><a href="#uv-tool-upgrade--python"><code>--python</code></a>, <code>-p</code> <i>python</i></dt><dd><p>Upgrade a tool, and specify it to use the given Python interpreter to build its environment. <p>May also be set with the <code>UV_PROJECT</code> environment variable.</p></dd><dt id="uv-tool-upgrade--python"><a href="#uv-tool-upgrade--python"><code>--python</code></a>, <code>-p</code> <i>python</i></dt><dd><p>Upgrade a tool, and specify it to use the given Python interpreter to build its environment.
Use with <code>--all</code> to apply to all tools.</p> Use with <code>--all</code> to apply to all tools.</p>
<p>See <a href="#uv-python">uv python</a> for details on Python discovery and supported request formats.</p> <p>See <a href="#uv-python">uv python</a> for details on Python discovery and supported request formats.</p>
<p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-tool-upgrade--quiet"><a href="#uv-tool-upgrade--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p> <p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-tool-upgrade--python-platform"><a href="#uv-tool-upgrade--python-platform"><code>--python-platform</code></a> <i>python-platform</i></dt><dd><p>The platform for which requirements should be installed.</p>
<p>Represented as a &quot;target triple&quot;, a string that describes the target platform in terms of its CPU, vendor, and operating system name, like <code>x86_64-unknown-linux-gnu</code> or <code>aarch64-apple-darwin</code>.</p>
<p>When targeting macOS (Darwin), the default minimum version is <code>12.0</code>. Use <code>MACOSX_DEPLOYMENT_TARGET</code> to specify a different minimum version, e.g., <code>13.0</code>.</p>
<p>WARNING: When specified, uv will select wheels that are compatible with the <em>target</em> platform; as a result, the installed distributions may not be compatible with the <em>current</em> platform. Conversely, any distributions that are built from source may be incompatible with the <em>target</em> platform, as they will be built for the <em>current</em> platform. The <code>--python-platform</code> option is intended for advanced use cases.</p>
<p>Possible values:</p>
<ul>
<li><code>windows</code>: An alias for <code>x86_64-pc-windows-msvc</code>, the default target for Windows</li>
<li><code>linux</code>: An alias for <code>x86_64-unknown-linux-gnu</code>, the default target for Linux</li>
<li><code>macos</code>: An alias for <code>aarch64-apple-darwin</code>, the default target for macOS</li>
<li><code>x86_64-pc-windows-msvc</code>: A 64-bit x86 Windows target</li>
<li><code>aarch64-pc-windows-msvc</code>: An ARM64 Windows target</li>
<li><code>i686-pc-windows-msvc</code>: A 32-bit x86 Windows target</li>
<li><code>x86_64-unknown-linux-gnu</code>: An x86 Linux target. Equivalent to <code>x86_64-manylinux_2_28</code></li>
<li><code>aarch64-apple-darwin</code>: An ARM-based macOS target, as seen on Apple Silicon devices</li>
<li><code>x86_64-apple-darwin</code>: An x86 macOS target</li>
<li><code>aarch64-unknown-linux-gnu</code>: An ARM64 Linux target. Equivalent to <code>aarch64-manylinux_2_28</code></li>
<li><code>aarch64-unknown-linux-musl</code>: An ARM64 Linux target</li>
<li><code>x86_64-unknown-linux-musl</code>: An <code>x86_64</code> Linux target</li>
<li><code>x86_64-manylinux2014</code>: An <code>x86_64</code> target for the <code>manylinux2014</code> platform. Equivalent to <code>x86_64-manylinux_2_17</code></li>
<li><code>x86_64-manylinux_2_17</code>: An <code>x86_64</code> target for the <code>manylinux_2_17</code> platform</li>
<li><code>x86_64-manylinux_2_28</code>: An <code>x86_64</code> target for the <code>manylinux_2_28</code> platform</li>
<li><code>x86_64-manylinux_2_31</code>: An <code>x86_64</code> target for the <code>manylinux_2_31</code> platform</li>
<li><code>x86_64-manylinux_2_32</code>: An <code>x86_64</code> target for the <code>manylinux_2_32</code> platform</li>
<li><code>x86_64-manylinux_2_33</code>: An <code>x86_64</code> target for the <code>manylinux_2_33</code> platform</li>
<li><code>x86_64-manylinux_2_34</code>: An <code>x86_64</code> target for the <code>manylinux_2_34</code> platform</li>
<li><code>x86_64-manylinux_2_35</code>: An <code>x86_64</code> target for the <code>manylinux_2_35</code> platform</li>
<li><code>x86_64-manylinux_2_36</code>: An <code>x86_64</code> target for the <code>manylinux_2_36</code> platform</li>
<li><code>x86_64-manylinux_2_37</code>: An <code>x86_64</code> target for the <code>manylinux_2_37</code> platform</li>
<li><code>x86_64-manylinux_2_38</code>: An <code>x86_64</code> target for the <code>manylinux_2_38</code> platform</li>
<li><code>x86_64-manylinux_2_39</code>: An <code>x86_64</code> target for the <code>manylinux_2_39</code> platform</li>
<li><code>x86_64-manylinux_2_40</code>: An <code>x86_64</code> target for the <code>manylinux_2_40</code> platform</li>
<li><code>aarch64-manylinux2014</code>: An ARM64 target for the <code>manylinux2014</code> platform. Equivalent to <code>aarch64-manylinux_2_17</code></li>
<li><code>aarch64-manylinux_2_17</code>: An ARM64 target for the <code>manylinux_2_17</code> platform</li>
<li><code>aarch64-manylinux_2_28</code>: An ARM64 target for the <code>manylinux_2_28</code> platform</li>
<li><code>aarch64-manylinux_2_31</code>: An ARM64 target for the <code>manylinux_2_31</code> platform</li>
<li><code>aarch64-manylinux_2_32</code>: An ARM64 target for the <code>manylinux_2_32</code> platform</li>
<li><code>aarch64-manylinux_2_33</code>: An ARM64 target for the <code>manylinux_2_33</code> platform</li>
<li><code>aarch64-manylinux_2_34</code>: An ARM64 target for the <code>manylinux_2_34</code> platform</li>
<li><code>aarch64-manylinux_2_35</code>: An ARM64 target for the <code>manylinux_2_35</code> platform</li>
<li><code>aarch64-manylinux_2_36</code>: An ARM64 target for the <code>manylinux_2_36</code> platform</li>
<li><code>aarch64-manylinux_2_37</code>: An ARM64 target for the <code>manylinux_2_37</code> platform</li>
<li><code>aarch64-manylinux_2_38</code>: An ARM64 target for the <code>manylinux_2_38</code> platform</li>
<li><code>aarch64-manylinux_2_39</code>: An ARM64 target for the <code>manylinux_2_39</code> platform</li>
<li><code>aarch64-manylinux_2_40</code>: An ARM64 target for the <code>manylinux_2_40</code> platform</li>
<li><code>wasm32-pyodide2024</code>: A wasm32 target using the Pyodide 2024 platform. Meant for use with Python 3.12</li>
</ul></dd><dt id="uv-tool-upgrade--quiet"><a href="#uv-tool-upgrade--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p> <p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p>
</dd><dt id="uv-tool-upgrade--reinstall"><a href="#uv-tool-upgrade--reinstall"><code>--reinstall</code></a>, <code>--force-reinstall</code></dt><dd><p>Reinstall all packages, regardless of whether they're already installed. Implies <code>--refresh</code></p> </dd><dt id="uv-tool-upgrade--reinstall"><a href="#uv-tool-upgrade--reinstall"><code>--reinstall</code></a>, <code>--force-reinstall</code></dt><dd><p>Reinstall all packages, regardless of whether they're already installed. Implies <code>--refresh</code></p>
</dd><dt id="uv-tool-upgrade--reinstall-package"><a href="#uv-tool-upgrade--reinstall-package"><code>--reinstall-package</code></a> <i>reinstall-package</i></dt><dd><p>Reinstall a specific package, regardless of whether it's already installed. Implies <code>--refresh-package</code></p> </dd><dt id="uv-tool-upgrade--reinstall-package"><a href="#uv-tool-upgrade--reinstall-package"><code>--reinstall-package</code></a> <i>reinstall-package</i></dt><dd><p>Reinstall a specific package, regardless of whether it's already installed. Implies <code>--refresh-package</code></p>