Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,9 @@ pub struct PipCompileArgs {
///
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
#[arg(long)]
pub python_platform: Option<TargetTriple>,

Expand Down Expand Up @@ -1767,6 +1770,9 @@ pub struct PipSyncArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down Expand Up @@ -2070,6 +2076,9 @@ pub struct PipInstallArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down Expand Up @@ -2392,6 +2401,9 @@ pub struct PipCheckArgs {
///
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
#[arg(long)]
pub python_platform: Option<TargetTriple>,
}
Expand Down Expand Up @@ -3318,6 +3330,9 @@ pub struct RunArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down Expand Up @@ -3595,6 +3610,9 @@ pub struct SyncArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down Expand Up @@ -4591,6 +4609,9 @@ pub struct ToolRunArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down Expand Up @@ -4713,6 +4734,9 @@ pub struct ToolInstallArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down Expand Up @@ -4810,6 +4834,9 @@ pub struct ToolUpgradeArgs {
/// 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`.
///
/// When targeting Android, the default minimum Android API level is `24`. Use
/// `ANDROID_API_LEVEL` to specify a different minimum version, e.g., `26`.
///
/// 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
Expand Down
54 changes: 54 additions & 0 deletions crates/uv-configuration/src/target_triple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,22 @@ pub enum TargetTriple {
#[serde(alias = "aarch64-manylinux240")]
Aarch64Manylinux240,

/// An ARM64 Android target.
///
/// By default uses Android API level 24, but respects
/// the `ANDROID_API_LEVEL` environment variable if set.
#[cfg_attr(feature = "clap", value(name = "aarch64-linux-android"))]
#[serde(rename = "aarch64-linux-android")]
Aarch64LinuxAndroid,

/// An `x86_64` Android target.
///
/// By default uses Android API level 24, but respects
/// the `ANDROID_API_LEVEL` environment variable if set.
#[cfg_attr(feature = "clap", value(name = "x86_64-linux-android"))]
#[serde(rename = "x86_64-linux-android")]
X8664LinuxAndroid,

/// A wasm32 target using the Pyodide 2024 platform. Meant for use with Python 3.12.
#[cfg_attr(feature = "clap", value(name = "wasm32-pyodide2024"))]
Wasm32Pyodide2024,
Expand Down Expand Up @@ -468,6 +484,20 @@ impl TargetTriple {
},
Arch::Wasm32,
),
Self::Aarch64LinuxAndroid => {
let api_level = android_api_level().map_or(24, |api_level| {
debug!("Found Android API level: {}", api_level);
api_level
});
Platform::new(Os::Android { api_level }, Arch::Aarch64)
}
Self::X8664LinuxAndroid => {
let api_level = android_api_level().map_or(24, |api_level| {
debug!("Found Android API level: {}", api_level);
api_level
});
Platform::new(Os::Android { api_level }, Arch::X86_64)
}
}
}

Expand Down Expand Up @@ -509,6 +539,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "aarch64",
Self::Aarch64Manylinux239 => "aarch64",
Self::Aarch64Manylinux240 => "aarch64",
Self::Aarch64LinuxAndroid => "aarch64",
Self::X8664LinuxAndroid => "x86_64",
Self::Wasm32Pyodide2024 => "wasm32",
}
}
Expand Down Expand Up @@ -551,6 +583,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "Linux",
Self::Aarch64Manylinux239 => "Linux",
Self::Aarch64Manylinux240 => "Linux",
Self::Aarch64LinuxAndroid => "Android",
Self::X8664LinuxAndroid => "Android",
Self::Wasm32Pyodide2024 => "Emscripten",
}
}
Expand Down Expand Up @@ -593,6 +627,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "",
Self::Aarch64Manylinux239 => "",
Self::Aarch64Manylinux240 => "",
Self::Aarch64LinuxAndroid => "",
Self::X8664LinuxAndroid => "",
// This is the value Emscripten gives for its version:
// https://github.com/emscripten-core/emscripten/blob/4.0.8/system/lib/libc/emscripten_syscall_stubs.c#L63
// It doesn't really seem to mean anything? But for completeness we include it here.
Expand Down Expand Up @@ -638,6 +674,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "",
Self::Aarch64Manylinux239 => "",
Self::Aarch64Manylinux240 => "",
Self::Aarch64LinuxAndroid => "",
Self::X8664LinuxAndroid => "",
// This is the Emscripten compiler version for Pyodide 2024.
// See https://pyodide.org/en/stable/development/abi.html#pyodide-2024-0
Self::Wasm32Pyodide2024 => "3.1.58",
Expand Down Expand Up @@ -682,6 +720,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "posix",
Self::Aarch64Manylinux239 => "posix",
Self::Aarch64Manylinux240 => "posix",
Self::Aarch64LinuxAndroid => "posix",
Self::X8664LinuxAndroid => "posix",
Self::Wasm32Pyodide2024 => "posix",
}
}
Expand Down Expand Up @@ -724,6 +764,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => "linux",
Self::Aarch64Manylinux239 => "linux",
Self::Aarch64Manylinux240 => "linux",
Self::Aarch64LinuxAndroid => "android",
Self::X8664LinuxAndroid => "android",
Self::Wasm32Pyodide2024 => "emscripten",
}
}
Expand Down Expand Up @@ -766,6 +808,8 @@ impl TargetTriple {
Self::Aarch64Manylinux238 => true,
Self::Aarch64Manylinux239 => true,
Self::Aarch64Manylinux240 => true,
Self::Aarch64LinuxAndroid => false,
Self::X8664LinuxAndroid => false,
Self::Wasm32Pyodide2024 => false,
}
}
Expand Down Expand Up @@ -799,3 +843,13 @@ fn macos_deployment_target() -> Option<(u16, u16)> {

Some((major, minor))
}

