@@ -136,9 +136,7 @@ fn compile<'a, 'cfg: 'a>(
136136 } ;
137137 work. then ( link_targets ( cx, unit, false ) ?)
138138 } else {
139- let work = if cx. bcx . build_config . cache_messages ( )
140- && cx. bcx . show_warnings ( unit. pkg . package_id ( ) )
141- {
139+ let work = if cx. bcx . show_warnings ( unit. pkg . package_id ( ) ) {
142140 replay_output_cache (
143141 unit. pkg . package_id ( ) ,
144142 unit. target ,
@@ -663,79 +661,31 @@ fn add_cap_lints(bcx: &BuildContext<'_, '_>, unit: &Unit<'_>, cmd: &mut ProcessB
663661
664662/// Add error-format flags to the command.
665663///
666- /// This is somewhat odd right now, but the general overview is that if
667- /// `-Zcache-messages` or `pipelined` is enabled then Cargo always uses JSON
668- /// output. This has several benefits, such as being easier to parse, handles
669- /// changing formats (for replaying cached messages), ensures atomic output (so
670- /// messages aren't interleaved), etc.
671- ///
672- /// It is intended in the future that Cargo *always* uses the JSON output (by
673- /// turning on cache-messages by default), and this function can be simplified.
664+ /// Cargo always uses JSON output. This has several benefits, such as being
665+ /// easier to parse, handles changing formats (for replaying cached messages),
666+ /// ensures atomic output (so messages aren't interleaved), allows for
667+ /// intercepting messages like rmeta artifacts, etc. rustc includes a
668+ /// "rendered" field in the JSON message with the message properly formatted,
669+ /// which Cargo will extract and display to the user.
674670fn add_error_format_and_color (
675671 cx : & Context < ' _ , ' _ > ,
676672 cmd : & mut ProcessBuilder ,
677673 pipelined : bool ,
678674) -> CargoResult < ( ) > {
679- // If this unit is producing a required rmeta file then we need to know
680- // when the rmeta file is ready so we can signal to the rest of Cargo that
681- // it can continue dependent compilations. To do this we are currently
682- // required to switch the compiler into JSON message mode, but we still
683- // want to present human readable errors as well. (this rabbit hole just
684- // goes and goes)
685- //
686- // All that means is that if we're not already in JSON mode we need to
687- // switch to JSON mode, ensure that rustc error messages can be rendered
688- // prettily, and then when parsing JSON messages from rustc we need to
689- // internally understand that we should extract the `rendered` field and
690- // present it if we can.
691- if cx. bcx . build_config . cache_messages ( ) || pipelined {
692- cmd. arg ( "--error-format=json" ) ;
693- let mut json = String :: from ( "--json=diagnostic-rendered-ansi" ) ;
694- if pipelined {
695- json. push_str ( ",artifacts" ) ;
696- }
697- match cx. bcx . build_config . message_format {
698- MessageFormat :: Short | MessageFormat :: Json { short : true , .. } => {
699- json. push_str ( ",diagnostic-short" ) ;
700- }
701- _ => { }
702- }
703- cmd. arg ( json) ;
704- } else {
705- let mut color = true ;
706- match cx. bcx . build_config . message_format {
707- MessageFormat :: Human => ( ) ,
708- MessageFormat :: Json {
709- ansi,
710- short,
711- render_diagnostics,
712- } => {
713- cmd. arg ( "--error-format" ) . arg ( "json" ) ;
714- // If ansi is explicitly requested, enable it. If we're
715- // rendering diagnostics ourselves then also enable it because
716- // we'll figure out what to do with the colors later.
717- if ansi || render_diagnostics {
718- cmd. arg ( "--json=diagnostic-rendered-ansi" ) ;
719- }
720- if short {
721- cmd. arg ( "--json=diagnostic-short" ) ;
722- }
723- color = false ;
724- }
725- MessageFormat :: Short => {
726- cmd. arg ( "--error-format" ) . arg ( "short" ) ;
727- }
728- }
729-
730- if color {
731- let color = if cx. bcx . config . shell ( ) . supports_color ( ) {
732- "always"
733- } else {
734- "never"
735- } ;
736- cmd. args ( & [ "--color" , color] ) ;
675+ cmd. arg ( "--error-format=json" ) ;
676+ let mut json = String :: from ( "--json=diagnostic-rendered-ansi" ) ;
677+ if pipelined {
678+ // Pipelining needs to know when rmeta files are finished. Tell rustc
679+ // to emit a message that cargo will intercept.
680+ json. push_str ( ",artifacts" ) ;
681+ }
682+ match cx. bcx . build_config . message_format {
683+ MessageFormat :: Short | MessageFormat :: Json { short : true , .. } => {
684+ json. push_str ( ",diagnostic-short" ) ;
737685 }
686+ _ => { }
738687 }
688+ cmd. arg ( json) ;
739689 Ok ( ( ) )
740690}
741691
@@ -1058,22 +1008,19 @@ struct OutputOptions {
10581008 color : bool ,
10591009 /// Where to write the JSON messages to support playback later if the unit
10601010 /// is fresh. The file is created lazily so that in the normal case, lots
1061- /// of empty files are not created. This is None if caching is disabled.
1011+ /// of empty files are not created. If this is None, the output will not
1012+ /// be cached (such as when replaying cached messages).
10621013 cache_cell : Option < ( PathBuf , LazyCell < File > ) > ,
10631014}
10641015
10651016impl OutputOptions {
10661017 fn new < ' a > ( cx : & Context < ' a , ' _ > , unit : & Unit < ' a > ) -> OutputOptions {
10671018 let look_for_metadata_directive = cx. rmeta_required ( unit) ;
10681019 let color = cx. bcx . config . shell ( ) . supports_color ( ) ;
1069- let cache_cell = if cx. bcx . build_config . cache_messages ( ) {
1070- let path = cx. files ( ) . message_cache_path ( unit) ;
1071- // Remove old cache, ignore ENOENT, which is the common case.
1072- drop ( fs:: remove_file ( & path) ) ;
1073- Some ( ( path, LazyCell :: new ( ) ) )
1074- } else {
1075- None
1076- } ;
1020+ let path = cx. files ( ) . message_cache_path ( unit) ;
1021+ // Remove old cache, ignore ENOENT, which is the common case.
1022+ drop ( fs:: remove_file ( & path) ) ;
1023+ let cache_cell = Some ( ( path, LazyCell :: new ( ) ) ) ;
10771024 OutputOptions {
10781025 format : cx. bcx . build_config . message_format ,
10791026 look_for_metadata_directive,
@@ -1100,23 +1047,35 @@ fn on_stderr_line(
11001047 target : & Target ,
11011048 options : & mut OutputOptions ,
11021049) -> CargoResult < ( ) > {
1103- // Check if caching is enabled.
1104- if let Some ( ( path, cell) ) = & mut options. cache_cell {
1105- // Cache the output, which will be replayed later when Fresh.
1106- let f = cell. try_borrow_mut_with ( || File :: create ( path) ) ?;
1107- debug_assert ! ( !line. contains( '\n' ) ) ;
1108- f. write_all ( line. as_bytes ( ) ) ?;
1109- f. write_all ( & [ b'\n' ] ) ?;
1050+ if on_stderr_line_inner ( state, line, package_id, target, options) ? {
1051+ // Check if caching is enabled.
1052+ if let Some ( ( path, cell) ) = & mut options. cache_cell {
1053+ // Cache the output, which will be replayed later when Fresh.
1054+ let f = cell. try_borrow_mut_with ( || File :: create ( path) ) ?;
1055+ debug_assert ! ( !line. contains( '\n' ) ) ;
1056+ f. write_all ( line. as_bytes ( ) ) ?;
1057+ f. write_all ( & [ b'\n' ] ) ?;
1058+ }
11101059 }
1060+ Ok ( ( ) )
1061+ }
11111062
1063+ /// Returns true if the line should be cached.
1064+ fn on_stderr_line_inner (
1065+ state : & JobState < ' _ > ,
1066+ line : & str ,
1067+ package_id : PackageId ,
1068+ target : & Target ,
1069+ options : & mut OutputOptions ,
1070+ ) -> CargoResult < bool > {
11121071 // We primarily want to use this function to process JSON messages from
11131072 // rustc. The compiler should always print one JSON message per line, and
11141073 // otherwise it may have other output intermingled (think RUST_LOG or
11151074 // something like that), so skip over everything that doesn't look like a
11161075 // JSON message.
11171076 if !line. starts_with ( '{' ) {
11181077 state. stderr ( line. to_string ( ) ) ;
1119- return Ok ( ( ) ) ;
1078+ return Ok ( true ) ;
11201079 }
11211080
11221081 let mut compiler_message: Box < serde_json:: value:: RawValue > = match serde_json:: from_str ( line) {
@@ -1128,7 +1087,7 @@ fn on_stderr_line(
11281087 Err ( e) => {
11291088 debug ! ( "failed to parse json: {:?}" , e) ;
11301089 state. stderr ( line. to_string ( ) ) ;
1131- return Ok ( ( ) ) ;
1090+ return Ok ( true ) ;
11321091 }
11331092 } ;
11341093
@@ -1164,14 +1123,13 @@ fn on_stderr_line(
11641123 . expect ( "strip should never fail" )
11651124 } ;
11661125 state. stderr ( rendered) ;
1167- return Ok ( ( ) ) ;
1126+ return Ok ( true ) ;
11681127 }
11691128 }
11701129
1171- // Remove color information from the rendered string. When pipelining is
1172- // enabled and/or when cached messages are enabled we're always asking
1173- // for ANSI colors from rustc, so unconditionally postprocess here and
1174- // remove ansi color codes.
1130+ // Remove color information from the rendered string if color is not
1131+ // enabled. Cargo always asks for ANSI colors from rustc. This allows
1132+ // cached replay to enable/disable colors without re-invoking rustc.
11751133 MessageFormat :: Json { ansi : false , .. } => {
11761134 #[ derive( serde:: Deserialize , serde:: Serialize ) ]
11771135 struct CompilerMessage {
@@ -1213,7 +1171,7 @@ fn on_stderr_line(
12131171 log:: debug!( "looks like metadata finished early!" ) ;
12141172 state. rmeta_produced ( ) ;
12151173 }
1216- return Ok ( ( ) ) ;
1174+ return Ok ( false ) ;
12171175 }
12181176 }
12191177
@@ -1231,7 +1189,7 @@ fn on_stderr_line(
12311189 // instead. We want the stdout of Cargo to always be machine parseable as
12321190 // stderr has our colorized human-readable messages.
12331191 state. stdout ( msg) ;
1234- Ok ( ( ) )
1192+ Ok ( true )
12351193}
12361194
12371195fn replay_output_cache (
@@ -1244,7 +1202,7 @@ fn replay_output_cache(
12441202 let target = target. clone ( ) ;
12451203 let mut options = OutputOptions {
12461204 format,
1247- look_for_metadata_directive : false ,
1205+ look_for_metadata_directive : true ,
12481206 color,
12491207 cache_cell : None ,
12501208 } ;
0 commit comments