Skip to content

Commit 0dc9f62

Browse files
committed
Resume propagation of linking to native dylibs
The reasons for this are outlined in issue #10743 as well as the comment I have now placed in the code. Closes #10743
1 parent 6437122 commit 0dc9f62

File tree

4 files changed

+74
-61
lines changed

4 files changed

+74
-61
lines changed

src/librustc/back/link.rs

+73-54
Original file line numberDiff line numberDiff line change
@@ -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
}

src/test/auxiliary/anon-extern-mod-cross-crate-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use std::libc;
1616

17+
#[link(name = "rustrt")]
1718
extern {
18-
#[link(name = "rustrt")]
1919
pub fn rust_get_test_int() -> libc::intptr_t;
2020
}

src/test/run-pass/anon-extern-mod-cross-crate-2.rs

-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ extern mod anonexternmod;
1515

1616
use anonexternmod::rust_get_test_int;
1717

18-
#[link(name = "rustrt")] // we have explicitly chosen to require this
19-
extern {}
20-
2118
pub fn main() {
2219
unsafe {
2320
rust_get_test_int();

src/test/run-pass/invoke-external-foreign.rs

-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818

1919
extern mod foreign_lib;
2020

21-
#[link(name = "rustrt")] // we have explicitly chosen to require this
22-
extern {}
23-
2421
pub fn main() {
2522
unsafe {
2623
let _foo = foreign_lib::rustrt::rust_get_test_int();

0 commit comments

Comments
 (0)