2023-10-05 20:59:58 -04:00
|
|
|
//! Abstractions for understanding the current platform (operating system and architecture).
|
|
|
|
|
|
2023-10-16 09:37:58 -04:00
|
|
|
use std::{fmt, io};
|
2023-10-05 20:59:58 -04:00
|
|
|
|
|
|
|
|
use platform_info::{PlatformInfo, PlatformInfoAPI, UNameAPI};
|
|
|
|
|
use thiserror::Error;
|
2023-10-30 18:10:17 +01:00
|
|
|
|
|
|
|
|
use crate::linux::detect_linux_libc;
|
|
|
|
|
use crate::mac_os::get_mac_os_version;
|
|
|
|
|
|
|
|
|
|
mod linux;
|
|
|
|
|
mod mac_os;
|
2023-10-05 20:59:58 -04:00
|
|
|
|
|
|
|
|
#[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 {
|
2023-10-10 23:30:53 -04:00
|
|
|
/// 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.
|
2023-10-05 20:59:58 -04:00
|
|
|
pub fn current() -> Result<Self, PlatformError> {
|
|
|
|
|
let os = Os::current()?;
|
|
|
|
|
let arch = Arch::current()?;
|
|
|
|
|
Ok(Self { os, arch })
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-10 23:30:53 -04:00
|
|
|
/// Return the platform's operating system.
|
2023-10-06 21:43:55 -04:00
|
|
|
pub fn os(&self) -> &Os {
|
|
|
|
|
&self.os
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-10 23:30:53 -04:00
|
|
|
/// Return the platform's architecture.
|
2023-10-06 21:43:55 -04:00
|
|
|
pub fn arch(&self) -> Arch {
|
|
|
|
|
self.arch
|
2023-10-05 20:59:58 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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 {
|
2023-10-30 18:10:17 +01:00
|
|
|
target_lexicon::OperatingSystem::Linux => detect_linux_libc()?,
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::OperatingSystem::Windows => Self::Windows,
|
2023-10-05 20:59:58 -04:00
|
|
|
target_lexicon::OperatingSystem::MacOSX { major, minor, .. } => {
|
2024-02-25 19:04:05 +00:00
|
|
|
Self::Macos { major, minor }
|
2023-10-05 20:59:58 -04:00
|
|
|
}
|
|
|
|
|
target_lexicon::OperatingSystem::Darwin => {
|
|
|
|
|
let (major, minor) = get_mac_os_version()?;
|
2024-02-25 19:04:05 +00:00
|
|
|
Self::Macos { major, minor }
|
2023-10-05 20:59:58 -04:00
|
|
|
}
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::OperatingSystem::Netbsd => Self::NetBsd {
|
|
|
|
|
release: Self::platform_info()?
|
|
|
|
|
.release()
|
|
|
|
|
.to_string_lossy()
|
|
|
|
|
.to_string(),
|
2023-10-05 20:59:58 -04:00
|
|
|
},
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::OperatingSystem::Freebsd => Self::FreeBsd {
|
|
|
|
|
release: Self::platform_info()?
|
|
|
|
|
.release()
|
|
|
|
|
.to_string_lossy()
|
|
|
|
|
.to_string(),
|
2023-10-05 20:59:58 -04:00
|
|
|
},
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::OperatingSystem::Openbsd => Self::OpenBsd {
|
|
|
|
|
release: Self::platform_info()?
|
|
|
|
|
.release()
|
|
|
|
|
.to_string_lossy()
|
|
|
|
|
.to_string(),
|
2023-10-05 20:59:58 -04:00
|
|
|
},
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::OperatingSystem::Dragonfly => Self::Dragonfly {
|
|
|
|
|
release: Self::platform_info()?
|
|
|
|
|
.release()
|
|
|
|
|
.to_string_lossy()
|
|
|
|
|
.to_string(),
|
2023-10-05 20:59:58 -04:00
|
|
|
},
|
|
|
|
|
target_lexicon::OperatingSystem::Illumos => {
|
2024-02-25 19:04:05 +00:00
|
|
|
let platform_info = Self::platform_info()?;
|
|
|
|
|
Self::Illumos {
|
2023-10-05 20:59:58 -04:00
|
|
|
release: platform_info.release().to_string_lossy().to_string(),
|
|
|
|
|
arch: platform_info.machine().to_string_lossy().to_string(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::OperatingSystem::Haiku => Self::Haiku {
|
|
|
|
|
release: Self::platform_info()?
|
|
|
|
|
.release()
|
|
|
|
|
.to_string_lossy()
|
|
|
|
|
.to_string(),
|
2023-10-05 20:59:58 -04:00
|
|
|
},
|
|
|
|
|
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 {
|
2024-02-25 19:04:05 +00:00
|
|
|
Self::Manylinux { .. } => write!(f, "Manylinux"),
|
|
|
|
|
Self::Musllinux { .. } => write!(f, "Musllinux"),
|
|
|
|
|
Self::Windows => write!(f, "Windows"),
|
|
|
|
|
Self::Macos { .. } => write!(f, "MacOS"),
|
|
|
|
|
Self::FreeBsd { .. } => write!(f, "FreeBSD"),
|
|
|
|
|
Self::NetBsd { .. } => write!(f, "NetBSD"),
|
|
|
|
|
Self::OpenBsd { .. } => write!(f, "OpenBSD"),
|
|
|
|
|
Self::Dragonfly { .. } => write!(f, "DragonFly"),
|
|
|
|
|
Self::Illumos { .. } => write!(f, "Illumos"),
|
|
|
|
|
Self::Haiku { .. } => write!(f, "Haiku"),
|
2023-10-05 20:59:58 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 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 {
|
2024-02-25 19:04:05 +00:00
|
|
|
Self::Aarch64 => write!(f, "aarch64"),
|
|
|
|
|
Self::Armv7L => write!(f, "armv7l"),
|
|
|
|
|
Self::Powerpc64Le => write!(f, "ppc64le"),
|
|
|
|
|
Self::Powerpc64 => write!(f, "ppc64"),
|
|
|
|
|
Self::X86 => write!(f, "i686"),
|
|
|
|
|
Self::X86_64 => write!(f, "x86_64"),
|
|
|
|
|
Self::S390X => write!(f, "s390x"),
|
2023-10-05 20:59:58 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Arch {
|
2024-02-25 19:04:05 +00:00
|
|
|
pub fn current() -> Result<Self, PlatformError> {
|
2023-10-05 20:59:58 -04:00
|
|
|
let target_triple = target_lexicon::HOST;
|
|
|
|
|
let arch = match target_triple.architecture {
|
2024-02-25 19:04:05 +00:00
|
|
|
target_lexicon::Architecture::X86_64 => Self::X86_64,
|
|
|
|
|
target_lexicon::Architecture::X86_32(_) => Self::X86,
|
|
|
|
|
target_lexicon::Architecture::Arm(_) => Self::Armv7L,
|
|
|
|
|
target_lexicon::Architecture::Aarch64(_) => Self::Aarch64,
|
|
|
|
|
target_lexicon::Architecture::Powerpc64 => Self::Powerpc64,
|
|
|
|
|
target_lexicon::Architecture::Powerpc64le => Self::Powerpc64Le,
|
|
|
|
|
target_lexicon::Architecture::S390x => Self::S390X,
|
2023-10-05 20:59:58 -04:00
|
|
|
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
|
2024-02-25 19:04:05 +00:00
|
|
|
Self::Aarch64 | Self::Armv7L | Self::Powerpc64 | Self::Powerpc64Le | Self::S390X => 17,
|
2023-10-05 20:59:58 -04:00
|
|
|
// manylinux 1
|
2024-02-25 19:04:05 +00:00
|
|
|
Self::X86 | Self::X86_64 => 5,
|
2023-10-05 20:59:58 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|