1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
pub mod argument_handling;
pub mod logging;
use anyhow::{anyhow, Context, Result};
use cargo_toml::Manifest;
use serde::Deserialize;
use cargo_metadata::Message;
use std::{
path::{Path, PathBuf},
process::{Command, Stdio},
};
pub struct Metadata {
pub chip: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
pub struct Meta {
pub chip: Option<String>,
}
pub fn read_metadata(work_dir: &Path) -> Result<Metadata> {
let cargo_toml = work_dir.join("Cargo.toml");
let cargo_toml_content = std::fs::read(&cargo_toml).context(format!(
"Unable to read configuration file '{}'",
cargo_toml.display(),
))?;
let meta = match Manifest::<Meta>::from_slice_with_metadata(&cargo_toml_content) {
Ok(m) => m.package.map(|p| p.metadata).flatten(),
Err(_e) => None,
};
Ok(Metadata {
chip: meta.and_then(|m| m.chip),
})
}
pub fn build_artifact(work_dir: &Path, args: &[String]) -> Result<PathBuf> {
let work_dir = dunce::canonicalize(work_dir)?;
let cargo_executable = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned());
log::debug!(
"Running '{}' in directory {}",
cargo_executable,
work_dir.display()
);
let cargo_command = Command::new(cargo_executable)
.current_dir(work_dir)
.arg("build")
.args(args)
.args(&["--message-format", "json-diagnostic-rendered-ansi"])
.stdout(Stdio::piped())
.spawn()?;
let output = cargo_command.wait_with_output()?;
let messages = Message::parse_stream(&output.stdout[..]);
let mut target_artifact = None;
for message in messages {
match message? {
Message::CompilerArtifact(artifact) => {
if artifact.executable.is_some() {
if target_artifact.is_some() {
return Err(anyhow!(
"Multiple binary artifacts found. \
Use '--bin' to specify which binary to flash."
));
} else {
target_artifact = Some(artifact);
}
}
}
Message::CompilerMessage(message) => {
if let Some(rendered) = message.message.rendered {
print!("{}", rendered);
}
}
_ => (),
}
}
if !output.status.success() {
return Err(anyhow!(
"Failed to run cargo build: exit code = {:?}",
output.status.code()
));
}
if let Some(artifact) = target_artifact {
Ok(artifact.executable.unwrap())
} else {
Err(anyhow!(
"Unable to find any binary artifacts. \
Use '--example' to specify an example to flash, \
or '--package' to specify which package to flash in a workspace."
))
}
}