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