about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2015-08-08 11:33:43 -0700
committerBrian Anderson <banderson@mozilla.com>2015-12-28 18:08:16 +0000
commit34dc0e0739e19811850f82f1e45b61ba97adc96e (patch)
treec8f85b3312c828bb49816465e03a989df4301f92 /src
parent27a1834ce522e3ec7fe4726b1661de16ee30c503 (diff)
downloadrust-34dc0e0739e19811850f82f1e45b61ba97adc96e.tar.gz
rust-34dc0e0739e19811850f82f1e45b61ba97adc96e.zip
Link with ld.gold by default
To disable, pass `-C disable-gold`
Diffstat (limited to 'src')
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc_trans/back/link.rs4
-rw-r--r--src/librustc_trans/back/linker.rs51
3 files changed, 57 insertions, 0 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index d1c7da1d107..745be426676 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -539,6 +539,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
         "explicitly enable the cfg(debug_assertions) directive"),
     inline_threshold: Option<usize> = (None, parse_opt_uint,
         "set the inlining threshold for"),
+    disable_gold: bool = (false, parse_bool,
+        "disable use of the ld.gold linker"),
 }
 
 
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index fb79f804932..1e5bac85ffc 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -1060,6 +1060,10 @@ fn link_args(cmd: &mut Linker,
         cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
     }
 
+    // Use the gold linker if possible instead of ld. It is much
+    // faster.
+    cmd.try_gold_linker();
+
     // Finally add all the linker arguments provided on the command line along
     // with any #[link_args] attributes found inside the crate
     if let Some(ref args) = sess.opts.cg.link_args {
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index 1ee1c9f1912..90ebf364367 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::env;
 use std::ffi::OsString;
 use std::fs::{self, File};
 use std::io::{self, BufWriter};
@@ -56,6 +57,7 @@ pub trait Linker {
     fn no_whole_archives(&mut self);
     fn export_symbols(&mut self, sess: &Session, trans: &CrateTranslation,
                       tmpdir: &Path);
+    fn try_gold_linker(&mut self);
 }
 
 pub struct GnuLinker<'a> {
@@ -199,6 +201,53 @@ impl<'a> Linker for GnuLinker<'a> {
     fn export_symbols(&mut self, _: &Session, _: &CrateTranslation, _: &Path) {
         // noop, visibility in object files takes care of this
     }
+
+    fn try_gold_linker(&mut self) {
+        // Only use gold under specific conditions that we know work
+
+        let gold_exists = match env::var_os("PATH") {
+            Some(ref env_path) => {
+                env::split_paths(env_path).any(|mut p| {
+                    p.push("ld.gold");
+                    p.exists()
+                })
+            }
+            None => false
+        };
+        let host_is_linux = cfg!(target_os = "linux");
+        // Defensively prevent trying to use gold for bogus cross-targets.
+        let target_is_host_compatible = {
+            let host_os_is_target_os = self.sess.target.target.target_os == env::consts::OS;
+            let host_arch_is_target_arch = self.sess.target.target.arch == env::consts::ARCH;
+            // Support x86_64->i686 and reverse
+            let host_and_target_are_x86ish =
+                (self.sess.target.target.arch == "x86" ||
+                 self.sess.target.target.arch == "x86_64") &&
+                (env::consts::ARCH == "x86" ||
+                 env::consts::ARCH == "x86_64");
+            host_os_is_target_os && (host_arch_is_target_arch || host_and_target_are_x86ish)
+        };
+        // We have strong confidence that x86 works, but not much
+        // visibility into other architectures.
+        let target_works_with_gold =
+            self.sess.target.target.arch == "x86" ||
+            self.sess.target.target.arch == "x86_64";
+        let opt_out = self.sess.opts.cg.disable_gold;
+
+        let can_use_gold =
+            gold_exists &&
+            host_is_linux &&
+            target_is_host_compatible &&
+            target_works_with_gold &&
+            !opt_out;
+
+        if can_use_gold {
+            info!("linking with ld.gold");
+            self.cmd.arg("-fuse-ld=gold");
+        } else {
+            info!("linking with ld");
+        }
+    }
 }
 
 pub struct MsvcLinker<'a> {
@@ -358,4 +407,6 @@ impl<'a> Linker for MsvcLinker<'a> {
         arg.push(path);
         self.cmd.arg(&arg);
     }
+
+    fn try_gold_linker(&mut self) {}
 }