Skip to content

Commit

Permalink
Update for libtest changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed Sep 3, 2019
1 parent aee4048 commit d4c3eea
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 163 deletions.
46 changes: 24 additions & 22 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
crates.insert("core");
crates.insert("panic_unwind");
crates.insert("compiler_builtins");
crates.insert("test");
} else if crates.contains("core") {
crates.insert("compiler_builtins");
}
Expand All @@ -31,18 +32,22 @@ pub fn resolve_std<'cfg>(
crates: &[String],
) -> CargoResult<(PackageSet<'cfg>, Resolve)> {
let src_path = detect_sysroot_src_path(ws)?;
let mut patch = HashMap::new();
let to_patch = [
"rustc-std-workspace-core",
"rustc-std-workspace-alloc",
"rustc-std-workspace-std",
];
let patches = to_patch
.iter()
.map(|name| {
let source_path = SourceId::for_path(&src_path.join("src").join("tools").join(name))?;
let dep = Dependency::parse_no_deprecated(name, None, source_path)?;
Ok(dep)
})
.collect::<CargoResult<Vec<_>>>()?;
let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap();
// rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' }
let source_path_core =
SourceId::for_path(&src_path.join("src/tools/rustc-std-workspace-core"))?;
let core = Dependency::parse_no_deprecated("rustc-std-workspace-core", None, source_path_core)?;
// rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
let source_path_alloc =
SourceId::for_path(&src_path.join("src/tools/rustc-std-workspace-alloc"))?;
let alloc =
Dependency::parse_no_deprecated("rustc-std-workspace-alloc", None, source_path_alloc)?;
patch.insert(crates_io_url, vec![core, alloc]);
let mut patch = HashMap::new();
patch.insert(crates_io_url, patches);
let members = vec![
String::from("src/libstd"),
String::from("src/libcore"),
Expand All @@ -67,21 +72,18 @@ pub fn resolve_std<'cfg>(
let config = ws.config();
// This is a delicate hack. In order for features to resolve correctly,
// the resolver needs to run a specific "current" member of the workspace.
// Thus, in order to set the features for `std`, we need to set `std` to
// be the "current" member. Since none of the other crates need to alter
// their features, this should be fine, for now. Perhaps in the future
// features will be decoupled from the resolver and it will be easier to
// control feature selection.
let current_manifest = src_path.join("src/libstd/Cargo.toml");
// Thus, in order to set the features for `std`, we need to set `libtest`
// to be the "current" member. `libtest` is the root, and all other
// standard library crates are dependencies from there. Since none of the
// other crates need to alter their features, this should be fine, for
// now. Perhaps in the future features will be decoupled from the resolver
// and it will be easier to control feature selection.
let current_manifest = src_path.join("src/libtest/Cargo.toml");
// TODO: Consider setting require_option_deps false?
// TODO: Consider doing something to enforce --locked? Or to prevent the
// lock file from being written, such as setting ephemeral.
let std_ws = Workspace::new_virtual(src_path, current_manifest, virtual_manifest, config)?;
// `test` is not in the default set because it is optional, but it needs
// to be part of the resolve in case we do need it.
let mut spec_pkgs = Vec::from(crates);
spec_pkgs.push("test".to_string());
let spec = Packages::Packages(spec_pkgs);
let spec = Packages::Packages(Vec::from(crates));
let specs = spec.to_package_id_specs(&std_ws)?;
let features = vec!["panic-unwind".to_string(), "backtrace".to_string()];
// dev_deps setting shouldn't really matter here.
Expand Down
143 changes: 2 additions & 141 deletions src/cargo/core/compiler/unit_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,12 @@ pub fn build_unit_dependencies<'a, 'cfg>(
};

let std_unit_deps = calc_deps_of_std(&mut state, std_roots)?;
let libtest_unit_deps = calc_deps_of_libtest(&mut state, std_roots, roots)?;

deps_of_roots(roots, &mut state)?;
super::links::validate_links(state.resolve(), &state.unit_dependencies)?;
// Hopefully there aren't any links conflicts with the standard library?

if let Some(mut std_unit_deps) = std_unit_deps {
if let Some(libtest_unit_deps) = libtest_unit_deps {
attach_std_test(&mut state, libtest_unit_deps, &std_unit_deps);
}
fixup_proc_macro(&mut std_unit_deps);
if let Some(std_unit_deps) = std_unit_deps {
attach_std_deps(&mut state, std_roots, std_unit_deps);
}

Expand Down Expand Up @@ -122,118 +117,6 @@ fn calc_deps_of_std<'a, 'cfg>(
)))
}

