Skip to content

Commit 3dcfdef

Browse files
committed
Auto merge of #8068 - ehuss:bcx-units, r=alexcrichton,ehuss
Refactor BuildContext This restructures the "front end" of the compile process so that the `UnitGraph` can be accessed by API users. Essentially, the `BuildContext` contains the result of generating the `UnitGraph`, and other bits of information collected along the way. This logically separates the build process into two phases: (1) generate the `UnitGraph` and `BuildContext` and (2) pass the `BuildContext` to `Context` which performs the actual compilation. The main challenge here is dealing with the references and lifetimes. The old code kept a bunch of things on the stack with various layers of references. Beside reorganizing things, the big change is to wrap `Package` and `Target` in `Rc`. This still requires the `UnitInterner` to be passed in and kept alive. It is possible to avoid that by placing all `Unit`s in `Rc`, but that had a roughly 5% performance hit (on fresh builds) because Units are very optimized to be used as hashable keys, and `Rc` loses those optimizations.
2 parents 8e8c62b + df5cb70 commit 3dcfdef

28 files changed

+831
-860
lines changed

src/bin/cargo/commands/build.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
6565
)?;
6666

6767
if let Some(out_dir) = args.value_of_path("out-dir", config) {
68-
compile_opts.export_dir = Some(out_dir);
68+
compile_opts.build_config.export_dir = Some(out_dir);
6969
} else if let Some(out_dir) = config.build_config()?.out_dir.as_ref() {
7070
let out_dir = out_dir.resolve_path(config);
71-
compile_opts.export_dir = Some(out_dir);
71+
compile_opts.build_config.export_dir = Some(out_dir);
7272
}
73-
if compile_opts.export_dir.is_some() {
73+
if compile_opts.build_config.export_dir.is_some() {
7474
config
7575
.cli_unstable()
7676
.fail_if_stable_opt("--out-dir", 6790)?;

src/cargo/core/compiler/build_config.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::util::ProcessBuilder;
44
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
55
use serde::ser;
66
use std::cell::RefCell;
7+
use std::path::PathBuf;
78

89
/// Configuration information for a rustc build.
910
#[derive(Debug)]
@@ -26,7 +27,15 @@ pub struct BuildConfig {
2627
pub unit_graph: bool,
2728
/// An optional override of the rustc process for primary units
2829
pub primary_unit_rustc: Option<ProcessBuilder>,
30+
/// A thread used by `cargo fix` to receive messages on a socket regarding
31+
/// the success/failure of applying fixes.
2932
pub rustfix_diagnostic_server: RefCell<Option<RustfixDiagnosticServer>>,
33+
/// The directory to copy final artifacts to. Note that even if `out_dir` is
34+
/// set, a copy of artifacts still could be found a `target/(debug\release)`
35+
/// as usual.
36+
// Note that, although the cmd-line flag name is `out-dir`, in code we use
37+
// `export_dir`, to avoid confusion with out dir at `target/debug/deps`.
38+
pub export_dir: Option<PathBuf>,
3039
}
3140

3241
impl BuildConfig {
@@ -70,6 +79,7 @@ impl BuildConfig {
7079
unit_graph: false,
7180
primary_unit_rustc: None,
7281
rustfix_diagnostic_server: RefCell::new(None),
82+
export_dir: None,
7383
})
7484
}
7585

src/cargo/core/compiler/build_context/mod.rs

+20-29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::core::compiler::unit::UnitInterner;
2-
use crate::core::compiler::{BuildConfig, BuildOutput, CompileKind, Unit};
1+
use crate::core::compiler::unit_graph::UnitGraph;
2+
use crate::core::compiler::{BuildConfig, CompileKind, Unit};
33
use crate::core::profiles::Profiles;
44
use crate::core::{InternedString, Workspace};
55
use crate::core::{PackageId, PackageSet};
@@ -8,7 +8,6 @@ use crate::util::errors::CargoResult;
88
use crate::util::Rustc;
99
use std::collections::HashMap;
1010
use std::path::PathBuf;
11-
use std::str;
1211

1312
mod target_info;
1413
pub use self::target_info::{FileFlavor, RustcTargetData, TargetInfo};
@@ -27,37 +26,40 @@ pub struct BuildContext<'a, 'cfg> {
2726
pub profiles: Profiles,
2827
pub build_config: &'a BuildConfig,
2928
/// Extra compiler args for either `rustc` or `rustdoc`.
30-
pub extra_compiler_args: HashMap<Unit<'a>, Vec<String>>,
29+
pub extra_compiler_args: HashMap<Unit, Vec<String>>,
3130
/// Package downloader.
32-
pub packages: &'a PackageSet<'cfg>,
33-
34-
/// Source of interning new units as they're created.
35-
pub units: &'a UnitInterner<'a>,
36-
31+
///
32+
/// This holds ownership of the `Package` objects.
33+
pub packages: PackageSet<'cfg>,
3734
/// Information about rustc and the target platform.
3835
pub target_data: RustcTargetData,
36+
/// The root units of `unit_graph` (units requested on the command-line).
37+
pub roots: Vec<Unit>,
38+
/// The dependency graph of units to compile.
39+
pub unit_graph: UnitGraph,
3940
}
4041

4142
impl<'a, 'cfg> BuildContext<'a, 'cfg> {
4243
pub fn new(
4344
ws: &'a Workspace<'cfg>,
44-
packages: &'a PackageSet<'cfg>,
45-
config: &'cfg Config,
45+
packages: PackageSet<'cfg>,
4646
build_config: &'a BuildConfig,
4747
profiles: Profiles,
48-
units: &'a UnitInterner<'a>,
49-
extra_compiler_args: HashMap<Unit<'a>, Vec<String>>,
48+
extra_compiler_args: HashMap<Unit, Vec<String>>,
5049
target_data: RustcTargetData,
50+
roots: Vec<Unit>,
51+
unit_graph: UnitGraph,
5152
) -> CargoResult<BuildContext<'a, 'cfg>> {
5253
Ok(BuildContext {
5354
ws,
55+
config: ws.config(),
5456
packages,
55-
config,
5657
build_config,
5758
profiles,
5859
extra_compiler_args,
59-
units,
6060
target_data,
61+
roots,
62+
unit_graph,
6163
})
6264
}
6365

@@ -89,30 +91,19 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
8991
self.build_config.jobs
9092
}
9193

92-
pub fn rustflags_args(&self, unit: &Unit<'_>) -> &[String] {
94+
pub fn rustflags_args(&self, unit: &Unit) -> &[String] {
9395
&self.target_data.info(unit.kind).rustflags
9496
}
9597

96-
pub fn rustdocflags_args(&self, unit: &Unit<'_>) -> &[String] {
98+
pub fn rustdocflags_args(&self, unit: &Unit) -> &[String] {
9799
&self.target_data.info(unit.kind).rustdocflags
98100
}
99101

100102
pub fn show_warnings(&self, pkg: PackageId) -> bool {
101103
pkg.source_id().is_path() || self.config.extra_verbose()
102104
}
103105

104-
pub fn extra_args_for(&self, unit: &Unit<'a>) -> Option<&Vec<String>> {
106+
pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec<String>> {
105107
self.extra_compiler_args.get(unit)
106108
}
107-
108-
/// If a build script is overridden, this returns the `BuildOutput` to use.
109-
///
110-
/// `lib_name` is the `links` library name and `kind` is whether it is for
111-
/// Host or Target.
112-
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
113-
self.target_data
114-
.target_config(kind)
115-
.links_overrides
116-
.get(lib_name)
117-
}
118109
}

src/cargo/core/compiler/build_context/target_info.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use crate::core::compiler::CompileKind;
2-
use crate::core::compiler::CompileTarget;
1+
use crate::core::compiler::{BuildOutput, CompileKind, CompileTarget};
32
use crate::core::{Dependency, TargetKind, Workspace};
43
use crate::util::config::{Config, StringList, TargetConfig};
54
use crate::util::{CargoResult, CargoResultExt, ProcessBuilder, Rustc};
@@ -583,4 +582,12 @@ impl RustcTargetData {
583582
CompileKind::Target(s) => &self.target_config[&s],
584583
}
585584
}
585+
586+
/// If a build script is overridden, this returns the `BuildOutput` to use.
587+
///
588+
/// `lib_name` is the `links` library name and `kind` is whether it is for
589+
/// Host or Target.
590+
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
591+
self.target_config(kind).links_overrides.get(lib_name)
592+
}
586593
}

