}
}
- 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
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
// 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;
}
}
}
-// # 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");
+ }
}
}
- }
+ });
}