@@ -996,24 +996,6 @@ fn stderr_isatty() -> bool {
996996pub fn run_cargo ( build : & Build , cargo : & mut Command , stamp : & Path , is_check : bool )
997997 -> Vec < PathBuf >
998998{
999- // Instruct Cargo to give us json messages on stdout, critically leaving
1000- // stderr as piped so we can get those pretty colors.
1001- cargo. arg ( "--message-format" ) . arg ( "json" )
1002- . stdout ( Stdio :: piped ( ) ) ;
1003-
1004- if stderr_isatty ( ) && build. ci_env == CiEnv :: None {
1005- // since we pass message-format=json to cargo, we need to tell the rustc
1006- // wrapper to give us colored output if necessary. This is because we
1007- // only want Cargo's JSON output, not rustcs.
1008- cargo. env ( "RUSTC_COLOR" , "1" ) ;
1009- }
1010-
1011- build. verbose ( & format ! ( "running: {:?}" , cargo) ) ;
1012- let mut child = match cargo. spawn ( ) {
1013- Ok ( child) => child,
1014- Err ( e) => panic ! ( "failed to execute command: {:?}\n error: {}" , cargo, e) ,
1015- } ;
1016-
1017999 // `target_root_dir` looks like $dir/$target/release
10181000 let target_root_dir = stamp. parent ( ) . unwrap ( ) ;
10191001 // `target_deps_dir` looks like $dir/$target/release/deps
@@ -1028,46 +1010,33 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo
10281010 // files we need to probe for later.
10291011 let mut deps = Vec :: new ( ) ;
10301012 let mut toplevel = Vec :: new ( ) ;
1031- let stdout = BufReader :: new ( child. stdout . take ( ) . unwrap ( ) ) ;
1032- for line in stdout. lines ( ) {
1033- let line = t ! ( line) ;
1034- let json: serde_json:: Value = if line. starts_with ( "{" ) {
1035- t ! ( serde_json:: from_str( & line) )
1036- } else {
1037- // If this was informational, just print it out and continue
1038- println ! ( "{}" , line) ;
1039- continue
1013+ let ok = stream_cargo ( build, cargo, & mut |msg| {
1014+ let filenames = match msg {
1015+ CargoMessage :: CompilerArtifact { filenames, .. } => filenames,
1016+ _ => return ,
10401017 } ;
1041- if json[ "reason" ] . as_str ( ) != Some ( "compiler-artifact" ) {
1042- if build. config . rustc_error_format . as_ref ( ) . map_or ( false , |e| e == "json" ) {
1043- // most likely not a cargo message, so let's send it out as well
1044- println ! ( "{}" , line) ;
1045- }
1046- continue
1047- }
1048- for filename in json[ "filenames" ] . as_array ( ) . unwrap ( ) {
1049- let filename = filename. as_str ( ) . unwrap ( ) ;
1018+ for filename in filenames {
10501019 // Skip files like executables
10511020 if !filename. ends_with ( ".rlib" ) &&
10521021 !filename. ends_with ( ".lib" ) &&
10531022 !is_dylib ( & filename) &&
10541023 !( is_check && filename. ends_with ( ".rmeta" ) ) {
1055- continue
1024+ return ;
10561025 }
10571026
10581027 let filename = Path :: new ( filename) ;
10591028
10601029 // If this was an output file in the "host dir" we don't actually
10611030 // worry about it, it's not relevant for us.
10621031 if filename. starts_with ( & host_root_dir) {
1063- continue ;
1032+ return ;
10641033 }
10651034
10661035 // If this was output in the `deps` dir then this is a precise file
10671036 // name (hash included) so we start tracking it.
10681037 if filename. starts_with ( & target_deps_dir) {
10691038 deps. push ( filename. to_path_buf ( ) ) ;
1070- continue ;
1039+ return ;
10711040 }
10721041
10731042 // Otherwise this was a "top level artifact" which right now doesn't
@@ -1088,15 +1057,10 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo
10881057
10891058 toplevel. push ( ( file_stem, extension, expected_len) ) ;
10901059 }
1091- }
1060+ } ) ;
10921061
1093- // Make sure Cargo actually succeeded after we read all of its stdout.
1094- let status = t ! ( child. wait( ) ) ;
1095- if !status. success ( ) {
1096- panic ! ( "command did not execute successfully: {:?}\n \
1097- expected success, got: {}",
1098- cargo,
1099- status) ;
1062+ if !ok {
1063+ panic ! ( "cargo must succeed" ) ;
11001064 }
11011065
11021066 // Ok now we need to actually find all the files listed in `toplevel`. We've
@@ -1167,3 +1131,63 @@ pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: boo
11671131 t ! ( t!( File :: create( stamp) ) . write_all( & new_contents) ) ;
11681132 deps
11691133}
1134+
1135+ pub fn stream_cargo (
1136+ build : & Build ,
1137+ cargo : & mut Command ,
1138+ cb : & mut FnMut ( CargoMessage ) ,
1139+ ) -> bool {
1140+ // Instruct Cargo to give us json messages on stdout, critically leaving
1141+ // stderr as piped so we can get those pretty colors.
1142+ cargo. arg ( "--message-format" ) . arg ( "json" )
1143+ . stdout ( Stdio :: piped ( ) ) ;
1144+
1145+ if stderr_isatty ( ) && build. ci_env == CiEnv :: None {
1146+ // since we pass message-format=json to cargo, we need to tell the rustc
1147+ // wrapper to give us colored output if necessary. This is because we
1148+ // only want Cargo's JSON output, not rustcs.
1149+ cargo. env ( "RUSTC_COLOR" , "1" ) ;
1150+ }
1151+
1152+ build. verbose ( & format ! ( "running: {:?}" , cargo) ) ;
1153+ let mut child = match cargo. spawn ( ) {
1154+ Ok ( child) => child,
1155+ Err ( e) => panic ! ( "failed to execute command: {:?}\n error: {}" , cargo, e) ,
1156+ } ;
1157+
1158+ // Spawn Cargo slurping up its JSON output. We'll start building up the
1159+ // `deps` array of all files it generated along with a `toplevel` array of
1160+ // files we need to probe for later.
1161+ let stdout = BufReader :: new ( child. stdout . take ( ) . unwrap ( ) ) ;
1162+ for line in stdout. lines ( ) {
1163+ let line = t ! ( line) ;
1164+ match serde_json:: from_str :: < CargoMessage > ( & line) {
1165+ Ok ( msg) => cb ( msg) ,
1166+ // If this was informational, just print it out and continue
1167+ Err ( _) => println ! ( "{}" , line)
1168+ }
1169+ }
1170+
1171+ // Make sure Cargo actually succeeded after we read all of its stdout.
1172+ let status = t ! ( child. wait( ) ) ;
1173+ if !status. success ( ) {
1174+ println ! ( "command did not execute successfully: {:?}\n \
1175+ expected success, got: {}",
1176+ cargo,
1177+ status) ;
1178+ }
1179+ status. success ( )
1180+ }
1181+
1182+ #[ derive( Deserialize ) ]
1183+ #[ serde( tag = "reason" , rename_all = "kebab-case" ) ]
1184+ pub enum CargoMessage < ' a > {
1185+ CompilerArtifact {
1186+ package_id : & ' a str ,
1187+ features : Vec < & ' a str > ,
1188+ filenames : Vec < & ' a str > ,
1189+ } ,
1190+ BuildScriptExecuted {
1191+ package_id : & ' a str ,
1192+ }
1193+ }
0 commit comments