Skip to content

Commit

Permalink
Add target
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Apr 18, 2024
1 parent 01532d9 commit 9552ff3
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 9 deletions.
7 changes: 7 additions & 0 deletions crates/uv/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use uv_toolchain::PythonVersion;

use crate::commands::{extra_name_with_clap_error, ListFormat, VersionFormat};
use crate::compat;
use crate::target::TargetTriple;

#[derive(Parser)]
#[command(author, version, long_version = crate::version::version(), about)]
Expand Down Expand Up @@ -485,6 +486,12 @@ pub(crate) struct PipCompileArgs {
#[arg(long, short)]
pub(crate) python_version: Option<PythonVersion>,

/// The platform for which requirements should be resolved.
///
/// Represented as a target triple (e.g., `x86_64-pc-windows-msvc`).
#[arg(long)]
pub(crate) platform: Option<TargetTriple>,

/// Limit candidate packages to those that were uploaded prior to the given date.
///
/// Accepts both RFC 3339 timestamps (e.g., `2006-12-02T02:07:43Z`) and UTC dates in the same
Expand Down
39 changes: 30 additions & 9 deletions crates/uv/src/commands/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use uv_warnings::warn_user;
use crate::commands::reporters::{DownloadReporter, ResolverReporter};
use crate::commands::{elapsed, ExitStatus};
use crate::printer::Printer;
use crate::target::TargetTriple;

/// Resolve a set of requirements into a set of pinned versions.
#[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)]
Expand Down Expand Up @@ -77,6 +78,7 @@ pub(crate) async fn pip_compile(
no_build_isolation: bool,
no_build: NoBuild,
python_version: Option<PythonVersion>,
target: Option<TargetTriple>,
exclude_newer: Option<ExcludeNewer>,
annotation_style: AnnotationStyle,
link_mode: LinkMode,
Expand Down Expand Up @@ -185,21 +187,40 @@ pub(crate) async fn pip_compile(
};

// Determine the tags, markers, and interpreter to use for resolution.
let tags = if let Some(python_version) = python_version.as_ref() {
Cow::Owned(Tags::from_env(
let tags = match (target, python_version.as_ref()) {
(Some(target), Some(python_version)) => Cow::Owned(Tags::from_env(
&target.platform(),
(python_version.major(), python_version.minor()),
interpreter.implementation_name(),
interpreter.implementation_tuple(),
interpreter.gil_disabled(),
)?),
(Some(target), None) => Cow::Owned(Tags::from_env(
&target.platform(),
interpreter.python_tuple(),
interpreter.implementation_name(),
interpreter.implementation_tuple(),
interpreter.gil_disabled(),
)?),
(None, Some(python_version)) => Cow::Owned(Tags::from_env(
interpreter.platform(),
(python_version.major(), python_version.minor()),
interpreter.implementation_name(),
interpreter.implementation_tuple(),
interpreter.gil_disabled(),
)?)
} else {
Cow::Borrowed(interpreter.tags()?)
)?),
(None, None) => Cow::Borrowed(interpreter.tags()?),
};

// Apply the platform tags to the markers.
let markers = match (target, python_version) {
(Some(target), Some(python_version)) => {
Cow::Owned(python_version.markers(&target.markers(interpreter.markers())))
}
(Some(target), None) => Cow::Owned(target.markers(interpreter.markers())),
(None, Some(python_version)) => Cow::Owned(python_version.markers(interpreter.markers())),
(None, None) => Cow::Borrowed(interpreter.markers()),
};
let markers = python_version.map_or_else(
|| Cow::Borrowed(interpreter.markers()),
|python_version| Cow::Owned(python_version.markers(interpreter.markers())),
);

// Generate, but don't enforce hashes for the requirements.
let hasher = if generate_hashes {
Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mod logging;
mod printer;
mod settings;
mod shell;
mod target;
mod version;

#[instrument]
Expand Down Expand Up @@ -254,6 +255,7 @@ async fn run() -> Result<ExitStatus> {
args.shared.no_build_isolation,
no_build,
args.shared.python_version,
args.platform,
args.shared.exclude_newer,
args.shared.annotation_style,
args.shared.link_mode,
Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::cli::{
PipListArgs, PipShowArgs, PipSyncArgs, PipUninstallArgs, VenvArgs,
};
use crate::commands::ListFormat;
use crate::target::TargetTriple;

/// The resolved global settings to use for any invocation of the CLI.
#[allow(clippy::struct_excessive_bools)]
Expand Down Expand Up @@ -74,6 +75,7 @@ pub(crate) struct PipCompileSettings {
pub(crate) src_file: Vec<PathBuf>,
pub(crate) constraint: Vec<PathBuf>,
pub(crate) r#override: Vec<PathBuf>,
pub(crate) platform: Option<TargetTriple>,
pub(crate) refresh: bool,
pub(crate) refresh_package: Vec<PackageName>,
pub(crate) upgrade: bool,
Expand Down Expand Up @@ -131,6 +133,7 @@ impl PipCompileSettings {
only_binary,
config_setting,
python_version,
platform,
exclude_newer,
no_emit_package,
emit_index_url,
Expand All @@ -149,6 +152,7 @@ impl PipCompileSettings {
src_file,
constraint,
r#override,
platform,
refresh,
refresh_package: refresh_package.unwrap_or_default(),
upgrade,
Expand Down
168 changes: 168 additions & 0 deletions crates/uv/src/target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use pep508_rs::MarkerEnvironment;
use platform_tags::{Arch, Os, Platform};

/// The supported target triples. Each triple consists of an architecture, vendor, and operating
/// system.
///
/// See: <https://doc.rust-lang.org/nightly/rustc/platform-support.html>
#[derive(Debug, Clone, Copy, Eq, PartialEq, clap::ValueEnum)]
pub(crate) enum TargetTriple {
#[value(name = "x86_64-pc-windows-msvc")]
X8664PcWindowsMsvc,
#[value(name = "x86_64-unknown-linux-gnu")]
X8664UnknownLinuxGnu,
#[value(name = "x86_64-apple-darwin")]
X8664AppleDarwin,
#[value(name = "aarch64-apple-darwin")]
Aarch64AppleDarwin,
#[value(name = "aarch64-unknown-linux-gnu")]
Aarch64UnknownLinuxGnu,
#[value(name = "aarch64-unknown-linux-musl")]
Aarch64UnknownLinuxMusl,
#[value(name = "x86_64-unknown-linux-musl")]
X8664UnknownLinuxMusl,
}

impl TargetTriple {
/// Return the [`Platform`] for the target.
pub(crate) fn platform(self) -> Platform {
match self {
Self::X8664PcWindowsMsvc => Platform::new(Os::Windows, Arch::X86_64),
Self::X8664UnknownLinuxGnu => Platform::new(
Os::Manylinux {
major: 2,
minor: 17,
},
Arch::X86_64,
),
Self::X8664AppleDarwin => Platform::new(
Os::Macos {
major: 10,
minor: 12,
},
Arch::X86_64,
),
Self::Aarch64AppleDarwin => Platform::new(
Os::Macos {
major: 11,
minor: 0,
},
Arch::Aarch64,
),
Self::Aarch64UnknownLinuxGnu => Platform::new(
Os::Manylinux {
major: 2,
minor: 17,
},
Arch::Aarch64,
),
Self::Aarch64UnknownLinuxMusl => {
Platform::new(Os::Musllinux { major: 1, minor: 2 }, Arch::Aarch64)
}
Self::X8664UnknownLinuxMusl => {
Platform::new(Os::Musllinux { major: 1, minor: 2 }, Arch::X86_64)
}
}
}

/// Return the `platform_machine` value for the target.
pub(crate) fn platform_machine(self) -> &'static str {
match self {
Self::X8664PcWindowsMsvc => "x86_64",
Self::X8664UnknownLinuxGnu => "x86_64",
Self::X8664AppleDarwin => "x86_64",
Self::Aarch64AppleDarwin => "aarch64",
Self::Aarch64UnknownLinuxGnu => "aarch64",
Self::Aarch64UnknownLinuxMusl => "aarch64",
Self::X8664UnknownLinuxMusl => "x86_64",
}
}

/// Return the `platform_system` value for the target.
pub(crate) fn platform_system(self) -> &'static str {
match self {
Self::X8664PcWindowsMsvc => "Windows",
Self::X8664UnknownLinuxGnu => "Linux",
Self::X8664AppleDarwin => "Darwin",
Self::Aarch64AppleDarwin => "Darwin",
Self::Aarch64UnknownLinuxGnu => "Linux",
Self::Aarch64UnknownLinuxMusl => "Linux",
Self::X8664UnknownLinuxMusl => "Linux",
}
}

/// Return the `platform_version` value for the target.
pub(crate) fn platform_version(self) -> &'static str {
match self {
Self::X8664PcWindowsMsvc => "",
Self::X8664UnknownLinuxGnu => "",
Self::X8664AppleDarwin => "",
Self::Aarch64AppleDarwin => "",
Self::Aarch64UnknownLinuxGnu => "",
Self::Aarch64UnknownLinuxMusl => "",
Self::X8664UnknownLinuxMusl => "",
}
}

/// Return the `platform_release` value for the target.
pub(crate) fn platform_release(self) -> &'static str {
match self {
Self::X8664PcWindowsMsvc => "",
Self::X8664UnknownLinuxGnu => "",
Self::X8664AppleDarwin => "",
Self::Aarch64AppleDarwin => "",
Self::Aarch64UnknownLinuxGnu => "",
Self::Aarch64UnknownLinuxMusl => "",
Self::X8664UnknownLinuxMusl => "",
}
}

/// Return the `os_name` value for the target.
pub(crate) fn os_name(self) -> &'static str {
match self {
Self::X8664PcWindowsMsvc => "nt",
Self::X8664UnknownLinuxGnu => "posix",
Self::X8664AppleDarwin => "posix",
Self::Aarch64AppleDarwin => "posix",
Self::Aarch64UnknownLinuxGnu => "posix",
Self::Aarch64UnknownLinuxMusl => "posix",
Self::X8664UnknownLinuxMusl => "posix",
}
}

/// Return the `sys_platform` value for the target.
pub(crate) fn sys_platform(self) -> &'static str {
match self {
Self::X8664PcWindowsMsvc => "win32",
Self::X8664UnknownLinuxGnu => "linux",
Self::X8664AppleDarwin => "darwin",
Self::Aarch64AppleDarwin => "darwin",
Self::Aarch64UnknownLinuxGnu => "linux",
Self::Aarch64UnknownLinuxMusl => "linux",
Self::X8664UnknownLinuxMusl => "linux",
}
}

/// Return a [`MarkerEnvironment`] compatible with the given [`TargetTriple`], based on
/// a base [`MarkerEnvironment`].
///
/// The returned [`MarkerEnvironment`] will preserve the base environment's Python version
/// markers, but override its platform markers.
pub(crate) fn markers(self, base: &MarkerEnvironment) -> MarkerEnvironment {
MarkerEnvironment {
// Platform markers
os_name: self.os_name().to_string(),
platform_machine: self.platform_machine().to_string(),
platform_system: self.platform_system().to_string(),
sys_platform: self.sys_platform().to_string(),
platform_release: self.platform_release().to_string(),
platform_version: self.platform_version().to_string(),
// Python version markers
implementation_name: base.implementation_name.clone(),
implementation_version: base.implementation_version.clone(),
platform_python_implementation: base.platform_python_implementation.clone(),
python_full_version: base.python_full_version.clone(),
python_version: base.python_version.clone(),
}
}
}
65 changes: 65 additions & 0 deletions crates/uv/tests/pip_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7811,6 +7811,71 @@ fn no_version_for_direct_dependency() -> Result<()> {
Ok(())
}

/// Compile against a dedicated platform, which may differ from the current platform.
#[test]
fn platform() -> Result<()> {
let context = TestContext::new("3.12");

let requirements_in = context.temp_dir.child("requirements.in");
requirements_in.write_str("black")?;

uv_snapshot!(context.compile()
.arg("requirements.in")
.arg("--platform")
.arg("aarch64-unknown-linux-gnu"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --platform aarch64-unknown-linux-gnu
black==24.3.0
click==8.1.7
# via black
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black
----- stderr -----
Resolved 6 packages in [TIME]
"###
);

uv_snapshot!(context.compile()
.arg("requirements.in")
.arg("--platform")
.arg("x86_64-pc-windows-msvc"), @r###"
success: true
exit_code: 0
----- stdout -----
# This file was autogenerated by uv via the following command:
# uv pip compile --cache-dir [CACHE_DIR] --exclude-newer 2024-03-25T00:00:00Z requirements.in --platform x86_64-pc-windows-msvc
black==24.3.0
click==8.1.7
# via black
colorama==0.4.6
# via click
mypy-extensions==1.0.0
# via black
packaging==24.0
# via black
pathspec==0.12.1
# via black
platformdirs==4.2.0
# via black
----- stderr -----
Resolved 7 packages in [TIME]
"###
);

Ok(())
}

/// Verify that command-line arguments take precedence over on-disk configuration.
#[test]
fn resolve_configuration() -> Result<()> {
Expand Down

0 comments on commit 9552ff3

Please sign in to comment.