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