1 use super::{Diagnostic, PackageId, Target};
2 use camino::Utf8PathBuf;
3 #[cfg(feature = "builder")]
4 use derive_builder::Builder;
5 use serde::{Deserialize, Serialize};
6 use std::fmt;
7 use 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)))]
15 pub 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)))]
34 pub 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)))]
58 pub 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)))]
72 pub 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)))]
95 pub 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")]
104 pub 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
122 impl 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.
parse_stream<R: BufRead>(input: R) -> MessageIter<R>125 pub fn parse_stream<R: BufRead>(input: R) -> MessageIter<R> {
126 MessageIter {
127 lines: input.lines(),
128 }
129 }
130 }
131
132 impl fmt::Display for CompilerMessage {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 write!(f, "{}", self.message)
135 }
136 }
137
138 /// An iterator of Messages.
139 pub struct MessageIter<R> {
140 lines: Lines<R>,
141 }
142
143 impl<R: BufRead> Iterator for MessageIter<R> {
144 type Item = io::Result<Message>;
next(&mut self) -> Option<Self::Item>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.
157 type 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")]
parse_messages<R: Read>(input: R) -> MessageIterator<R>163 pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> {
164 serde_json::Deserializer::from_reader(input).into_iter::<Message>()
165 }
166