From 17ad504fef35191fe53874bd2fe77ffd14d8e1b9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 13 Mar 2014 18:47:43 -0700 Subject: [PATCH] rustc: Topographically sort rust dependencies This commit starts to topographically sort rust dependencies on the linker command line. The reason for this is that linkers use right-hand libraries to resolve left-hand libraries symbols, which is especially crucial for us because we're using --as-needed on linux. --- src/librustc/metadata/cstore.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index d502018da17..e6628da89f5 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -143,16 +143,44 @@ impl CStore { self.used_link_args.with_mut(|s| s.clear()); } + // This method is used when generating the command line to pass through to + // system linker. The linker expects undefined symbols on the left of the + // command line to be defined in libraries on the right, not the other way + // around. For more info, see some comments in the add_used_library function + // below. + // + // In order to get this left-to-right dependency ordering, we perform a + // topological sort of all crates putting the leaves at the right-most + // positions. pub fn get_used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option)> { + let mut ordering = Vec::new(); + fn visit(cstore: &CStore, cnum: ast::CrateNum, + ordering: &mut Vec) { + if ordering.as_slice().contains(&cnum) { return } + let meta = cstore.get_crate_data(cnum); + for (_, &dep) in meta.cnum_map.borrow().get().iter() { + visit(cstore, dep, ordering); + } + ordering.push(cnum); + }; + for (&num, _) in self.metas.borrow().get().iter() { + visit(self, num, &mut ordering); + } + ordering.as_mut_slice().reverse(); + let ordering = ordering.as_slice(); let used_crate_sources = self.used_crate_sources.borrow(); - used_crate_sources.get() + let mut libs = used_crate_sources.get() .iter() .map(|src| (src.cnum, match prefer { RequireDynamic => src.dylib.clone(), RequireStatic => src.rlib.clone(), })) - .collect() + .collect(); + libs.sort_by(|&(a, _), &(b, _)| { + ordering.position_elem(&a).cmp(&ordering.position_elem(&b)) + }); + libs } pub fn add_used_library(&self, lib: ~str, kind: NativeLibaryKind) {