diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 4e407d52329ff..9ac99b267169e 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -1487,15 +1487,24 @@ fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session, // crate as well. // // The use case for this is a little subtle. In theory the native -// dependencies of a crate a purely an implementation detail of the crate +// dependencies of a crate are purely an implementation detail of the crate // itself, but the problem arises with generic and inlined functions. If a // generic function calls a native function, then the generic function must // be instantiated in the target crate, meaning that the native symbol must // also be resolved in the target crate. fn add_upstream_native_libraries(args: &mut Vec<~str>, sess: &Session) { - let cstore = &sess.cstore; - cstore.iter_crate_data(|cnum, _| { - let libs = csearch::get_native_libraries(cstore, cnum); + // Be sure to use a topological sorting of crates becuase there may be + // interdependencies between native libraries. When passing -nodefaultlibs, + // for example, almost all native libraries depend on libc, so we have to + // make sure that's all the way at the right (liblibc is near the base of + // the dependency chain). + // + // This passes RequireStatic, but the actual requirement doesn't matter, + // we're just getting an ordering of crate numbers, we're not worried about + // the paths. + let crates = sess.cstore.get_used_crates(cstore::RequireStatic); + for (cnum, _) in crates.move_iter() { + let libs = csearch::get_native_libraries(&sess.cstore, cnum); for &(kind, ref lib) in libs.iter() { match kind { cstore::NativeUnknown => args.push("-l" + *lib), @@ -1508,5 +1517,5 @@ fn add_upstream_native_libraries(args: &mut Vec<~str>, sess: &Session) { } } } - }); + } } diff --git a/src/test/run-make/interdependent-c-libraries/Makefile b/src/test/run-make/interdependent-c-libraries/Makefile new file mode 100644 index 0000000000000..7654917b46232 --- /dev/null +++ b/src/test/run-make/interdependent-c-libraries/Makefile @@ -0,0 +1,15 @@ +-include ../tools.mk + +# The rust crate foo will link to the native library foo, while the rust crate +# bar will link to the native library bar. There is also a dependency between +# the native library bar to the natibe library foo. +# +# This test ensures that the ordering of -lfoo and -lbar on the command line is +# correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo' +# library will be stripped out, and the linkage will fail. + +all: $(call STATICLIB,foo) $(call STATICLIB,bar) + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(RUSTC) main.rs -Z print-link-args + diff --git a/src/test/run-make/interdependent-c-libraries/bar.c b/src/test/run-make/interdependent-c-libraries/bar.c new file mode 100644 index 0000000000000..812c975352872 --- /dev/null +++ b/src/test/run-make/interdependent-c-libraries/bar.c @@ -0,0 +1,3 @@ +void foo(); + +void bar() { foo(); } diff --git a/src/test/run-make/interdependent-c-libraries/bar.rs b/src/test/run-make/interdependent-c-libraries/bar.rs new file mode 100644 index 0000000000000..5311af2959b2c --- /dev/null +++ b/src/test/run-make/interdependent-c-libraries/bar.rs @@ -0,0 +1,23 @@ +// 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 crate foo; + +#[link(name = "bar")] +extern { + fn bar(); +} + +pub fn doit() { + unsafe { bar(); } +} + diff --git a/src/test/run-make/interdependent-c-libraries/foo.c b/src/test/run-make/interdependent-c-libraries/foo.c new file mode 100644 index 0000000000000..85e6cd8c3909a --- /dev/null +++ b/src/test/run-make/interdependent-c-libraries/foo.c @@ -0,0 +1 @@ +void foo() {} diff --git a/src/test/run-make/interdependent-c-libraries/foo.rs b/src/test/run-make/interdependent-c-libraries/foo.rs new file mode 100644 index 0000000000000..f94c6edb97d71 --- /dev/null +++ b/src/test/run-make/interdependent-c-libraries/foo.rs @@ -0,0 +1,20 @@ +// 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"] + +#[link(name = "foo")] +extern { + fn foo(); +} + +pub fn doit() { + unsafe { foo(); } +} diff --git a/src/test/run-make/interdependent-c-libraries/main.rs b/src/test/run-make/interdependent-c-libraries/main.rs new file mode 100644 index 0000000000000..f42e3dd44a924 --- /dev/null +++ b/src/test/run-make/interdependent-c-libraries/main.rs @@ -0,0 +1,16 @@ +// 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; +extern crate bar; + +fn main() { + bar::doit(); +}