Skip to content

Commit 36160ed

Browse files
author
Alex Helfet
committed
Merge remote-tracking branch 'origin/master' into first-update-precise
2 parents f1f8f60 + ceb1389 commit 36160ed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1617
-832
lines changed

ARCHITECTURE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,16 @@ to nightly rustc).
132132
## Logging
133133

134134
Cargo uses [`env_logger`], so you can set
135-
`RUST_LOG` environment variable to get the logs. This is useful both for diagnosing
135+
`CARGO_LOG` environment variable to get the logs. This is useful both for diagnosing
136136
bugs in stable Cargo and for local development. Cargo also has internal hierarchical
137137
profiling infrastructure, which is activated via `CARGO_PROFILE` variable
138138

139139
```
140140
# Outputs all logs with levels debug and higher
141-
$ RUST_LOG=debug cargo generate-lockfile
141+
$ CARGO_LOG=debug cargo generate-lockfile
142142
143143
# Don't forget that you can filter by module as well
144-
$ RUST_LOG=cargo::core::resolver=trace cargo generate-lockfile
144+
$ CARGO_LOG=cargo::core::resolver=trace cargo generate-lockfile
145145
146146
# Output first three levels of profiling info
147147
$ CARGO_PROFILE=3 cargo generate-lockfile

src/bin/cargo/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ use crate::command_prelude::*;
2020

2121
fn main() {
2222
#[cfg(feature = "pretty-env-logger")]
23-
pretty_env_logger::init();
23+
pretty_env_logger::init_custom_env("CARGO_LOG");
2424
#[cfg(not(feature = "pretty-env-logger"))]
25-
env_logger::init();
25+
env_logger::init_from_env("CARGO_LOG");
2626
cargo::core::maybe_allow_nightly_features();
2727

2828
let mut config = match Config::default() {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ pub struct TargetInfo {
2020
}
2121

2222
/// Type of each file generated by a Unit.
23-
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
23+
#[derive(Clone, PartialEq, Eq, Debug)]
2424
pub enum FileFlavor {
2525
/// Not a special file type.
2626
Normal,
2727
/// Something you can link against (e.g., a library).
28-
Linkable,
28+
Linkable { rmeta: bool },
2929
/// Piece of external debug information (e.g., `.dSYM`/`.pdb` file).
3030
DebugInfo,
3131
}
@@ -75,7 +75,7 @@ impl TargetInfo {
7575
.arg("___")
7676
.arg("--print=file-names")
7777
.args(&rustflags)
78-
.env_remove("RUST_LOG");
78+
.env_remove("RUSTC_LOG");
7979

8080
let target_triple = requested_target
8181
.as_ref()

src/cargo/core/compiler/context/compilation_files.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
308308
path,
309309
hardlink: None,
310310
export_path: None,
311-
flavor: FileFlavor::Linkable,
311+
flavor: FileFlavor::Linkable { rmeta: false },
312312
});
313313
} else {
314314
let mut add = |crate_type: &str, flavor: FileFlavor| -> CargoResult<()> {
@@ -372,12 +372,21 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
372372
add(
373373
kind.crate_type(),
374374
if kind.linkable() {
375-
FileFlavor::Linkable
375+
FileFlavor::Linkable { rmeta: false }
376376
} else {
377377
FileFlavor::Normal
378378
},
379379
)?;
380380
}
381+
let path = out_dir.join(format!("lib{}.rmeta", file_stem));
382+
if !unit.target.requires_upstream_objects() {
383+
ret.push(OutputFile {
384+
path,
385+
hardlink: None,
386+
export_path: None,
387+
flavor: FileFlavor::Linkable { rmeta: true },
388+
});
389+
}
381390
}
382391
}
383392
}

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

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ pub struct Context<'a, 'cfg: 'a> {
4242
unit_dependencies: HashMap<Unit<'a>, Vec<Unit<'a>>>,
4343
files: Option<CompilationFiles<'a, 'cfg>>,
4444
package_cache: HashMap<PackageId, &'a Package>,
45+
46+
/// A flag indicating whether pipelining is enabled for this compilation
47+
/// session. Pipelining largely only affects the edges of the dependency
48+
/// graph that we generate at the end, and otherwise it's pretty
49+
/// straightforward.
50+
pipelining: bool,
51+
52+
/// A set of units which are compiling rlibs and are expected to produce
53+
/// metadata files in addition to the rlib itself. This is only filled in
54+
/// when `pipelining` above is enabled.
55+
rmeta_required: HashSet<Unit<'a>>,
4556
}
4657

4758
impl<'a, 'cfg> Context<'a, 'cfg> {
@@ -60,6 +71,12 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
6071
.chain_err(|| "failed to create jobserver")?,
6172
};
6273

74+
let pipelining = bcx
75+
.config
76+
.get_bool("build.pipelining")?
77+
.map(|t| t.val)
78+
.unwrap_or(false);
79+
6380
Ok(Self {
6481
bcx,
6582
compilation: Compilation::new(bcx)?,
@@ -76,6 +93,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
7693
unit_dependencies: HashMap::new(),
7794
files: None,
7895
package_cache: HashMap::new(),
96+
rmeta_required: HashSet::new(),
97+
pipelining,
7998
})
8099
}
81100

@@ -261,12 +280,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
261280
self.primary_packages
262281
.extend(units.iter().map(|u| u.pkg.package_id()));
263282

264-
build_unit_dependencies(
265-
units,
266-
self.bcx,
267-
&mut self.unit_dependencies,
268-
&mut self.package_cache,
269-
)?;
283+
build_unit_dependencies(self, units)?;
270284
let files = CompilationFiles::new(
271285
units,
272286
host_layout,
@@ -453,6 +467,27 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
453467
}
454468
Ok(())
455469
}
470+
471+
/// Returns whether when `parent` depends on `dep` if it only requires the
472+
/// metadata file from `dep`.
473+
pub fn only_requires_rmeta(&self, parent: &Unit<'a>, dep: &Unit<'a>) -> bool {
474+
// this is only enabled when pipelining is enabled
475+
self.pipelining
476+
// We're only a candidate for requiring an `rmeta` file if we
477+
// ourselves are building an rlib,
478+
&& !parent.target.requires_upstream_objects()
479+
&& parent.mode == CompileMode::Build
480+
// Our dependency must also be built as an rlib, otherwise the
481+
// object code must be useful in some fashion
482+
&& !dep.target.requires_upstream_objects()
483+
&& dep.mode == CompileMode::Build
484+
}
485+
486+
/// Returns whether when `unit` is built whether it should emit metadata as
487+
/// well because some compilations rely on that.
488+
pub fn rmeta_required(&self, unit: &Unit<'a>) -> bool {
489+
self.rmeta_required.contains(unit)
490+
}
456491
}
457492

458493
#[derive(Default)]

src/cargo/core/compiler/context/unit_dependencies.rs

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,35 @@
1515
//! (for example, with and without tests), so we actually build a dependency
1616
//! graph of `Unit`s, which capture these properties.
1717
18-
use std::cell::RefCell;
19-
use std::collections::{HashMap, HashSet};
20-
21-
use log::trace;
22-
23-
use super::{BuildContext, CompileMode, Kind};
2418
use crate::core::compiler::Unit;
19+
use crate::core::compiler::{BuildContext, CompileMode, Context, Kind};
2520
use crate::core::dependency::Kind as DepKind;
2621
use crate::core::package::Downloads;
2722
use crate::core::profiles::UnitFor;
2823
use crate::core::{Package, PackageId, Target};
2924
use crate::CargoResult;
25+
use log::trace;
26+
use std::collections::{HashMap, HashSet};
3027

3128
struct State<'a: 'tmp, 'cfg: 'a, 'tmp> {
32-
bcx: &'tmp BuildContext<'a, 'cfg>,
33-
deps: &'tmp mut HashMap<Unit<'a>, Vec<Unit<'a>>>,
34-
pkgs: RefCell<&'tmp mut HashMap<PackageId, &'a Package>>,
29+
cx: &'tmp mut Context<'a, 'cfg>,
3530
waiting_on_download: HashSet<PackageId>,
3631
downloads: Downloads<'a, 'cfg>,
3732
}
3833

3934
pub fn build_unit_dependencies<'a, 'cfg>(
35+
cx: &mut Context<'a, 'cfg>,
4036
roots: &[Unit<'a>],
41-
bcx: &BuildContext<'a, 'cfg>,
42-
deps: &mut HashMap<Unit<'a>, Vec<Unit<'a>>>,
43-
pkgs: &mut HashMap<PackageId, &'a Package>,
4437
) -> CargoResult<()> {
45-
assert!(deps.is_empty(), "can only build unit deps once");
38+
assert!(
39+
cx.unit_dependencies.is_empty(),
40+
"can only build unit deps once"
41+
);
4642

4743
let mut state = State {
48-
bcx,
49-
deps,
50-
pkgs: RefCell::new(pkgs),
44+
downloads: cx.bcx.packages.enable_download()?,
45+
cx,
5146
waiting_on_download: HashSet::new(),
52-
downloads: bcx.packages.enable_download()?,
5347
};
5448

5549
loop {
@@ -62,7 +56,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
6256
// cleared, and avoid building the lib thrice (once with `panic`, once
6357
// without, once for `--test`). In particular, the lib included for
6458
// Doc tests and examples are `Build` mode here.
65-
let unit_for = if unit.mode.is_any_test() || bcx.build_config.test() {
59+
let unit_for = if unit.mode.is_any_test() || state.cx.bcx.build_config.test() {
6660
UnitFor::new_test()
6761
} else if unit.target.is_custom_build() {
6862
// This normally doesn't happen, except `clean` aggressively
@@ -79,20 +73,23 @@ pub fn build_unit_dependencies<'a, 'cfg>(
7973

8074
if !state.waiting_on_download.is_empty() {
8175
state.finish_some_downloads()?;
82-
state.deps.clear();
76+
state.cx.unit_dependencies.clear();
8377
} else {
8478
break;
8579
}
8680
}
87-
trace!("ALL UNIT DEPENDENCIES {:#?}", state.deps);
8881

8982
connect_run_custom_build_deps(&mut state);
9083

84+
trace!("ALL UNIT DEPENDENCIES {:#?}", state.cx.unit_dependencies);
85+
86+
record_units_requiring_metadata(state.cx);
87+
9188
// Dependencies are used in tons of places throughout the backend, many of
9289
// which affect the determinism of the build itself. As a result be sure
9390
// that dependency lists are always sorted to ensure we've always got a
9491
// deterministic output.
95-
for list in state.deps.values_mut() {
92+
for list in state.cx.unit_dependencies.values_mut() {
9693
list.sort();
9794
}
9895

@@ -104,16 +101,16 @@ fn deps_of<'a, 'cfg, 'tmp>(
104101
state: &mut State<'a, 'cfg, 'tmp>,
105102
unit_for: UnitFor,
106103
) -> CargoResult<()> {
107-
// Currently the `deps` map does not include `unit_for`. This should
104+
// Currently the `unit_dependencies` map does not include `unit_for`. This should
108105
// be safe for now. `TestDependency` only exists to clear the `panic`
109106
// flag, and you'll never ask for a `unit` with `panic` set as a
110107
// `TestDependency`. `CustomBuild` should also be fine since if the
111108
// requested unit's settings are the same as `Any`, `CustomBuild` can't
112109
// affect anything else in the hierarchy.
113-
if !state.deps.contains_key(unit) {
110+
if !state.cx.unit_dependencies.contains_key(unit) {
114111
let unit_deps = compute_deps(unit, state, unit_for)?;
115112
let to_insert: Vec<_> = unit_deps.iter().map(|&(unit, _)| unit).collect();
116-
state.deps.insert(*unit, to_insert);
113+
state.cx.unit_dependencies.insert(*unit, to_insert);
117114
for (unit, unit_for) in unit_deps {
118115
deps_of(&unit, state, unit_for)?;
119116
}
@@ -131,13 +128,13 @@ fn compute_deps<'a, 'cfg, 'tmp>(
131128
unit_for: UnitFor,
132129
) -> CargoResult<Vec<(Unit<'a>, UnitFor)>> {
133130
if unit.mode.is_run_custom_build() {
134-
return compute_deps_custom_build(unit, state.bcx);
131+
return compute_deps_custom_build(unit, state.cx.bcx);
135132
} else if unit.mode.is_doc() && !unit.mode.is_any_test() {
136133
// Note: this does not include doc test.
137134
return compute_deps_doc(unit, state);
138135
}
139136

140-
let bcx = state.bcx;
137+
let bcx = state.cx.bcx;
141138
let id = unit.pkg.package_id();
142139
let deps = bcx.resolve.deps(id).filter(|&(_id, deps)| {
143140
assert!(!deps.is_empty());
@@ -295,7 +292,7 @@ fn compute_deps_doc<'a, 'cfg, 'tmp>(
295292
unit: &Unit<'a>,
296293
state: &mut State<'a, 'cfg, 'tmp>,
297294
) -> CargoResult<Vec<(Unit<'a>, UnitFor)>> {
298-
let bcx = state.bcx;
295+
let bcx = state.cx.bcx;
299296
let deps = bcx
300297
.resolve
301298
.deps(unit.pkg.package_id())
@@ -448,7 +445,7 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
448445
// have the build script as the key and the library would be in the
449446
// value's set.
450447
let mut reverse_deps = HashMap::new();
451-
for (unit, deps) in state.deps.iter() {
448+
for (unit, deps) in state.cx.unit_dependencies.iter() {
452449
for dep in deps {
453450
if dep.mode == CompileMode::RunCustomBuild {
454451
reverse_deps
@@ -469,7 +466,8 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
469466
// `dep_build_script` to manufacture an appropriate build script unit to
470467
// depend on.
471468
for unit in state
472-
.deps
469+
.cx
470+
.unit_dependencies
473471
.keys()
474472
.filter(|k| k.mode == CompileMode::RunCustomBuild)
475473
{
@@ -480,13 +478,13 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
480478

481479
let to_add = reverse_deps
482480
.iter()
483-
.flat_map(|reverse_dep| state.deps[reverse_dep].iter())
481+
.flat_map(|reverse_dep| state.cx.unit_dependencies[reverse_dep].iter())
484482
.filter(|other| {
485483
other.pkg != unit.pkg
486484
&& other.target.linkable()
487485
&& other.pkg.manifest().links().is_some()
488486
})
489-
.filter_map(|other| dep_build_script(other, state.bcx).map(|p| p.0))
487+
.filter_map(|other| dep_build_script(other, state.cx.bcx).map(|p| p.0))
490488
.collect::<HashSet<_>>();
491489

492490
if !to_add.is_empty() {
@@ -497,21 +495,39 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
497495

498496
// And finally, add in all the missing dependencies!
499497
for (unit, new_deps) in new_deps {
500-
state.deps.get_mut(&unit).unwrap().extend(new_deps);
498+
state
499+
.cx
500+
.unit_dependencies
501+
.get_mut(&unit)
502+
.unwrap()
503+
.extend(new_deps);
504+
}
505+
}
506+
507+
/// Records the list of units which are required to emit metadata.
508+
///
509+
/// Units which depend only on the metadata of others requires the others to
510+
/// actually produce metadata, so we'll record that here.
511+
fn record_units_requiring_metadata(cx: &mut Context<'_, '_>) {
512+
for (key, deps) in cx.unit_dependencies.iter() {
513+
for dep in deps {
514+
if cx.only_requires_rmeta(key, dep) {
515+
cx.rmeta_required.insert(*dep);
516+
}
517+
}
501518
}
502519
}
503520

504521
impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> {
505522
fn get(&mut self, id: PackageId) -> CargoResult<Option<&'a Package>> {
506-
let mut pkgs = self.pkgs.borrow_mut();
507-
if let Some(pkg) = pkgs.get(&id) {
523+
if let Some(pkg) = self.cx.package_cache.get(&id) {
508524
return Ok(Some(pkg));
509525
}
510526
if !self.waiting_on_download.insert(id) {
511527
return Ok(None);
512528
}
513529
if let Some(pkg) = self.downloads.start(id)? {
514-
pkgs.insert(id, pkg);
530+
self.cx.package_cache.insert(id, pkg);
515531
self.waiting_on_download.remove(&id);
516532
return Ok(Some(pkg));
517533
}
@@ -531,7 +547,7 @@ impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> {
531547
loop {
532548
let pkg = self.downloads.wait()?;
533549
self.waiting_on_download.remove(&pkg.package_id());
534-
self.pkgs.borrow_mut().insert(pkg.package_id(), pkg);
550+
self.cx.package_cache.insert(pkg.package_id(), pkg);
535551

536552
// Arbitrarily choose that 5 or more packages concurrently download
537553
// is a good enough number to "fill the network pipe". If we have

0 commit comments

Comments
 (0)