use crate::core::compiler::{BuildContext, CompileKind, CompileMode, RustcTargetData, Unit};
use crate::core::profiles::UnitFor;
use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};
use crate::core::resolver::{HasDevUnits, ResolveOpts};
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
use crate::ops::{self, Packages};
use crate::util::errors::CargoResult;
use std::collections::{HashMap, HashSet};
use std::env;
use std::path::PathBuf;
pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
let value = value.unwrap_or("std");
let mut crates: HashSet<&str> = value.split(',').collect();
if crates.contains("std") {
crates.insert("core");
crates.insert("alloc");
crates.insert("proc_macro");
crates.insert("panic_unwind");
crates.insert("compiler_builtins");
} else if crates.contains("core") {
crates.insert("compiler_builtins");
}
crates.into_iter().map(|s| s.to_string()).collect()
}
pub fn resolve_std<'cfg>(
ws: &Workspace<'cfg>,
target_data: &RustcTargetData,
requested_target: CompileKind,
crates: &[String],
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
let src_path = detect_sysroot_src_path(target_data)?;
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();
let mut patch = HashMap::new();
patch.insert(crates_io_url, patches);
let members = vec![
String::from("src/libstd"),
String::from("src/libcore"),
String::from("src/liballoc"),
String::from("src/libtest"),
];
let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new(
&src_path,
&Some(members),
&None,
&None,
));
let virtual_manifest = crate::core::VirtualManifest::new(
Vec::new(),
patch,
ws_config,
None,
crate::core::Features::default(),
);
let config = ws.config();
let current_manifest = src_path.join("src/libtest/Cargo.toml");
let mut std_ws = Workspace::new_virtual(src_path, current_manifest, virtual_manifest, config)?;
std_ws.set_require_optional_deps(false);
let mut spec_pkgs = Vec::from(crates);
spec_pkgs.push("test".to_string());
let spec = Packages::Packages(spec_pkgs);
let specs = spec.to_package_id_specs(&std_ws)?;
let features = vec!["panic-unwind".to_string(), "backtrace".to_string()];
let opts = ResolveOpts::new(
false, &features, false,
true,
);
let resolve = ops::resolve_ws_with_opts(
&std_ws,
target_data,
requested_target,
&opts,
&specs,
HasDevUnits::No,
)?;
Ok((
resolve.pkg_set,
resolve.targeted_resolve,
resolve.resolved_features,
))
}
pub fn generate_std_roots<'a>(
bcx: &BuildContext<'a, '_>,
crates: &[String],
std_resolve: &'a Resolve,
std_features: &ResolvedFeatures,
kind: CompileKind,
) -> CargoResult<Vec<Unit<'a>>> {
let std_ids = crates
.iter()
.map(|crate_name| std_resolve.query(crate_name))
.collect::<CargoResult<Vec<PackageId>>>()?;
let std_pkgs = bcx.packages.get_many(std_ids)?;
std_pkgs
.into_iter()
.map(|pkg| {
let lib = pkg
.targets()
.iter()
.find(|t| t.is_lib())
.expect("std has a lib");
let unit_for = UnitFor::new_normal();
let mode = CompileMode::Build;
let profile = bcx.profiles.get_profile(
pkg.package_id(),
false,
unit_for,
mode,
);
let features =
std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);
Ok(bcx.units.intern(
pkg, lib, profile, kind, mode, features, true,
))
})
.collect::<CargoResult<Vec<_>>>()
}
fn detect_sysroot_src_path(target_data: &RustcTargetData) -> CargoResult<PathBuf> {
if let Some(s) = env::var_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
return Ok(s.into());
}
let src_path = target_data
.info(CompileKind::Host)
.sysroot
.join("lib")
.join("rustlib")
.join("src")
.join("rust");
let lock = src_path.join("Cargo.lock");
if !lock.exists() {
anyhow::bail!(
"{:?} does not exist, unable to build with the standard \
library, try:\n rustup component add rust-src",
lock
);
}
Ok(src_path)
}