@@ -1127,8 +1127,9 @@ fn link_args(sess: Session,
1127
1127
}
1128
1128
}
1129
1129
1130
- add_upstream_rust_crates ( & mut args, sess, dylib) ;
1131
1130
add_local_native_libraries ( & mut args, sess) ;
1131
+ add_upstream_rust_crates ( & mut args, sess, dylib) ;
1132
+ add_upstream_native_libraries ( & mut args, sess) ;
1132
1133
1133
1134
// # Telling the linker what we're doing
1134
1135
@@ -1168,6 +1169,42 @@ fn link_args(sess: Session,
1168
1169
return args;
1169
1170
}
1170
1171
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
+
1171
1208
// # Rust Crate linking
1172
1209
//
1173
1210
// 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,
1197
1234
// all dynamic libaries require dynamic dependencies (see above), so
1198
1235
// it's satisfactory to include either all static libraries or all
1199
1236
// dynamic libraries.
1200
- let crates = cstore:: get_used_crates ( cstore,
1201
- cstore:: RequireStatic ) ;
1237
+ let crates = cstore:: get_used_crates ( cstore, cstore:: RequireStatic ) ;
1202
1238
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 ( ) ) ;
1224
1242
}
1225
1243
return ;
1226
1244
}
@@ -1253,38 +1271,39 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session,
1253
1271
}
1254
1272
}
1255
1273
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:
1257
1277
//
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.
1263
1280
//
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
+ }
1287
1306
}
1288
1307
}
1289
- }
1308
+ } ) ;
1290
1309
}
0 commit comments