29bd0a4ed8
musl (which we already use in ruff) allows statically linked binaries on linux. This PR switches to rustls and vendors and fixes the glibc detection. Using static musl builds makes it easier to avoid glibc errors in docker and we'll need it later for alpine users anyway. An alternative is using vendored openssl.
190 lines
6.4 KiB
Rust
190 lines
6.4 KiB
Rust
//! Abstractions for understanding the current platform (operating system and architecture).
|
|
|
|
use std::{fmt, io};
|
|
|
|
use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
|
|
use thiserror::Error;
|
|
|
|
use crate::linux::detect_linux_libc;
|
|
use crate::mac_os::get_mac_os_version;
|
|
|
|
mod linux;
|
|
mod mac_os;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum PlatformError {
|
|
#[error(transparent)]
|
|
IOError(#[from] io::Error),
|
|
#[error("Failed to detect the operating system version: {0}")]
|
|
OsVersionDetectionError(String),
|
|
}
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
pub struct Platform {
|
|
os: Os,
|
|
arch: Arch,
|
|
}
|
|
|
|
impl Platform {
|
|
/// Create a new platform from the given operating system and architecture.
|
|
pub fn new(os: Os, arch: Arch) -> Self {
|
|
Self { os, arch }
|
|
}
|
|
|
|
/// Create a new platform from the current operating system and architecture.
|
|
pub fn current() -> Result<Self, PlatformError> {
|
|
let os = Os::current()?;
|
|
let arch = Arch::current()?;
|
|
Ok(Self { os, arch })
|
|
}
|
|
|
|
/// Return the platform's operating system.
|
|
pub fn os(&self) -> &Os {
|
|
&self.os
|
|
}
|
|
|
|
/// Return the platform's architecture.
|
|
pub fn arch(&self) -> Arch {
|
|
self.arch
|
|
}
|
|
}
|
|
|
|
/// All supported operating systems.
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
pub enum Os {
|
|
Manylinux { major: u16, minor: u16 },
|
|
Musllinux { major: u16, minor: u16 },
|
|
Windows,
|
|
Macos { major: u16, minor: u16 },
|
|
FreeBsd { release: String },
|
|
NetBsd { release: String },
|
|
OpenBsd { release: String },
|
|
Dragonfly { release: String },
|
|
Illumos { release: String, arch: String },
|
|
Haiku { release: String },
|
|
}
|
|
|
|
impl Os {
|
|
pub fn current() -> Result<Self, PlatformError> {
|
|
let target_triple = target_lexicon::HOST;
|
|
|
|
let os = match target_triple.operating_system {
|
|
target_lexicon::OperatingSystem::Linux => detect_linux_libc()?,
|
|
target_lexicon::OperatingSystem::Windows => Os::Windows,
|
|
target_lexicon::OperatingSystem::MacOSX { major, minor, .. } => {
|
|
Os::Macos { major, minor }
|
|
}
|
|
target_lexicon::OperatingSystem::Darwin => {
|
|
let (major, minor) = get_mac_os_version()?;
|
|
Os::Macos { major, minor }
|
|
}
|
|
target_lexicon::OperatingSystem::Netbsd => Os::NetBsd {
|
|
release: Os::platform_info()?.release().to_string_lossy().to_string(),
|
|
},
|
|
target_lexicon::OperatingSystem::Freebsd => Os::FreeBsd {
|
|
release: Os::platform_info()?.release().to_string_lossy().to_string(),
|
|
},
|
|
target_lexicon::OperatingSystem::Openbsd => Os::OpenBsd {
|
|
release: Os::platform_info()?.release().to_string_lossy().to_string(),
|
|
},
|
|
target_lexicon::OperatingSystem::Dragonfly => Os::Dragonfly {
|
|
release: Os::platform_info()?.release().to_string_lossy().to_string(),
|
|
},
|
|
target_lexicon::OperatingSystem::Illumos => {
|
|
let platform_info = Os::platform_info()?;
|
|
Os::Illumos {
|
|
release: platform_info.release().to_string_lossy().to_string(),
|
|
arch: platform_info.machine().to_string_lossy().to_string(),
|
|
}
|
|
}
|
|
target_lexicon::OperatingSystem::Haiku => Os::Haiku {
|
|
release: Os::platform_info()?.release().to_string_lossy().to_string(),
|
|
},
|
|
unsupported => {
|
|
return Err(PlatformError::OsVersionDetectionError(format!(
|
|
"The operating system {unsupported:?} is not supported"
|
|
)));
|
|
}
|
|
};
|
|
Ok(os)
|
|
}
|
|
|
|
fn platform_info() -> Result<PlatformInfo, PlatformError> {
|
|
PlatformInfo::new().map_err(|err| PlatformError::OsVersionDetectionError(err.to_string()))
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Os {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
Os::Manylinux { .. } => write!(f, "Manylinux"),
|
|
Os::Musllinux { .. } => write!(f, "Musllinux"),
|
|
Os::Windows => write!(f, "Windows"),
|
|
Os::Macos { .. } => write!(f, "MacOS"),
|
|
Os::FreeBsd { .. } => write!(f, "FreeBSD"),
|
|
Os::NetBsd { .. } => write!(f, "NetBSD"),
|
|
Os::OpenBsd { .. } => write!(f, "OpenBSD"),
|
|
Os::Dragonfly { .. } => write!(f, "DragonFly"),
|
|
Os::Illumos { .. } => write!(f, "Illumos"),
|
|
Os::Haiku { .. } => write!(f, "Haiku"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// All supported CPU architectures
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
pub enum Arch {
|
|
Aarch64,
|
|
Armv7L,
|
|
Powerpc64Le,
|
|
Powerpc64,
|
|
X86,
|
|
X86_64,
|
|
S390X,
|
|
}
|
|
|
|
impl fmt::Display for Arch {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
Arch::Aarch64 => write!(f, "aarch64"),
|
|
Arch::Armv7L => write!(f, "armv7l"),
|
|
Arch::Powerpc64Le => write!(f, "ppc64le"),
|
|
Arch::Powerpc64 => write!(f, "ppc64"),
|
|
Arch::X86 => write!(f, "i686"),
|
|
Arch::X86_64 => write!(f, "x86_64"),
|
|
Arch::S390X => write!(f, "s390x"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Arch {
|
|
pub fn current() -> Result<Arch, PlatformError> {
|
|
let target_triple = target_lexicon::HOST;
|
|
let arch = match target_triple.architecture {
|
|
target_lexicon::Architecture::X86_64 => Arch::X86_64,
|
|
target_lexicon::Architecture::X86_32(_) => Arch::X86,
|
|
target_lexicon::Architecture::Arm(_) => Arch::Armv7L,
|
|
target_lexicon::Architecture::Aarch64(_) => Arch::Aarch64,
|
|
target_lexicon::Architecture::Powerpc64 => Arch::Powerpc64,
|
|
target_lexicon::Architecture::Powerpc64le => Arch::Powerpc64Le,
|
|
target_lexicon::Architecture::S390x => Arch::S390X,
|
|
unsupported => {
|
|
return Err(PlatformError::OsVersionDetectionError(format!(
|
|
"The architecture {unsupported} is not supported"
|
|
)));
|
|
}
|
|
};
|
|
Ok(arch)
|
|
}
|
|
|
|
/// Returns the oldest possible Manylinux tag for this architecture
|
|
pub fn get_minimum_manylinux_minor(&self) -> u16 {
|
|
match self {
|
|
// manylinux 2014
|
|
Arch::Aarch64 | Arch::Armv7L | Arch::Powerpc64 | Arch::Powerpc64Le | Arch::S390X => 17,
|
|
// manylinux 1
|
|
Arch::X86 | Arch::X86_64 => 5,
|
|
}
|
|
}
|
|
}
|