1 //! Serialization formats for cargo messages.
2
3 use std::borrow;
4 use std::path;
5
6 pub mod diagnostic;
7
8 #[cfg(feature = "test_unstable")]
9 pub mod test;
10
11 type CowPath<'a> = borrow::Cow<'a, path::Path>;
12 type CowStr<'a> = borrow::Cow<'a, str>;
13
14 /// A cargo message
15 #[derive(Debug, Clone, Serialize, Deserialize)]
16 #[serde(tag = "reason", rename_all = "kebab-case")]
17 pub enum Message<'a> {
18 /// Build completed, all further output should not be parsed
19 BuildFinished(BuildFinished),
20 /// The compiler generated an artifact
21 #[serde(borrow)]
22 CompilerArtifact(Artifact<'a>),
23 /// The compiler wants to display a message
24 #[serde(borrow)]
25 CompilerMessage(FromCompiler<'a>),
26 /// A build script successfully executed.
27 #[serde(borrow)]
28 BuildScriptExecuted(BuildScript<'a>),
29 #[cfg(not(feature = "strict_unstable"))]
30 #[doc(hidden)]
31 #[serde(other)]
32 Unknown,
33 }
34
35 /// Build completed, all further output should not be parsed
36 #[derive(Debug, Clone, Serialize, Deserialize)]
37 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
38 #[non_exhaustive]
39 pub struct BuildFinished {
40 success: bool,
41 }
42
43 /// A compiler-generated file.
44 #[derive(Debug, Clone, Serialize, Deserialize)]
45 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
46 #[non_exhaustive]
47 pub struct Artifact<'a> {
48 /// The workspace member this artifact belongs to
49 #[serde(borrow)]
50 pub package_id: WorkspaceMember<'a>,
51 /// The target this artifact was compiled for
52 #[serde(borrow)]
53 pub target: Target<'a>,
54 /// The profile this artifact was compiled with
55 #[serde(borrow)]
56 pub profile: ArtifactProfile<'a>,
57 /// The enabled features for this artifact
58 #[serde(borrow)]
59 pub features: Vec<CowStr<'a>>,
60 /// The full paths to the generated artifacts
61 #[serde(borrow)]
62 pub filenames: Vec<CowPath<'a>>,
63 /// The full paths to the generated artifacts
64 #[serde(borrow)]
65 #[serde(default)]
66 pub executable: Option<CowPath<'a>>,
67 /// If true, then the files were already generated
68 pub fresh: bool,
69 }
70
71 /// A single target (lib, bin, example, ...) provided by a crate
72 #[derive(Clone, Serialize, Deserialize, Debug)]
73 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
74 #[non_exhaustive]
75 pub struct Target<'a> {
76 /// Name as given in the `Cargo.toml` or generated from the file name
77 #[serde(borrow)]
78 pub name: CowStr<'a>,
79 /// Kind of target ("bin", "example", "test", "bench", "lib")
80 #[serde(borrow)]
81 pub kind: Vec<CowStr<'a>>,
82 /// Almost the same as `kind`, except when an example is a library instad of an executable.
83 /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
84 #[serde(default)]
85 #[serde(borrow)]
86 pub crate_types: Vec<CowStr<'a>>,
87 /// Whether this is a doctest or not
88 #[serde(default)]
89 pub doctest: Option<bool>,
90 /// Whether this is a test file
91 #[serde(default)]
92 pub test: bool,
93
94 #[serde(default)]
95 #[serde(rename = "required-features")]
96 /// This target is built only if these features are enabled.
97 /// It doesn't apply to `lib` targets.
98 #[serde(borrow)]
99 pub required_features: Vec<CowStr<'a>>,
100 /// Path to the main source file of the target
101 #[serde(borrow)]
102 pub src_path: CowPath<'a>,
103 /// Rust edition for this target
104 #[serde(default = "edition_default")]
105 #[serde(borrow)]
106 pub edition: CowStr<'a>,
107 }
108
edition_default() -> CowStr<'static>109 fn edition_default() -> CowStr<'static> {
110 "2015".into()
111 }
112
113 /// A workspace member. This is basically identical to `cargo::core::package_id::PackageId`, except
114 /// that this does not use `Arc` internally.
115 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
116 #[serde(transparent)]
117 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
118 pub struct WorkspaceMember<'a> {
119 /// The raw package id as given by cargo
120 #[serde(borrow)]
121 raw: CowStr<'a>,
122 }
123
124 /// Profile settings used to determine which compiler flags to use for a
125 /// target.
126 #[derive(Debug, Clone, Serialize, Deserialize)]
127 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
128 #[non_exhaustive]
129 pub struct ArtifactProfile<'a> {
130 /// Optimization level. Possible values are 0-3, s or z.
131 #[serde(borrow)]
132 pub opt_level: CowStr<'a>,
133 /// The amount of debug info. 0 for none, 1 for limited, 2 for full
134 pub debuginfo: Option<u32>,
135 /// State of the `cfg(debug_assertions)` directive, enabling macros like
136 /// `debug_assert!`
137 pub debug_assertions: bool,
138 /// State of the overflow checks.
139 pub overflow_checks: bool,
140 /// Whether this profile is a test
141 pub test: bool,
142 }
143
144 /// Message left by the compiler
145 #[derive(Debug, Clone, Serialize, Deserialize)]
146 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
147 #[non_exhaustive]
148 pub struct FromCompiler<'a> {
149 /// The workspace member this message belongs to
150 #[serde(borrow)]
151 pub package_id: WorkspaceMember<'a>,
152 /// The target this message is aimed at
153 #[serde(borrow)]
154 pub target: Target<'a>,
155 /// The message the compiler sent.
156 #[serde(borrow)]
157 pub message: diagnostic::Diagnostic<'a>,
158 }
159
160 /// Output of a Build Script execution.
161 #[derive(Debug, Clone, Serialize, Deserialize)]
162 #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
163 #[non_exhaustive]
164 pub struct BuildScript<'a> {
165 /// The workspace member this build script execution belongs to
166 #[serde(borrow)]
167 pub package_id: WorkspaceMember<'a>,
168 /// The outdir used.
169 #[serde(borrow)]
170 #[serde(default)]
171 pub out_dir: Option<CowPath<'a>>,
172 /// The libs to link
173 #[serde(borrow)]
174 pub linked_libs: Vec<CowStr<'a>>,
175 /// The paths to search when resolving libs
176 #[serde(borrow)]
177 pub linked_paths: Vec<CowPath<'a>>,
178 /// The paths to search when resolving libs
179 #[serde(borrow)]
180 pub cfgs: Vec<CowPath<'a>>,
181 /// The environment variables to add to the compilation
182 #[serde(borrow)]
183 pub env: Vec<(CowStr<'a>, CowStr<'a>)>,
184 }
185
186 #[cfg(not(feature = "print"))]
log_message(msg: &Message<'_>)187 pub(crate) fn log_message(msg: &Message<'_>) {
188 match msg {
189 Message::BuildFinished(ref finished) => {
190 log::trace!("Build Finished: {:?}", finished.success);
191 }
192 Message::CompilerArtifact(ref art) => {
193 log::trace!("Building {:#?}", art.package_id,);
194 }
195 Message::CompilerMessage(ref comp) => {
196 let content = comp
197 .message
198 .rendered
199 .as_ref()
200 .map(|s| s.as_ref())
201 .unwrap_or(comp.message.message.as_ref());
202 match comp.message.level {
203 diagnostic::DiagnosticLevel::Ice => log::error!("{}", content),
204 diagnostic::DiagnosticLevel::Error => log::error!("{}", content),
205 diagnostic::DiagnosticLevel::Warning => log::warn!("{}", content),
206 diagnostic::DiagnosticLevel::Note => log::info!("{}", content),
207 diagnostic::DiagnosticLevel::Help => log::info!("{}", content),
208 #[cfg(not(feature = "strict_unstable"))]
209 _ => log::warn!("Unknown message: {:#?}", msg),
210 }
211 }
212 Message::BuildScriptExecuted(ref script) => {
213 log::trace!("Ran script from {:#?}", script.package_id);
214 }
215 #[cfg(not(feature = "strict_unstable"))]
216 _ => {
217 log::warn!("Unknown message: {:#?}", msg);
218 }
219 }
220 }
221
222 #[cfg(feature = "print")]
log_message(msg: &Message<'_>)223 pub(crate) fn log_message(msg: &Message<'_>) {
224 match msg {
225 Message::BuildFinished(ref finished) => {
226 println!("Build Finished: {:?}", finished.success);
227 }
228 Message::CompilerArtifact(ref art) => {
229 println!("Building {:#?}", art.package_id,);
230 }
231 Message::CompilerMessage(ref comp) => {
232 let content = comp
233 .message
234 .rendered
235 .as_ref()
236 .map(|s| s.as_ref())
237 .unwrap_or_else(|| comp.message.message.as_ref());
238 match comp.message.level {
239 diagnostic::DiagnosticLevel::Ice => println!("{}", content),
240 diagnostic::DiagnosticLevel::Error => println!("{}", content),
241 diagnostic::DiagnosticLevel::Warning => println!("{}", content),
242 diagnostic::DiagnosticLevel::Note => println!("{}", content),
243 diagnostic::DiagnosticLevel::Help => println!("{}", content),
244 #[cfg(not(feature = "strict_unstable"))]
245 _ => warn!("Unknown message: {:#?}", msg),
246 }
247 }
248 Message::BuildScriptExecuted(ref script) => {
249 println!("Ran script from {:#?}", script.package_id);
250 }
251 #[cfg(not(feature = "strict_unstable"))]
252 _ => {
253 println!("Unknown message: {:#?}", msg);
254 }
255 }
256 }
257