about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-25 20:37:02 +0000
committerbors <bors@rust-lang.org>2017-09-25 20:37:02 +0000
commit6c476ce462333fccd89ce3ed8c290998db874653 (patch)
treeb038e489f1b2bbaa639778c0061506fbe96826ad
parent3df1f7b82d9bede5122ee745cdd4e731abbce892 (diff)
parent314c2b14479a98acf9155dce43348e77073a09a1 (diff)
downloadrust-6c476ce462333fccd89ce3ed8c290998db874653.tar.gz
rust-6c476ce462333fccd89ce3ed8c290998db874653.zip
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`.
-rw-r--r--src/librustc/middle/dependency_format.rs86
-rw-r--r--src/test/compile-fail/cdylib-deps-must-be-static.rs2
-rw-r--r--src/test/compile-fail/rmeta_lib.rs2
3 files changed, 49 insertions, 41 deletions
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 1c7d0b76a64..db0ecb6aa5e 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -112,52 +112,61 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return Vec::new();
     }
 
-    match ty {
-        // If the global prefer_dynamic switch is turned off, first attempt
-        // static linkage (this can fail).
-        config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
-            if let Some(v) = attempt_static(tcx) {
-                return v;
-            }
-        }
+    let preferred_linkage = match ty {
+        // cdylibs must have all static dependencies.
+        config::CrateTypeCdylib => Linkage::Static,
+
+        // Generating a dylib without `-C prefer-dynamic` means that we're going
+        // to try to eagerly statically link all dependencies. This is normally
+        // done for end-product dylibs, not intermediate products.
+        config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
+        config::CrateTypeDylib => Linkage::Dynamic,
+
+        // If the global prefer_dynamic switch is turned off, or the final
+        // executable will be statically linked, prefer static crate linkage.
+        config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic ||
+            sess.crt_static() => Linkage::Static,
+        config::CrateTypeExecutable => Linkage::Dynamic,
+
+        // proc-macro crates are required to be dylibs, and they're currently
+        // required to link to libsyntax as well.
+        config::CrateTypeProcMacro => Linkage::Dynamic,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        config::CrateTypeRlib => return Vec::new(),
-
-        // Staticlibs and cdylibs must have all static dependencies. If any fail
-        // to be found, we generate some nice pretty errors.
-        config::CrateTypeStaticlib |
-        config::CrateTypeCdylib => {
-            if let Some(v) = attempt_static(tcx) {
-                return v;
-            }
+        config::CrateTypeRlib => Linkage::NotLinked,
+
+        // staticlibs must have all static dependencies.
+        config::CrateTypeStaticlib => Linkage::Static,
+    };
+
+    if preferred_linkage == Linkage::NotLinked {
+        // If the crate is not linked, there are no link-time dependencies.
+        return Vec::new();
+    }
+
+    if preferred_linkage == Linkage::Static {
+        // Attempt static linkage first. For dylibs and executables, we may be
+        // able to retry below with dynamic linkage.
+        if let Some(v) = attempt_static(tcx) {
+            return v;
+        }
+
+        // Staticlibs, cdylibs, and static executables must have all static
+        // dependencies. If any are not found, generate some nice pretty errors.
+        if ty == config::CrateTypeCdylib || ty == config::CrateTypeStaticlib ||
+                (ty == config::CrateTypeExecutable && sess.crt_static() &&
+                !sess.target.target.options.crt_static_allows_dylibs) {
             for &cnum in tcx.crates().iter() {
                 if tcx.dep_kind(cnum).macros_only() { continue }
                 let src = tcx.used_crate_source(cnum);
                 if src.rlib.is_some() { continue }
-                sess.err(&format!("dependency `{}` not found in rlib format",
+                sess.err(&format!("crate `{}` required to be available in rlib format, \
+                                  but was not found in this form",
                                   tcx.crate_name(cnum)));
             }
             return Vec::new();
         }
-
-        // Generating a dylib without `-C prefer-dynamic` means that we're going
-        // to try to eagerly statically link all dependencies. This is normally
-        // done for end-product dylibs, not intermediate products.
-        config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => {
-            if let Some(v) = attempt_static(tcx) {
-                return v;
-            }
-        }
-
-        // Everything else falls through below. This will happen either with the
-        // `-C prefer-dynamic` or because we're a proc-macro crate. Note that
-        // proc-macro crates are required to be dylibs, and they're currently
-        // required to link to libsyntax as well.
-        config::CrateTypeExecutable |
-        config::CrateTypeDylib |
-        config::CrateTypeProcMacro => {},
     }
 
     let mut formats = FxHashMap();
@@ -236,10 +245,9 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     Linkage::Static => "rlib",
                     _ => "dylib",
                 };
-                let name = tcx.crate_name(cnum);
-                sess.err(&format!("crate `{}` required to be available in {}, \
-                                  but it was not available in this form",
-                                  name, kind));
+                sess.err(&format!("crate `{}` required to be available in {} format, \
+                                  but was not found in this form",
+                                  tcx.crate_name(cnum), kind));
             }
         }
     }
diff --git a/src/test/compile-fail/cdylib-deps-must-be-static.rs b/src/test/compile-fail/cdylib-deps-must-be-static.rs
index 853507cbc6d..bf7189c21fb 100644
--- a/src/test/compile-fail/cdylib-deps-must-be-static.rs
+++ b/src/test/compile-fail/cdylib-deps-must-be-static.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: dependency `cdylib_dep` not found in rlib format
+// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
 // aux-build:cdylib-dep.rs
 // ignore-musl
 // ignore-emscripten
diff --git a/src/test/compile-fail/rmeta_lib.rs b/src/test/compile-fail/rmeta_lib.rs
index 3b7d1f3cc90..a61ff05e8c8 100644
--- a/src/test/compile-fail/rmeta_lib.rs
+++ b/src/test/compile-fail/rmeta_lib.rs
@@ -10,7 +10,7 @@
 
 // aux-build:rmeta_meta.rs
 // no-prefer-dynamic
-// error-pattern: crate `rmeta_meta` required to be available in rlib, but it was not available
+// error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
 
 // Check that building a non-metadata crate fails if a dependent crate is
 // metadata-only.