]> git.lizzy.rs Git - rust.git/commitdiff
Resume propagation of linking to native dylibs
authorAlex Crichton <alex@alexcrichton.com>
Mon, 2 Dec 2013 22:37:30 +0000 (14:37 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 3 Dec 2013 16:19:33 +0000 (08:19 -0800)
The reasons for this are outlined in issue #10743 as well as the comment I have
now placed in the code.

Closes #10743

src/librustc/back/link.rs
src/test/auxiliary/anon-extern-mod-cross-crate-1.rs
src/test/run-pass/anon-extern-mod-cross-crate-2.rs
src/test/run-pass/invoke-external-foreign.rs

index 6b9f8f763968e09f4a5833b67ed6265ef0d45613..cf8fd77b47a50803c1ad8611202646b074c59df7 100644 (file)
@@ -1127,8 +1127,9 @@ fn link_args(sess: Session,
         }
     }
 
-    add_upstream_rust_crates(&mut args, sess, dylib);
     add_local_native_libraries(&mut args, sess);
+    add_upstream_rust_crates(&mut args, sess, dylib);
+    add_upstream_native_libraries(&mut args, sess);
 
     // # Telling the linker what we're doing
 
@@ -1168,6 +1169,42 @@ fn link_args(sess: Session,
     return args;
 }
 
+// # Native library linking
+//
+// User-supplied library search paths (-L on the cammand line) These are
+// the same paths used to find Rust crates, so some of them may have been
+// added already by the previous crate linking code. This only allows them
+// to be found at compile time so it is still entirely up to outside
+// forces to make sure that library can be found at runtime.
+//
+// Also note that the native libraries linked here are only the ones located
+// in the current crate. Upstream crates with native library dependencies
+// may have their native library pulled in above.
+fn add_local_native_libraries(args: &mut ~[~str], sess: Session) {
+    for path in sess.opts.addl_lib_search_paths.iter() {
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        args.push("-L" + path.as_str().unwrap().to_owned());
+    }
+
+    let rustpath = filesearch::rust_path();
+    for path in rustpath.iter() {
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        args.push("-L" + path.as_str().unwrap().to_owned());
+    }
+
+    for &(ref l, kind) in cstore::get_used_libraries(sess.cstore).iter() {
+        match kind {
+            cstore::NativeUnknown | cstore::NativeStatic => {
+                args.push("-l" + *l);
+            }
+            cstore::NativeFramework => {
+                args.push(~"-framework");
+                args.push(l.to_owned());
+            }
+        }
+    }
+}
+
 // # Rust Crate linking
 //
 // Rust crates are not considered at all when creating an rlib output. All
