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::dependency::Dependency;
12use crate::core::profiles::{Profile, UnitFor};
13use crate::util::CargoResult;
14use crate::util::Unhashed;
15use crate::util::interning::InternedString;
16use std::collections::HashMap;
17
18pub type UnitGraph = HashMap<Unit, Vec<UnitDep>>;
20
21#[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
23pub struct UnitDep {
24 pub unit: Unit,
26 pub unit_for: UnitFor,
29 pub extern_crate_name: InternedString,
31 pub dep_name: Option<InternedString>,
41 pub public: bool,
43 pub noprelude: bool,
45 pub nounused: bool,
47 pub manifest_deps: Unhashed<Option<Vec<Dependency>>>,
51}
52
53const VERSION: u32 = 1;
54
55#[derive(serde::Serialize)]
56struct SerializedUnitGraph<'a> {
57 version: u32,
58 units: Vec<SerializedUnit<'a>>,
59 roots: Vec<usize>,
60}
61
62#[derive(serde::Serialize)]
63struct SerializedUnit<'a> {
64 pkg_id: PackageIdSpec,
65 target: &'a Target,
66 profile: &'a Profile,
67 platform: CompileKind,
68 mode: CompileMode,
69 features: &'a Vec<InternedString>,
70 #[serde(skip_serializing_if = "std::ops::Not::not")] is_std: bool,
72 dependencies: Vec<SerializedUnitDep>,
73}
74
75#[derive(serde::Serialize)]
76struct SerializedUnitDep {
77 index: usize,
78 extern_crate_name: InternedString,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 public: Option<bool>,
82 #[serde(skip_serializing_if = "Option::is_none")]
84 noprelude: Option<bool>,
85 #[serde(skip_serializing_if = "Option::is_none")]
87 nounused: Option<bool>,
88 }
91
92pub fn emit_serialized_unit_graph(
95 root_units: &[Unit],
96 unit_graph: &UnitGraph,
97 gctx: &GlobalContext,
98) -> CargoResult<()> {
99 let mut units: Vec<(&Unit, &Vec<UnitDep>)> = unit_graph.iter().collect();
100 units.sort_unstable();
101 let indices: HashMap<&Unit, usize> = units
103 .iter()
104 .enumerate()
105 .map(|(i, val)| (val.0, i))
106 .collect();
107 let roots = root_units.iter().map(|root| indices[root]).collect();
108 let ser_units = units
109 .iter()
110 .map(|(unit, unit_deps)| {
111 let dependencies = unit_deps
112 .iter()
113 .map(|unit_dep| {
114 let (public, noprelude, nounused) = if gctx.nightly_features_allowed {
116 (
117 Some(unit_dep.public),
118 Some(unit_dep.noprelude),
119 Some(unit_dep.nounused),
120 )
121 } else {
122 (None, None, None)
123 };
124 SerializedUnitDep {
125 index: indices[&unit_dep.unit],
126 extern_crate_name: unit_dep.extern_crate_name,
127 public,
128 noprelude,
129 nounused,
130 }
131 })
132 .collect();
133 SerializedUnit {
134 pkg_id: unit.pkg.package_id().to_spec(),
135 target: &unit.target,
136 profile: &unit.profile,
137 platform: unit.kind,
138 mode: unit.mode,
139 features: &unit.features,
140 is_std: unit.is_std,
141 dependencies,
142 }
143 })
144 .collect();
145
146 gctx.shell().print_json(&SerializedUnitGraph {
147 version: VERSION,
148 units: ser_units,
149 roots,
150 })
151}