Skip to content

Commit 780d6df

Browse files
committed
Parse rmeta directives coming from rustc
This commit updates Cargo to process JSON directives emitted by rustc when we're pipelining compilation. In this mode Cargo will attempt to start subsequent compilations of crates as soon as possible, fully completing the features of pipelined compilations in Cargo!
1 parent 678575a commit 780d6df

File tree

1 file changed

+37
-23
lines changed

1 file changed

+37
-23
lines changed

src/cargo/core/compiler/mod.rs

+37-23
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,16 @@ fn rustc<'a, 'cfg>(
231231
// present it if we can.
232232
let extract_rendered_errors = if rmeta_produced {
233233
match cx.bcx.build_config.message_format {
234-
MessageFormat::Json => false,
234+
MessageFormat::Json => {
235+
rustc.arg("-Zemit-directives");
236+
false
237+
}
235238
MessageFormat::Human => {
236239
rustc
237240
.arg("--error-format=json")
238241
.arg("--json-rendered=termcolor")
239-
.arg("-Zunstable-options");
242+
.arg("-Zunstable-options")
243+
.arg("-Zemit-directives");
240244
true
241245
}
242246

@@ -315,32 +319,20 @@ fn rustc<'a, 'cfg>(
315319
mode,
316320
&mut |line| on_stdout_line(state, line, package_id, &target),
317321
&mut |line| {
318-
on_stderr_line(state, line, package_id, &target, extract_rendered_errors)
322+
on_stderr_line(
323+
state,
324+
line,
325+
package_id,
326+
&target,
327+
extract_rendered_errors,
328+
rmeta_produced,
329+
)
319330
},
320331
)
321332
.map_err(internal_if_simple_exit_code)
322333
.chain_err(|| format!("Could not compile `{}`.", name))?;
323334
}
324335

325-
// FIXME(rust-lang/rust#58465): this is the whole point of "pipelined
326-
// compilation" in Cargo. We want to, here in this unit, call
327-
// `finish_rmeta` as soon as we can which indicates that the metadata
328-
// file is emitted by rustc and ready to go. This will start dependency
329-
// compilations as soon as possible.
330-
//
331-
// The compiler doesn't currently actually implement the ability to let
332-
// us know, however, when the metadata file is ready to go. It actually
333-
// today produces the file very late in compilation, far later than it
334-
// would otherwise be able to do!
335-
//
336-
// In any case this is all covered by the issue above. This is just a
337-
// marker for "yes we unconditionally do this today but tomorrow we
338-
// should actually read what rustc is doing and execute this at an
339-
// appropriate time, ideally long before rustc finishes completely".
340-
if rmeta_produced {
341-
state.rmeta_produced();
342-
}
343-
344336
if do_rename && real_name != crate_name {
345337
let dst = &outputs[0].path;
346338
let src = dst.with_file_name(
@@ -698,7 +690,7 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
698690
rustdoc
699691
.exec_with_streaming(
700692
&mut |line| on_stdout_line(state, line, package_id, &target),
701-
&mut |line| on_stderr_line(state, line, package_id, &target, false),
693+
&mut |line| on_stderr_line(state, line, package_id, &target, false, false),
702694
false,
703695
)
704696
.chain_err(|| format!("Could not document `{}`.", name))?;
@@ -1094,6 +1086,7 @@ fn on_stderr_line(
10941086
package_id: PackageId,
10951087
target: &Target,
10961088
extract_rendered_errors: bool,
1089+
look_for_metadata_directive: bool,
10971090
) -> CargoResult<()> {
10981091
// We primarily want to use this function to process JSON messages from
10991092
// rustc. The compiler should always print one JSON message per line, and
@@ -1124,6 +1117,27 @@ fn on_stderr_line(
11241117
}
11251118
}
11261119

1120+
// In some modes of execution we will execute rustc with `-Z
1121+
// emit-directives` to look for metadata files being produced. When this
1122+
// happens we may be able to start subsequent compilations more quickly than
1123+
// waiting for an entire compile to finish, possibly using more parallelism
1124+
// available to complete a compilation session more quickly.
1125+
//
1126+
// In these cases look for a matching directive and inform Cargo internally
1127+
// that a metadata file has been produced.
1128+
if look_for_metadata_directive {
1129+
#[derive(serde::Deserialize)]
1130+
struct CompilerDirective {
1131+
directive: String,
1132+
}
1133+
if let Ok(directive) = serde_json::from_str::<CompilerDirective>(compiler_message.get()) {
1134+
if directive.directive.starts_with("metadata file written") {
1135+
state.rmeta_produced();
1136+
return Ok(())
1137+
}
1138+
}
1139+
}
1140+
11271141
// And failing all that above we should have a legitimate JSON diagnostic
11281142
// from the compiler, so wrap it in an external Cargo JSON message
11291143
// indicating which package it came from and then emit it.

0 commit comments

Comments
 (0)