/// Compute all the dependencies for libtest.
/// Returns None if libtest is not needed.
fn calc_deps_of_libtest<'a, 'cfg>(
mut state: &mut State<'a, 'cfg>,
std_roots: &[Unit<'a>],
roots: &[Unit<'a>],
) -> CargoResult<Option<UnitGraph<'a>>> {
// Conditionally include libtest.
if std_roots.is_empty()
|| !roots
.iter()
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
{
return Ok(None);
}
state.is_std = true;
let test_id = state.resolve().query("test")?;
let test_pkg = state.get(test_id)?.expect("test doesn't need downloading");
let test_target = test_pkg
.targets()
.iter()
.find(|t| t.is_lib())
.expect("test has a lib");
let test_unit = new_unit(
state,
test_pkg,
test_target,
UnitFor::new_normal(),
Kind::Target,
CompileMode::Build,
);
let res = calc_deps_of_std(state, &[test_unit])?;
state.is_std = false;
Ok(res)
}

/// `proc_macro` has an implicit dependency on `std`, add it.
fn fixup_proc_macro<'a>(std_unit_deps: &mut UnitGraph<'a>) {
// Synthesize a dependency from proc_macro -> std.
//
// This is a gross hack. This wouldn't be necessary with `--sysroot`. See
// also libtest below.
if let Some(std) = std_unit_deps
.keys()
.find(|unit| unit.pkg.name().as_str() == "std" && unit.target.is_lib())
.cloned()
{
for (unit, deps) in std_unit_deps.iter_mut() {
if unit.pkg.name().as_str() == "proc_macro" {
deps.push(UnitDep {
unit: std,
unit_for: UnitFor::new_normal(),
extern_crate_name: InternedString::new("std"),
public: true,
});
}
}
}
}

/// Add libtest as a dependency of any test unit that needs it.
fn attach_std_test<'a, 'cfg>(
state: &mut State<'a, 'cfg>,
mut libtest_unit_deps: UnitGraph<'a>,
std_unit_deps: &UnitGraph<'a>,
) {
// Attach libtest to any test unit.
let (test_unit, test_deps) = libtest_unit_deps
.iter_mut()
.find(|(k, _v)| k.pkg.name().as_str() == "test" && k.target.is_lib())
.expect("test in deps");
for (unit, deps) in state.unit_dependencies.iter_mut() {
if unit.mode.is_rustc_test() && unit.target.harness() {
// `public` here will need to be driven by toml declaration.
deps.push(UnitDep {
unit: *test_unit,
unit_for: UnitFor::new_normal(),
extern_crate_name: test_unit.pkg.name(),
public: false,
});
}
}

// Synthesize a dependency from libtest -> libc.
//
// This is a gross hack. In theory, libtest should explicitly list this,
// but presumably it would cause libc to be built again when it just uses
// the version from sysroot. This won't be necessary if Cargo uses
// `--sysroot`.
let libc_unit = std_unit_deps
.keys()
.find(|unit| unit.pkg.name().as_str() == "libc" && unit.target.is_lib())
.expect("libc in deps");
let libc_dep = UnitDep {
unit: *libc_unit,
unit_for: UnitFor::new_normal(),
extern_crate_name: InternedString::new(&libc_unit.target.crate_name()),
public: false,
};
test_deps.push(libc_dep);

// And also include the dependencies of libtest itself.
for (unit, deps) in libtest_unit_deps.into_iter() {
if let Some(other_unit) = state.unit_dependencies.insert(unit, deps) {
panic!(
"libtest unit collision with existing unit: {:?}",
other_unit
);
}
}
}

/// Add the standard library units to the `unit_dependencies`.
fn attach_std_deps<'a, 'cfg>(
state: &mut State<'a, 'cfg>,
Expand Down Expand Up @@ -647,29 +530,7 @@ fn check_or_build_mode(mode: CompileMode, target: &Target) -> CompileMode {
}
}

fn new_unit<'a>(
state: &State<'a, '_>,
pkg: &'a Package,
target: &'a Target,
unit_for: UnitFor,
kind: Kind,
mode: CompileMode,
) -> Unit<'a> {
let profile = state.bcx.profiles.get_profile(
pkg.package_id(),
state.bcx.ws.is_member(pkg),
unit_for,
mode,
state.bcx.build_config.release,
);

let features = state.resolve().features_sorted(pkg.package_id());
state
.bcx
.units
.intern(pkg, target, profile, kind, mode, features)
}

/// Create a new Unit for a dependency from `parent` to `pkg` and `target`.
fn new_unit_dep<'a>(
state: &State<'a, '_>,
parent: &Unit<'a>,
Expand Down

0 comments on commit d4c3eea

Please sign in to comment.