cargo/compiler/build_context/mod.rs
1//! [`BuildContext`] is a (mostly) static information about a build task.
2
3use std::path::Path;
4
5use crate::compiler::BuildConfig;
6use crate::compiler::CompileKind;
7use crate::compiler::Unit;
8use crate::compiler::UnitIndex;
9use crate::compiler::unit_graph::UnitGraph;
10use crate::context::GlobalContext;
11use crate::util::Rustc;
12use crate::util::data_structures::{HashMap, HashSet};
13use crate::util::errors::CargoResult;
14use crate::util::interning::InternedString;
15use crate::util::logger::BuildLogger;
16use crate::workspace::PackageSet;
17use crate::workspace::Workspace;
18use crate::workspace::dependency::DepKind;
19use crate::workspace::profiles::Profiles;
20
21mod target_info;
22pub use self::target_info::FileFlavor;
23pub use self::target_info::FileType;
24pub use self::target_info::RustcTargetData;
25pub use self::target_info::TargetInfo;
26
27/// The build context, containing complete information needed for a build task
28/// before it gets started.
29///
30/// It is intended that this is mostly static information. Stuff that mutates
31/// during the build can be found in the parent [`BuildRunner`]. (I say mostly,
32/// because this has internal caching, but nothing that should be observable
33/// or require &mut.)
34///
35/// As a result, almost every field on `BuildContext` is public, including
36///
37/// * a resolved [`UnitGraph`] of your dependencies,
38/// * a [`Profiles`] containing compiler flags presets,
39/// * a [`RustcTargetData`] containing host and target platform information,
40/// * and a [`PackageSet`] for further package downloads,
41///
42/// just to name a few. Learn more on each own documentation.
43///
44/// # How to use
45///
46/// To prepare a build task, you may not want to use [`BuildContext::new`] directly,
47/// since it is often too lower-level.
48/// Instead, [`ops::create_bcx`] is usually what you are looking for.
49///
50/// After a `BuildContext` is built, the next stage of building is handled in [`BuildRunner`].
51///
52/// [`BuildRunner`]: crate::compiler::BuildRunner
53/// [`ops::create_bcx`]: crate::ops::create_bcx
54pub struct BuildContext<'a, 'gctx> {
55 /// The workspace the build is for.
56 pub ws: &'a Workspace<'gctx>,
57
58 /// The cargo context.
59 pub gctx: &'gctx GlobalContext,
60
61 /// Build logger for `-Zbuild-analysis`.
62 pub logger: Option<&'a BuildLogger>,
63
64 /// This contains a collection of compiler flags presets.
65 pub profiles: Profiles,
66
67 /// Configuration information for a rustc build.
68 pub build_config: &'a BuildConfig,
69
70 /// Associated [`DepKind`]s for root targets
71 pub selected_dep_kinds: DepKindSet,
72
73 /// Extra compiler args for either `rustc` or `rustdoc`.
74 pub extra_compiler_args: HashMap<Unit, Vec<String>>,
75
76 /// Package downloader.
77 ///
78 /// This holds ownership of the `Package` objects.
79 pub packages: PackageSet<'gctx>,
80
81 /// Information about rustc and the target platform.
82 pub target_data: RustcTargetData<'gctx>,
83
84 /// The root units of `unit_graph` (units requested on the command-line).
85 pub roots: Vec<Unit>,
86
87 /// The dependency graph of units to compile.
88 pub unit_graph: UnitGraph,
89
90 /// A map from unit to index.
91 pub unit_to_index: HashMap<Unit, UnitIndex>,
92
93 /// Reverse-dependencies of documented units, used by the `rustdoc --scrape-examples` flag.
94 pub scrape_units: Vec<Unit>,
95
96 /// The list of all kinds that are involved in this build
97 pub all_kinds: HashSet<CompileKind>,
98}
99
100impl<'a, 'gctx> BuildContext<'a, 'gctx> {
101 pub fn new(
102 ws: &'a Workspace<'gctx>,
103 logger: Option<&'a BuildLogger>,
104 packages: PackageSet<'gctx>,
105 build_config: &'a BuildConfig,
106 selected_dep_kinds: DepKindSet,
107 profiles: Profiles,
108 extra_compiler_args: HashMap<Unit, Vec<String>>,
109 target_data: RustcTargetData<'gctx>,
110 roots: Vec<Unit>,
111 unit_graph: UnitGraph,
112 unit_to_index: HashMap<Unit, UnitIndex>,
113 scrape_units: Vec<Unit>,
114 ) -> CargoResult<BuildContext<'a, 'gctx>> {
115 let all_kinds = unit_graph
116 .keys()
117 .map(|u| u.kind)
118 .chain(build_config.requested_kinds.iter().copied())
119 .chain(std::iter::once(CompileKind::Host))
120 .collect();
121
122 Ok(BuildContext {
123 ws,
124 gctx: ws.gctx(),
125 logger,
126 packages,
127 build_config,
128 selected_dep_kinds,
129 profiles,
130 extra_compiler_args,
131 target_data,
132 roots,
133 unit_graph,
134 unit_to_index,
135 scrape_units,
136 all_kinds,
137 })
138 }
139
140 /// Information of the `rustc` this build task will use.
141 pub fn rustc(&self) -> &Rustc {
142 &self.target_data.rustc
143 }
144
145 /// Gets the host architecture triple.
146 ///
147 /// For example, `x86_64-unknown-linux-gnu`, would be
148 /// - machine: `x86_64`,
149 /// - hardware-platform: `unknown`,
150 /// - operating system: `linux-gnu`.
151 pub fn host_triple(&self) -> InternedString {
152 self.target_data.rustc.host
153 }
154
155 /// Gets the number of jobs specified for this build.
156 pub fn jobs(&self) -> u32 {
157 self.build_config.jobs
158 }
159
160 /// Extra compiler args for either `rustc` or `rustdoc`.
161 ///
162 /// As of now, these flags come from the trailing args of either
163 /// `cargo rustc` or `cargo rustdoc`.
164 pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec<String>> {
165 self.extra_compiler_args.get(unit)
166 }
167
168 /// Gets the path to the sysroot.
169 ///
170 /// Helper function that uses GlobalContext.
171 pub fn get_sysroot(&self) -> &'gctx Path {
172 // cfg::bad_cfg_discovery tests that these panics aren't reachable
173 let rustc = self
174 .gctx
175 .load_global_rustc(Some(self.ws))
176 .expect("rustc load ok");
177 self.gctx.get_sysroot(&rustc).expect("sysroot fetch ok")
178 }
179}
180
181#[derive(Copy, Clone, Default, Debug)]
182pub struct DepKindSet {
183 pub build: bool,
184 pub normal: bool,
185 pub dev: bool,
186}
187
188impl DepKindSet {
189 pub fn contains(&self, kind: DepKind) -> bool {
190 match kind {
191 DepKind::Build => self.build,
192 DepKind::Normal => self.normal,
193 DepKind::Development => self.dev,
194 }
195 }
196}