|
1 | 1 | use crate::core::compiler::{CompileKind, RustcTargetData};
|
2 |
| -use crate::core::dependency::DepKind; |
| 2 | +use crate::core::dependency::{ArtifactKind, DepKind}; |
3 | 3 | use crate::core::package::SerializedPackage;
|
4 | 4 | use crate::core::resolver::{features::CliFeatures, HasDevUnits, Resolve};
|
5 |
| -use crate::core::{Dependency, Package, PackageId, Workspace}; |
| 5 | +use crate::core::{Package, PackageId, Target, Workspace}; |
6 | 6 | use crate::ops::{self, Packages};
|
7 | 7 | use crate::util::interning::InternedString;
|
8 | 8 | use crate::util::CargoResult;
|
@@ -90,15 +90,26 @@ struct Dep {
|
90 | 90 | struct DepKindInfo {
|
91 | 91 | kind: DepKind,
|
92 | 92 | target: Option<Platform>,
|
93 |
| -} |
94 | 93 |
|
95 |
| -impl From<&Dependency> for DepKindInfo { |
96 |
| - fn from(dep: &Dependency) -> DepKindInfo { |
97 |
| - DepKindInfo { |
98 |
| - kind: dep.kind(), |
99 |
| - target: dep.platform().cloned(), |
100 |
| - } |
101 |
| - } |
| 94 | + // vvvvv The fields below are introduced for `-Z bindeps`. |
| 95 | + /// Artifact's crate type, e.g. staticlib, cdylib, bin... |
| 96 | + #[serde(skip_serializing_if = "Option::is_none")] |
| 97 | + artifact: Option<&'static str>, |
| 98 | + /// What the manifest calls the crate. |
| 99 | + /// |
| 100 | + /// A renamed dependency will show the rename instead of original name. |
| 101 | + #[serde(skip_serializing_if = "Option::is_none")] |
| 102 | + extern_name: Option<InternedString>, |
| 103 | + /// Equivalent to `{ target = "…" }` in an artifact dependency requirement. |
| 104 | + /// |
| 105 | + /// * If the target points to a custom target JSON file, the path will be absolute. |
| 106 | + /// * If the target is a build assumed target `{ target = "target" }`, it will show as `<target>`. |
| 107 | + #[serde(skip_serializing_if = "Option::is_none")] |
| 108 | + compile_target: Option<InternedString>, |
| 109 | + /// Executable name for an artifact binary dependency. |
| 110 | + #[serde(skip_serializing_if = "Option::is_none")] |
| 111 | + bin_name: Option<String>, |
| 112 | + // ^^^^^ The fields above are introduced for `-Z bindeps`. |
102 | 113 | }
|
103 | 114 |
|
104 | 115 | /// Builds the resolve graph as it will be displayed to the user.
|
@@ -206,22 +217,101 @@ fn build_resolve_graph_r(
|
206 | 217 | }
|
207 | 218 | })
|
208 | 219 | .filter_map(|(dep_id, deps)| {
|
209 |
| - let mut dep_kinds: Vec<_> = deps.iter().map(DepKindInfo::from).collect(); |
| 220 | + let mut dep_kinds = Vec::new(); |
| 221 | + |
| 222 | + let targets = package_map[&dep_id].targets(); |
| 223 | + |
| 224 | + // Try to get the extern name for lib, or crate name for bins. |
| 225 | + let extern_name = |target| { |
| 226 | + resolve |
| 227 | + .extern_crate_name_and_dep_name(pkg_id, dep_id, target) |
| 228 | + .map(|(ext_crate_name, _)| ext_crate_name) |
| 229 | + .ok() |
| 230 | + }; |
| 231 | + |
| 232 | + let lib_target_name = targets.iter().find(|t| t.is_lib()).map(extern_name); |
| 233 | + |
| 234 | + for dep in deps.iter() { |
| 235 | + let mut include_lib = || { |
| 236 | + dep_kinds.push(DepKindInfo { |
| 237 | + kind: dep.kind(), |
| 238 | + target: dep.platform().cloned(), |
| 239 | + artifact: None, |
| 240 | + extern_name: lib_target_name, |
| 241 | + compile_target: None, |
| 242 | + bin_name: None, |
| 243 | + }); |
| 244 | + }; |
| 245 | + |
| 246 | + // When we do have a library target, include them in deps if... |
| 247 | + match (dep.artifact(), lib_target_name) { |
| 248 | + // it is also an artifact dep with `{ …, lib = true }` |
| 249 | + (Some(a), Some(_)) if a.is_lib() => include_lib(), |
| 250 | + // it is not an artifact dep at all |
| 251 | + (None, Some(_)) => include_lib(), |
| 252 | + _ => {} |
| 253 | + } |
| 254 | + |
| 255 | + // No need to proceed if there is no artifact dependency. |
| 256 | + let Some(artifact_requirements) = dep.artifact() else { |
| 257 | + continue; |
| 258 | + }; |
| 259 | + |
| 260 | + let compile_target = match artifact_requirements.target() { |
| 261 | + Some(t) => t |
| 262 | + .to_compile_target() |
| 263 | + .map(|t| t.rustc_target()) |
| 264 | + // Given that Cargo doesn't know which target it should resolve to, |
| 265 | + // when an artifact dep is specified with { target = "target" }, |
| 266 | + // keep it with a special "<target>" string, |
| 267 | + .or_else(|| Some(InternedString::new("<target>"))), |
| 268 | + None => None, |
| 269 | + }; |
| 270 | + |
| 271 | + let mut extend = |kind: &ArtifactKind, filter: &dyn Fn(&&Target) -> bool| { |
| 272 | + let iter = targets.iter().filter(filter).map(|target| DepKindInfo { |
| 273 | + kind: dep.kind(), |
| 274 | + target: dep.platform().cloned(), |
| 275 | + artifact: Some(kind.crate_type()), |
| 276 | + extern_name: extern_name(target), |
| 277 | + compile_target, |
| 278 | + bin_name: target.is_bin().then(|| target.name().to_string()), |
| 279 | + }); |
| 280 | + dep_kinds.extend(iter); |
| 281 | + }; |
| 282 | + |
| 283 | + for kind in artifact_requirements.kinds() { |
| 284 | + match kind { |
| 285 | + ArtifactKind::Cdylib => extend(kind, &|t| t.is_cdylib()), |
| 286 | + ArtifactKind::Staticlib => extend(kind, &|t| t.is_staticlib()), |
| 287 | + ArtifactKind::AllBinaries => extend(kind, &|t| t.is_bin()), |
| 288 | + ArtifactKind::SelectedBinary(bin_name) => { |
| 289 | + extend(kind, &|t| t.is_bin() && t.name() == bin_name.as_str()) |
| 290 | + } |
| 291 | + }; |
| 292 | + } |
| 293 | + } |
| 294 | + |
210 | 295 | dep_kinds.sort();
|
211 |
| - package_map |
212 |
| - .get(&dep_id) |
213 |
| - .and_then(|pkg| pkg.targets().iter().find(|t| t.is_lib())) |
214 |
| - .and_then(|lib_target| { |
215 |
| - resolve |
216 |
| - .extern_crate_name_and_dep_name(pkg_id, dep_id, lib_target) |
217 |
| - .map(|(ext_crate_name, _)| ext_crate_name) |
218 |
| - .ok() |
219 |
| - }) |
220 |
| - .map(|name| Dep { |
| 296 | + |
| 297 | + let pkg = normalize_id(dep_id); |
| 298 | + |
| 299 | + match (lib_target_name, dep_kinds.len()) { |
| 300 | + (Some(name), _) => Some(Dep { |
221 | 301 | name,
|
222 |
| - pkg: normalize_id(dep_id), |
| 302 | + pkg, |
223 | 303 | dep_kinds,
|
224 |
| - }) |
| 304 | + }), |
| 305 | + // No lib target exists but contains artifact deps. |
| 306 | + (None, 1..) => Some(Dep { |
| 307 | + name: InternedString::new(""), |
| 308 | + pkg, |
| 309 | + dep_kinds, |
| 310 | + }), |
| 311 | + // No lib or artifact dep exists. |
| 312 | + // Ususally this mean parent depending on non-lib bin crate. |
| 313 | + (None, _) => None, |
| 314 | + } |
225 | 315 | })
|
226 | 316 | .collect();
|
227 | 317 | let dumb_deps: Vec<PackageId> = deps.iter().map(|dep| normalize_id(dep.pkg)).collect();
|
|
0 commit comments