src/cargo/core/compiler/build_plan.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ struct SerializedBuildPlan {
4545
}
4646

4747
impl Invocation {
48-
pub fn new(unit: &Unit<'_>, deps: Vec<usize>) -> Invocation {
48+
pub fn new(unit: &Unit, deps: Vec<usize>) -> Invocation {
4949
let id = unit.pkg.package_id();
5050
Invocation {
5151
package_name: id.name().to_string(),
@@ -109,7 +109,7 @@ impl BuildPlan {
109109
}
110110
}
111111

112-
pub fn add<'a>(&mut self, cx: &Context<'a, '_>, unit: &Unit<'a>) -> CargoResult<()> {
112+
pub fn add(&mut self, cx: &Context<'_, '_>, unit: &Unit) -> CargoResult<()> {
113113
let id = self.plan.invocations.len();
114114
self.invocation_map.insert(unit.buildkey(), id);
115115
let deps = cx

src/cargo/core/compiler/compilation.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ pub struct Compilation<'cfg> {
8686
}
8787

8888
impl<'cfg> Compilation<'cfg> {
89-
pub fn new<'a>(
90-
bcx: &BuildContext<'a, 'cfg>,
91-
default_kind: CompileKind,
92-
) -> CargoResult<Compilation<'cfg>> {
89+
pub fn new<'a>(bcx: &BuildContext<'a, 'cfg>) -> CargoResult<Compilation<'cfg>> {
9390
let mut rustc = bcx.rustc().process();
9491
let mut primary_rustc_process = bcx.build_config.primary_unit_rustc.clone();
9592
let mut rustc_workspace_wrapper_process = bcx.rustc().workspace_process();
@@ -103,6 +100,7 @@ impl<'cfg> Compilation<'cfg> {
103100
}
104101
}
105102

103+
let default_kind = bcx.build_config.requested_kind;
106104
Ok(Compilation {
107105
// TODO: deprecated; remove.
108106
native_dirs: BTreeSet::new(),

0 commit comments

Comments
 (0)