|
51 | 51 | //! Additionally, the algorithm is geared towards finding *any* solution rather
|
52 | 52 | //! than finding a number of solutions (there are normally quite a few).
|
53 | 53 |
|
54 |
| -use rustc_data_structures::fx::FxHashMap; |
| 54 | +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
55 | 55 | use rustc_hir::def_id::CrateNum;
|
56 | 56 | use rustc_middle::bug;
|
57 | 57 | use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
|
58 | 58 | use rustc_middle::ty::TyCtxt;
|
59 | 59 | use rustc_session::config::CrateType;
|
60 | 60 | use rustc_session::cstore::CrateDepKind;
|
61 | 61 | use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
|
| 62 | +use rustc_span::sym; |
62 | 63 | use tracing::info;
|
63 | 64 |
|
64 | 65 | use crate::creader::CStore;
|
65 | 66 | use crate::errors::{
|
66 | 67 | BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
|
67 |
| - NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes, |
| 68 | + NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired, |
| 69 | + TwoPanicRuntimes, |
68 | 70 | };
|
69 | 71 |
|
70 | 72 | pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
|
@@ -160,25 +162,49 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
160 | 162 | Linkage::Dynamic | Linkage::IncludedFromDylib => {}
|
161 | 163 | }
|
162 | 164 |
|
| 165 | + let all_dylibs = || { |
| 166 | + tcx.crates(()).iter().filter(|&&cnum| { |
| 167 | + !tcx.dep_kind(cnum).macros_only() && tcx.used_crate_source(cnum).dylib.is_some() |
| 168 | + }) |
| 169 | + }; |
| 170 | + |
| 171 | + let mut upstream_in_dylibs = FxHashSet::default(); |
| 172 | + |
| 173 | + if tcx.features().rustc_private { |
| 174 | + // We need this to prevent users of `rustc_driver` from linking dynamically to `std` |
| 175 | + // which does not work as `std` is also statically linked into `rustc_driver`. |
| 176 | + |
| 177 | + // Find all libraries statically linked to upstream dylibs. |
| 178 | + for &cnum in all_dylibs() { |
| 179 | + let deps = tcx.dylib_dependency_formats(cnum); |
| 180 | + for &(depnum, style) in deps.iter() { |
| 181 | + if let RequireStatic = style { |
| 182 | + upstream_in_dylibs.insert(depnum); |
| 183 | + } |
| 184 | + } |
| 185 | + } |
| 186 | + } |
| 187 | + |
163 | 188 | let mut formats = FxHashMap::default();
|
164 | 189 |
|
165 | 190 | // Sweep all crates for found dylibs. Add all dylibs, as well as their
|
166 | 191 | // dependencies, ensuring there are no conflicts. The only valid case for a
|
167 | 192 | // dependency to be relied upon twice is for both cases to rely on a dylib.
|
168 |
| - for &cnum in tcx.crates(()).iter() { |
169 |
| - if tcx.dep_kind(cnum).macros_only() { |
| 193 | + for &cnum in all_dylibs() { |
| 194 | + if upstream_in_dylibs.contains(&cnum) { |
| 195 | + info!("skipping dylib: {}", tcx.crate_name(cnum)); |
| 196 | + // If this dylib is also available statically linked to another dylib |
| 197 | + // we try to use that instead. |
170 | 198 | continue;
|
171 | 199 | }
|
| 200 | + |
172 | 201 | let name = tcx.crate_name(cnum);
|
173 |
| - let src = tcx.used_crate_source(cnum); |
174 |
| - if src.dylib.is_some() { |
175 |
| - info!("adding dylib: {}", name); |
176 |
| - add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static); |
177 |
| - let deps = tcx.dylib_dependency_formats(cnum); |
178 |
| - for &(depnum, style) in deps.iter() { |
179 |
| - info!("adding {:?}: {}", style, tcx.crate_name(depnum)); |
180 |
| - add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static); |
181 |
| - } |
| 202 | + info!("adding dylib: {}", name); |
| 203 | + add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static); |
| 204 | + let deps = tcx.dylib_dependency_formats(cnum); |
| 205 | + for &(depnum, style) in deps.iter() { |
| 206 | + info!("adding {:?}: {}", style, tcx.crate_name(depnum)); |
| 207 | + add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static); |
182 | 208 | }
|
183 | 209 | }
|
184 | 210 |
|
@@ -268,12 +294,15 @@ fn add_library(
|
268 | 294 | // This error is probably a little obscure, but I imagine that it
|
269 | 295 | // can be refined over time.
|
270 | 296 | if link2 != link || link == RequireStatic {
|
| 297 | + let linking_to_rustc_driver = tcx.sess.psess.unstable_features.is_nightly_build() |
| 298 | + && tcx.crates(()).iter().any(|&cnum| tcx.crate_name(cnum) == sym::rustc_driver); |
271 | 299 | tcx.dcx().emit_err(CrateDepMultiple {
|
272 | 300 | crate_name: tcx.crate_name(cnum),
|
273 | 301 | non_static_deps: unavailable_as_static
|
274 | 302 | .drain(..)
|
275 | 303 | .map(|cnum| NonStaticCrateDep { crate_name: tcx.crate_name(cnum) })
|
276 | 304 | .collect(),
|
| 305 | + rustc_driver_help: linking_to_rustc_driver.then_some(RustcDriverHelp), |
277 | 306 | });
|
278 | 307 | }
|
279 | 308 | }
|
|
0 commit comments