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