Skip to content

Commit 03d8ea4

Browse files
MabezDevicewind1991
authored andcommitted
Improve project builder
* Remove `cargo_project` it fails to parse complex config.toml * Instead, retrieve the artifact paths from the cargo build invokation * Use `anyhow` to handle errors instead of unwraps
1 parent f9f1d04 commit 03d8ea4

File tree

3 files changed

+76
-51
lines changed

3 files changed

+76
-51
lines changed

cargo-espflash/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ cargo-project = "0.2.4"
1515
espflash = { version = "0.1.3", path = "../espflash" }
1616
pico-args = "0.4.0"
1717
serial = "0.4"
18-
color-eyre = "0.5.10"
1918
serde = { version = "1", features = ["derive"] }
2019
toml = "0.5"
21-
guess_host_triple = "0.1.2"
20+
cargo_metadata = "0.14.0"
21+
guess_host_triple = "0.1.2"
22+
anyhow = "1.0"

cargo-espflash/src/cargo_config.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ pub fn has_build_std<P: AsRef<Path>>(project_path: P) -> bool {
3131
Ok(toml) => toml,
3232
Err(_) => return false,
3333
};
34-
toml.unstable
35-
.build_std
36-
.iter()
37-
.any(|option| option == "core")
34+
35+
!toml.unstable.build_std.is_empty()
3836
}
3937

4038
fn config_path(project_path: &Path) -> Option<PathBuf> {

cargo-espflash/src/main.rs

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use std::path::PathBuf;
66
use std::process::{exit, Command, ExitStatus, Stdio};
77

88
use crate::cargo_config::has_build_std;
9-
use cargo_project::{Artifact, Profile, Project};
10-
use color_eyre::{eyre::WrapErr, Report, Result};
9+
use anyhow::{anyhow, bail, Context, Result};
10+
use cargo_metadata::Message;
1111
use espflash::{Config, Flasher};
1212
use pico_args::Arguments;
1313
use serial::{BaudRate, SerialPort};
@@ -20,21 +20,21 @@ fn main() -> Result<()> {
2020
return usage();
2121
}
2222

23-
let port = args.serial.or(config.connection.serial).unwrap();
23+
let port = args
24+
.serial
25+
.or(config.connection.serial)
26+
.context("serial port missing")?;
2427

2528
let speed = args.speed.map(|v| BaudRate::from_speed(v as usize));
2629

27-
// Since the application exits without flashing the device when '--board-info'
28-
// is passed, we will not waste time building if said flag was set.
29-
if !args.board_info {
30-
let status = build(args.release, &args.example, &args.features);
31-
if !status.success() {
32-
exit_with_process_status(status)
33-
}
34-
}
30+
// Don't build if we are just querying board info
31+
let path = if !args.board_info {
32+
build(args.release, &args.example, &args.features)?
33+
} else {
34+
PathBuf::new()
35+
};
3536

36-
let mut serial =
37-
serial::open(&port).wrap_err_with(|| format!("Failed to open serial port {}", port))?;
37+
let mut serial = serial::open(&port).context(format!("Failed to open serial port {}", port))?;
3838
serial.reconfigure(&|settings| {
3939
settings.set_baud_rate(BaudRate::Baud115200)?;
4040
Ok(())
@@ -45,8 +45,6 @@ fn main() -> Result<()> {
4545
return board_info(&flasher);
4646
}
4747

48-
let path = get_artifact_path(args.release, &args.example)
49-
.expect("Could not find the build artifact path");
5048
let elf_data = read(&path)?;
5149

5250
if args.ram {
@@ -117,27 +115,7 @@ fn parse_args() -> Result<AppArgs> {
117115
Ok(app_args)
118116
}
119117

120-
fn get_artifact_path(release: bool, example: &Option<String>) -> Result<PathBuf> {
121-
let project = Project::query(".").expect("failed to parse project");
122-
123-
let artifact = match example {
124-
Some(example) => Artifact::Example(example.as_str()),
125-
None => Artifact::Bin(project.name()),
126-
};
127-
128-
let profile = if release {
129-
Profile::Release
130-
} else {
131-
Profile::Dev
132-
};
133-
134-
let host = guess_host_triple::guess_host_triple().expect("Failed to guess host triple");
135-
project
136-
.path(artifact, profile, project.target(), host)
137-
.map_err(Report::msg)
138-
}
139-
140-
fn build(release: bool, example: &Option<String>, features: &Option<String>) -> ExitStatus {
118+
fn build(release: bool, example: &Option<String>, features: &Option<String>) -> Result<PathBuf> {
141119
let mut args: Vec<String> = vec![];
142120

143121
if release {
@@ -161,20 +139,68 @@ fn build(release: bool, example: &Option<String>, features: &Option<String>) ->
161139
}
162140

163141
if !has_build_std(".") {
164-
println!("NOTE: --tool cargo currently requires the unstable build-std, ensure .cargo/config{{.toml}} has the appropriate options.");
165-
println!("See: https://doc.rust-lang.org/cargo/reference/unstable.html#build-std");
166-
// TODO early exit here
142+
bail!(
143+
r#"cargo currently requires the unstable build-std, ensure .cargo/config{{.toml}} has the appropriate options.
144+
See: https://doc.rust-lang.org/cargo/reference/unstable.html#build-std"#
145+
);
167146
};
168147

169-
Command::new("cargo")
148+
let output = Command::new("cargo")
170149
.arg("build")
171150
.args(args)
172-
.stdout(Stdio::inherit())
151+
.args(&["--message-format", "json-diagnostic-rendered-ansi"])
152+
.stdout(Stdio::piped())
173153
.stderr(Stdio::inherit())
174-
.spawn()
175-
.unwrap()
176-
.wait()
177-
.unwrap()
154+
.spawn()?
155+
.wait_with_output()?;
156+
157+
// Parse build output.
158+
let messages = Message::parse_stream(&output.stdout[..]);
159+
160+
// Find artifacts.
161+
let mut target_artifact = None;
162+
163+
for message in messages {
164+
match message? {
165+
Message::CompilerArtifact(artifact) => {
166+
if artifact.executable.is_some() {
167+
if target_artifact.is_some() {
168+
// We found multiple binary artifacts,
169+
// so we don't know which one to use.
170+
bail!("Multiple artifacts found, please specify one with --bin");
171+
} else {
172+
target_artifact = Some(artifact);
173+
}
174+
}
175+
}
176+
Message::CompilerMessage(message) => {
177+
if let Some(rendered) = message.message.rendered {
178+
print!("{}", rendered);
179+
}
180+
}
181+
// Ignore other messages.
182+
_ => (),
183+
}
184+
}
185+
186+
// Check if the command succeeded, otherwise return an error.
187+
// Any error messages occuring during the build are shown above,
188+
// when the compiler messages are rendered.
189+
if !output.status.success() {
190+
exit_with_process_status(output.status);
191+
}
192+
193+
if let Some(artifact) = target_artifact {
194+
let artifact_path = PathBuf::from(
195+
artifact
196+
.executable
197+
.ok_or(anyhow!("artifact executable path is missing"))?
198+
.as_path(),
199+
);
200+
Ok(artifact_path)
201+
} else {
202+
bail!("Artifact not found");
203+
}
178204
}
179205

180206
#[cfg(unix)]

0 commit comments

Comments
 (0)