Skip to content

Commit 3768c4f

Browse files
committed
rustc: Move local native libs back in link-args
With linkers on unix systems, libraries on the right of the command line are used to resolve symbols in those on the left of the command line. This means that arguments must have a right-to-left dependency chain (things on the left depend on things on the right). This is currently done by ordering the linker arguments as 1. Local object 2. Local native libraries 3. Upstream rust libraries 4. Upstream native libraries This commit swaps the order of 2 and 3 so upstream rust libraries have access to local native libraries. It has been seen that some upstream crates don't specify the library that they link to because the name varies per platform (e.g. lua/glfw/etc). This commit enables building these libraries by allowing the upstream rust crate to have access to local native libraries. I believe that the failure mode for this scheme is when an upstream rust crate depends on a symbol in an upstream library which is then redefined in a local library. This failure mode is incredibly uncommon, and the failure mode also varies per platform (OSX behaves differently), so I believe that a change like this is fine to make. Closes #12446
1 parent 05a2d32 commit 3768c4f

File tree

5 files changed

+78
-1
lines changed

5 files changed

+78
-1
lines changed

src/librustc/back/link.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,8 +1132,41 @@ fn link_args(sess: Session,
11321132
args.push(~"-Wl,--allow-multiple-definition");
11331133
}
11341134

1135-
add_local_native_libraries(&mut args, sess);
1135+
// Take careful note of the ordering of the arguments we pass to the linker
1136+
// here. Linkers will assume that things on the left depend on things to the
1137+
// right. Things on the right cannot depend on things on the left. This is
1138+
// all formally implemented in terms of resolving symbols (libs on the right
1139+
// resolve unknown symbols of libs on the left, but not vice versa).
1140+
//
1141+
// For this reason, we have organized the arguments we pass to the linker as
1142+
// such:
1143+
//
1144+
// 1. The local object that LLVM just generated
1145+
// 2. Upstream rust libraries
1146+
// 3. Local native libraries
1147+
// 4. Upstream native libraries
1148+
//
1149+
// This is generally fairly natural, but some may expect 2 and 3 to be
1150+
// swapped. The reason that all native libraries are put last is that it's
1151+
// not recommended for a native library to depend on a symbol from a rust
1152+
// crate. If this is the case then a staticlib crate is recommended, solving
1153+
// the problem.
1154+
//
1155+
// Additionally, it is occasionally the case that upstream rust libraries
1156+
// depend on a local native library. In the case of libraries such as
1157+
// lua/glfw/etc the name of the library isn't the same across all platforms,
1158+
// so only the consumer crate of a library knows the actual name. This means
1159+
// that downstream crates will provide the #[link] attribute which upstream
1160+
// crates will depend on. Hence local native libraries are after out
1161+
// upstream rust crates.
1162+
//
1163+
// In theory this means that a symbol in an upstream native library will be
1164+
// shadowed by a local native library when it wouldn't have been before, but
1165+
// this kind of behavior is pretty platform specific and generally not
1166+
// recommended anyway, so I don't think we're shooting ourself in the foot
1167+
// much with that.
11361168
add_upstream_rust_crates(&mut args, sess, dylib, tmpdir);
1169+
add_local_native_libraries(&mut args, sess);
11371170
add_upstream_native_libraries(&mut args, sess);
11381171

11391172
// # Telling the linker what we're doing
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-include ../tools.mk
2+
3+
all: $(call STATICLIB,foo)
4+
$(RUSTC) foo.rs
5+
$(RUSTC) bar.rs
6+
$(call RUN,bar)

src/test/run-make/issue-12446/bar.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate foo;
12+
13+
#[link(name = "foo")]
14+
extern {}
15+
16+
fn main() {
17+
foo::foo();
18+
}

src/test/run-make/issue-12446/foo.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void some_c_symbol() {}

src/test/run-make/issue-12446/foo.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[crate_type = "rlib"];
12+
13+
extern {
14+
fn some_c_symbol();
15+
}
16+
17+
pub fn foo() {
18+
unsafe { some_c_symbol() }
19+
}

0 commit comments

Comments
 (0)