Skip to content

Detect whether cc (the linker) is gcc or clang. #17231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 12 additions & 29 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use super::svh::Svh;
use super::write::{OutputTypeBitcode, OutputTypeExe, OutputTypeObject};
use driver::driver::{CrateTranslation, OutputFilenames, Input, FileInput};
use driver::config::NoDebugInfo;
use driver::session::{CcArgumentsFormat, GccArguments};
use driver::session::Session;
use driver::config;
use metadata::common::LinkMeta;
Expand Down Expand Up @@ -72,7 +73,6 @@ pub static RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: uint =
pub static RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: uint =
RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8;


/*
* Name mangling and its relationship to metadata. This is complex. Read
* carefully.
Expand Down Expand Up @@ -380,29 +380,6 @@ pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> Stri
mangle(path.chain(Some(gensym_name(flav)).move_iter()), None)
}

pub fn get_cc_prog(sess: &Session) -> String {
match sess.opts.cg.linker {
Some(ref linker) => return linker.to_string(),
None => {}
}

// In the future, FreeBSD will use clang as default compiler.
// It would be flexible to use cc (system's default C compiler)
// instead of hard-coded gcc.
// For Windows, there is no cc command, so we add a condition to make it use gcc.
match sess.targ_cfg.os {
abi::OsWindows => "gcc",
_ => "cc",
}.to_string()
}

pub fn get_ar_prog(sess: &Session) -> String {
match sess.opts.cg.ar {
Some(ref ar) => (*ar).clone(),
None => "ar".to_string()
}
}

pub fn remove(sess: &Session, path: &Path) {
match fs::unlink(path) {
Ok(..) => {}
Expand Down Expand Up @@ -811,11 +788,11 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");

// The invocations of cc share some flags across platforms
let pname = get_cc_prog(sess);
let mut cmd = Command::new(pname.as_slice());
let (pname, args_fmt) = sess.get_cc_prog();
let mut cmd = Command::new(pname);

cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice());
link_args(&mut cmd, sess, dylib, tmpdir.path(),
link_args(&mut cmd, args_fmt, sess, dylib, tmpdir.path(),
trans, obj_filename, out_filename);

if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
Expand Down Expand Up @@ -867,6 +844,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
}

fn link_args(cmd: &mut Command,
args_fmt: CcArgumentsFormat,
sess: &Session,
dylib: bool,
tmpdir: &Path,
Expand Down Expand Up @@ -929,8 +907,13 @@ fn link_args(cmd: &mut Command,
cmd.arg("-nodefaultlibs");
}

// Rust does its' own LTO
cmd.arg("-fno-lto").arg("-fno-use-linker-plugin");
// Rust does its own LTO
cmd.arg("-fno-lto");

// clang fails hard if -fno-use-linker-plugin is passed
if args_fmt == GccArguments {
cmd.arg("-fno-use-linker-plugin");
}

// If we're building a dylib, we don't use --gc-sections because LLVM has
// already done the best it can do, and we also don't want to eliminate the
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

use back::lto;
use back::link::{get_cc_prog, remove};
use back::link::{remove};
use driver::driver::{CrateTranslation, ModuleTranslation, OutputFilenames};
use driver::config::NoDebugInfo;
use driver::session::Session;
Expand Down Expand Up @@ -632,8 +632,8 @@ pub fn run_passes(sess: &Session,
None
};

let pname = get_cc_prog(sess);
let mut cmd = Command::new(pname.as_slice());
let pname = sess.get_cc_prog_str();
let mut cmd = Command::new(pname);

cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice());
cmd.arg("-nostdlib");
Expand Down Expand Up @@ -828,8 +828,8 @@ fn run_work_multithreaded(sess: &Session,
}

pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
let pname = get_cc_prog(sess);
let mut cmd = Command::new(pname.as_slice());
let pname = sess.get_cc_prog_str();
let mut cmd = Command::new(pname);

cmd.arg("-c").arg("-o").arg(outputs.path(OutputTypeObject))
.arg(outputs.temp_path(OutputTypeAssembly));
Expand Down
83 changes: 82 additions & 1 deletion src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use metadata::filesearch;
use lint;
use util::nodemap::NodeMap;

use syntax::abi;
use syntax::ast::NodeId;
use syntax::codemap::Span;
use syntax::diagnostic;
Expand All @@ -26,8 +27,22 @@ use syntax::parse::token;
use syntax::parse::ParseSess;
use syntax::{ast, codemap};

use std::os;
use std::cell::{Cell, RefCell};
use std::io::Command;
use std::os;
use std::str;

/// The `cc` program used for linking will accept command line
/// arguments according to one of the following formats.
#[deriving(PartialEq, Show)]
pub enum CcArgumentsFormat {
/// GNU compiler collection (GCC) compatible format.
GccArguments,
/// LLVM Clang front-end compatible format.
ClangArguments,
/// Unknown argument format; assume lowest common denominator among above.
UnknownCcArgumentFormat,
}

// Represents the data associated with a compilation
// session for a single crate.
Expand Down Expand Up @@ -55,6 +70,11 @@ pub struct Session {
/// The maximum recursion limit for potentially infinitely recursive
/// operations such as auto-dereference and monomorphization.
pub recursion_limit: Cell<uint>,

/// What command line options are acceptable to cc program;
/// locally memoized (i.e. initialized at most once).
/// See `Session::cc_prog` and `Session::cc_args_format`.
memo_cc_args_format: Cell<Option<CcArgumentsFormat>>,
}

impl Session {
Expand Down Expand Up @@ -202,6 +222,66 @@ impl Session {
driver::host_triple(),
&self.opts.addl_lib_search_paths)
}

pub fn get_cc_prog_str(&self) -> &str {
match self.opts.cg.linker {
Some(ref linker) => return linker.as_slice(),
None => {}
}

// In the future, FreeBSD will use clang as default compiler.
// It would be flexible to use cc (system's default C compiler)
// instead of hard-coded gcc.
// For Windows, there is no cc command, so we add a condition to make it use gcc.
match self.targ_cfg.os {
abi::OsWindows => "gcc",
_ => "cc",
}
}

pub fn get_ar_prog_str(&self) -> &str {
match self.opts.cg.ar {
Some(ref ar) => ar.as_slice(),
None => "ar"
}
}

pub fn get_cc_args_format(&self) -> CcArgumentsFormat {
match self.memo_cc_args_format.get() {
Some(args_format) => return args_format,
None => {}
}

// Extract the args format: invoke `cc --version`, then search
// for identfying substrings.
let prog_str = self.get_cc_prog_str();
let mut command = Command::new(prog_str);
let presult = match command.arg("--version").output() {
Ok(p) => p,
Err(e) => fail!("failed to execute process: {}", e),
};

let output = str::from_utf8_lossy(presult.output.as_slice());
let output = output.as_slice();
let args_fmt = if output.contains("clang") {
ClangArguments
} else if output.contains("GCC") ||
output.contains("Free Software Foundation") {
GccArguments
} else {
UnknownCcArgumentFormat
};

// Memoize the args format.
self.memo_cc_args_format.set(Some(args_fmt));

args_fmt
}

pub fn get_cc_prog(&self) -> (&str, CcArgumentsFormat) {
(self.get_cc_prog_str(), self.get_cc_args_format())
}

}

pub fn build_session(sopts: config::Options,
Expand Down Expand Up @@ -256,6 +336,7 @@ pub fn build_session_(sopts: config::Options,
crate_metadata: RefCell::new(Vec::new()),
features: front::feature_gate::Features::new(),
recursion_limit: Cell::new(64),
memo_cc_args_format: Cell::new(None),
};

sess.lint_store.borrow_mut().register_builtin(Some(&sess));
Expand Down