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, 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    /// Path to the `Cargo.toml` file
38    #[serde(default)]
39    pub manifest_path: Utf8PathBuf,
40    /// The target this artifact was compiled for
41    pub target: Target,
42    /// The profile this artifact was compiled with
43    pub profile: ArtifactProfile,
44    /// The enabled features for this artifact
45    pub features: Vec<String>,
46    /// The full paths to the generated artifacts
47    /// (e.g. binary file and separate debug info)
48    pub filenames: Vec<Utf8PathBuf>,
49    /// Path to the executable file
50    pub executable: Option<Utf8PathBuf>,
51    /// If true, then the files were already generated
52    pub fresh: bool,
53}
54
55/// Message left by the compiler
56// TODO: Better name. This one comes from machine_message.rs
57#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
58#[cfg_attr(feature = "builder", derive(Builder))]
59#[non_exhaustive]
60#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
61pub struct CompilerMessage {
62    /// The package this message belongs to
63    pub package_id: PackageId,
64    /// The target this message is aimed at
65    pub target: Target,
66    /// The message the compiler sent.
67    pub message: Diagnostic,
68}
69
70/// Output of a build script execution.
71#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
72#[cfg_attr(feature = "builder", derive(Builder))]
73#[non_exhaustive]
74#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
75pub struct BuildScript {
76    /// The package this build script execution belongs to
77    pub package_id: PackageId,
78    /// The libs to link
79    pub linked_libs: Vec<Utf8PathBuf>,
80    /// The paths to search when resolving libs
81    pub linked_paths: Vec<Utf8PathBuf>,
82    /// Various `--cfg` flags to pass to the compiler
83    pub cfgs: Vec<String>,
84    /// The environment variables to add to the compilation
85    pub env: Vec<(String, String)>,
86    /// The `OUT_DIR` environment variable where this script places its output
87    ///
88    /// Added in Rust 1.41.
89    #[serde(default)]
90    pub out_dir: Utf8PathBuf,
91}
92
93/// Final result of a build.
94#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
95#[cfg_attr(feature = "builder", derive(Builder))]
96#[non_exhaustive]
97#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
98pub struct BuildFinished {
99    /// Whether or not the build finished successfully.
100    pub success: bool,
101}
102
103/// A cargo message
104#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
105#[non_exhaustive]
106#[serde(tag = "reason", rename_all = "kebab-case")]
107pub enum Message {
108    /// The compiler generated an artifact
109    CompilerArtifact(Artifact),
110    /// The compiler wants to display a message
111    CompilerMessage(CompilerMessage),
112    /// A build script successfully executed.
113    BuildScriptExecuted(BuildScript),
114    /// The build has finished.
115    ///
116    /// This is emitted at the end of the build as the last message.
117    /// Added in Rust 1.44.
118    BuildFinished(BuildFinished),
119    /// A line of text which isn't a cargo or compiler message.
120    /// Line separator is not included
121    #[serde(skip)]
122    TextLine(String),
123}
124
125impl Message {
126    /// Creates an iterator of Message from a Read outputting a stream of JSON
127    /// messages. For usage information, look at the top-level documentation.
128    pub fn parse_stream<R: Read>(input: R) -> MessageIter<R> {
129        MessageIter { input }
130    }
131}
132
133impl fmt::Display for CompilerMessage {
134    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135        write!(f, "{}", self.message)
136    }
137}
138
139/// An iterator of Messages.
140pub struct MessageIter<R> {
141    input: R,
142}
143
144impl<R: BufRead> Iterator for MessageIter<R> {
145    type Item = io::Result<Message>;
146    fn next(&mut self) -> Option<Self::Item> {
147        let mut line = String::new();
148        self.input
149            .read_line(&mut line)
150            .map(|n| {
151                if n == 0 {
152                    None
153                } else {
154                    if line.ends_with('\n') {
155                        line.truncate(line.len() - 1);
156                    }
157                    let mut deserializer = serde_json::Deserializer::from_str(&line);
158                    deserializer.disable_recursion_limit();
159                    Some(Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(line)))
160                }
161            })
162            .transpose()
163    }
164}
165
166/// An iterator of Message.
167type MessageIterator<R> =
168    serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>;
169
170/// Creates an iterator of Message from a Read outputting a stream of JSON
171/// messages. For usage information, look at the top-level documentation.
172#[deprecated(note = "Use Message::parse_stream instead")]
173pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> {
174    serde_json::Deserializer::from_reader(input).into_iter::<Message>()
175}