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.entrypoint("entrypoint");
87        if let Some(clang) = &args.clang {
88            self.cc_env(&args.target, clang);
89        } else {
90            // If we couldn't find clang, use the default from the
91            // system path. This will then error if we try to build
92            // using cc-rs, but will succeed otherwise.
93            self.cc_env(&args.target, "clang");
94        }
95        if let Some(ar) = &args.ar {
96            self.ar_env(&args.target, ar);
97        } else {
98            // do nothing, let cc-rs find ar itself
99        }
100        self.append_cflags(&args.target, toolchain::cflags(args));
101
102        self
103    }
104}
105
106impl Args {
107    pub fn prepare_sysroot(&self) -> Result<()> {
108        // Build sysroot
109        sysroot::build(self)?;
110
111        // Build toolchain
112        toolchain::prepare(self)?;
113
114        Ok(())
115    }
116}