/// Return the Android API level as parsed from the environment.
fn android_api_level() -> Option<u16> {
let api_level_str = std::env::var(EnvVars::ANDROID_API_LEVEL).ok()?;

// Parse the api level.
let api_level = api_level_str.parse::<u16>().ok()?;

Some(api_level)
}
2 changes: 2 additions & 0 deletions crates/uv-platform-tags/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum PlatformError {
IOError(#[from] io::Error),
#[error("Failed to detect the operating system version: {0}")]
OsVersionDetectionError(String),
#[error("Failed to detect the arch: {0}")]
ArchDetectionError(String),
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
Expand Down
47 changes: 39 additions & 8 deletions crates/uv-platform-tags/src/platform_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::str::FromStr;

use uv_small_str::SmallString;

use crate::tags::AndroidAbi;
use crate::{Arch, BinaryFormat};

/// A tag to represent the platform compatibility of a Python distribution.
Expand Down Expand Up @@ -56,7 +57,7 @@ pub enum PlatformTag {
/// Ex) `win_ia64`
WinIa64,
/// Ex) `android_21_x86_64`
Android { api_level: u16, arch: Arch },
Android { api_level: u16, abi: AndroidAbi },
/// Ex) `freebsd_12_x86_64`
FreeBsd { release_arch: SmallString },
/// Ex) `netbsd_9_x86_64`
Expand Down Expand Up @@ -179,7 +180,7 @@ impl PlatformTag {
..
} | Self::WinArm64
| Self::Android {
arch: Arch::Aarch64,
abi: AndroidAbi::Arm64V8a,
..
}
)
Expand Down Expand Up @@ -267,7 +268,7 @@ impl std::fmt::Display for PlatformTag {
Self::WinAmd64 => write!(f, "win_amd64"),
Self::WinArm64 => write!(f, "win_arm64"),
Self::WinIa64 => write!(f, "win_ia64"),
Self::Android { api_level, arch } => write!(f, "android_{api_level}_{arch}"),
Self::Android { api_level, abi } => write!(f, "android_{api_level}_{abi}"),
Self::FreeBsd { release_arch } => write!(f, "freebsd_{release_arch}"),
Self::NetBsd { release_arch } => write!(f, "netbsd_{release_arch}"),
Self::OpenBsd { release_arch } => write!(f, "openbsd_{release_arch}"),
Expand Down Expand Up @@ -489,7 +490,7 @@ impl FromStr for PlatformTag {
}

if let Some(rest) = s.strip_prefix("android_") {
// Ex) android_21_arm64
// Ex) android_21_arm64_v8a
let underscore = memchr::memchr(b'_', rest.as_bytes()).ok_or_else(|| {
ParsePlatformTagError::InvalidFormat {
platform: "android",
Expand All @@ -505,22 +506,22 @@ impl FromStr for PlatformTag {
tag: s.to_string(),
})?;

let arch_str = &rest[underscore + 1..];
if arch_str.is_empty() {
let abi_str = &rest[underscore + 1..];
if abi_str.is_empty() {
return Err(ParsePlatformTagError::InvalidFormat {
platform: "android",
tag: s.to_string(),
});
}

let arch = arch_str
let abi = abi_str
.parse()
.map_err(|_| ParsePlatformTagError::InvalidArch {
platform: "android",
tag: s.to_string(),
})?;

return Ok(Self::Android { api_level, arch });
return Ok(Self::Android { api_level, abi });
}

if let Some(rest) = s.strip_prefix("freebsd_") {
Expand Down Expand Up @@ -684,6 +685,7 @@ mod tests {
use std::str::FromStr;

use crate::platform_tag::{ParsePlatformTagError, PlatformTag};
use crate::tags::AndroidAbi;
use crate::{Arch, BinaryFormat};

#[test]
Expand Down Expand Up @@ -964,6 +966,35 @@ mod tests {
);
}

#[test]
fn android_platform() {
let tag = PlatformTag::Android {
api_level: 21,
abi: AndroidAbi::Arm64V8a,
};
assert_eq!(
PlatformTag::from_str("android_21_arm64_v8a").as_ref(),
Ok(&tag)
);
assert_eq!(tag.to_string(), "android_21_arm64_v8a");

assert_eq!(
PlatformTag::from_str("android_X_arm64_v8a"),
Err(ParsePlatformTagError::InvalidApiLevel {
platform: "android",
tag: "android_X_arm64_v8a".to_string()
})
);

assert_eq!(
PlatformTag::from_str("android_21_aarch64"),
Err(ParsePlatformTagError::InvalidArch {
platform: "android",
tag: "android_21_aarch64".to_string()
})
);
}

#[test]
fn unknown_platform() {
assert_eq!(
Expand Down
Loading
Loading