Skip to content

Commit

Permalink
rustc: Move local native libs back in link-args
Browse files Browse the repository at this point in the history
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 rust-lang#12446
  • Loading branch information
alexcrichton committed Feb 27, 2014
1 parent 05a2d32 commit 3768c4f
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 1 deletion.
35 changes: 34 additions & 1 deletion src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/test/run-make/issue-12446/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-include ../tools.mk

all: $(call STATICLIB,foo)
$(RUSTC) foo.rs
$(RUSTC) bar.rs
$(call RUN,bar)
18 changes: 18 additions & 0 deletions src/test/run-make/issue-12446/bar.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
}
1 change: 1 addition & 0 deletions src/test/run-make/issue-12446/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
void some_c_symbol() {}
19 changes: 19 additions & 0 deletions src/test/run-make/issue-12446/foo.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() }
}

3 comments on commit 3768c4f

@brson
Copy link

@brson brson commented on 3768c4f Feb 27, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

@alexcrichton
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors: retry

@alexcrichton
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors: retry

Please sign in to comment.