@@ -1197,30 +1234,11 @@ fn unlib(config: @session::config, stem: &str) -> ~str {
         // all dynamic libaries require dynamic dependencies (see above), so
         // it's satisfactory to include either all static libraries or all
         // dynamic libraries.
-        let crates = cstore::get_used_crates(cstore,
-                                             cstore::RequireStatic);
+        let crates = cstore::get_used_crates(cstore, cstore::RequireStatic);
         if crates.iter().all(|&(_, ref p)| p.is_some()) {
-            for &(cnum, ref path) in crates.iter() {
-                let cratepath = path.clone().unwrap();
-
-                // If we're linking to the static version of the crate, then
-                // we're mostly good to go. The caveat here is that we need to
-                // pull in the static crate's native dependencies.
-                args.push(cratepath.as_str().unwrap().to_owned());
-
-                let libs = csearch::get_native_libraries(sess.cstore, cnum);
-                for &(kind, ref lib) in libs.iter() {
-                    match kind {
-                        cstore::NativeUnknown => args.push("-l" + *lib),
-                        cstore::NativeFramework => {
-                            args.push(~"-framework");
-                            args.push(lib.to_owned());
-                        }
-                        cstore::NativeStatic => {
-                            sess.bug("statics shouldn't be propagated");
-                        }
-                    }
-                }
+            for (_, path) in crates.move_iter() {
+                let path = path.unwrap();
+                args.push(path.as_str().unwrap().to_owned());
             }
             return;
         }
@@ -1253,38 +1271,39 @@ fn unlib(config: @session::config, stem: &str) -> ~str {
     }
 }
 
-// # Native library linking
+// Link in all of our upstream crates' native dependencies. Remember that
+// all of these upstream native depenencies are all non-static
+// dependencies. We've got two cases then:
 //
-// User-supplied library search paths (-L on the cammand line) These are
-// the same paths used to find Rust crates, so some of them may have been
-// added already by the previous crate linking code. This only allows them
-// to be found at compile time so it is still entirely up to outside
-// forces to make sure that library can be found at runtime.
+// 1. The upstream crate is an rlib. In this case we *must* link in the
+//    native dependency because the rlib is just an archive.
 //
-// Also note that the native libraries linked here are only the ones located
-// in the current crate. Upstream crates with native library dependencies
-// may have their native library pulled in above.
-fn add_local_native_libraries(args: &mut ~[~str], sess: Session) {
-    for path in sess.opts.addl_lib_search_paths.iter() {
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        args.push("-L" + path.as_str().unwrap().to_owned());
-    }
-
-    let rustpath = filesearch::rust_path();
-    for path in rustpath.iter() {
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        args.push("-L" + path.as_str().unwrap().to_owned());
-    }
-
-    for &(ref l, kind) in cstore::get_used_libraries(sess.cstore).iter() {
-        match kind {
-            cstore::NativeUnknown | cstore::NativeStatic => {
-                args.push("-l" + *l);
-            }
-            cstore::NativeFramework => {
-                args.push(~"-framework");
-                args.push(l.to_owned());
+// 2. The upstream crate is a dylib. In order to use the dylib, we have to
+//    have the dependency present on the system somewhere. Thus, we don't
+//    gain a whole lot from not linking in the dynamic dependency to this
+//    crate as well.
+//
+// The use case for this is a little subtle. In theory the native
+// dependencies of a crate a purely an implementation detail of the crate
+// itself, but the problem arises with generic and inlined functions. If a
+// generic function calls a native function, then the generic function must
+// be instantiated in the target crate, meaning that the native symbol must
+// also be resolved in the target crate.
+fn add_upstream_native_libraries(args: &mut ~[~str], sess: Session) {
+    let cstore = sess.cstore;
+    cstore::iter_crate_data(cstore, |cnum, _| {
+        let libs = csearch::get_native_libraries(cstore, cnum);
+        for &(kind, ref lib) in libs.iter() {
+            match kind {
+                cstore::NativeUnknown => args.push("-l" + *lib),
+                cstore::NativeFramework => {
+                    args.push(~"-framework");
+                    args.push(lib.to_owned());
+                }
+                cstore::NativeStatic => {
+                    sess.bug("statics shouldn't be propagated");
+                }
             }
         }
-    }
+    });
 }
index 01a90f1ad449b73e460dce483864dfe896fe33bc..cce7df565048902e1c64e6e423c2fe744ed02571 100644 (file)
@@ -14,7 +14,7 @@
 
 use std::libc;
 
+#[link(name = "rustrt")]
 extern {
-    #[link(name = "rustrt")]
     pub fn rust_get_test_int() -> libc::intptr_t;
 }
index 4c2e78db398452be7e20719fad04ef6798378aa7..e31f28ed7a20ed15d2d4f5fbe994a211dcbdeef1 100644 (file)
@@ -15,9 +15,6 @@
 
 use anonexternmod::rust_get_test_int;
 
-#[link(name = "rustrt")] // we have explicitly chosen to require this
-extern {}
-
 pub fn main() {
     unsafe {
         rust_get_test_int();
index ec531d391e42283706b4d15e6b72e8455e491266..b48b8c3cd4599a6fa49730d5f7198e2c62135873 100644 (file)
@@ -18,9 +18,6 @@
 
 extern mod foreign_lib;
 
-#[link(name = "rustrt")] // we have explicitly chosen to require this
-extern {}
-
 pub fn main() {
     unsafe {
         let _foo = foreign_lib::rustrt::rust_get_test_int();