From 34dc0e0739e19811850f82f1e45b61ba97adc96e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 8 Aug 2015 11:33:43 -0700 Subject: [PATCH] Link with ld.gold by default To disable, pass `-C disable-gold` --- src/librustc/session/config.rs | 2 ++ src/librustc_trans/back/link.rs | 4 +++ src/librustc_trans/back/linker.rs | 51 +++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) 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 = (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) {} }