use serde_derive::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum Arch {
X86,
X86_64,
Mips,
PowerPC,
PowerPC64,
Arm,
AArch64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum OS {
Windows,
MacOS,
IOS,
Linux,
Android,
FreeBSD,
DragonFly,
Bitrig,
OpenBSD,
NetBSD,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum Family {
Windows,
Unix,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum Env {
Gnu,
Msvc,
Musl,
None,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum PointerWidth {
P64,
P32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum Endian {
Little,
Big,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct Target {
pub arch: Arch,
pub os: OS,
pub family: Family,
pub env: Env,
pub pointer_width: PointerWidth,
pub endian: Endian,
}
impl Target {
pub fn short_text(&self) -> String {
format!(
"{:?}-{:?}-{:?}-{:?}",
self.arch, self.os, self.family, self.env
)
.to_lowercase()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Condition {
Arch(Arch),
OS(OS),
Family(Family),
Env(Env),
PointerWidth(PointerWidth),
Endian(Endian),
And(Vec<Condition>),
Or(Vec<Condition>),
Not(Box<Condition>),
True,
False,
}
#[cfg(target_arch = "x86")]
pub fn current_arch() -> Arch {
Arch::X86
}
#[cfg(target_arch = "x86_64")]
pub fn current_arch() -> Arch {
Arch::X86_64
}
#[cfg(target_arch = "mips")]
pub fn current_arch() -> Arch {
Arch::Mips
}
#[cfg(target_arch = "powerpc")]
pub fn current_arch() -> Arch {
Arch::PowerPC
}
#[cfg(target_arch = "powerpc64")]
pub fn current_arch() -> Arch {
Arch::PowerPC64
}
#[cfg(target_arch = "arm")]
pub fn current_arch() -> Arch {
Arch::Arm
}
#[cfg(target_arch = "aarch64")]
pub fn current_arch() -> Arch {
Arch::AArch64
}
#[cfg(target_os = "windows")]
pub fn current_os() -> OS {
OS::Windows
}
#[cfg(target_os = "macos")]
pub fn current_os() -> OS {
OS::MacOS
}
#[cfg(target_os = "ios")]
pub fn current_os() -> OS {
OS::IOS
}
#[cfg(target_os = "linux")]
pub fn current_os() -> OS {
OS::Linux
}
#[cfg(target_os = "android")]
pub fn current_os() -> OS {
OS::Android
}
#[cfg(target_os = "freebsd")]
pub fn current_os() -> OS {
OS::FreeBSD
}
#[cfg(target_os = "dragonfly")]
pub fn current_os() -> OS {
OS::DragonFly
}
#[cfg(target_os = "bitrig")]
pub fn current_os() -> OS {
OS::Bitrig
}
#[cfg(target_os = "openbsd")]
pub fn current_os() -> OS {
OS::OpenBSD
}
#[cfg(target_os = "netbsd")]
pub fn current_os() -> OS {
OS::NetBSD
}
#[cfg(target_family = "unix")]
pub fn current_family() -> Family {
Family::Unix
}
#[cfg(target_family = "windows")]
pub fn current_family() -> Family {
Family::Windows
}
#[cfg(target_env = "gnu")]
pub fn current_env() -> Env {
Env::Gnu
}
#[cfg(target_env = "msvc")]
pub fn current_env() -> Env {
Env::Msvc
}
#[cfg(target_env = "musl")]
pub fn current_env() -> Env {
Env::Musl
}
#[cfg(target_env = "")]
pub fn current_env() -> Env {
Env::None
}
#[cfg(target_pointer_width = "32")]
pub fn current_pointer_width() -> PointerWidth {
PointerWidth::P32
}
#[cfg(target_pointer_width = "64")]
pub fn current_pointer_width() -> PointerWidth {
PointerWidth::P64
}
#[cfg(target_endian = "little")]
pub fn current_endian() -> Endian {
Endian::Little
}
#[cfg(target_endian = "big")]
pub fn current_endian() -> Endian {
Endian::Big
}
pub fn current_target() -> Target {
Target {
arch: current_arch(),
os: current_os(),
family: current_family(),
env: current_env(),
pointer_width: current_pointer_width(),
endian: current_endian(),
}
}
impl Condition {
pub fn eval(&self, target: &Target) -> bool {
use crate::target::Condition::*;
match self {
Arch(arch) => &target.arch == arch,
OS(os) => &target.os == os,
Family(family) => &target.family == family,
Env(env) => &target.env == env,
PointerWidth(pointer_width) => &target.pointer_width == pointer_width,
Endian(endian) => &target.endian == endian,
And(conditions) => conditions.iter().all(|c| c.eval(target)),
Or(conditions) => conditions.iter().any(|c| c.eval(target)),
Not(condition) => !condition.eval(target),
True => true,
False => false,
}
}
pub fn negate(&self) -> Condition {
Condition::Not(Box::new(self.clone()))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct LibraryTarget {
pub target: Target,
pub cpp_library_version: Option<String>,
}
impl LibraryTarget {
pub fn short_text(&self) -> String {
if let Some(cpp_library_version) = &self.cpp_library_version {
format!("v{} on {}", cpp_library_version, self.target.short_text())
} else {
self.target.short_text()
}
}
}