@@ -1127,8 +1127,9 @@ fn link_args(sess: Session,
11271127 }
11281128 }
11291129
1130- add_upstream_rust_crates ( & mut args, sess, dylib) ;
11311130 add_local_native_libraries ( & mut args, sess) ;
1131+ add_upstream_rust_crates ( & mut args, sess, dylib) ;
1132+ add_upstream_native_libraries ( & mut args, sess) ;
11321133
11331134 // # Telling the linker what we're doing
11341135
@@ -1168,6 +1169,42 @@ fn link_args(sess: Session,
11681169 return args;
11691170}
11701171
1172+ // # Native library linking
1173+ //
1174+ // User-supplied library search paths (-L on the cammand line) These are
1175+ // the same paths used to find Rust crates, so some of them may have been
1176+ // added already by the previous crate linking code. This only allows them
1177+ // to be found at compile time so it is still entirely up to outside
1178+ // forces to make sure that library can be found at runtime.
1179+ //
1180+ // Also note that the native libraries linked here are only the ones located
1181+ // in the current crate. Upstream crates with native library dependencies
1182+ // may have their native library pulled in above.
1183+ fn add_local_native_libraries ( args : & mut ~[ ~str ] , sess : Session ) {
1184+ for path in sess. opts . addl_lib_search_paths . iter ( ) {
1185+ // FIXME (#9639): This needs to handle non-utf8 paths
1186+ args. push ( "-L" + path. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1187+ }
1188+
1189+ let rustpath = filesearch:: rust_path ( ) ;
1190+ for path in rustpath. iter ( ) {
1191+ // FIXME (#9639): This needs to handle non-utf8 paths
1192+ args. push ( "-L" + path. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1193+ }
1194+
1195+ for & ( ref l, kind) in cstore:: get_used_libraries ( sess. cstore ) . iter ( ) {
1196+ match kind {
1197+ cstore:: NativeUnknown | cstore:: NativeStatic => {
1198+ args. push ( "-l" + * l) ;
1199+ }
1200+ cstore:: NativeFramework => {
1201+ args. push ( ~"-framework") ;
1202+ args. push ( l. to_owned ( ) ) ;
1203+ }
1204+ }
1205+ }
1206+ }
1207+
11711208// # Rust Crate linking
11721209//
11731210// Rust crates are not considered at all when creating an rlib output. All
@@ -1197,30 +1234,11 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session,
11971234 // all dynamic libaries require dynamic dependencies (see above), so
11981235 // it's satisfactory to include either all static libraries or all
11991236 // dynamic libraries.
1200- let crates = cstore:: get_used_crates ( cstore,
1201- cstore:: RequireStatic ) ;
1237+ let crates = cstore:: get_used_crates ( cstore, cstore:: RequireStatic ) ;
12021238 if crates. iter ( ) . all ( |& ( _, ref p) | p. is_some ( ) ) {
1203- for & ( cnum, ref path) in crates. iter ( ) {
1204- let cratepath = path. clone ( ) . unwrap ( ) ;
1205-
1206- // If we're linking to the static version of the crate, then
1207- // we're mostly good to go. The caveat here is that we need to
1208- // pull in the static crate's native dependencies.
1209- args. push ( cratepath. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1210-
1211- let libs = csearch:: get_native_libraries ( sess. cstore , cnum) ;
1212- for & ( kind, ref lib) in libs. iter ( ) {
1213- match kind {
1214- cstore:: NativeUnknown => args. push ( "-l" + * lib) ,
1215- cstore:: NativeFramework => {
1216- args. push ( ~"-framework") ;
1217- args. push ( lib. to_owned ( ) ) ;
1218- }
1219- cstore:: NativeStatic => {
1220- sess. bug ( "statics shouldn't be propagated" ) ;
1221- }
1222- }
1223- }
1239+ for ( _, path) in crates. move_iter ( ) {
1240+ let path = path. unwrap ( ) ;
1241+ args. push ( path. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
12241242 }
12251243 return ;
12261244 }
@@ -1253,38 +1271,39 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session,
12531271 }
12541272}
12551273
1256- // # Native library linking
1274+ // Link in all of our upstream crates' native dependencies. Remember that
1275+ // all of these upstream native depenencies are all non-static
1276+ // dependencies. We've got two cases then:
12571277//
1258- // User-supplied library search paths (-L on the cammand line) These are
1259- // the same paths used to find Rust crates, so some of them may have been
1260- // added already by the previous crate linking code. This only allows them
1261- // to be found at compile time so it is still entirely up to outside
1262- // forces to make sure that library can be found at runtime.
1278+ // 1. The upstream crate is an rlib. In this case we *must* link in the
1279+ // native dependency because the rlib is just an archive.
12631280//
1264- // Also note that the native libraries linked here are only the ones located
1265- // in the current crate. Upstream crates with native library dependencies
1266- // may have their native library pulled in above.
1267- fn add_local_native_libraries ( args : & mut ~[ ~str ] , sess : Session ) {
1268- for path in sess. opts . addl_lib_search_paths . iter ( ) {
1269- // FIXME (#9639): This needs to handle non-utf8 paths
1270- args. push ( "-L" + path. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1271- }
1272-
1273- let rustpath = filesearch:: rust_path ( ) ;
1274- for path in rustpath. iter ( ) {
1275- // FIXME (#9639): This needs to handle non-utf8 paths
1276- args. push ( "-L" + path. as_str ( ) . unwrap ( ) . to_owned ( ) ) ;
1277- }
1278-
1279- for & ( ref l, kind) in cstore:: get_used_libraries ( sess. cstore ) . iter ( ) {
1280- match kind {
1281- cstore:: NativeUnknown | cstore:: NativeStatic => {
1282- args. push ( "-l" + * l) ;
1283- }
1284- cstore:: NativeFramework => {
1285- args. push ( ~"-framework") ;
1286- args. push ( l. to_owned ( ) ) ;
1281+ // 2. The upstream crate is a dylib. In order to use the dylib, we have to
1282+ // have the dependency present on the system somewhere. Thus, we don't
1283+ // gain a whole lot from not linking in the dynamic dependency to this
1284+ // crate as well.
1285+ //
1286+ // The use case for this is a little subtle. In theory the native
1287+ // dependencies of a crate a purely an implementation detail of the crate
1288+ // itself, but the problem arises with generic and inlined functions. If a
1289+ // generic function calls a native function, then the generic function must
1290+ // be instantiated in the target crate, meaning that the native symbol must
1291+ // also be resolved in the target crate.
1292+ fn add_upstream_native_libraries ( args : & mut ~[ ~str ] , sess : Session ) {
1293+ let cstore = sess. cstore ;
1294+ cstore:: iter_crate_data ( cstore, |cnum, _| {
1295+ let libs = csearch:: get_native_libraries ( cstore, cnum) ;
1296+ for & ( kind, ref lib) in libs. iter ( ) {
1297+ match kind {
1298+ cstore:: NativeUnknown => args. push ( "-l" + * lib) ,
1299+ cstore:: NativeFramework => {
1300+ args. push ( ~"-framework") ;
1301+ args. push ( lib. to_owned ( ) ) ;
1302+ }
1303+ cstore:: NativeStatic => {
1304+ sess. bug ( "statics shouldn't be propagated" ) ;
1305+ }
12871306 }
12881307 }
1289- }
1308+ } ) ;
12901309}
0 commit comments