polyhorn_cli/core/
cargo_rustc.rs1use cargo_metadata::{Message, MetadataCommand};
2use std::io::{BufReader, Result};
3use std::path::{Path, PathBuf};
4use std::process::{Command, Stdio};
5
6#[derive(Default)]
8pub struct CargoRustc {
9 manifest_path: PathBuf,
10 cfg: Option<String>,
11 crate_type: Option<String>,
12 target: Option<String>,
13 profile: Option<String>,
14 flags: Vec<String>,
15 release: bool,
16}
17
18impl CargoRustc {
19 pub fn new(manifest_path: &Path) -> CargoRustc {
22 CargoRustc {
23 manifest_path: manifest_path.to_owned(),
24 ..Default::default()
25 }
26 }
27
28 pub fn cfg(mut self, cfg: &str) -> CargoRustc {
30 self.cfg = Some(cfg.to_owned());
31 self
32 }
33
34 pub fn profile(mut self, profile: &str) -> CargoRustc {
36 self.profile = Some(profile.to_owned());
37 self
38 }
39
40 pub fn crate_type(mut self, crate_type: &str) -> CargoRustc {
43 self.crate_type = Some(crate_type.to_owned());
44 self
45 }
46
47 pub fn release(mut self, release: bool) -> CargoRustc {
49 self.release = release;
50 self
51 }
52
53 pub fn target(mut self, target: &str) -> CargoRustc {
55 self.target = Some(target.to_owned());
56 self
57 }
58
59 pub fn flags(mut self, flags: &[&str]) -> CargoRustc {
61 self.flags = flags.into_iter().map(|flag| flag.to_string()).collect();
62 self
63 }
64
65 pub fn build(self) -> Result<PathBuf> {
68 let metadata = MetadataCommand::new()
69 .manifest_path(&self.manifest_path)
70 .exec()
71 .unwrap();
72 let root_id = metadata.resolve.unwrap().root.unwrap();
73 let package = metadata
74 .packages
75 .iter()
76 .find(|package| package.id == root_id)
77 .unwrap();
78
79 let mut command = Command::new("cargo");
80 command.arg("rustc");
81 command.arg("--manifest-path");
82 command.arg(&self.manifest_path);
83
84 if let Some(target) = self.target.as_ref() {
85 command.arg("--target");
86 command.arg(target);
87 }
88
89 if let Some(profile) = self.profile.as_ref() {
90 command.arg("--profile");
91 command.arg(profile);
92 }
93
94 if self.release {
95 command.arg("--release");
96 }
97
98 command.arg("--message-format=json-render-diagnostics");
99
100 command.arg("--");
101
102 if let Some(cfg) = self.cfg.as_ref() {
103 command.arg("--cfg");
104 command.arg(cfg);
105 }
106
107 if let Some(crate_type) = self.crate_type.as_ref() {
108 command.arg("--crate-type");
109 command.arg(crate_type);
110 }
111
112 command.args(&self.flags);
113
114 command.stdout(Stdio::piped());
115 command.stderr(Stdio::inherit());
116
117 let mut process = command.spawn().unwrap();
118
119 let reader = BufReader::new(process.stdout.take().unwrap());
120
121 let mut path = None;
122
123 for message in Message::parse_stream(reader) {
124 match message.unwrap() {
125 Message::CompilerArtifact(artifact) => {
126 if artifact.package_id == package.id {
127 path = artifact.filenames.first().cloned();
128 }
129 }
130 _ => {}
131 }
132 }
133
134 match process.wait()? {
135 status if status.success() => {}
136 status => {
137 std::process::exit(status.code().unwrap());
138 }
139 }
140
141 Ok(path.unwrap())
142 }
143}