about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-03-13 18:47:43 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-03-15 22:26:36 -0700
commit17ad504fef35191fe53874bd2fe77ffd14d8e1b9 (patch)
tree9b0e09c20f0f71bfba78e55e7bc372b5896b33f0
parent0b3df19c6a02a743dae904245c6f98424e75af8c (diff)
downloadrust-17ad504fef35191fe53874bd2fe77ffd14d8e1b9.tar.gz
rust-17ad504fef35191fe53874bd2fe77ffd14d8e1b9.zip
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.
-rw-r--r--src/librustc/metadata/cstore.rs32
1 files 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<Path>)> {
+        let mut ordering = Vec::new();
+        fn visit(cstore: &CStore, cnum: ast::CrateNum,
+                 ordering: &mut Vec<ast::CrateNum>) {
+            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) {