aboutsummaryrefslogtreecommitdiff
path: root/crates/project_model
diff options
context:
space:
mode:
Diffstat (limited to 'crates/project_model')
-rw-r--r--crates/project_model/Cargo.toml2
-rw-r--r--crates/project_model/src/sysroot.rs2
-rw-r--r--crates/project_model/src/workspace.rs608
3 files changed, 287 insertions, 325 deletions
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml
index 2d53bcbcc..e0c591603 100644
--- a/crates/project_model/Cargo.toml
+++ b/crates/project_model/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12[dependencies] 12[dependencies]
13log = "0.4.8" 13log = "0.4.8"
14rustc-hash = "1.1.0" 14rustc-hash = "1.1.0"
15cargo_metadata = "0.12.0" 15cargo_metadata = "=0.12.0"
16serde = { version = "1.0.106", features = ["derive"] } 16serde = { version = "1.0.106", features = ["derive"] }
17serde_json = "1.0.48" 17serde_json = "1.0.48"
18anyhow = "1.0.26" 18anyhow = "1.0.26"
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs
index b0e8863f6..f0a43eaf6 100644
--- a/crates/project_model/src/sysroot.rs
+++ b/crates/project_model/src/sysroot.rs
@@ -37,7 +37,7 @@ impl Sysroot {
37 pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ { 37 pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ {
38 // core is added as a dependency before std in order to 38 // core is added as a dependency before std in order to
39 // mimic rustcs dependency order 39 // mimic rustcs dependency order
40 vec!["core", "alloc", "std"].into_iter().filter_map(move |it| Some((it, self.by_name(it)?))) 40 ["core", "alloc", "std"].iter().filter_map(move |&it| Some((it, self.by_name(it)?)))
41 } 41 }
42 42
43 pub fn proc_macro(&self) -> Option<SysrootCrate> { 43 pub fn proc_macro(&self) -> Option<SysrootCrate> {
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index 9ebb0a811..a71f96164 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -12,8 +12,8 @@ use proc_macro_api::ProcMacroClient;
12use rustc_hash::{FxHashMap, FxHashSet}; 12use rustc_hash::{FxHashMap, FxHashSet};
13 13
14use crate::{ 14use crate::{
15 cargo_workspace, cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoWorkspace, ProjectJson, 15 cargo_workspace, cfg_flag::CfgFlag, sysroot::SysrootCrate, utf8_stdout, CargoConfig,
16 ProjectManifest, Sysroot, TargetKind, 16 CargoWorkspace, ProjectJson, ProjectManifest, Sysroot, TargetKind,
17}; 17};
18 18
19/// `PackageRoot` describes a package root folder. 19/// `PackageRoot` describes a package root folder.
@@ -70,12 +70,8 @@ impl ProjectWorkspace {
70 format!("Failed to deserialize json file {}", project_json.display()) 70 format!("Failed to deserialize json file {}", project_json.display())
71 })?; 71 })?;
72 let project_location = project_json.parent().unwrap().to_path_buf(); 72 let project_location = project_json.parent().unwrap().to_path_buf();
73 let project = ProjectJson::new(&project_location, data); 73 let project_json = ProjectJson::new(&project_location, data);
74 let sysroot = match &project.sysroot_src { 74 ProjectWorkspace::load_inline(project_json)?
75 Some(path) => Some(Sysroot::load(path)?),
76 None => None,
77 };
78 ProjectWorkspace::Json { project, sysroot }
79 } 75 }
80 ProjectManifest::CargoToml(cargo_toml) => { 76 ProjectManifest::CargoToml(cargo_toml) => {
81 let cargo_version = utf8_stdout({ 77 let cargo_version = utf8_stdout({
@@ -150,43 +146,38 @@ impl ProjectWorkspace {
150 }) 146 })
151 })) 147 }))
152 .collect::<Vec<_>>(), 148 .collect::<Vec<_>>(),
153 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => { 149 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => cargo
154 let roots = cargo 150 .packages()
155 .packages() 151 .map(|pkg| {
156 .map(|pkg| { 152 let is_member = cargo[pkg].is_member;
157 let is_member = cargo[pkg].is_member; 153 let pkg_root = cargo[pkg].root().to_path_buf();
158 let pkg_root = cargo[pkg].root().to_path_buf(); 154
159 155 let mut include = vec![pkg_root.clone()];
160 let mut include = vec![pkg_root.clone()]; 156 include.extend(cargo[pkg].out_dir.clone());
161 include.extend(cargo[pkg].out_dir.clone()); 157
162 158 let mut exclude = vec![pkg_root.join(".git")];
163 let mut exclude = vec![pkg_root.join(".git")]; 159 if is_member {
164 if is_member { 160 exclude.push(pkg_root.join("target"));
165 exclude.push(pkg_root.join("target")); 161 } else {
166 } else { 162 exclude.push(pkg_root.join("tests"));
167 exclude.push(pkg_root.join("tests")); 163 exclude.push(pkg_root.join("examples"));
168 exclude.push(pkg_root.join("examples")); 164 exclude.push(pkg_root.join("benches"));
169 exclude.push(pkg_root.join("benches")); 165 }
170 } 166 PackageRoot { is_member, include, exclude }
171 PackageRoot { is_member, include, exclude } 167 })
172 }) 168 .chain(sysroot.crates().map(|krate| PackageRoot {
173 .chain(sysroot.crates().map(|krate| PackageRoot { 169 is_member: false,
170 include: vec![sysroot[krate].root_dir().to_path_buf()],
171 exclude: Vec::new(),
172 }))
173 .chain(rustc.into_iter().flat_map(|rustc| {
174 rustc.packages().map(move |krate| PackageRoot {
174 is_member: false, 175 is_member: false,
175 include: vec![sysroot[krate].root_dir().to_path_buf()], 176 include: vec![rustc[krate].root().to_path_buf()],
176 exclude: Vec::new(), 177 exclude: Vec::new(),
177 })); 178 })
178 if let Some(rustc_packages) = rustc { 179 }))
179 roots 180 .collect(),
180 .chain(rustc_packages.packages().map(|krate| PackageRoot {
181 is_member: false,
182 include: vec![rustc_packages[krate].root().to_path_buf()],
183 exclude: Vec::new(),
184 }))
185 .collect()
186 } else {
187 roots.collect()
188 }
189 }
190 } 181 }
191 } 182 }
192 183
@@ -206,312 +197,280 @@ impl ProjectWorkspace {
206 proc_macro_client: &ProcMacroClient, 197 proc_macro_client: &ProcMacroClient,
207 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 198 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
208 ) -> CrateGraph { 199 ) -> CrateGraph {
209 let mut crate_graph = CrateGraph::default(); 200 let mut crate_graph = match self {
210 match self {
211 ProjectWorkspace::Json { project, sysroot } => { 201 ProjectWorkspace::Json { project, sysroot } => {
212 let sysroot_dps = sysroot 202 project_json_to_crate_graph(target, proc_macro_client, load, project, sysroot)
213 .as_ref()
214 .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load));
215
216 let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default();
217 let crates: FxHashMap<_, _> = project
218 .crates()
219 .filter_map(|(crate_id, krate)| {
220 let file_path = &krate.root_module;
221 let file_id = match load(&file_path) {
222 Some(id) => id,
223 None => {
224 log::error!("failed to load crate root {}", file_path.display());
225 return None;
226 }
227 };
228
229 let env = krate.env.clone().into_iter().collect();
230 let proc_macro = krate
231 .proc_macro_dylib_path
232 .clone()
233 .map(|it| proc_macro_client.by_dylib_path(&it));
234
235 let target = krate.target.as_deref().or(target);
236 let target_cfgs = cfg_cache
237 .entry(target)
238 .or_insert_with(|| get_rustc_cfg_options(target));
239
240 let mut cfg_options = CfgOptions::default();
241 cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned());
242
243 Some((
244 crate_id,
245 crate_graph.add_crate_root(
246 file_id,
247 krate.edition,
248 krate.display_name.clone(),
249 cfg_options,
250 env,
251 proc_macro.unwrap_or_default(),
252 ),
253 ))
254 })
255 .collect();
256
257 for (from, krate) in project.crates() {
258 if let Some(&from) = crates.get(&from) {
259 if let Some((public_deps, _proc_macro)) = &sysroot_dps {
260 for (name, to) in public_deps.iter() {
261 if let Err(_) = crate_graph.add_dep(from, name.clone(), *to) {
262 log::error!("cyclic dependency on {} for {:?}", name, from)
263 }
264 }
265 }
266
267 for dep in &krate.deps {
268 let to_crate_id = dep.crate_id;
269 if let Some(&to) = crates.get(&to_crate_id) {
270 if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
271 log::error!("cyclic dependency {:?} -> {:?}", from, to);
272 }
273 }
274 }
275 }
276 }
277 } 203 }
278 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => { 204 ProjectWorkspace::Cargo { cargo, sysroot, rustc } => {
279 let (public_deps, libproc_macro) = 205 cargo_to_crate_graph(target, proc_macro_client, load, cargo, sysroot, rustc)
280 sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load); 206 }
207 };
208 if crate_graph.patch_cfg_if() {
209 log::debug!("Patched std to depend on cfg-if")
210 } else {
211 log::debug!("Did not patch std to depend on cfg-if")
212 }
213 crate_graph
214 }
215}
216
217fn project_json_to_crate_graph(
218 target: Option<&str>,
219 proc_macro_client: &ProcMacroClient,
220 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
221 project: &ProjectJson,
222 sysroot: &Option<Sysroot>,
223) -> CrateGraph {
224 let mut crate_graph = CrateGraph::default();
225 let sysroot_deps = sysroot
226 .as_ref()
227 .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load));
228
229 let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default();
230 let crates: FxHashMap<CrateId, CrateId> = project
231 .crates()
232 .filter_map(|(crate_id, krate)| {
233 let file_path = &krate.root_module;
234 let file_id = load(&file_path)?;
235 Some((crate_id, krate, file_id))
236 })
237 .map(|(crate_id, krate, file_id)| {
238 let env = krate.env.clone().into_iter().collect();
239 let proc_macro =
240 krate.proc_macro_dylib_path.clone().map(|it| proc_macro_client.by_dylib_path(&it));
241
242 let target = krate.target.as_deref().or(target);
243 let target_cfgs =
244 cfg_cache.entry(target).or_insert_with(|| get_rustc_cfg_options(target));
245
246 let mut cfg_options = CfgOptions::default();
247 cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned());
248 (
249 crate_id,
250 crate_graph.add_crate_root(
251 file_id,
252 krate.edition,
253 krate.display_name.clone(),
254 cfg_options,
255 env,
256 proc_macro.unwrap_or_default(),
257 ),
258 )
259 })
260 .collect();
281 261
282 let mut cfg_options = CfgOptions::default(); 262 for (from, krate) in project.crates() {
283 cfg_options.extend(get_rustc_cfg_options(target)); 263 if let Some(&from) = crates.get(&from) {
264 if let Some((public_deps, _proc_macro)) = &sysroot_deps {
265 for (name, to) in public_deps.iter() {
266 add_dep(&mut crate_graph, from, name.clone(), *to)
267 }
268 }
284 269
285 let mut pkg_to_lib_crate = FxHashMap::default(); 270 for dep in &krate.deps {
271 if let Some(&to) = crates.get(&dep.crate_id) {
272 add_dep(&mut crate_graph, from, dep.name.clone(), to)
273 }
274 }
275 }
276 }
277 crate_graph
278}
286 279
287 // Add test cfg for non-sysroot crates 280fn cargo_to_crate_graph(
288 cfg_options.insert_atom("test".into()); 281 target: Option<&str>,
289 cfg_options.insert_atom("debug_assertions".into()); 282 proc_macro_client: &ProcMacroClient,
283 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
284 cargo: &CargoWorkspace,
285 sysroot: &Sysroot,
286 rustc: &Option<CargoWorkspace>,
287) -> CrateGraph {
288 let mut crate_graph = CrateGraph::default();
289 let (public_deps, libproc_macro) =
290 sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load);
290 291
291 let mut pkg_crates = FxHashMap::default(); 292 let mut cfg_options = CfgOptions::default();
293 cfg_options.extend(get_rustc_cfg_options(target));
292 294
293 // Next, create crates for each package, target pair 295 let mut pkg_to_lib_crate = FxHashMap::default();
294 for pkg in cargo.packages() { 296
295 let mut lib_tgt = None; 297 // Add test cfg for non-sysroot crates
296 for &tgt in cargo[pkg].targets.iter() { 298 cfg_options.insert_atom("test".into());
297 if let Some(crate_id) = add_target_crate_root( 299 cfg_options.insert_atom("debug_assertions".into());
300
301 let mut pkg_crates = FxHashMap::default();
302
303 // Next, create crates for each package, target pair
304 for pkg in cargo.packages() {
305 let mut lib_tgt = None;
306 for &tgt in cargo[pkg].targets.iter() {
307 if let Some(file_id) = load(&cargo[tgt].root) {
308 let crate_id = add_target_crate_root(
309 &mut crate_graph,
310 &cargo[pkg],
311 &cfg_options,
312 proc_macro_client,
313 file_id,
314 );
315 if cargo[tgt].kind == TargetKind::Lib {
316 lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
317 pkg_to_lib_crate.insert(pkg, crate_id);
318 }
319 if cargo[tgt].is_proc_macro {
320 if let Some(proc_macro) = libproc_macro {
321 add_dep(
298 &mut crate_graph, 322 &mut crate_graph,
299 &cargo[pkg], 323 crate_id,
300 &cargo[tgt], 324 CrateName::new("proc_macro").unwrap(),
301 &cfg_options, 325 proc_macro,
302 proc_macro_client, 326 );
303 load,
304 ) {
305 if cargo[tgt].kind == TargetKind::Lib {
306 lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
307 pkg_to_lib_crate.insert(pkg, crate_id);
308 }
309 if cargo[tgt].is_proc_macro {
310 if let Some(proc_macro) = libproc_macro {
311 if let Err(_) = crate_graph.add_dep(
312 crate_id,
313 CrateName::new("proc_macro").unwrap(),
314 proc_macro,
315 ) {
316 log::error!(
317 "cyclic dependency on proc_macro for {}",
318 &cargo[pkg].name
319 )
320 }
321 }
322 }
323
324 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
325 }
326 } 327 }
328 }
327 329
328 // Set deps to the core, std and to the lib target of the current package 330 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
329 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 331 }
330 if let Some((to, name)) = lib_tgt.clone() { 332 }
331 // For root projects with dashes in their name, 333
332 // cargo metadata does not do any normalization, 334 // Set deps to the core, std and to the lib target of the current package
333 // so we do it ourselves currently 335 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
334 let name = CrateName::normalize_dashes(&name); 336 if let Some((to, name)) = lib_tgt.clone() {
335 if to != from && crate_graph.add_dep(from, name, to).is_err() { 337 if to != from {
336 log::error!( 338 // For root projects with dashes in their name,
337 "cyclic dependency between targets of {}", 339 // cargo metadata does not do any normalization,
338 &cargo[pkg].name 340 // so we do it ourselves currently
339 ) 341 let name = CrateName::normalize_dashes(&name);
340 } 342 add_dep(&mut crate_graph, from, name, to);
341 } 343 }
342 for (name, krate) in public_deps.iter() { 344 }
343 if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) { 345 for (name, krate) in public_deps.iter() {
344 log::error!( 346 add_dep(&mut crate_graph, from, name.clone(), *krate);
345 "cyclic dependency on {} for {}", 347 }
346 name, 348 }
347 &cargo[pkg].name 349 }
348 ) 350
349 } 351 // Now add a dep edge from all targets of upstream to the lib
350 } 352 // target of downstream.
351 } 353 for pkg in cargo.packages() {
354 for dep in cargo[pkg].dependencies.iter() {
355 let name = CrateName::new(&dep.name).unwrap();
356 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
357 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
358 add_dep(&mut crate_graph, from, name.clone(), to)
352 } 359 }
360 }
361 }
362 }
353 363
354 // Now add a dep edge from all targets of upstream to the lib 364 let mut rustc_pkg_crates = FxHashMap::default();
355 // target of downstream. 365
356 for pkg in cargo.packages() { 366 // If the user provided a path to rustc sources, we add all the rustc_private crates
357 for dep in cargo[pkg].dependencies.iter() { 367 // and create dependencies on them for the crates in the current workspace
358 let name = CrateName::new(&dep.name).unwrap(); 368 if let Some(rustc_workspace) = rustc {
359 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { 369 for pkg in rustc_workspace.packages() {
360 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 370 for &tgt in rustc_workspace[pkg].targets.iter() {
361 if let Err(_) = crate_graph.add_dep(from, name.clone(), to) { 371 if rustc_workspace[tgt].kind != TargetKind::Lib {
362 log::error!( 372 continue;
363 "cyclic dependency {} -> {}", 373 }
364 &cargo[pkg].name, 374 // Exclude alloc / core / std
365 &cargo[dep.pkg].name 375 if rustc_workspace[tgt]
366 ) 376 .root
367 } 377 .components()
368 } 378 .any(|c| c == Component::Normal("library".as_ref()))
369 } 379 {
370 } 380 continue;
371 } 381 }
372 382
373 let mut rustc_pkg_crates = FxHashMap::default(); 383 if let Some(file_id) = load(&rustc_workspace[tgt].root) {
374 384 let crate_id = add_target_crate_root(
375 // If the user provided a path to rustc sources, we add all the rustc_private crates 385 &mut crate_graph,
376 // and create dependencies on them for the crates in the current workspace 386 &rustc_workspace[pkg],
377 if let Some(rustc_workspace) = rustc { 387 &cfg_options,
378 for pkg in rustc_workspace.packages() { 388 proc_macro_client,
379 for &tgt in rustc_workspace[pkg].targets.iter() { 389 file_id,
380 if rustc_workspace[tgt].kind != TargetKind::Lib { 390 );
381 continue; 391 pkg_to_lib_crate.insert(pkg, crate_id);
382 } 392 // Add dependencies on the core / std / alloc for rustc
383 // Exclude alloc / core / std 393 for (name, krate) in public_deps.iter() {
384 if rustc_workspace[tgt] 394 add_dep(&mut crate_graph, crate_id, name.clone(), *krate);
385 .root
386 .components()
387 .any(|c| c == Component::Normal("library".as_ref()))
388 {
389 continue;
390 }
391
392 if let Some(crate_id) = add_target_crate_root(
393 &mut crate_graph,
394 &rustc_workspace[pkg],
395 &rustc_workspace[tgt],
396 &cfg_options,
397 proc_macro_client,
398 load,
399 ) {
400 pkg_to_lib_crate.insert(pkg, crate_id);
401 // Add dependencies on the core / std / alloc for rustc
402 for (name, krate) in public_deps.iter() {
403 if let Err(_) =
404 crate_graph.add_dep(crate_id, name.clone(), *krate)
405 {
406 log::error!(
407 "cyclic dependency on {} for {}",
408 name,
409 &cargo[pkg].name
410 )
411 }
412 }
413 rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
414 }
415 }
416 } 395 }
417 // Now add a dep edge from all targets of upstream to the lib 396 rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
418 // target of downstream. 397 }
419 for pkg in rustc_workspace.packages() { 398 }
420 for dep in rustc_workspace[pkg].dependencies.iter() { 399 }
421 let name = CrateName::new(&dep.name).unwrap(); 400 // Now add a dep edge from all targets of upstream to the lib
422 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { 401 // target of downstream.
423 for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { 402 for pkg in rustc_workspace.packages() {
424 if let Err(_) = crate_graph.add_dep(from, name.clone(), to) { 403 for dep in rustc_workspace[pkg].dependencies.iter() {
425 log::error!( 404 let name = CrateName::new(&dep.name).unwrap();
426 "cyclic dependency {} -> {}", 405 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
427 &rustc_workspace[pkg].name, 406 for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
428 &rustc_workspace[dep.pkg].name 407 add_dep(&mut crate_graph, from, name.clone(), to);
429 )
430 }
431 }
432 }
433 }
434 } 408 }
409 }
410 }
411 }
435 412
436 // Add dependencies for all the crates of the current workspace to rustc_private libraries 413 // Add dependencies for all the crates of the current workspace to rustc_private libraries
437 for dep in rustc_workspace.packages() { 414 for dep in rustc_workspace.packages() {
438 let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); 415 let name = CrateName::normalize_dashes(&rustc_workspace[dep].name);
439 416
440 if let Some(&to) = pkg_to_lib_crate.get(&dep) { 417 if let Some(&to) = pkg_to_lib_crate.get(&dep) {
441 for pkg in cargo.packages() { 418 for pkg in cargo.packages() {
442 if !cargo[pkg].is_member { 419 if !cargo[pkg].is_member {
443 continue; 420 continue;
444 } 421 }
445 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 422 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
446 if let Err(_) = crate_graph.add_dep(from, name.clone(), to) { 423 add_dep(&mut crate_graph, from, name.clone(), to);
447 log::error!(
448 "cyclic dependency {} -> {}",
449 &cargo[pkg].name,
450 &rustc_workspace[dep].name
451 )
452 }
453 }
454 }
455 }
456 } 424 }
457 } 425 }
458 } 426 }
459 } 427 }
460 if crate_graph.patch_cfg_if() {
461 log::debug!("Patched std to depend on cfg-if")
462 } else {
463 log::debug!("Did not patch std to depend on cfg-if")
464 }
465 crate_graph
466 } 428 }
429 crate_graph
467} 430}
468 431
469fn add_target_crate_root( 432fn add_target_crate_root(
470 crate_graph: &mut CrateGraph, 433 crate_graph: &mut CrateGraph,
471 pkg: &cargo_workspace::PackageData, 434 pkg: &cargo_workspace::PackageData,
472 tgt: &cargo_workspace::TargetData,
473 cfg_options: &CfgOptions, 435 cfg_options: &CfgOptions,
474 proc_macro_client: &ProcMacroClient, 436 proc_macro_client: &ProcMacroClient,
475 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, 437 file_id: FileId,
476) -> Option<CrateId> { 438) -> CrateId {
477 let root = tgt.root.as_path(); 439 let edition = pkg.edition;
478 if let Some(file_id) = load(root) { 440 let cfg_options = {
479 let edition = pkg.edition; 441 let mut opts = cfg_options.clone();
480 let cfg_options = { 442 for feature in pkg.features.iter() {
481 let mut opts = cfg_options.clone(); 443 opts.insert_key_value("feature".into(), feature.into());
482 for feature in pkg.features.iter() { 444 }
483 opts.insert_key_value("feature".into(), feature.into()); 445 opts.extend(pkg.cfgs.iter().cloned());
484 } 446 opts
485 opts.extend(pkg.cfgs.iter().cloned()); 447 };
486 opts 448 let mut env = Env::default();
487 }; 449 if let Some(out_dir) = &pkg.out_dir {
488 let mut env = Env::default(); 450 // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
489 if let Some(out_dir) = &pkg.out_dir { 451 if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
490 // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() 452 env.set("OUT_DIR", out_dir);
491 if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
492 env.set("OUT_DIR", out_dir);
493 }
494 } 453 }
495 let proc_macro = pkg
496 .proc_macro_dylib_path
497 .as_ref()
498 .map(|it| proc_macro_client.by_dylib_path(&it))
499 .unwrap_or_default();
500
501 let display_name = CrateDisplayName::from_canonical_name(pkg.name.clone());
502 let crate_id = crate_graph.add_crate_root(
503 file_id,
504 edition,
505 Some(display_name),
506 cfg_options,
507 env,
508 proc_macro.clone(),
509 );
510
511 return Some(crate_id);
512 } 454 }
513 None 455 let proc_macro = pkg
456 .proc_macro_dylib_path
457 .as_ref()
458 .map(|it| proc_macro_client.by_dylib_path(&it))
459 .unwrap_or_default();
460
461 let display_name = CrateDisplayName::from_canonical_name(pkg.name.clone());
462 let crate_id = crate_graph.add_crate_root(
463 file_id,
464 edition,
465 Some(display_name),
466 cfg_options,
467 env,
468 proc_macro.clone(),
469 );
470
471 crate_id
514} 472}
473
515fn sysroot_to_crate_graph( 474fn sysroot_to_crate_graph(
516 crate_graph: &mut CrateGraph, 475 crate_graph: &mut CrateGraph,
517 sysroot: &Sysroot, 476 sysroot: &Sysroot,
@@ -520,19 +479,18 @@ fn sysroot_to_crate_graph(
520) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) { 479) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
521 let mut cfg_options = CfgOptions::default(); 480 let mut cfg_options = CfgOptions::default();
522 cfg_options.extend(get_rustc_cfg_options(target)); 481 cfg_options.extend(get_rustc_cfg_options(target));
523 let sysroot_crates: FxHashMap<_, _> = sysroot 482 let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = sysroot
524 .crates() 483 .crates()
525 .filter_map(|krate| { 484 .filter_map(|krate| {
526 let file_id = load(&sysroot[krate].root)?; 485 let file_id = load(&sysroot[krate].root)?;
527 486
528 let env = Env::default(); 487 let env = Env::default();
529 let proc_macro = vec![]; 488 let proc_macro = vec![];
530 let name = CrateName::new(&sysroot[krate].name) 489 let display_name = CrateDisplayName::from_canonical_name(sysroot[krate].name.clone());
531 .expect("Sysroot crates' names do not contain dashes");
532 let crate_id = crate_graph.add_crate_root( 490 let crate_id = crate_graph.add_crate_root(
533 file_id, 491 file_id,
534 Edition::Edition2018, 492 Edition::Edition2018,
535 Some(name.into()), 493 Some(display_name),
536 cfg_options.clone(), 494 cfg_options.clone(),
537 env, 495 env,
538 proc_macro, 496 proc_macro,
@@ -545,9 +503,7 @@ fn sysroot_to_crate_graph(
545 for &to in sysroot[from].deps.iter() { 503 for &to in sysroot[from].deps.iter() {
546 let name = CrateName::new(&sysroot[to].name).unwrap(); 504 let name = CrateName::new(&sysroot[to].name).unwrap();
547 if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) { 505 if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) {
548 if let Err(_) = crate_graph.add_dep(from, name, to) { 506 add_dep(crate_graph, from, name, to);
549 log::error!("cyclic dependency between sysroot crates")
550 }
551 } 507 }
552 } 508 }
553 } 509 }
@@ -588,3 +544,9 @@ fn get_rustc_cfg_options(target: Option<&str>) -> Vec<CfgFlag> {
588 544
589 res 545 res
590} 546}
547
548fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
549 if let Err(err) = graph.add_dep(from, name, to) {
550 log::error!("{}", err)
551 }
552}