use super::{Diagnostic, PackageId, Target}; use camino::Utf8PathBuf; #[cfg(feature = "builder")] use derive_builder::Builder; use serde::{Deserialize, Serialize}; use std::fmt; use std::io::{self, BufRead, Read}; /// Profile settings used to determine which compiler flags to use for a /// target. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "builder", derive(Builder))] #[non_exhaustive] #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] pub struct ArtifactProfile { /// Optimization level. Possible values are 0-3, s or z. pub opt_level: String, /// The amount of debug info. 0 for none, 1 for limited, 2 for full pub debuginfo: Option, /// State of the `cfg(debug_assertions)` directive, enabling macros like /// `debug_assert!` pub debug_assertions: bool, /// State of the overflow checks. pub overflow_checks: bool, /// Whether this profile is a test pub test: bool, } /// A compiler-generated file. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "builder", derive(Builder))] #[non_exhaustive] #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] pub struct Artifact { /// The package this artifact belongs to pub package_id: PackageId, /// Path to the `Cargo.toml` file #[serde(default)] pub manifest_path: Utf8PathBuf, /// The target this artifact was compiled for pub target: Target, /// The profile this artifact was compiled with pub profile: ArtifactProfile, /// The enabled features for this artifact pub features: Vec, /// The full paths to the generated artifacts /// (e.g. binary file and separate debug info) pub filenames: Vec, /// Path to the executable file pub executable: Option, /// If true, then the files were already generated pub fresh: bool, } /// Message left by the compiler // TODO: Better name. This one comes from machine_message.rs #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "builder", derive(Builder))] #[non_exhaustive] #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] pub struct CompilerMessage { /// The package this message belongs to pub package_id: PackageId, /// The target this message is aimed at pub target: Target, /// The message the compiler sent. pub message: Diagnostic, } /// Output of a build script execution. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "builder", derive(Builder))] #[non_exhaustive] #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] pub struct BuildScript { /// The package this build script execution belongs to pub package_id: PackageId, /// The libs to link pub linked_libs: Vec, /// The paths to search when resolving libs pub linked_paths: Vec, /// Various `--cfg` flags to pass to the compiler pub cfgs: Vec, /// The environment variables to add to the compilation pub env: Vec<(String, String)>, /// The `OUT_DIR` environment variable where this script places its output /// /// Added in Rust 1.41. #[serde(default)] pub out_dir: Utf8PathBuf, } /// Final result of a build. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[cfg_attr(feature = "builder", derive(Builder))] #[non_exhaustive] #[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] pub struct BuildFinished { /// Whether or not the build finished successfully. pub success: bool, } /// A cargo message #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[non_exhaustive] #[serde(tag = "reason", rename_all = "kebab-case")] pub enum Message { /// The compiler generated an artifact CompilerArtifact(Artifact), /// The compiler wants to display a message CompilerMessage(CompilerMessage), /// A build script successfully executed. BuildScriptExecuted(BuildScript), /// The build has finished. /// /// This is emitted at the end of the build as the last message. /// Added in Rust 1.44. BuildFinished(BuildFinished), /// A line of text which isn't a cargo or compiler message. /// Line separator is not included #[serde(skip)] TextLine(String), } impl Message { /// Creates an iterator of Message from a Read outputting a stream of JSON /// messages. For usage information, look at the top-level documentation. pub fn parse_stream(input: R) -> MessageIter { MessageIter { input } } } impl fmt::Display for CompilerMessage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.message) } } /// An iterator of Messages. pub struct MessageIter { input: R, } impl Iterator for MessageIter { type Item = io::Result; fn next(&mut self) -> Option { let mut line = String::new(); self.input .read_line(&mut line) .map(|n| { if n == 0 { None } else { if line.ends_with('\n') { line.truncate(line.len() - 1); } let mut deserializer = serde_json::Deserializer::from_str(&line); deserializer.disable_recursion_limit(); Some(Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(line))) } }) .transpose() } } /// An iterator of Message. type MessageIterator = serde_json::StreamDeserializer<'static, serde_json::de::IoRead, Message>; /// Creates an iterator of Message from a Read outputting a stream of JSON /// messages. For usage information, look at the top-level documentation. #[deprecated(note = "Use Message::parse_stream instead")] pub fn parse_messages(input: R) -> MessageIterator { serde_json::Deserializer::from_reader(input).into_iter::() }