Skip to main content

cargo_hyperlight/
toolchain_flags.rs

1// this file is used both from the cargo-hyperlight library (via
2// `mod`) and from the wrapper and config scripts that are built for
3// $HOST in a package specified in wrapper/_Cargo.toml. So, it can
4// only use imports available in both those environments.
5
6use std::borrow::Cow;
7use std::ffi::{OsStr, OsString};
8use std::path::PathBuf;
9
10pub(crate) struct Args {
11    pub(crate) includes_dir: PathBuf,
12    pub(crate) c_libs_dir: PathBuf,
13    #[allow(unused)] // used in the wrapper, but not the host
14    pub(crate) wrapper_dir: PathBuf,
15    pub(crate) target: String,
16    pub(crate) with_guest_capi: bool,
17}
18impl Args {
19    fn clang_target(&self) -> &'static OsStr {
20        if self.target.starts_with("aarch64") {
21            "--target=aarch64-unknown-linux-none".as_ref()
22        } else {
23            "--target=x86_64-unknown-linux-none".as_ref()
24        }
25    }
26}
27
28fn os(x: &(impl AsRef<OsStr> + ?Sized)) -> Cow<'_, OsStr> {
29    x.as_ref().into()
30}
31
32pub struct Flags(pub(crate) Vec<Cow<'static, OsStr>>);
33impl Flags {
34    /// This will behave badly with spaces/special characters/etc,
35    /// which is why it is called `joined` and not
36    /// `joined_escaped`. That's OK for all the flags we use for now.
37    pub fn joined(&self) -> OsString {
38        let mut all = OsString::new();
39        all.push(&self.0[0]);
40        for flag in &self.0[1..] {
41            all.push(os(" "));
42            all.push(flag);
43        }
44        all
45    }
46}
47
48pub(crate) fn cflags(args: &Args, bootstrap: bool) -> Flags {
49    const COMMON_FLAGS: &[&str] = &[
50        "-U__linux__",
51        "-fPIC",
52        // We don't support stack protectors at the moment, but Arch Linux clang
53        // auto-enables them for -linux platforms, so explicitly disable them.
54        "-fno-stack-protector",
55        "-fstack-clash-protection",
56        "-mstack-probe-size=4096",
57        "-nostdlibinc",
58        // Define HYPERLIGHT as we use this to conditionally enable/disable code
59        // in the libc headers
60        "-DHYPERLIGHT=1",
61        "-D__HYPERLIGHT__=1",
62    ];
63
64    const X86_64_FLAGS: &[&str] = &["-mno-red-zone"];
65
66    const AARCH64_FLAGS: &[&str] = &["-mstrict-align", "-march=armv8.1-a+fp+simd"];
67
68    let mut flags: Vec<Cow<'_, OsStr>> = Vec::new();
69    flags.push(args.clang_target().into());
70    COMMON_FLAGS
71        .iter()
72        .chain(if args.target.starts_with("x86_64") {
73            X86_64_FLAGS.iter()
74        } else if args.target.starts_with("aarch64") {
75            AARCH64_FLAGS.iter()
76        } else {
77            [].iter()
78        })
79        .for_each(|x| flags.push(os(x)));
80
81    if !bootstrap {
82        flags.push(os("-isystem"));
83        flags.push(Cow::Owned(args.includes_dir.clone().into()));
84    }
85    Flags(flags)
86}
87
88pub(crate) fn ldflags(args: &Args) -> Flags {
89    const COMMON_FLAGS: &[&str] = &[
90        "-e",
91        "entrypoint",
92        "-nostdlib",
93        "-pie",
94        "-Wl,--no-dynamic-linker",
95    ];
96
97    let mut flags = Vec::new();
98    flags.push(args.clang_target().into());
99    COMMON_FLAGS.iter().for_each(|x| flags.push(os(x)));
100
101    flags.push(os("-L"));
102    flags.push(Cow::Owned(args.c_libs_dir.clone().into()));
103
104    Flags(flags)
105}
106
107pub(crate) fn libs(args: &Args) -> Flags {
108    let mut flags = Vec::new();
109    if args.with_guest_capi {
110        flags.push(os("-l"));
111        flags.push(os("hyperlight_guest_capi"));
112    }
113    Flags(flags)
114}