diff options
Diffstat (limited to 'crates/project_model/src/build_data.rs')
-rw-r--r-- | crates/project_model/src/build_data.rs | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs index c2c87b207..fdf4b2d55 100644 --- a/crates/project_model/src/build_data.rs +++ b/crates/project_model/src/build_data.rs | |||
@@ -18,7 +18,7 @@ use stdx::JodChild; | |||
18 | use crate::{cfg_flag::CfgFlag, CargoConfig}; | 18 | use crate::{cfg_flag::CfgFlag, CargoConfig}; |
19 | 19 | ||
20 | #[derive(Debug, Clone, Default, PartialEq, Eq)] | 20 | #[derive(Debug, Clone, Default, PartialEq, Eq)] |
21 | pub(crate) struct BuildData { | 21 | pub(crate) struct PackageBuildData { |
22 | /// List of config flags defined by this package's build script | 22 | /// List of config flags defined by this package's build script |
23 | pub(crate) cfgs: Vec<CfgFlag>, | 23 | pub(crate) cfgs: Vec<CfgFlag>, |
24 | /// List of cargo-related environment variables with their value | 24 | /// List of cargo-related environment variables with their value |
@@ -32,6 +32,16 @@ pub(crate) struct BuildData { | |||
32 | pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, | 32 | pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, |
33 | } | 33 | } |
34 | 34 | ||
35 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | ||
36 | pub(crate) struct WorkspaceBuildData { | ||
37 | per_package: FxHashMap<String, PackageBuildData>, | ||
38 | } | ||
39 | |||
40 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | ||
41 | pub struct BuildDataResult { | ||
42 | per_workspace: FxHashMap<AbsPathBuf, WorkspaceBuildData>, | ||
43 | } | ||
44 | |||
35 | #[derive(Clone, Debug)] | 45 | #[derive(Clone, Debug)] |
36 | pub(crate) struct BuildDataConfig { | 46 | pub(crate) struct BuildDataConfig { |
37 | cargo_toml: AbsPathBuf, | 47 | cargo_toml: AbsPathBuf, |
@@ -52,13 +62,6 @@ pub struct BuildDataCollector { | |||
52 | configs: FxHashMap<AbsPathBuf, BuildDataConfig>, | 62 | configs: FxHashMap<AbsPathBuf, BuildDataConfig>, |
53 | } | 63 | } |
54 | 64 | ||
55 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | ||
56 | pub struct BuildDataResult { | ||
57 | data: FxHashMap<AbsPathBuf, BuildDataMap>, | ||
58 | } | ||
59 | |||
60 | pub(crate) type BuildDataMap = FxHashMap<String, BuildData>; | ||
61 | |||
62 | impl BuildDataCollector { | 65 | impl BuildDataCollector { |
63 | pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) { | 66 | pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) { |
64 | self.configs.insert(workspace_root.to_path_buf(), config); | 67 | self.configs.insert(workspace_root.to_path_buf(), config); |
@@ -67,7 +70,7 @@ impl BuildDataCollector { | |||
67 | pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result<BuildDataResult> { | 70 | pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result<BuildDataResult> { |
68 | let mut res = BuildDataResult::default(); | 71 | let mut res = BuildDataResult::default(); |
69 | for (path, config) in self.configs.iter() { | 72 | for (path, config) in self.configs.iter() { |
70 | res.data.insert( | 73 | res.per_workspace.insert( |
71 | path.clone(), | 74 | path.clone(), |
72 | collect_from_workspace( | 75 | collect_from_workspace( |
73 | &config.cargo_toml, | 76 | &config.cargo_toml, |
@@ -81,9 +84,15 @@ impl BuildDataCollector { | |||
81 | } | 84 | } |
82 | } | 85 | } |
83 | 86 | ||
87 | impl WorkspaceBuildData { | ||
88 | pub(crate) fn get(&self, package_id: &str) -> Option<&PackageBuildData> { | ||
89 | self.per_package.get(package_id) | ||
90 | } | ||
91 | } | ||
92 | |||
84 | impl BuildDataResult { | 93 | impl BuildDataResult { |
85 | pub(crate) fn get(&self, root: &AbsPath) -> Option<&BuildDataMap> { | 94 | pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> { |
86 | self.data.get(&root.to_path_buf()) | 95 | self.per_workspace.get(workspace_root) |
87 | } | 96 | } |
88 | } | 97 | } |
89 | 98 | ||
@@ -102,7 +111,7 @@ fn collect_from_workspace( | |||
102 | cargo_features: &CargoConfig, | 111 | cargo_features: &CargoConfig, |
103 | packages: &Vec<cargo_metadata::Package>, | 112 | packages: &Vec<cargo_metadata::Package>, |
104 | progress: &dyn Fn(String), | 113 | progress: &dyn Fn(String), |
105 | ) -> Result<BuildDataMap> { | 114 | ) -> Result<WorkspaceBuildData> { |
106 | let mut cmd = Command::new(toolchain::cargo()); | 115 | let mut cmd = Command::new(toolchain::cargo()); |
107 | cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"]) | 116 | cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"]) |
108 | .arg(cargo_toml.as_ref()); | 117 | .arg(cargo_toml.as_ref()); |
@@ -136,7 +145,7 @@ fn collect_from_workspace( | |||
136 | let child_stdout = child.stdout.take().unwrap(); | 145 | let child_stdout = child.stdout.take().unwrap(); |
137 | let stdout = BufReader::new(child_stdout); | 146 | let stdout = BufReader::new(child_stdout); |
138 | 147 | ||
139 | let mut res = BuildDataMap::default(); | 148 | let mut res = WorkspaceBuildData::default(); |
140 | for message in cargo_metadata::Message::parse_stream(stdout).flatten() { | 149 | for message in cargo_metadata::Message::parse_stream(stdout).flatten() { |
141 | match message { | 150 | match message { |
142 | Message::BuildScriptExecuted(BuildScript { | 151 | Message::BuildScriptExecuted(BuildScript { |
@@ -154,16 +163,17 @@ fn collect_from_workspace( | |||
154 | } | 163 | } |
155 | acc | 164 | acc |
156 | }; | 165 | }; |
157 | let res = res.entry(package_id.repr.clone()).or_default(); | 166 | let package_build_data = |
167 | res.per_package.entry(package_id.repr.clone()).or_default(); | ||
158 | // cargo_metadata crate returns default (empty) path for | 168 | // cargo_metadata crate returns default (empty) path for |
159 | // older cargos, which is not absolute, so work around that. | 169 | // older cargos, which is not absolute, so work around that. |
160 | if !out_dir.as_str().is_empty() { | 170 | if !out_dir.as_str().is_empty() { |
161 | let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string())); | 171 | let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string())); |
162 | res.out_dir = Some(out_dir); | 172 | package_build_data.out_dir = Some(out_dir); |
163 | res.cfgs = cfgs; | 173 | package_build_data.cfgs = cfgs; |
164 | } | 174 | } |
165 | 175 | ||
166 | res.envs = env; | 176 | package_build_data.envs = env; |
167 | } | 177 | } |
168 | Message::CompilerArtifact(message) => { | 178 | Message::CompilerArtifact(message) => { |
169 | progress(format!("metadata {}", message.target.name)); | 179 | progress(format!("metadata {}", message.target.name)); |
@@ -173,8 +183,9 @@ fn collect_from_workspace( | |||
173 | // Skip rmeta file | 183 | // Skip rmeta file |
174 | if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) { | 184 | if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) { |
175 | let filename = AbsPathBuf::assert(PathBuf::from(&filename)); | 185 | let filename = AbsPathBuf::assert(PathBuf::from(&filename)); |
176 | let res = res.entry(package_id.repr.clone()).or_default(); | 186 | let package_build_data = |
177 | res.proc_macro_dylib_path = Some(filename); | 187 | res.per_package.entry(package_id.repr.clone()).or_default(); |
188 | package_build_data.proc_macro_dylib_path = Some(filename); | ||
178 | } | 189 | } |
179 | } | 190 | } |
180 | } | 191 | } |
@@ -188,12 +199,12 @@ fn collect_from_workspace( | |||
188 | } | 199 | } |
189 | 200 | ||
190 | for package in packages { | 201 | for package in packages { |
191 | let build_data = res.entry(package.id.repr.clone()).or_default(); | 202 | let package_build_data = res.per_package.entry(package.id.repr.clone()).or_default(); |
192 | inject_cargo_env(package, build_data); | 203 | inject_cargo_env(package, package_build_data); |
193 | if let Some(out_dir) = &build_data.out_dir { | 204 | if let Some(out_dir) = &package_build_data.out_dir { |
194 | // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() | 205 | // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() |
195 | if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { | 206 | if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { |
196 | build_data.envs.push(("OUT_DIR".to_string(), out_dir)); | 207 | package_build_data.envs.push(("OUT_DIR".to_string(), out_dir)); |
197 | } | 208 | } |
198 | } | 209 | } |
199 | } | 210 | } |
@@ -212,7 +223,7 @@ fn is_dylib(path: &Utf8Path) -> bool { | |||
212 | /// Recreates the compile-time environment variables that Cargo sets. | 223 | /// Recreates the compile-time environment variables that Cargo sets. |
213 | /// | 224 | /// |
214 | /// Should be synced with <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates> | 225 | /// Should be synced with <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates> |
215 | fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildData) { | 226 | fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut PackageBuildData) { |
216 | let env = &mut build_data.envs; | 227 | let env = &mut build_data.envs; |
217 | 228 | ||
218 | // FIXME: Missing variables: | 229 | // FIXME: Missing variables: |