Browse Source

Merge pull request #215 from ronnychevalier/rc/flag_if_supported

config: add flag_if_supported
cmd
Alex Crichton 8 years ago
committed by GitHub
parent
commit
ee4c0f11ca
  1. 2
      gcc-test/build.rs
  2. 70
      src/lib.rs
  3. 14
      tests/test.rs

2
gcc-test/build.rs

@ -11,6 +11,8 @@ fn main() {
gcc::Config::new() gcc::Config::new()
.file("src/foo.c") .file("src/foo.c")
.flag_if_supported("-Wall")
.flag_if_supported("-Wfoo-bar-this-flag-does-not-exist")
.define("FOO", None) .define("FOO", None)
.define("BAR", Some("1")) .define("BAR", Some("1"))
.compile("libfoo.a"); .compile("libfoo.a");

70
src/lib.rs

@ -86,6 +86,7 @@ pub struct Config {
static_crt: Option<bool>, static_crt: Option<bool>,
shared_flag: Option<bool>, shared_flag: Option<bool>,
static_flag: Option<bool>, static_flag: Option<bool>,
check_file_created: bool,
} }
/// Configuration used to represent an invocation of a C compiler. /// Configuration used to represent an invocation of a C compiler.
@ -200,6 +201,7 @@ impl Config {
cargo_metadata: true, cargo_metadata: true,
pic: None, pic: None,
static_crt: None, static_crt: None,
check_file_created: false,
} }
} }
@ -260,6 +262,51 @@ impl Config {
self self
} }
fn is_flag_supported(&mut self, flag: &str) -> io::Result<bool> {
let out_dir = self.get_out_dir();
let src = out_dir.join("flag_check.c");
if !self.check_file_created {
write!(fs::File::create(&src)?, "int main(void) {{ return 0; }}")?;
self.check_file_created = true;
}
let obj = out_dir.join("flag_check");
let target = self.get_target();
let mut cfg = Config::new();
cfg.flag(flag)
.target(&target)
.opt_level(0)
.host(&target)
.debug(false)
.cpp(self.cpp);
let compiler = cfg.get_compiler();
let mut cmd = compiler.to_command();
command_add_output_file(&mut cmd, &obj, target.contains("msvc"), false);
cmd.arg(&src);
let output = cmd.output()?;
Ok(output.stderr.is_empty())
}
/// Add an arbitrary flag to the invocation of the compiler if it supports it
///
/// # Example
///
/// ```no_run
/// gcc::Config::new()
/// .file("src/foo.c")
/// .flag_if_supported("-Wlogical-op") // only supported by GCC
/// .flag_if_supported("-Wunreachable-code") // only supported by clang
/// .compile("foo");
/// ```
pub fn flag_if_supported(&mut self, flag: &str) -> &mut Config {
if self.is_flag_supported(flag).unwrap_or(false) {
self.flag(flag)
} else {
self
}
}
/// Set the `-shared` flag. /// Set the `-shared` flag.
/// ///
/// When enabled, the compiler will produce a shared object which can /// When enabled, the compiler will produce a shared object which can
@ -599,15 +646,7 @@ impl Config {
.to_string_lossy() .to_string_lossy()
.into_owned()) .into_owned())
}; };
if msvc && is_asm { command_add_output_file(&mut cmd, dst, msvc, is_asm);
cmd.arg("/Fo").arg(dst);
} else if msvc {
let mut s = OsString::from("/Fo");
s.push(&dst);
cmd.arg(s);
} else {
cmd.arg("-o").arg(&dst);
}
cmd.arg(if msvc { "/c" } else { "-c" }); cmd.arg(if msvc { "/c" } else { "-c" });
cmd.arg(file); cmd.arg(file);
@ -1344,3 +1383,16 @@ fn fail(s: &str) -> ! {
println!("\n\n{}\n\n", s); println!("\n\n{}\n\n", s);
panic!() panic!()
} }
fn command_add_output_file(cmd: &mut Command, dst: &Path, msvc: bool, is_asm: bool) {
if msvc && is_asm {
cmd.arg("/Fo").arg(dst);
} else if msvc {
let mut s = OsString::from("/Fo");
s.push(&dst);
cmd.arg(s);
} else {
cmd.arg("-o").arg(&dst);
}
}

14
tests/test.rs

@ -183,6 +183,20 @@ fn gnu_shared() {
.must_not_have("-static"); .must_not_have("-static");
} }
#[test]
fn gnu_flag_if_supported() {
let test = Test::gnu();
test.gcc()
.file("foo.c")
.flag_if_supported("-Wall")
.flag_if_supported("-Wflag-does-not-exist")
.compile("libfoo.a");
test.cmd(0)
.must_have("-Wall")
.must_not_have("-Wflag-does-not-exist");
}
#[test] #[test]
fn gnu_static() { fn gnu_static() {
let test = Test::gnu(); let test = Test::gnu();

Loading…
Cancel
Save