Skip to main content

flowey_lib_hvlite/
common.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Vocabulary types for the most-common build profiles, architectures,
5//! platforms, and target triples used in the OpenVMM/OpenHCL tree.
6//!
7//! Outside of a few binaries / libraries that are intimately tied to one
8//! particular architecture / platform, most things in the hvlite tree run on a
9//! common subset of supported target triples + build profiles.
10
11use flowey::node::prelude::*;
12
13/// Vocabulary type for artifacts that only get built using the two most
14/// common cargo build profiles (i.e: `release` vs. `debug`).
15///
16/// More specialized artifacts should use the
17/// [`BuildProfile`](crate::run_cargo_build::BuildProfile) type, which
18/// enumerates _all_ build profiles defined in HvLite's `Cargo.toml` file.
19#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
20pub enum CommonProfile {
21    Release,
22    Debug,
23}
24
25impl CommonProfile {
26    pub fn from_release(release: bool) -> Self {
27        match release {
28            true => Self::Release,
29            false => Self::Debug,
30        }
31    }
32
33    pub fn to_release(self) -> bool {
34        match self {
35            Self::Release => true,
36            Self::Debug => false,
37        }
38    }
39}
40
41impl From<CommonProfile> for crate::run_cargo_build::BuildProfile {
42    fn from(value: CommonProfile) -> Self {
43        match value {
44            CommonProfile::Release => crate::run_cargo_build::BuildProfile::Release,
45            CommonProfile::Debug => crate::run_cargo_build::BuildProfile::Debug,
46        }
47    }
48}
49
50/// Vocabulary type for artifacts that only get built for the most common
51/// actively-supported architectures in the hvlite tree.
52#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
53pub enum CommonArch {
54    X86_64,
55    Aarch64,
56}
57
58impl CommonArch {
59    /// Convert to a [`target_lexicon::Architecture`].
60    pub fn as_arch(&self) -> target_lexicon::Architecture {
61        match self {
62            CommonArch::X86_64 => target_lexicon::Architecture::X86_64,
63            CommonArch::Aarch64 => {
64                target_lexicon::Architecture::Aarch64(target_lexicon::Aarch64Architecture::Aarch64)
65            }
66        }
67    }
68
69    /// Convert from a [`target_lexicon::Triple`], failing if the triple's
70    /// architecture is not one of the common architectures.
71    pub fn from_triple(triple: &target_lexicon::Triple) -> anyhow::Result<Self> {
72        Self::from_architecture(triple.architecture)
73    }
74
75    /// Convert from a [`target_lexicon::Architecture`], failing if it is not
76    /// one of the common architectures.
77    pub fn from_architecture(arch: target_lexicon::Architecture) -> anyhow::Result<Self> {
78        Ok(match arch {
79            target_lexicon::Architecture::Aarch64(target_lexicon::Aarch64Architecture::Aarch64) => {
80                Self::Aarch64
81            }
82            target_lexicon::Architecture::X86_64 => Self::X86_64,
83            _ => anyhow::bail!("unsupported arch {arch}"),
84        })
85    }
86}
87
88impl TryFrom<FlowArch> for CommonArch {
89    type Error = anyhow::Error;
90
91    fn try_from(arch: FlowArch) -> anyhow::Result<Self> {
92        Ok(match arch {
93            FlowArch::X86_64 => Self::X86_64,
94            FlowArch::Aarch64 => Self::Aarch64,
95            arch => anyhow::bail!("unsupported arch {arch}"),
96        })
97    }
98}
99
100/// Vocabulary type for artifacts that only get built for the most common
101/// actively-supported platforms in the hvlite tree.
102#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
103pub enum CommonPlatform {
104    WindowsMsvc,
105    /// Windows via the GNU (mingw-w64) toolchain. Used to cross-compile
106    /// Windows *guest* payloads (e.g. pipette) from a non-WSL Linux host,
107    /// where the MSVC toolchain / Windows SDK is unavailable.
108    WindowsGnu,
109    LinuxGnu,
110    LinuxMusl,
111    MacOs,
112}
113
114impl TryFrom<FlowPlatform> for CommonPlatform {
115    type Error = anyhow::Error;
116
117    fn try_from(platform: FlowPlatform) -> anyhow::Result<Self> {
118        Ok(match platform {
119            FlowPlatform::Windows => Self::WindowsMsvc,
120            FlowPlatform::Linux(_) => Self::LinuxGnu,
121            FlowPlatform::MacOs => Self::MacOs,
122            platform => anyhow::bail!("unsupported platform {platform}"),
123        })
124    }
125}
126
127#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
128pub enum CommonTriple {
129    Common {
130        arch: CommonArch,
131        platform: CommonPlatform,
132    },
133    Custom(target_lexicon::Triple),
134}
135
136impl CommonTriple {
137    pub const X86_64_WINDOWS_MSVC: Self = Self::Common {
138        arch: CommonArch::X86_64,
139        platform: CommonPlatform::WindowsMsvc,
140    };
141    pub const X86_64_WINDOWS_GNU: Self = Self::Common {
142        arch: CommonArch::X86_64,
143        platform: CommonPlatform::WindowsGnu,
144    };
145    pub const X86_64_LINUX_GNU: Self = Self::Common {
146        arch: CommonArch::X86_64,
147        platform: CommonPlatform::LinuxGnu,
148    };
149    pub const X86_64_LINUX_MUSL: Self = Self::Common {
150        arch: CommonArch::X86_64,
151        platform: CommonPlatform::LinuxMusl,
152    };
153    pub const AARCH64_WINDOWS_MSVC: Self = Self::Common {
154        arch: CommonArch::Aarch64,
155        platform: CommonPlatform::WindowsMsvc,
156    };
157    pub const AARCH64_WINDOWS_GNU: Self = Self::Common {
158        arch: CommonArch::Aarch64,
159        platform: CommonPlatform::WindowsGnu,
160    };
161    pub const AARCH64_LINUX_GNU: Self = Self::Common {
162        arch: CommonArch::Aarch64,
163        platform: CommonPlatform::LinuxGnu,
164    };
165    pub const AARCH64_LINUX_MUSL: Self = Self::Common {
166        arch: CommonArch::Aarch64,
167        platform: CommonPlatform::LinuxMusl,
168    };
169}
170
171impl std::fmt::Debug for CommonTriple {
172    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
173        std::fmt::Debug::fmt(&self.as_triple(), f)
174    }
175}
176
177impl std::fmt::Display for CommonTriple {
178    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179        std::fmt::Display::fmt(&self.as_triple(), f)
180    }
181}
182
183impl PartialOrd for CommonTriple {
184    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
185        Some(self.cmp(other))
186    }
187}
188
189impl Ord for CommonTriple {
190    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
191        self.as_triple()
192            .to_string()
193            .cmp(&other.as_triple().to_string())
194    }
195}
196
197impl CommonTriple {
198    pub fn as_triple(&self) -> target_lexicon::Triple {
199        match self {
200            CommonTriple::Common { arch, platform } => match platform {
201                CommonPlatform::WindowsMsvc => target_lexicon::Triple {
202                    architecture: arch.as_arch(),
203                    vendor: target_lexicon::Vendor::Pc,
204                    operating_system: target_lexicon::OperatingSystem::Windows,
205                    environment: target_lexicon::Environment::Msvc,
206                    binary_format: target_lexicon::BinaryFormat::Coff,
207                },
208                CommonPlatform::WindowsGnu => target_lexicon::Triple {
209                    architecture: arch.as_arch(),
210                    vendor: target_lexicon::Vendor::Pc,
211                    operating_system: target_lexicon::OperatingSystem::Windows,
212                    environment: target_lexicon::Environment::Gnu,
213                    binary_format: target_lexicon::BinaryFormat::Coff,
214                },
215                CommonPlatform::LinuxGnu => target_lexicon::Triple {
216                    architecture: arch.as_arch(),
217                    vendor: target_lexicon::Vendor::Unknown,
218                    operating_system: target_lexicon::OperatingSystem::Linux,
219                    environment: target_lexicon::Environment::Gnu,
220                    binary_format: target_lexicon::BinaryFormat::Elf,
221                },
222                CommonPlatform::LinuxMusl => target_lexicon::Triple {
223                    architecture: arch.as_arch(),
224                    vendor: target_lexicon::Vendor::Unknown,
225                    operating_system: target_lexicon::OperatingSystem::Linux,
226                    environment: target_lexicon::Environment::Musl,
227                    binary_format: target_lexicon::BinaryFormat::Elf,
228                },
229                CommonPlatform::MacOs => target_lexicon::Triple {
230                    architecture: arch.as_arch(),
231                    vendor: target_lexicon::Vendor::Apple,
232                    operating_system: target_lexicon::OperatingSystem::Darwin(None),
233                    environment: target_lexicon::Environment::Unknown,
234                    binary_format: target_lexicon::BinaryFormat::Macho,
235                },
236            },
237            CommonTriple::Custom(t) => t.clone(),
238        }
239    }
240
241    /// Get the common architecture of this triple, failing if the triple's
242    /// architecture is not one of the common architectures.
243    pub fn common_arch(&self) -> anyhow::Result<CommonArch> {
244        match self {
245            CommonTriple::Common { arch, .. } => Ok(*arch),
246            CommonTriple::Custom(target) => CommonArch::from_triple(target),
247        }
248    }
249}