diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index bfc7fdb1466..33d3a1c67f2 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -1132,8 +1132,41 @@ fn link_args(sess: Session, args.push(~"-Wl,--allow-multiple-definition"); } - add_local_native_libraries(&mut args, sess); + // Take careful note of the ordering of the arguments we pass to the linker + // here. Linkers will assume that things on the left depend on things to the + // right. Things on the right cannot depend on things on the left. This is + // all formally implemented in terms of resolving symbols (libs on the right + // resolve unknown symbols of libs on the left, but not vice versa). + // + // For this reason, we have organized the arguments we pass to the linker as + // such: + // + // 1. The local object that LLVM just generated + // 2. Upstream rust libraries + // 3. Local native libraries + // 4. Upstream native libraries + // + // This is generally fairly natural, but some may expect 2 and 3 to be + // swapped. The reason that all native libraries are put last is that it's + // not recommended for a native library to depend on a symbol from a rust + // crate. If this is the case then a staticlib crate is recommended, solving + // the problem. + // + // Additionally, it is occasionally the case that upstream rust libraries + // depend on a local native library. In the case of libraries such as + // lua/glfw/etc the name of the library isn't the same across all platforms, + // so only the consumer crate of a library knows the actual name. This means + // that downstream crates will provide the #[link] attribute which upstream + // crates will depend on. Hence local native libraries are after out + // upstream rust crates. + // + // In theory this means that a symbol in an upstream native library will be + // shadowed by a local native library when it wouldn't have been before, but + // this kind of behavior is pretty platform specific and generally not + // recommended anyway, so I don't think we're shooting ourself in the foot + // much with that. add_upstream_rust_crates(&mut args, sess, dylib, tmpdir); + add_local_native_libraries(&mut args, sess); add_upstream_native_libraries(&mut args, sess); // # Telling the linker what we're doing diff --git a/src/test/run-make/issue-12446/Makefile b/src/test/run-make/issue-12446/Makefile new file mode 100644 index 00000000000..e864ee0058c --- /dev/null +++ b/src/test/run-make/issue-12446/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(call STATICLIB,foo) + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(call RUN,bar) diff --git a/src/test/run-make/issue-12446/bar.rs b/src/test/run-make/issue-12446/bar.rs new file mode 100644 index 00000000000..cd41058744d --- /dev/null +++ b/src/test/run-make/issue-12446/bar.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +#[link(name = "foo")] +extern {} + +fn main() { + foo::foo(); +} diff --git a/src/test/run-make/issue-12446/foo.c b/src/test/run-make/issue-12446/foo.c new file mode 100644 index 00000000000..a58cd8bb7c9 --- /dev/null +++ b/src/test/run-make/issue-12446/foo.c @@ -0,0 +1 @@ +void some_c_symbol() {} diff --git a/src/test/run-make/issue-12446/foo.rs b/src/test/run-make/issue-12446/foo.rs new file mode 100644 index 00000000000..f16dd5e1d5c --- /dev/null +++ b/src/test/run-make/issue-12446/foo.rs @@ -0,0 +1,19 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[crate_type = "rlib"]; + +extern { + fn some_c_symbol(); +} + +pub fn foo() { + unsafe { some_c_symbol() } +}