Skip to content

Commit 6c476ce

Browse files
committed
Auto merge of #44279 - smaeul:crt_static-deps, r=alexcrichton
Require rlibs for dependent crates when linking static executables This handles the case for `CrateTypeExecutable` and `+crt_static`. I reworked the match block to avoid duplicating the `attempt_static` and error checking code again (this case would have been a copy of the `CrateTypeCdylib`/`CrateTypeStaticlib` case). On `linux-musl` targets where `std` was built with `crt_static = false` in `config.toml`, this change brings the test suite from entirely failing to mostly passing. This change should not affect behavior for other crate types, or for targets which do not respect `+crt_static`.
2 parents 3df1f7b + 314c2b1 commit 6c476ce

File tree

3 files changed

+49
-41
lines changed

3 files changed

+49
-41
lines changed

src/librustc/middle/dependency_format.rs

+47-39
Original file line numberDiff line numberDiff line change
@@ -112,52 +112,61 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
112112
return Vec::new();
113113
}
114114

115-
match ty {
116-
// If the global prefer_dynamic switch is turned off, first attempt
117-
// static linkage (this can fail).
118-
config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
119-
if let Some(v) = attempt_static(tcx) {
120-
return v;
121-
}
122-
}
115+
let preferred_linkage = match ty {
116+
// cdylibs must have all static dependencies.
117+
config::CrateTypeCdylib => Linkage::Static,
118+
119+
// Generating a dylib without `-C prefer-dynamic` means that we're going
120+
// to try to eagerly statically link all dependencies. This is normally
121+
// done for end-product dylibs, not intermediate products.
122+
config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
123+
config::CrateTypeDylib => Linkage::Dynamic,
124+
125+
// If the global prefer_dynamic switch is turned off, or the final
126+
// executable will be statically linked, prefer static crate linkage.
127+
config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic ||
128+
sess.crt_static() => Linkage::Static,
129+
config::CrateTypeExecutable => Linkage::Dynamic,
130+
131+
// proc-macro crates are required to be dylibs, and they're currently
132+
// required to link to libsyntax as well.
133+
config::CrateTypeProcMacro => Linkage::Dynamic,
123134

124135
// No linkage happens with rlibs, we just needed the metadata (which we
125136
// got long ago), so don't bother with anything.
126-
config::CrateTypeRlib => return Vec::new(),
127-
128-
// Staticlibs and cdylibs must have all static dependencies. If any fail
129-
// to be found, we generate some nice pretty errors.
130-
config::CrateTypeStaticlib |
131-
config::CrateTypeCdylib => {
132-
if let Some(v) = attempt_static(tcx) {
133-
return v;
134-
}
137+
config::CrateTypeRlib => Linkage::NotLinked,
138+
139+
// staticlibs must have all static dependencies.
140+
config::CrateTypeStaticlib => Linkage::Static,
141+
};
142+
143+
if preferred_linkage == Linkage::NotLinked {
144+
// If the crate is not linked, there are no link-time dependencies.
145+
return Vec::new();
146+
}
147+
148+
if preferred_linkage == Linkage::Static {
149+
// Attempt static linkage first. For dylibs and executables, we may be
150+
// able to retry below with dynamic linkage.
151+
if let Some(v) = attempt_static(tcx) {
152+
return v;
153+
}
154+
155+
// Staticlibs, cdylibs, and static executables must have all static
156+
// dependencies. If any are not found, generate some nice pretty errors.
157+
if ty == config::CrateTypeCdylib || ty == config::CrateTypeStaticlib ||
158+
(ty == config::CrateTypeExecutable && sess.crt_static() &&
159+
!sess.target.target.options.crt_static_allows_dylibs) {
135160
for &cnum in tcx.crates().iter() {
136161
if tcx.dep_kind(cnum).macros_only() { continue }
137162
let src = tcx.used_crate_source(cnum);
138163
if src.rlib.is_some() { continue }
139-
sess.err(&format!("dependency `{}` not found in rlib format",
164+
sess.err(&format!("crate `{}` required to be available in rlib format, \
165+
but was not found in this form",
140166
tcx.crate_name(cnum)));
141167
}
142168
return Vec::new();
143169
}
144-
145-
// Generating a dylib without `-C prefer-dynamic` means that we're going
146-
// to try to eagerly statically link all dependencies. This is normally
147-
// done for end-product dylibs, not intermediate products.
148-
config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => {
149-
if let Some(v) = attempt_static(tcx) {
150-
return v;
151-
}
152-
}
153-
154-
// Everything else falls through below. This will happen either with the
155-
// `-C prefer-dynamic` or because we're a proc-macro crate. Note that
156-
// proc-macro crates are required to be dylibs, and they're currently
157-
// required to link to libsyntax as well.
158-
config::CrateTypeExecutable |
159-
config::CrateTypeDylib |
160-
config::CrateTypeProcMacro => {},
161170
}
162171

163172
let mut formats = FxHashMap();
@@ -236,10 +245,9 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
236245
Linkage::Static => "rlib",
237246
_ => "dylib",
238247
};
239-
let name = tcx.crate_name(cnum);
240-
sess.err(&format!("crate `{}` required to be available in {}, \
241-
but it was not available in this form",
242-
name, kind));
248+
sess.err(&format!("crate `{}` required to be available in {} format, \
249+
but was not found in this form",
250+
tcx.crate_name(cnum), kind));
243251
}
244252
}
245253
}

src/test/compile-fail/cdylib-deps-must-be-static.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern: dependency `cdylib_dep` not found in rlib format
11+
// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
1212
// aux-build:cdylib-dep.rs
1313
// ignore-musl
1414
// ignore-emscripten

src/test/compile-fail/rmeta_lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// aux-build:rmeta_meta.rs
1212
// no-prefer-dynamic
13-
// error-pattern: crate `rmeta_meta` required to be available in rlib, but it was not available
13+
// error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
1414

1515
// Check that building a non-metadata crate fails if a dependent crate is
1616
// metadata-only.

0 commit comments

Comments
 (0)