Skip to content

Commit

Permalink
Emit more info on --message-format=json
Browse files Browse the repository at this point in the history
This adds more output on Cargo's behalf to the output of
`--message-format=json`. Cargo will now emit a message when a crate is finished
compiling with a list of all files that were just generated along with a message
when a build script finishes executing with linked libraries and linked library
paths.

Closes rust-lang#3212
  • Loading branch information
alexcrichton committed Dec 2, 2016
1 parent 71a6cc9 commit 9f6d798
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 35 deletions.
21 changes: 20 additions & 1 deletion src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ impl Encodable for TargetKind {
}
}

#[derive(RustcEncodable, RustcDecodable, Clone, PartialEq, Eq, Debug, Hash)]
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Profile {
pub opt_level: String,
pub lto: bool,
Expand All @@ -139,6 +139,25 @@ pub struct Profile {
pub panic: Option<String>,
}

#[derive(RustcEncodable)]
struct SerializedProfile<'a> {
opt_level: &'a str,
debuginfo: bool,
debug_assertions: bool,
test: bool,
}

impl Encodable for Profile {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
SerializedProfile {
opt_level: &self.opt_level,
debuginfo: self.debuginfo,
debug_assertions: self.debug_assertions,
test: self.test,
}.encode(s)
}
}

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct Profiles {
pub release: Profile,
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
let mut build_config = scrape_build_config(config, jobs, target)?;
build_config.release = release;
build_config.test = mode == CompileMode::Test || mode == CompileMode::Bench;
build_config.json_errors = message_format == MessageFormat::Json;
build_config.json_messages = message_format == MessageFormat::Json;
if let CompileMode::Doc { deps } = mode {
build_config.doc_all = deps;
}
Expand Down Expand Up @@ -512,7 +512,7 @@ fn scrape_target_config(config: &Config, triple: &str)
let (flags, definition) = value.string(&k)?;
let whence = format!("in `{}` (in {})", key,
definition.display());
let (paths, links) =
let (paths, links) =
BuildOutput::parse_rustc_flags(&flags, &whence)
?;
output.library_paths.extend(paths);
Expand Down
15 changes: 15 additions & 0 deletions src/cargo/ops/cargo_rustc/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::sync::{Mutex, Arc};
use core::PackageId;
use util::{CargoResult, Human, Freshness, Cfg};
use util::{internal, ChainError, profile, paths};
use util::machine_message;

use super::job::Work;
use super::{fingerprint, Kind, Context, Unit};
Expand Down Expand Up @@ -168,6 +169,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
output_file.clone());
let build_scripts = super::load_build_deps(cx, unit);
let kind = unit.kind;
let json_messages = cx.build_config.json_messages;

// Check to see if the build script as already run, and if it has keep
// track of whether it has told us about some explicit dependencies
Expand Down Expand Up @@ -242,6 +244,19 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
// state informing what variables were discovered via our script as
// well.
let parsed_output = BuildOutput::parse(&output.stdout, &pkg_name)?;

if json_messages {
let library_paths = parsed_output.library_paths.iter().map(|l| {
l.display().to_string()
}).collect::<Vec<_>>();
machine_message::emit(machine_message::BuildScript {
package_id: &id,
linked_libs: &parsed_output.library_links,
linked_paths: &library_paths,
cfgs: &parsed_output.cfgs,
});
}

build_state.insert(id, kind, parsed_output);
Ok(())
});
Expand Down
37 changes: 27 additions & 10 deletions src/cargo/ops/cargo_rustc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct BuildConfig {
pub release: bool,
pub test: bool,
pub doc_all: bool,
pub json_errors: bool,
pub json_messages: bool,
}

#[derive(Clone, Default)]
Expand Down Expand Up @@ -246,9 +246,15 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
let cwd = cx.config.cwd().to_path_buf();

