@@ -6,8 +6,8 @@ use std::path::PathBuf;
6
6
use std:: process:: { exit, Command , ExitStatus , Stdio } ;
7
7
8
8
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 ;
11
11
use espflash:: { Config , Flasher } ;
12
12
use pico_args:: Arguments ;
13
13
use serial:: { BaudRate , SerialPort } ;
@@ -20,21 +20,21 @@ fn main() -> Result<()> {
20
20
return usage ( ) ;
21
21
}
22
22
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" ) ?;
24
27
25
28
let speed = args. speed . map ( |v| BaudRate :: from_speed ( v as usize ) ) ;
26
29
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
+ } ;
35
36
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) ) ?;
38
38
serial. reconfigure ( & |settings| {
39
39
settings. set_baud_rate ( BaudRate :: Baud115200 ) ?;
40
40
Ok ( ( ) )
@@ -45,8 +45,6 @@ fn main() -> Result<()> {
45
45
return board_info ( & flasher) ;
46
46
}
47
47
48
- let path = get_artifact_path ( args. release , & args. example )
49
- . expect ( "Could not find the build artifact path" ) ;
50
48
let elf_data = read ( & path) ?;
51
49
52
50
if args. ram {
@@ -117,27 +115,7 @@ fn parse_args() -> Result<AppArgs> {
117
115
Ok ( app_args)
118
116
}
119
117
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 > {
141
119
let mut args: Vec < String > = vec ! [ ] ;
142
120
143
121
if release {
@@ -161,20 +139,68 @@ fn build(release: bool, example: &Option<String>, features: &Option<String>) ->
161
139
}
162
140
163
141
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
+ ) ;
167
146
} ;
168
147
169
- Command :: new ( "cargo" )
148
+ let output = Command :: new ( "cargo" )
170
149
. arg ( "build" )
171
150
. args ( args)
172
- . stdout ( Stdio :: inherit ( ) )
151
+ . args ( & [ "--message-format" , "json-diagnostic-rendered-ansi" ] )
152
+ . stdout ( Stdio :: piped ( ) )
173
153
. 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
+ }
178
204
}
179
205
180
206
#[ cfg( unix) ]
0 commit comments