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, 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 | /// 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)))] |
61 | pub 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)))] |
75 | pub 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)))] |
98 | pub 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" )] |
107 | pub 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 | |
125 | impl 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 | |
133 | impl 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. |
140 | pub struct MessageIter<R> { |
141 | input: R, |
142 | } |
143 | |
144 | impl<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. |
167 | type 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" )] |
173 | pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> { |
174 | serde_json::Deserializer::from_reader(input).into_iter::<Message>() |
175 | } |
176 | |