Warn when trying to link to a library that is not linkable.
authorLukas Lueg <lukas.lueg@gmail.com>
Sat, 9 Dec 2017 14:24:08 +0000 (15:24 +0100)
committerLukas Lueg <lukas.lueg@gmail.com>
Sun, 10 Dec 2017 19:36:24 +0000 (20:36 +0100)
If a dependency is a library that provides no linkable targets, we warn
about the impending error in rustc about an unresolvable `extern crate`.

Fixes #3169.

src/cargo/ops/cargo_rustc/mod.rs
tests/build.rs

index bc0c812ca208f995f7b8878b15c7959e43b1397e..d0def53d799a7f15ae260db989c1df122a2f07a0 100644 (file)
@@ -896,12 +896,31 @@ fn build_deps_args<'a, 'cfg>(cmd: &mut ProcessBuilder,
         });
     }
 
-    for unit in cx.dep_targets(unit)?.iter() {
+    let dep_targets = cx.dep_targets(unit)?;
+
+    // If there is not one linkable target but should, rustc fails later
+    // on if there is an `extern crate` for it. This may turn into a hard
+    // error in the future, see PR #4797
+    if !dep_targets.iter().any(|u| !u.profile.doc && u.target.linkable()) {
+        if let Some(u) = dep_targets.iter()
+                         .filter(|u| !u.profile.doc && u.target.is_lib())
+                         .next() {
+                cx.config.shell().warn(format!("The package `{}` \
+provides no linkable target. The compiler might raise an error while compiling \
+`{}`. Consider adding 'dylib' or 'rlib' to key `crate-type` in `{}`'s \
+Cargo.toml. This warning might turn into a hard error in the future.",
+                                       u.target.crate_name(),
+                                       unit.target.crate_name(),
+                                       u.target.crate_name()))?;
+            }
+    }
+
+    for unit in dep_targets {
         if unit.profile.run_custom_build {
-            cmd.env("OUT_DIR", &cx.build_script_out_dir(unit));
+            cmd.env("OUT_DIR", &cx.build_script_out_dir(&unit));
         }
         if unit.target.linkable() && !unit.profile.doc {
-            link_to(cmd, cx, unit)?;
+            link_to(cmd, cx, &unit)?;
         }
     }
 
index 523e42d913077ec53e266f23e7954116f1bae604..796fe1fcda5ce17b74be1ce4f627c6f3fd5ff552 100644 (file)
@@ -3971,3 +3971,34 @@ fn all_targets_no_lib() {
             -C debuginfo=2 --test [..]")
         );
 }
+
+#[test]
+fn no_linkable_target() {
+    // Issue 3169. This is currently not an error as per discussion in PR #4797
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.1.0"
+            authors = []
+            [dependencies]
+            the_lib = { path = "the_lib" }
+        "#)
+        .file("src/main.rs", "fn main() {}")
+        .file("the_lib/Cargo.toml", r#"
+            [package]
+            name = "the_lib"
+            version = "0.1.0"
+            [lib]
+            name = "the_lib"
+            crate-type = ["staticlib"]
+        "#)
+        .file("the_lib/src/lib.rs", "pub fn foo() {}")
+        .build();
+    assert_that(p.cargo("build"),
+                execs()
+                .with_status(0)
+                .with_stderr_contains("\
+                [WARNING] The package `the_lib` provides no linkable [..] \
+while compiling `foo`. [..] in `the_lib`'s Cargo.toml. [..]"));
+}