Skip to main content

cargo/core/compiler/build_context/
mod.rs

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