cargo_hyperlight/
lib.rs

1use anyhow::Result;
2
3mod cargo_cmd;
4mod cli;
5mod command;
6mod sysroot;
7mod toolchain;
8
9use cargo_cmd::CargoCmd;
10use cli::Args;
11pub use command::Command;
12
13/// Constructs a new `Command` for launching cargo targeting
14/// [hyperlight](https://github.com/hyperlight-dev/hyperlight) guest code.
15///
16/// The value of the `CARGO` environment variable is used if it is set; otherwise, the
17/// default `cargo` from the system PATH is used.
18/// If `RUSTUP_TOOLCHAIN` is set in the environment, it is also propagated to the
19/// child process to ensure correct functioning of the rustup wrappers.
20///
21/// The default configuration is:
22/// - No arguments to the program
23/// - Inherits the current process's environment
24/// - Inherits the current process's working directory
25///
26/// # Errors
27///
28/// This function will return an error if:
29/// - If the `CARGO` environment variable is set but it specifies an invalid path
30/// - If the `CARGO` environment variable is not set and the `cargo` program cannot be found in the system PATH
31///
32/// # Examples
33///
34/// Basic usage:
35///
36/// ```rust
37/// use cargo_hyperlight::cargo;
38///
39/// let command = cargo().unwrap();
40/// ```
41pub fn cargo() -> Result<Command> {
42    Command::new()
43}
44
45impl Args {
46    pub fn sysroot_dir(&self) -> std::path::PathBuf {
47        self.target_dir.join("sysroot")
48    }
49
50    pub fn triplet_dir(&self) -> std::path::PathBuf {
51        self.sysroot_dir()
52            .join("lib")
53            .join("rustlib")
54            .join(&self.target)
55    }
56
57    pub fn build_dir(&self) -> std::path::PathBuf {
58        self.sysroot_dir().join("target")
59    }
60
61    pub fn libs_dir(&self) -> std::path::PathBuf {
62        self.triplet_dir().join("lib")
63    }
64
65    pub fn includes_dir(&self) -> std::path::PathBuf {
66        self.triplet_dir().join("include")
67    }
68
69    pub fn crate_dir(&self) -> std::path::PathBuf {
70        self.sysroot_dir().join("crate")
71    }
72
73    pub fn build_plan_dir(&self) -> std::path::PathBuf {
74        self.sysroot_dir().join("build-plan")
75    }
76}
77
78trait CargoCommandExt {
79    fn populate_from_args(&mut self, args: &Args) -> &mut Self;
80}
81
82impl CargoCommandExt for std::process::Command {
83    fn populate_from_args(&mut self, args: &Args) -> &mut Self {
84        self.target(&args.target);
85        self.sysroot(args.sysroot_dir());
86        self.append_rustflags("--cfg=hyperlight");
87        self.append_rustflags("--check-cfg=cfg(hyperlight)");
88        self.entrypoint("entrypoint");
89        if let Some(clang) = &args.clang {
90            self.cc_env(&args.target, clang);
91        } else {
92            // If we couldn't find clang, use the default from the
93            // system path. This will then error if we try to build
94            // using cc-rs, but will succeed otherwise.
95            self.cc_env(&args.target, "clang");
96        }
97        if let Some(ar) = &args.ar {
98            self.ar_env(&args.target, ar);
99        } else {
100            // do nothing, let cc-rs find ar itself
101        }
102        self.append_cflags(&args.target, toolchain::cflags(args));
103
104        self
105    }
106}
107
108impl Args {
109    pub fn prepare_sysroot(&self) -> Result<()> {
110        // Build sysroot
111        sysroot::build(self)?;
112
113        // Build toolchain
114        toolchain::prepare(self)?;
115
116        Ok(())
117    }
118}