@@ -996,24 +996,6 @@ fn stderr_isatty() -> bool {
996
996
pub fn run_cargo ( build : & Build , cargo : & mut Command , stamp : & Path , is_check : bool )
997
997
-> Vec < PathBuf >
998
998
{
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
-
1017
999
// `target_root_dir` looks like $dir/$target/release
1018
1000
let target_root_dir = stamp. parent ( ) . unwrap ( ) ;
1019
1001
// `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
1028
1010
// files we need to probe for later.
1029
1011
let mut deps = Vec :: new ( ) ;
1030
1012
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 ,
1040
1017
} ;
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 {
1050
1019
// Skip files like executables
1051
1020
if !filename. ends_with ( ".rlib" ) &&
1052
1021
!filename. ends_with ( ".lib" ) &&
1053
1022
!is_dylib ( & filename) &&
1054
1023
!( is_check && filename. ends_with ( ".rmeta" ) ) {
1055
- continue
1024
+ return ;
1056
1025
}
1057
1026
1058
1027
let filename = Path :: new ( filename) ;
1059
1028
1060
1029
// If this was an output file in the "host dir" we don't actually
1061
1030
// worry about it, it's not relevant for us.
1062
1031
if filename. starts_with ( & host_root_dir) {
1063
- continue ;
1032
+ return ;
1064
1033
}
1065
1034
1066
1035
// If this was output in the `deps` dir then this is a precise file
1067
1036
// name (hash included) so we start tracking it.
1068
1037
if filename. starts_with ( & target_deps_dir) {
1069
1038
deps. push ( filename. to_path_buf ( ) ) ;
1070
- continue ;
1039
+ return ;
1071
1040
}
1072
1041
1073
1042
// 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
1088
1057
1089
1058
toplevel. push ( ( file_stem, extension, expected_len) ) ;
1090
1059
}
1091
- }
1060
+ } ) ;
1092
1061
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" ) ;
1100
1064
}
1101
1065
1102
1066
// 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
1167
1131
t ! ( t!( File :: create( stamp) ) . write_all( & new_contents) ) ;
1168
1132
deps
1169
1133
}
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