cargo_metadata/
messages.rs

1use super::{Diagnostic, PackageId, Target};
2use camino::Utf8PathBuf;
3#[cfg(feature = "builder")]
4use derive_builder::Builder;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::io::{self, BufRead, Lines, Read};
8
9/// Profile settings used to determine which compiler flags to use for a
10/// target.
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "builder", derive(Builder))]
13#[non_exhaustive]
14#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
15pub struct ArtifactProfile {
16    /// Optimization level. Possible values are 0-3, s or z.
17    pub opt_level: String,
18    /// The amount of debug info. 0 for none, 1 for limited, 2 for full
19    pub debuginfo: Option<u32>,
20    /// State of the `cfg(debug_assertions)` directive, enabling macros like
21    /// `debug_assert!`
22    pub debug_assertions: bool,
23    /// State of the overflow checks.
24    pub overflow_checks: bool,
25    /// Whether this profile is a test
26    pub test: bool,
27}
28
29/// A compiler-generated file.
30#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
31#[cfg_attr(feature = "builder", derive(Builder))]
32#[non_exhaustive]
33#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
34pub struct Artifact {
35    /// The package this artifact belongs to
36    pub package_id: PackageId,
37    /// The target this artifact was compiled for
38    pub target: Target,
39    /// The profile this artifact was compiled with
40    pub profile: ArtifactProfile,
41    /// The enabled features for this artifact
42    pub features: Vec<String>,
43    /// The full paths to the generated artifacts
44    /// (e.g. binary file and separate debug info)
45    pub filenames: Vec<Utf8PathBuf>,
46    /// Path to the executable file
47    pub executable: Option<Utf8PathBuf>,
48    /// If true, then the files were already generated
49    pub fresh: bool,
50}
51
52/// Message left by the compiler
53// TODO: Better name. This one comes from machine_message.rs
54#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
55#[cfg_attr(feature = "builder", derive(Builder))]
56#[non_exhaustive]
57#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
58pub struct CompilerMessage {
59    /// The package this message belongs to
60    pub package_id: PackageId,
61    /// The target this message is aimed at
62    pub target: Target,
63    /// The message the compiler sent.
64    pub message: Diagnostic,
65}
66
67/// Output of a build script execution.
68#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
69#[cfg_attr(feature = "builder", derive(Builder))]
70#[non_exhaustive]
71#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
72pub struct BuildScript {
73    /// The package this build script execution belongs to
74    pub package_id: PackageId,
75    /// The libs to link
76    pub linked_libs: Vec<Utf8PathBuf>,
77    /// The paths to search when resolving libs
78    pub linked_paths: Vec<Utf8PathBuf>,
79    /// Various `--cfg` flags to pass to the compiler
80    pub cfgs: Vec<String>,
81    /// The environment variables to add to the compilation
82    pub env: Vec<(String, String)>,
83    /// The `OUT_DIR` environment variable where this script places its output
84    ///
85    /// Added in Rust 1.41.
86    #[serde(default)]
87    pub out_dir: Utf8PathBuf,
88}
89
90/// Final result of a build.
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
92#[cfg_attr(feature = "builder", derive(Builder))]
93#[non_exhaustive]
94#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
95pub struct BuildFinished {
96    /// Whether or not the build finished successfully.
97    pub success: bool,
98}
99
100/// A cargo message
101#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
102#[non_exhaustive]
103#[serde(tag = "reason", rename_all = "kebab-case")]
104pub enum Message {
105    /// The compiler generated an artifact
106    CompilerArtifact(Artifact),
107    /// The compiler wants to display a message
108    CompilerMessage(CompilerMessage),
109    /// A build script successfully executed.
110    BuildScriptExecuted(BuildScript),
111    /// The build has finished.
112    ///
113    /// This is emitted at the end of the build as the last message.
114    /// Added in Rust 1.44.
115    BuildFinished(BuildFinished),
116    /// A line of text which isn't a cargo or compiler message.
117    /// Line separator is not included
118    #[serde(skip)]
119    TextLine(String),
120}
121
122impl Message {
123    /// Creates an iterator of Message from a Read outputting a stream of JSON
124    /// messages. For usage information, look at the top-level documentation.
125    pub fn parse_stream<R: BufRead>(input: R) -> MessageIter<R> {
126        MessageIter {
127            lines: input.lines(),
128        }
129    }
130}
131
132impl fmt::Display for CompilerMessage {
133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134        write!(f, "{}", self.message)
135    }
136}
137
138/// An iterator of Messages.
139pub struct MessageIter<R> {
140    lines: Lines<R>,
141}
142
143impl<R: BufRead> Iterator for MessageIter<R> {
144    type Item = io::Result<Message>;
145    fn next(&mut self) -> Option<Self::Item> {
146        let line = self.lines.next()?;
147        let message = line.map(|it| {
148            let mut deserializer = serde_json::Deserializer::from_str(&it);
149            deserializer.disable_recursion_limit();
150            Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(it))
151        });
152        Some(message)
153    }
154}
155
156/// An iterator of Message.
157type MessageIterator<R> =
158    serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>;
159
160/// Creates an iterator of Message from a Read outputting a stream of JSON
161/// messages. For usage information, look at the top-level documentation.
162#[deprecated(note = "Use Message::parse_stream instead")]
163pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> {
164    serde_json::Deserializer::from_reader(input).into_iter::<Message>()
165}