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