Skip to content

Commit

Permalink
Auto merge of #11241 - weihanglo:doc/build_context, r=epage
Browse files Browse the repository at this point in the history
Polish docs for module `build_context`
  • Loading branch information
bors committed Oct 17, 2022
2 parents 76293b3 + d86d3bf commit e008032
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 14 deletions.
54 changes: 51 additions & 3 deletions src/cargo/core/compiler/build_context/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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`.
Expand All @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand Down
59 changes: 48 additions & 11 deletions src/cargo/core/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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("-")
Expand All @@ -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"),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -268,7 +294,7 @@ impl TargetInfo {
sysroot_host_libdir,
sysroot_target_libdir,
rustflags,
rustdocflags: env_args(
rustdocflags: extra_args(
config,
requested_kinds,
&rustc.host,
Expand All @@ -294,7 +320,7 @@ impl TargetInfo {
true
}

/// All the target `cfg` settings.
/// All the target [`Cfg`] settings.
pub fn cfg(&self) -> &[Cfg] {
&self.cfg
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
///
Expand All @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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()?;
Expand All @@ -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>,
}

Expand Down

0 comments on commit e008032

Please sign in to comment.