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 = String::new();
148 self.input
149 .read_line(&mut line)
150 .map(|n: usize| {
151 if n == 0 {
152 None
153 } else {
154 if line.ends_with('\n') {
155 line.truncate(new_len:line.len() - 1);
156 }
157 let mut deserializer: 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}
176