Skip to content

Commit

Permalink
Add target
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Apr 19, 2024
1 parent a241bc7 commit 5cc156e
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 9 deletions.
9 changes: 9 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 @@ -520,6 +521,14 @@ 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", a string that describes the target platform in terms of
/// its CPU, vendor, and operating system name, like `x86_64-unknown-linux-gnu` or
/// `aaarch64-apple-darwin`.
#[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 @@ -46,6 +46,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 @@ -78,6 +79,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 @@ -193,21 +195,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 @@ -134,6 +136,7 @@ impl PipCompileSettings {
only_binary,
config_setting,
python_version,
platform,
exclude_newer,
no_emit_package,
emit_index_url,
Expand All @@ -152,6 +155,7 @@ impl PipCompileSettings {
src_file,
constraint,
r#override,
platform,
refresh,
refresh_package: refresh_package.unwrap_or_default(),
upgrade,
Expand Down
190 changes: 190 additions & 0 deletions crates/uv/src/target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
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 {
/// An alias for `x86_64-pc-windows-msvc`, the default target for Windows.
Windows,

/// An alias for `x86_64-unknown-linux-gnu`, the default target for Linux.
Linux,

/// An alias for `aarch64-apple-darwin`, the default target for macOS.
Macos,

/// An x86 Windows target.
#[value(name = "x86_64-pc-windows-msvc")]
X8664PcWindowsMsvc,

/// An x86 Linux target.
#[value(name = "x86_64-unknown-linux-gnu")]
X8664UnknownLinuxGnu,

/// An ARM-based macOS target, as seen on Apple Silicon devices.
#[value(name = "aarch64-apple-darwin")]
Aarch64AppleDarwin,

/// An x86 macOS target.
#[value(name = "x86_64-apple-darwin")]
X8664AppleDarwin,

/// An ARM64 Linux target.
#[value(name = "aarch64-unknown-linux-gnu")]
Aarch64UnknownLinuxGnu,

/// An ARM64 Linux target.
#[value(name = "aarch64-unknown-linux-musl")]
Aarch64UnknownLinuxMusl,

/// An x86_64 Linux target.
#[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::Windows | Self::X8664PcWindowsMsvc => Platform::new(Os::Windows, Arch::X86_64),
Self::Linux | Self::X8664UnknownLinuxGnu => Platform::new(
Os::Manylinux {
major: 2,
minor: 17,
},
Arch::X86_64,
),
Self::Macos | Self::Aarch64AppleDarwin => Platform::new(
Os::Macos {
major: 11,
minor: 0,
},
Arch::Aarch64,
),
Self::X8664AppleDarwin => Platform::new(
Os::Macos {
major: 10,
minor: 12,
},
Arch::X86_64,
),
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::Windows | Self::X8664PcWindowsMsvc => "x86_64",
Self::Linux | Self::X8664UnknownLinuxGnu => "x86_64",
Self::Macos | Self::Aarch64AppleDarwin => "aarch64",
Self::X8664AppleDarwin => "x86_64",
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::Windows | Self::X8664PcWindowsMsvc => "Windows",
Self::Linux | Self::X8664UnknownLinuxGnu => "Linux",
Self::Macos | Self::Aarch64AppleDarwin => "Darwin",
Self::X8664AppleDarwin => "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::Windows | Self::X8664PcWindowsMsvc => "",
Self::Linux | Self::X8664UnknownLinuxGnu => "",
Self::Macos | Self::Aarch64AppleDarwin => "",
Self::X8664AppleDarwin => "",
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::Windows | Self::X8664PcWindowsMsvc => "",
Self::Linux | Self::X8664UnknownLinuxGnu => "",
Self::Macos | Self::Aarch64AppleDarwin => "",
Self::X8664AppleDarwin => "",
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::Windows | Self::X8664PcWindowsMsvc => "nt",
Self::Linux | Self::X8664UnknownLinuxGnu => "posix",
Self::Macos | Self::Aarch64AppleDarwin => "posix",
Self::X8664AppleDarwin => "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::Windows | Self::X8664PcWindowsMsvc => "win32",
Self::Linux | Self::X8664UnknownLinuxGnu => "linux",
Self::Macos | Self::Aarch64AppleDarwin => "darwin",
Self::X8664AppleDarwin => "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(),
}
}
}
Loading

0 comments on commit 5cc156e

Please sign in to comment.