diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 624a6e88ae6..a32b6db3956 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -1,3 +1,5 @@ +//! [`BuildContext`] is a (mostly) static information about a build task. + use crate::core::compiler::unit_graph::UnitGraph; use crate::core::compiler::{BuildConfig, CompileKind, Unit}; use crate::core::profiles::Profiles; @@ -15,19 +17,42 @@ pub use self::target_info::{ FileFlavor, FileType, RustDocFingerprint, RustcTargetData, TargetInfo, }; -/// The build context, containing all information about a build task. +/// The build context, containing complete infomration needed for a build task +/// before it gets started. /// /// It is intended that this is mostly static information. Stuff that mutates -/// during the build can be found in the parent `Context`. (I say mostly, +/// during the build can be found in the parent [`Context`]. (I say mostly, /// because this has internal caching, but nothing that should be observable /// or require &mut.) +/// +/// As a result, almost every field on `BuildContext` is public, including +/// +/// * a resolved [`UnitGraph`] of your dependencies, +/// * a [`Profiles`] containing compiler flags presets, +/// * a [`RustcTargetData`] containing host and target platform information, +/// * and a [`PackageSet`] for further package downloads, +/// +/// just to name a few. Learn more on each own documentation. +/// +/// # How to use +/// +/// To prepare a build task, you may not want to use [`BuildContext::new`] directly, +/// since it is often too lower-level. +/// Instead, [`ops::create_bcx`] is usually what you are looking for. +/// +/// [`Context`]: crate::core::compiler::Context +/// [`ops::create_bcx`]: crate::ops::create_bcx pub struct BuildContext<'a, 'cfg> { /// The workspace the build is for. pub ws: &'a Workspace<'cfg>, /// The cargo configuration. pub config: &'cfg Config, + + /// This contains a collection of compiler flags presets. pub profiles: Profiles, + + /// Configuration information for a rustc build. pub build_config: &'a BuildConfig, /// Extra compiler args for either `rustc` or `rustdoc`. @@ -47,7 +72,7 @@ pub struct BuildContext<'a, 'cfg> { /// The dependency graph of units to compile. pub unit_graph: UnitGraph, - /// Reverse-dependencies of documented units, used by the rustdoc --scrape-examples flag. + /// Reverse-dependencies of documented units, used by the `rustdoc --scrape-examples` flag. pub scrape_units: Vec<Unit>, /// The list of all kinds that are involved in this build @@ -88,6 +113,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { }) } + /// Information of the `rustc` this build task will use. pub fn rustc(&self) -> &Rustc { &self.target_data.rustc } @@ -116,14 +142,36 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { self.build_config.jobs } + /// Extra compiler flags to pass to `rustc` for a given unit. + /// + /// Although it depends on the caller, in the current Cargo implementation, + /// these flags take precendence over those from [`BuildContext::extra_args_for`]. + /// + /// As of now, these flags come from environment variables and configurations. + /// See [`TargetInfo.rustflags`] for more on how Cargo collects them. + /// + /// [`TargetInfo.rustflags`]: TargetInfo::rustflags pub fn rustflags_args(&self, unit: &Unit) -> &[String] { &self.target_data.info(unit.kind).rustflags } + /// Extra compiler flags to pass to `rustdoc` for a given unit. + /// + /// Although it depends on the caller, in the current Cargo implementation, + /// these flags take precendence over those from [`BuildContext::extra_args_for`]. + /// + /// As of now, these flags come from environment variables and configurations. + /// See [`TargetInfo.rustdocflags`] for more on how Cargo collects them. + /// + /// [`TargetInfo.rustdocflags`]: TargetInfo::rustdocflags pub fn rustdocflags_args(&self, unit: &Unit) -> &[String] { &self.target_data.info(unit.kind).rustdocflags } + /// Extra compiler args for either `rustc` or `rustdoc`. + /// + /// As of now, these flags come from the trailing args of either + /// `cargo rustc` or `cargo rustdoc`. pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec<String>> { self.extra_compiler_args.get(unit) } diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index d37b1b9614d..a8561278e58 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -1,3 +1,12 @@ +//! This modules contains types storing information of target platfroms. +//! +//! Normally, call [`RustcTargetData::new`] to construct all the target +//! platform once, and then query info on your demand. For example, +//! +//! * [`RustcTargetData::dep_platform_activated`] to check if platform is activated. +//! * [`RustcTargetData::info`] to get a [`TargetInfo`] for an in-depth query. +//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types. + use crate::core::compiler::{ BuildOutput, CompileKind, CompileMode, CompileTarget, Context, CrateType, }; @@ -16,8 +25,9 @@ use std::str::{self, FromStr}; /// Information about the platform target gleaned from querying rustc. /// -/// `RustcTargetData` keeps two of these, one for the host and one for the -/// target. If no target is specified, it uses a clone from the host. +/// [`RustcTargetData`] keeps several of these, one for the host and the others +/// for other specified targets. If no target is specified, it uses a clone from +/// the host. #[derive(Clone)] pub struct TargetInfo { /// A base process builder for discovering crate type information. In @@ -41,9 +51,9 @@ pub struct TargetInfo { /// Path to the "lib" directory in the sysroot which rustc uses for linking /// target libraries. pub sysroot_target_libdir: PathBuf, - /// Extra flags to pass to `rustc`, see `env_args`. + /// Extra flags to pass to `rustc`, see [`extra_args`]. pub rustflags: Vec<String>, - /// Extra flags to pass to `rustdoc`, see `env_args`. + /// Extra flags to pass to `rustdoc`, see [`extra_args`]. pub rustdocflags: Vec<String>, /// Whether or not rustc supports the `-Csplit-debuginfo` flag. pub supports_split_debuginfo: bool, @@ -132,13 +142,20 @@ impl FileType { } impl TargetInfo { + /// Learns the information of target platform from `rustc` invocation(s). + /// + /// Generally, the first time calling this function is expensive, as it may + /// query `rustc` several times. To reduce the cost, output of each `rustc` + /// invocation is cached by [`Rustc::cached_output`]. + /// + /// Search `Tricky` to learn why querying `rustc` several times is needed. pub fn new( config: &Config, requested_kinds: &[CompileKind], rustc: &Rustc, kind: CompileKind, ) -> CargoResult<TargetInfo> { - let mut rustflags = env_args( + let mut rustflags = extra_args( config, requested_kinds, &rustc.host, @@ -149,6 +166,13 @@ impl TargetInfo { let mut turn = 0; loop { let extra_fingerprint = kind.fingerprint_hash(); + + // Query rustc for several kinds of info from each line of output: + // 0) file-names (to determine output file prefix/suffix for given crate type) + // 1) sysroot + // 2) cfg + // + // Search `--print` to see what we query so far. let mut process = rustc.workspace_process(); process .arg("-") @@ -174,6 +198,8 @@ impl TargetInfo { for crate_type in KNOWN_CRATE_TYPES.iter() { process.arg("--crate-type").arg(crate_type.as_str()); } + + // An extra `rustc` call to determine `-Csplit-debuginfo=packed` support. let supports_split_debuginfo = rustc .cached_output( process.clone().arg("-Csplit-debuginfo=packed"), @@ -233,7 +259,7 @@ impl TargetInfo { // recalculate `rustflags` from above now that we have `cfg` // information - let new_flags = env_args( + let new_flags = extra_args( config, requested_kinds, &rustc.host, @@ -268,7 +294,7 @@ impl TargetInfo { sysroot_host_libdir, sysroot_target_libdir, rustflags, - rustdocflags: env_args( + rustdocflags: extra_args( config, requested_kinds, &rustc.host, @@ -294,7 +320,7 @@ impl TargetInfo { true } - /// All the target `cfg` settings. + /// All the target [`Cfg`] settings. pub fn cfg(&self) -> &[Cfg] { &self.cfg } @@ -580,6 +606,7 @@ fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String { result } +/// Compiler flags for either rustc or rustdoc. #[derive(Debug, Copy, Clone)] enum Flags { Rust, @@ -614,6 +641,7 @@ impl Flags { /// - `target.*.rustflags` from the config (.cargo/config) /// - `target.cfg(..).rustflags` from the config /// - `host.*.rustflags` from the config if compiling a host artifact or without `--target` +/// (requires `-Zhost-config`) /// /// then if none of those were found /// @@ -624,7 +652,7 @@ impl Flags { /// For those artifacts, _only_ `host.*.rustflags` is respected, and no other configuration /// sources, _regardless of the value of `target-applies-to-host`_. This is counterintuitive, but /// necessary to retain backwards compatibility with older versions of Cargo. -fn env_args( +fn extra_args( config: &Config, requested_kinds: &[CompileKind], host_triple: &str, @@ -669,6 +697,8 @@ fn env_args( } } +/// Gets compiler flags from environment variables. +/// See [`extra_args`] for more. fn rustflags_from_env(flags: Flags) -> Option<Vec<String>> { // First try CARGO_ENCODED_RUSTFLAGS from the environment. // Prefer this over RUSTFLAGS since it's less prone to encoding errors. @@ -693,6 +723,8 @@ fn rustflags_from_env(flags: Flags) -> Option<Vec<String>> { None } +/// Gets compiler flags from `[target]` section in the config. +/// See [`extra_args`] for more. fn rustflags_from_target( config: &Config, host_triple: &str, @@ -734,6 +766,8 @@ fn rustflags_from_target( } } +/// Gets compiler flags from `[host]` section in the config. +/// See [`extra_args`] for more. fn rustflags_from_host( config: &Config, flag: Flags, @@ -750,6 +784,8 @@ fn rustflags_from_host( Ok(list.as_ref().map(|l| l.val.as_slice().to_vec())) } +/// Gets compiler flags from `[build]` section in the config. +/// See [`extra_args`] for more. fn rustflags_from_build(config: &Config, flag: Flags) -> CargoResult<Option<Vec<String>>> { // Then the `build.rustflags` value. let build = config.build_config()?; @@ -773,11 +809,12 @@ pub struct RustcTargetData<'cfg> { /// `rustc` is invoked without a `--target` flag. This is used for /// procedural macros, build scripts, etc. host_config: TargetConfig, + /// Information about the host platform. host_info: TargetInfo, - /// Build information for targets that we're building for. This will be - /// empty if the `--target` flag is not passed. + /// Build information for targets that we're building for. target_config: HashMap<CompileTarget, TargetConfig>, + /// Information about the target platform that we're building for. target_info: HashMap<CompileTarget, TargetInfo>, }