Skip to main content

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}