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::*;
12use std::collections::BTreeMap;
13
14pub(crate) const OPENVMM_GITHUB_OWNER: &str = "microsoft";
15pub(crate) const OPENVMM_GITHUB_REPO: &str = "openvmm";
16pub(crate) const OPENVMM_DEPS_GITHUB_REPO: &str = "openvmm-deps";
17
18/// Environment for OpenHCL builds that must use prebuilt native libraries.
19pub(crate) fn openhcl_build_env() -> BTreeMap<String, String> {
20    BTreeMap::from([
21        ("CC_FORCE_DISABLE".into(), "1".into()),
22        (
23            "CMAKE".into(),
24            "cmake-is-forbidden-during-openvmm-hcl-build".into(),
25        ),
26    ])
27}
28
29pub(crate) fn openssl_dev_packages(platform: FlowPlatform) -> anyhow::Result<Vec<String>> {
30    Ok(match platform {
31        FlowPlatform::Linux(distro) => match distro {
32            FlowPlatformLinuxDistro::Ubuntu => vec!["libssl-dev".into()],
33            FlowPlatformLinuxDistro::Fedora | FlowPlatformLinuxDistro::AzureLinux => {
34                vec!["openssl-devel".into(), "perl".into()]
35            }
36            FlowPlatformLinuxDistro::Arch => vec!["openssl".into(), "perl".into()],
37            FlowPlatformLinuxDistro::OpenSuse => {
38                vec!["libopenssl-devel".into(), "perl".into()]
39            }
40            FlowPlatformLinuxDistro::Nix => Vec::new(),
41            FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"),
42        },
43        _ => Vec::new(),
44    })
45}
46
47/// Vocabulary type for artifacts that only get built using the two most
48/// common cargo build profiles (i.e: `release` vs. `debug`).
49///
50/// More specialized artifacts should use the
51/// [`BuildProfile`](crate::run_cargo_build::BuildProfile) type, which
52/// enumerates _all_ build profiles defined in HvLite's `Cargo.toml` file.
53#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
54pub enum CommonProfile {
55    Release,
56    Debug,
57}
58
59impl CommonProfile {
60    pub fn from_release(release: bool) -> Self {
61        match release {
62            true => Self::Release,
63            false => Self::Debug,
64        }
65    }
66
67    pub fn to_release(self) -> bool {
68        match self {
69            Self::Release => true,
70            Self::Debug => false,
71        }
72    }
73}
74
75impl From<CommonProfile> for crate::run_cargo_build::BuildProfile {
76    fn from(value: CommonProfile) -> Self {
77        match value {
78            CommonProfile::Release => crate::run_cargo_build::BuildProfile::Release,
79            CommonProfile::Debug => crate::run_cargo_build::BuildProfile::Debug,
80        }
81    }
82}
83
84impl From<CommonProfile> for flowey_lib_common::run_cargo_build::CargoBuildProfile {
85    fn from(value: CommonProfile) -> Self {
86        match value {
87            CommonProfile::Release => Self::Release,
88            CommonProfile::Debug => Self::Debug,
89        }
90    }
91}
92
93/// Vocabulary type for artifacts that only get built for the most common
94/// actively-supported architectures in the hvlite tree.
95#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
96pub enum CommonArch {
97    X86_64,
98    Aarch64,
99}
100
101impl CommonArch {
102    /// Target the OpenHCL minimal runtime, leaving target translation to
103    /// [`crate::run_cargo_build`].
104    pub fn minimal_rt_triple(self) -> target_lexicon::Triple {
105        target_lexicon::Triple {
106            architecture: self.as_arch(),
107            operating_system: target_lexicon::OperatingSystem::None_,
108            environment: target_lexicon::Environment::Unknown,
109            vendor: target_lexicon::Vendor::Custom(target_lexicon::CustomVendor::Static(
110                "minimal_rt",
111            )),
112            binary_format: target_lexicon::BinaryFormat::Unknown,
113        }
114    }
115
116    /// Convert to a [`target_lexicon::Architecture`].
117    pub fn as_arch(&self) -> target_lexicon::Architecture {
118        match self {
119            CommonArch::X86_64 => target_lexicon::Architecture::X86_64,
120            CommonArch::Aarch64 => {
121                target_lexicon::Architecture::Aarch64(target_lexicon::Aarch64Architecture::Aarch64)
122            }
123        }
124    }
125
126    /// Convert from a [`target_lexicon::Triple`], failing if the triple's
127    /// architecture is not one of the common architectures.
128    pub fn from_triple(triple: &target_lexicon::Triple) -> anyhow::Result<Self> {
129        Self::from_architecture(triple.architecture)
130    }
131
132    /// Convert from a [`target_lexicon::Architecture`], failing if it is not
133    /// one of the common architectures.
134    pub fn from_architecture(arch: target_lexicon::Architecture) -> anyhow::Result<Self> {
135        Ok(match arch {
136            target_lexicon::Architecture::Aarch64(target_lexicon::Aarch64Architecture::Aarch64) => {
137                Self::Aarch64
138            }
139            target_lexicon::Architecture::X86_64 => Self::X86_64,
140            _ => anyhow::bail!("unsupported arch {arch}"),
141        })
142    }
143}
144
145impl TryFrom<FlowArch> for CommonArch {
146    type Error = anyhow::Error;
147
148    fn try_from(arch: FlowArch) -> anyhow::Result<Self> {
149        Ok(match arch {
150            FlowArch::X86_64 => Self::X86_64,
151            FlowArch::Aarch64 => Self::Aarch64,
152            arch => anyhow::bail!("unsupported arch {arch}"),
153        })
154    }
155}
156
157/// Vocabulary type for artifacts that only get built for the most common
158/// actively-supported platforms in the hvlite tree.
159#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
160pub enum CommonPlatform {
161    WindowsMsvc,
162    /// Windows via the GNU (mingw-w64) toolchain. Used to cross-compile
163    /// Windows *guest* payloads (e.g. pipette) from a non-WSL Linux host,
164    /// where the MSVC toolchain / Windows SDK is unavailable.
165    WindowsGnu,
166    LinuxGnu,
167    LinuxMusl,
168    MacOs,
169}
170
171impl TryFrom<FlowPlatform> for CommonPlatform {
172    type Error = anyhow::Error;
173
174    fn try_from(platform: FlowPlatform) -> anyhow::Result<Self> {
175        Ok(match platform {
176            FlowPlatform::Windows => Self::WindowsMsvc,
177            FlowPlatform::Linux(_) => Self::LinuxGnu,
178            FlowPlatform::MacOs => Self::MacOs,
179            platform => anyhow::bail!("unsupported platform {platform}"),
180        })
181    }
182}
183
184#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
185pub enum CommonTriple {
186    Common {
187        arch: CommonArch,
188        platform: CommonPlatform,
189    },
190    Custom(target_lexicon::Triple),
191}
192
193impl CommonTriple {
194    pub const X86_64_WINDOWS_MSVC: Self = Self::Common {
195        arch: CommonArch::X86_64,
196        platform: CommonPlatform::WindowsMsvc,
197    };
198    pub const X86_64_WINDOWS_GNU: Self = Self::Common {
199        arch: CommonArch::X86_64,
200        platform: CommonPlatform::WindowsGnu,
201    };
202    pub const X86_64_LINUX_GNU: Self = Self::Common {
203        arch: CommonArch::X86_64,
204        platform: CommonPlatform::LinuxGnu,
205    };
206    pub const X86_64_LINUX_MUSL: Self = Self::Common {
207        arch: CommonArch::X86_64,
208        platform: CommonPlatform::LinuxMusl,
209    };
210    pub const AARCH64_WINDOWS_MSVC: Self = Self::Common {
211        arch: CommonArch::Aarch64,
212        platform: CommonPlatform::WindowsMsvc,
213    };
214    pub const AARCH64_WINDOWS_GNU: Self = Self::Common {
215        arch: CommonArch::Aarch64,
216        platform: CommonPlatform::WindowsGnu,
217    };
218    pub const AARCH64_LINUX_GNU: Self = Self::Common {
219        arch: CommonArch::Aarch64,
220        platform: CommonPlatform::LinuxGnu,
221    };
222    pub const AARCH64_LINUX_MUSL: Self = Self::Common {
223        arch: CommonArch::Aarch64,
224        platform: CommonPlatform::LinuxMusl,
225    };
226}
227
228impl std::fmt::Debug for CommonTriple {
229    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230        std::fmt::Debug::fmt(&self.as_triple(), f)
231    }
232}
233
234impl std::fmt::Display for CommonTriple {
235    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236        std::fmt::Display::fmt(&self.as_triple(), f)
237    }
238}
239
240impl PartialOrd for CommonTriple {
241    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
242        Some(self.cmp(other))
243    }
244}
245
246impl Ord for CommonTriple {
247    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
248        self.as_triple()
249            .to_string()
250            .cmp(&other.as_triple().to_string())
251    }
252}
253
254impl CommonTriple {
255    pub fn as_triple(&self) -> target_lexicon::Triple {
256        match self {
257            CommonTriple::Common { arch, platform } => match platform {
258                CommonPlatform::WindowsMsvc => target_lexicon::Triple {
259                    architecture: arch.as_arch(),
260                    vendor: target_lexicon::Vendor::Pc,
261                    operating_system: target_lexicon::OperatingSystem::Windows,
262                    environment: target_lexicon::Environment::Msvc,
263                    binary_format: target_lexicon::BinaryFormat::Coff,
264                },
265                CommonPlatform::WindowsGnu => target_lexicon::Triple {
266                    architecture: arch.as_arch(),
267                    vendor: target_lexicon::Vendor::Pc,
268                    operating_system: target_lexicon::OperatingSystem::Windows,
269                    environment: target_lexicon::Environment::Gnu,
270                    binary_format: target_lexicon::BinaryFormat::Coff,
271                },
272                CommonPlatform::LinuxGnu => target_lexicon::Triple {
273                    architecture: arch.as_arch(),
274                    vendor: target_lexicon::Vendor::Unknown,
275                    operating_system: target_lexicon::OperatingSystem::Linux,
276                    environment: target_lexicon::Environment::Gnu,
277                    binary_format: target_lexicon::BinaryFormat::Elf,
278                },
279                CommonPlatform::LinuxMusl => target_lexicon::Triple {
280                    architecture: arch.as_arch(),
281                    vendor: target_lexicon::Vendor::Unknown,
282                    operating_system: target_lexicon::OperatingSystem::Linux,
283                    environment: target_lexicon::Environment::Musl,
284                    binary_format: target_lexicon::BinaryFormat::Elf,
285                },
286                CommonPlatform::MacOs => target_lexicon::Triple {
287                    architecture: arch.as_arch(),
288                    vendor: target_lexicon::Vendor::Apple,
289                    operating_system: target_lexicon::OperatingSystem::Darwin(None),
290                    environment: target_lexicon::Environment::Unknown,
291                    binary_format: target_lexicon::BinaryFormat::Macho,
292                },
293            },
294            CommonTriple::Custom(t) => t.clone(),
295        }
296    }
297
298    /// Get the common architecture of this triple, failing if the triple's
299    /// architecture is not one of the common architectures.
300    pub fn common_arch(&self) -> anyhow::Result<CommonArch> {
301        match self {
302            CommonTriple::Common { arch, .. } => Ok(*arch),
303            CommonTriple::Custom(target) => CommonArch::from_triple(target),
304        }
305    }
306}