/src/cargo/core/compiler/unit_graph.rs

https://gitlab.com/frewsxcv/cargo · Rust · 129 lines · 102 code · 8 blank · 19 comment · 2 complexity · a4454d50e5e7ab51dbb99711cf97c3b9 MD5 · raw file

  1. use crate::core::compiler::Unit;
  2. use crate::core::compiler::{CompileKind, CompileMode};
  3. use crate::core::profiles::{Profile, UnitFor};
  4. use crate::core::{PackageId, Target};
  5. use crate::util::interning::InternedString;
  6. use crate::util::CargoResult;
  7. use crate::Config;
  8. use std::collections::HashMap;
  9. use std::io::Write;
  10. /// The dependency graph of Units.
  11. pub type UnitGraph = HashMap<Unit, Vec<UnitDep>>;
  12. /// A unit dependency.
  13. #[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
  14. pub struct UnitDep {
  15. /// The dependency unit.
  16. pub unit: Unit,
  17. /// The purpose of this dependency (a dependency for a test, or a build
  18. /// script, etc.). Do not use this after the unit graph has been built.
  19. pub unit_for: UnitFor,
  20. /// The name the parent uses to refer to this dependency.
  21. pub extern_crate_name: InternedString,
  22. /// If `Some`, the name of the dependency if renamed in toml.
  23. /// It's particularly interesting to artifact dependencies which rely on it
  24. /// for naming their environment variables. Note that the `extern_crate_name`
  25. /// cannot be used for this as it also may be the build target itself,
  26. /// which isn't always the renamed dependency name.
  27. pub dep_name: Option<InternedString>,
  28. /// Whether or not this is a public dependency.
  29. pub public: bool,
  30. /// If `true`, the dependency should not be added to Rust's prelude.
  31. pub noprelude: bool,
  32. }
  33. const VERSION: u32 = 1;
  34. #[derive(serde::Serialize)]
  35. struct SerializedUnitGraph<'a> {
  36. version: u32,
  37. units: Vec<SerializedUnit<'a>>,
  38. roots: Vec<usize>,
  39. }
  40. #[derive(serde::Serialize)]
  41. struct SerializedUnit<'a> {
  42. pkg_id: PackageId,
  43. target: &'a Target,
  44. profile: &'a Profile,
  45. platform: CompileKind,
  46. mode: CompileMode,
  47. features: &'a Vec<InternedString>,
  48. #[serde(skip_serializing_if = "std::ops::Not::not")] // hide for unstable build-std
  49. is_std: bool,
  50. dependencies: Vec<SerializedUnitDep>,
  51. }
  52. #[derive(serde::Serialize)]
  53. struct SerializedUnitDep {
  54. index: usize,
  55. extern_crate_name: InternedString,
  56. // This is only set on nightly since it is unstable.
  57. #[serde(skip_serializing_if = "Option::is_none")]
  58. public: Option<bool>,
  59. // This is only set on nightly since it is unstable.
  60. #[serde(skip_serializing_if = "Option::is_none")]
  61. noprelude: Option<bool>,
  62. // Intentionally not including `unit_for` because it is a low-level
  63. // internal detail that is mostly used for building the graph.
  64. }
  65. pub fn emit_serialized_unit_graph(
  66. root_units: &[Unit],
  67. unit_graph: &UnitGraph,
  68. config: &Config,
  69. ) -> CargoResult<()> {
  70. let mut units: Vec<(&Unit, &Vec<UnitDep>)> = unit_graph.iter().collect();
  71. units.sort_unstable();
  72. // Create a map for quick lookup for dependencies.
  73. let indices: HashMap<&Unit, usize> = units
  74. .iter()
  75. .enumerate()
  76. .map(|(i, val)| (val.0, i))
  77. .collect();
  78. let roots = root_units.iter().map(|root| indices[root]).collect();
  79. let ser_units = units
  80. .iter()
  81. .map(|(unit, unit_deps)| {
  82. let dependencies = unit_deps
  83. .iter()
  84. .map(|unit_dep| {
  85. // https://github.com/rust-lang/rust/issues/64260 when stabilized.
  86. let (public, noprelude) = if config.nightly_features_allowed {
  87. (Some(unit_dep.public), Some(unit_dep.noprelude))
  88. } else {
  89. (None, None)
  90. };
  91. SerializedUnitDep {
  92. index: indices[&unit_dep.unit],
  93. extern_crate_name: unit_dep.extern_crate_name,
  94. public,
  95. noprelude,
  96. }
  97. })
  98. .collect();
  99. SerializedUnit {
  100. pkg_id: unit.pkg.package_id(),
  101. target: &unit.target,
  102. profile: &unit.profile,
  103. platform: unit.kind,
  104. mode: unit.mode,
  105. features: &unit.features,
  106. is_std: unit.is_std,
  107. dependencies,
  108. }
  109. })
  110. .collect();
  111. let s = SerializedUnitGraph {
  112. version: VERSION,
  113. units: ser_units,
  114. roots,
  115. };
  116. let stdout = std::io::stdout();
  117. let mut lock = stdout.lock();
  118. serde_json::to_writer(&mut lock, &s)?;
  119. drop(writeln!(lock));
  120. Ok(())
  121. }