cargo/core/compiler/
unit_graph.rs1use cargo_util_schemas::core::PackageIdSpec;
6
7use crate::GlobalContext;
8use crate::core::Target;
9use crate::core::compiler::Unit;
10use crate::core::compiler::{CompileKind, CompileMode};
11use crate::core::profiles::{Profile, UnitFor};
12use crate::util::CargoResult;
13use crate::util::interning::InternedString;
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>,
39 pub public: bool,
41 pub noprelude: bool,
43 pub nounused: bool,
45}
46
47const VERSION: u32 = 1;
48
49#[derive(serde::Serialize)]
50struct SerializedUnitGraph<'a> {
51 version: u32,
52 units: Vec<SerializedUnit<'a>>,
53 roots: Vec<usize>,
54}
55
56#[derive(serde::Serialize)]
57struct SerializedUnit<'a> {
58 pkg_id: PackageIdSpec,
59 target: &'a Target,
60 profile: &'a Profile,
61 platform: CompileKind,
62 mode: CompileMode,
63 features: &'a Vec<InternedString>,
64 #[serde(skip_serializing_if = "std::ops::Not::not")] is_std: bool,
66 dependencies: Vec<SerializedUnitDep>,
67}
68
69#[derive(serde::Serialize)]
70struct SerializedUnitDep {
71 index: usize,
72 extern_crate_name: InternedString,
73 #[serde(skip_serializing_if = "Option::is_none")]
75 public: Option<bool>,
76 #[serde(skip_serializing_if = "Option::is_none")]
78 noprelude: Option<bool>,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 nounused: Option<bool>,
82 }
85
86pub fn emit_serialized_unit_graph(
89 root_units: &[Unit],
90 unit_graph: &UnitGraph,
91 gctx: &GlobalContext,
92) -> CargoResult<()> {
93 let mut units: Vec<(&Unit, &Vec<UnitDep>)> = unit_graph.iter().collect();
94 units.sort_unstable();
95 let indices: HashMap<&Unit, usize> = units
97 .iter()
98 .enumerate()
99 .map(|(i, val)| (val.0, i))
100 .collect();
101 let roots = root_units.iter().map(|root| indices[root]).collect();
102 let ser_units = units
103 .iter()
104 .map(|(unit, unit_deps)| {
105 let dependencies = unit_deps
106 .iter()
107 .map(|unit_dep| {
108 let (public, noprelude, nounused) = if gctx.nightly_features_allowed {
110 (
111 Some(unit_dep.public),
112 Some(unit_dep.noprelude),
113 Some(unit_dep.nounused),
114 )
115 } else {
116 (None, None, None)
117 };
118 SerializedUnitDep {
119 index: indices[&unit_dep.unit],
120 extern_crate_name: unit_dep.extern_crate_name,
121 public,
122 noprelude,
123 nounused,
124 }
125 })
126 .collect();
127 SerializedUnit {
128 pkg_id: unit.pkg.package_id().to_spec(),
129 target: &unit.target,
130 profile: &unit.profile,
131 platform: unit.kind,
132 mode: unit.mode,
133 features: &unit.features,
134 is_std: unit.is_std,
135 dependencies,
136 }
137 })
138 .collect();
139
140 gctx.shell().print_json(&SerializedUnitGraph {
141 version: VERSION,
142 units: ser_units,
143 roots,
144 })
145}