rustc.args(&cx.rustflags_args(unit)?);
let json_errors = cx.build_config.json_errors;
let json_messages = cx.build_config.json_messages;
let package_id = unit.pkg.package_id().clone();
let target = unit.target.clone();
let profile = unit.profile.clone();
let features = cx.resolve.features(unit.pkg.package_id())
.into_iter()
.flat_map(|i| i)
.map(|s| s.to_string())
.collect::<Vec<_>>();
return Ok(Work::new(move |state| {
// Only at runtime have we discovered what the extra -L and -l
// arguments are for native libraries, so we process those here. We
Expand All @@ -273,7 +279,7 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
}

state.running(&rustc);
if json_errors {
if json_messages {
rustc.exec_with_streaming(
&mut |line| if !line.is_empty() {
Err(internal(&format!("compiler stdout is not empty: `{}`", line)))
Expand All @@ -285,12 +291,11 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
internal(&format!("compiler produced invalid json: `{}`", line))
})?;

machine_message::FromCompiler::new(
&package_id,
&target,
compiler_message
).emit();

machine_message::emit(machine_message::FromCompiler {
package_id: &package_id,
target: &target,
message: compiler_message,
});
Ok(())
},
).map(|_| ())
Expand Down Expand Up @@ -321,6 +326,18 @@ fn rustc(cx: &mut Context, unit: &Unit) -> CargoResult<Work> {
fingerprint::append_current_dir(&dep_info_loc, &cwd)?;
}

if json_messages {
machine_message::emit(machine_message::Artifact {
package_id: &package_id,
target: &target,
profile: &profile,
features: features,
filenames: filenames.iter().map(|&(ref src, _, _)| {
src.display().to_string()
}).collect(),
});
}

Ok(())
}));

Expand Down Expand Up @@ -527,7 +544,7 @@ fn build_base_args(cx: &mut Context,
cmd.arg("--color").arg(&color_config.to_string());
}

if cx.build_config.json_errors {
if cx.build_config.json_messages {
cmd.arg("--error-format").arg("json");
}

Expand Down
74 changes: 52 additions & 22 deletions src/cargo/util/machine_message.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,60 @@
use rustc_serialize::json;
use core::{PackageId, Target};
use rustc_serialize::Encodable;
use rustc_serialize::json::{self, Json};

use core::{PackageId, Target, Profile};

pub trait Message: Encodable {
fn reason(&self) -> &str;
}

pub fn emit<T: Message>(t: T) {
let json = json::encode(&t).unwrap();
let mut map = match json.parse().unwrap() {
Json::Object(obj) => obj,
_ => panic!("not a json object"),
};
map.insert("reason".to_string(), Json::String(t.reason().to_string()));
println!("{}", Json::Object(map));
}

#[derive(RustcEncodable)]
pub struct FromCompiler<'a> {
reason: &'static str,
package_id: &'a PackageId,
target: &'a Target,
message: json::Json,
}

impl<'a> FromCompiler<'a> {
pub fn new(package_id: &'a PackageId,
target: &'a Target,
message: json::Json)
-> FromCompiler<'a> {
FromCompiler {
reason: "compiler-message",
package_id: package_id,
target: target,
message: message,
}
pub package_id: &'a PackageId,
pub target: &'a Target,
pub message: json::Json,
}

impl<'a> Message for FromCompiler<'a> {
fn reason(&self) -> &str {
"compiler-message"
}
}

pub fn emit(self) {
let json = json::encode(&self).unwrap();
println!("{}", json);
#[derive(RustcEncodable)]
pub struct Artifact<'a> {
pub package_id: &'a PackageId,
pub target: &'a Target,
pub profile: &'a Profile,
pub features: Vec<String>,
pub filenames: Vec<String>,
}

impl<'a> Message for Artifact<'a> {
fn reason(&self) -> &str {
"compiler-artifact"
}
}

#[derive(RustcEncodable)]
pub struct BuildScript<'a> {
pub package_id: &'a PackageId,
pub linked_libs: &'a [String],
pub linked_paths: &'a [String],
pub cfgs: &'a [String],
}

impl<'a> Message for BuildScript<'a> {
fn reason(&self) -> &str {
"build-script-executed"
}
}
28 changes: 28 additions & 0 deletions tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2411,6 +2411,20 @@ fn compiler_json_error_format() {
}
}
{
"reason":"compiler-artifact",
"profile": {
"debug_assertions": true,
"debuginfo": true,
"opt_level": "0",
"test": false
},
"features": [],
"package_id":"bar 0.5.0 ([..])",
"target":{"kind":["lib"],"name":"bar","src_path":"[..]lib.rs"},
"filenames":["[..].rlib"]
}
{
"reason":"compiler-message",
"package_id":"foo 0.5.0 ([..])",
Expand All @@ -2426,6 +2440,20 @@ fn compiler_json_error_format() {
}]
}
}
{
"reason":"compiler-artifact",
"package_id":"foo 0.5.0 ([..])",
"target":{"kind":["bin"],"name":"foo","src_path":"[..]main.rs"},
"profile": {
"debug_assertions": true,
"debuginfo": true,
"opt_level": "0",
"test": false
},
"features": [],
"filenames": ["[..]"]
}
"#));
}

Expand Down

0 comments on commit 9f6d798

Please sign in to comment.