1use crate::compiler::UnitInterner;
4use crate::compiler::unit_dependencies::IsArtifact;
5use crate::compiler::{CompileKind, CompileMode, RustcTargetData, Unit};
6use crate::ops::{self, Packages};
7use crate::resolver::HasDevUnits;
8use crate::resolver::Resolve;
9use crate::resolver::features::{CliFeatures, FeaturesFor, ResolvedFeatures};
10use crate::util::errors::CargoResult;
11use crate::workspace::profiles::{Profiles, UnitFor};
12use crate::workspace::{PackageId, PackageSet, Workspace};
13
14use crate::util::data_structures::{HashMap, HashSet};
15use std::path::PathBuf;
16
17use super::BuildConfig;
18
19fn std_crates<'a>(crates: &'a [String], default: &'static str, units: &[Unit]) -> HashSet<&'a str> {
20 let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str()));
21 if crates.is_empty() {
24 crates.insert(default);
25 }
26 if crates.contains("std") {
27 crates.insert("core");
28 crates.insert("alloc");
29 crates.insert("proc_macro");
30 crates.insert("panic_unwind");
31 crates.insert("compiler_builtins");
32 if units
35 .iter()
36 .any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
37 {
38 crates.insert("test");
39 }
40 } else if crates.contains("core") {
41 crates.insert("compiler_builtins");
42 }
43
44 crates
45}
46
47pub fn resolve_std<'gctx>(
51 ws: &Workspace<'gctx>,
52 target_data: &mut RustcTargetData<'gctx>,
53 build_config: &BuildConfig,
54 crates: &[String],
55 kinds: &[CompileKind],
56) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> {
57 let src_path = detect_sysroot_src_path(target_data)?;
58 let std_ws_manifest_path = src_path.join("Cargo.toml");
59 let gctx = ws.gctx();
60 let mut std_ws = Workspace::new(&std_ws_manifest_path, gctx)?;
63 std_ws.set_require_optional_deps(false);
67 let specs = {
68 let maybe_std = kinds
73 .iter()
74 .any(|kind| target_data.info(*kind).maybe_support_std());
75 let mut crates = std_crates(crates, if maybe_std { "std" } else { "core" }, &[]);
76 crates.insert("sysroot");
79 let specs = Packages::Packages(crates.into_iter().map(Into::into).collect());
80 specs.to_package_id_specs(&std_ws)?
81 };
82 let features = match &gctx.cli_unstable().build_std_features {
83 Some(list) => list.clone(),
84 None => vec![
85 "panic-unwind".to_string(),
86 "backtrace".to_string(),
87 "default".to_string(),
88 ],
89 };
90 let cli_features = CliFeatures::from_command_line(
91 &features, false, false,
92 )?;
93 let dry_run = false;
94 let mut resolve = ops::resolve_ws_with_opts(
95 &std_ws,
96 target_data,
97 &build_config.requested_kinds,
98 &cli_features,
99 &specs,
100 HasDevUnits::No,
101 crate::resolver::features::ForceAllTargets::No,
102 dry_run,
103 )?;
104 debug_assert_eq!(resolve.specs_and_features.len(), 1);
105 Ok((
106 resolve.pkg_set,
107 resolve.targeted_resolve,
108 resolve
109 .specs_and_features
110 .pop()
111 .expect("resolve should have a single spec with resolved features")
112 .resolved_features,
113 ))
114}
115
116pub fn generate_std_roots(
121 crates: &[String],
122 units: &[Unit],
123 std_resolve: &Resolve,
124 std_features: &ResolvedFeatures,
125 kinds: &[CompileKind],
126 package_set: &PackageSet<'_>,
127 interner: &UnitInterner,
128 profiles: &Profiles,
129 target_data: &RustcTargetData<'_>,
130) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {
131 let mut ret = HashMap::default();
133 let (maybe_std, maybe_core): (Vec<&CompileKind>, Vec<_>) = kinds
134 .iter()
135 .partition(|kind| target_data.info(**kind).maybe_support_std());
136 for (default_crate, kinds) in [("core", maybe_core), ("std", maybe_std)] {
137 if kinds.is_empty() {
138 continue;
139 }
140 generate_roots(
141 &mut ret,
142 default_crate,
143 crates,
144 units,
145 std_resolve,
146 std_features,
147 &kinds,
148 package_set,
149 interner,
150 profiles,
151 target_data,
152 )?;
153 }
154
155 Ok(ret)
156}
157
158fn generate_roots(
159 ret: &mut HashMap<CompileKind, Vec<Unit>>,
160 default: &'static str,
161 crates: &[String],
162 units: &[Unit],
163 std_resolve: &Resolve,
164 std_features: &ResolvedFeatures,
165 kinds: &[&CompileKind],
166 package_set: &PackageSet<'_>,
167 interner: &UnitInterner,
168 profiles: &Profiles,
169 target_data: &RustcTargetData<'_>,
170) -> CargoResult<()> {
171 let std_ids = std_crates(crates, default, units)
172 .iter()
173 .map(|crate_name| std_resolve.query(crate_name))
174 .collect::<CargoResult<Vec<PackageId>>>()?;
175 let std_pkgs = package_set.get_many(std_ids)?;
176
177 for pkg in std_pkgs {
178 let lib = pkg
179 .targets()
180 .iter()
181 .find(|t| t.is_lib())
182 .expect("std has a lib");
183 let mode = CompileMode::Build;
187 let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);
188 for kind in kinds {
189 let kind = **kind;
190 let list = ret.entry(kind).or_insert_with(Vec::new);
191 let unit_for = UnitFor::new_normal(kind);
192 let profile = profiles.get_profile(
193 pkg.package_id(),
194 false,
195 false,
196 unit_for,
197 kind,
198 );
199 list.push(interner.intern(
200 pkg,
201 lib,
202 profile,
203 kind,
204 mode,
205 features.clone(),
206 target_data.info(kind).rustflags.clone(),
207 target_data.info(kind).rustdocflags.clone(),
208 target_data.target_config(kind).links_overrides.clone(),
209 true,
210 0,
211 IsArtifact::No,
212 None,
213 false,
214 ));
215 }
216 }
217 Ok(())
218}
219
220fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult<PathBuf> {
221 if let Some(s) = target_data.gctx.get_env_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
222 return Ok(s.into());
223 }
224
225 let src_path = target_data
227 .info(CompileKind::Host)
228 .sysroot
229 .join("lib")
230 .join("rustlib")
231 .join("src")
232 .join("rust")
233 .join("library");
234 let lock = src_path.join("Cargo.lock");
235 if !lock.exists() {
236 let msg = format!(
237 "{:?} does not exist, unable to build with the standard \
238 library, try:\n rustup component add rust-src",
239 lock
240 );
241 match target_data.gctx.get_env("RUSTUP_TOOLCHAIN") {
242 Ok(rustup_toolchain) => {
243 anyhow::bail!("{} --toolchain {}", msg, rustup_toolchain);
244 }
245 Err(_) => {
246 anyhow::bail!(msg);
247 }
248 }
249 }
250 Ok(src_path)
251}