cargo/core/compiler/
unit_graph.rs1use cargo_util_schemas::core::PackageIdSpec;
6
7use crate::core::compiler::Unit;
8use crate::core::compiler::{CompileKind, CompileMode};
9use crate::core::profiles::{Profile, UnitFor};
10use crate::core::Target;
11use crate::util::interning::InternedString;
12use crate::util::CargoResult;
13use crate::GlobalContext;
14use std::collections::HashMap;
15
16pub type UnitGraph = HashMap<Unit, Vec<UnitDep>>;
18
19#[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
21pub struct UnitDep {
22 pub unit: Unit,
24 pub unit_for: UnitFor,
27 pub extern_crate_name: InternedString,
29 pub dep_name: Option<InternedString>,
35 pub public: bool,
37 pub noprelude: bool,
39}
40
41const VERSION: u32 = 1;
42
43#[derive(serde::Serialize)]
44struct SerializedUnitGraph<'a> {
45 version: u32,
46 units: Vec<SerializedUnit<'a>>,
47 roots: Vec<usize>,
48}
49
50#[derive(serde::Serialize)]
51struct SerializedUnit<'a> {
52 pkg_id: PackageIdSpec,
53 target: &'a Target,
54 profile: &'a Profile,
55 platform: CompileKind,
56 mode: CompileMode,
57 features: &'a Vec<InternedString>,
58 #[serde(skip_serializing_if = "std::ops::Not::not")] is_std: bool,
60 dependencies: Vec<SerializedUnitDep>,
61}
62
63#[derive(serde::Serialize)]
64struct SerializedUnitDep {
65 index: usize,
66 extern_crate_name: InternedString,
67 #[serde(skip_serializing_if = "Option::is_none")]
69 public: Option<bool>,
70 #[serde(skip_serializing_if = "Option::is_none")]
72 noprelude: Option<bool>,
73 }
76
77pub fn emit_serialized_unit_graph(
80 root_units: &[Unit],
81 unit_graph: &UnitGraph,
82 gctx: &GlobalContext,
83) -> CargoResult<()> {
84 let mut units: Vec<(&Unit, &Vec<UnitDep>)> = unit_graph.iter().collect();
85 units.sort_unstable();
86 let indices: HashMap<&Unit, usize> = units
88 .iter()
89 .enumerate()
90 .map(|(i, val)| (val.0, i))
91 .collect();
92 let roots = root_units.iter().map(|root| indices[root]).collect();
93 let ser_units = units
94 .iter()
95 .map(|(unit, unit_deps)| {
96 let dependencies = unit_deps
97 .iter()
98 .map(|unit_dep| {
99 let (public, noprelude) = if gctx.nightly_features_allowed {
101 (Some(unit_dep.public), Some(unit_dep.noprelude))
102 } else {
103 (None, None)
104 };
105 SerializedUnitDep {
106 index: indices[&unit_dep.unit],
107 extern_crate_name: unit_dep.extern_crate_name,
108 public,
109 noprelude,
110 }
111 })
112 .collect();
113 SerializedUnit {
114 pkg_id: unit.pkg.package_id().to_spec(),
115 target: &unit.target,
116 profile: &unit.profile,
117 platform: unit.kind,
118 mode: unit.mode,
119 features: &unit.features,
120 is_std: unit.is_std,
121 dependencies,
122 }
123 })
124 .collect();
125
126 gctx.shell().print_json(&SerializedUnitGraph {
127 version: VERSION,
128 units: ser_units,
129 roots,
130 })
131}