Skip to content

Commit ee4c0f1

Browse files
authored
Merge pull request #215 from ronnychevalier/rc/flag_if_supported
config: add flag_if_supported
2 parents 93b3531 + 590a974 commit ee4c0f1

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

gcc-test/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ fn main() {
1111

1212
gcc::Config::new()
1313
.file("src/foo.c")
14+
.flag_if_supported("-Wall")
15+
.flag_if_supported("-Wfoo-bar-this-flag-does-not-exist")
1416
.define("FOO", None)
1517
.define("BAR", Some("1"))
1618
.compile("libfoo.a");

src/lib.rs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub struct Config {
8686
static_crt: Option<bool>,
8787
shared_flag: Option<bool>,
8888
static_flag: Option<bool>,
89+
check_file_created: bool,
8990
}
9091

9192
/// Configuration used to represent an invocation of a C compiler.
@@ -200,6 +201,7 @@ impl Config {
200201
cargo_metadata: true,
201202
pic: None,
202203
static_crt: None,
204+
check_file_created: false,
203205
}
204206
}
205207

@@ -260,6 +262,51 @@ impl Config {
260262
self
261263
}
262264

265+
fn is_flag_supported(&mut self, flag: &str) -> io::Result<bool> {
266+
let out_dir = self.get_out_dir();
267+
let src = out_dir.join("flag_check.c");
268+
if !self.check_file_created {
269+
write!(fs::File::create(&src)?, "int main(void) {{ return 0; }}")?;
270+
self.check_file_created = true;
271+
}
272+
273+
let obj = out_dir.join("flag_check");
274+
let target = self.get_target();
275+
let mut cfg = Config::new();
276+
cfg.flag(flag)
277+
.target(&target)
278+
.opt_level(0)
279+
.host(&target)
280+
.debug(false)
281+
.cpp(self.cpp);
282+
let compiler = cfg.get_compiler();
283+
let mut cmd = compiler.to_command();
284+
command_add_output_file(&mut cmd, &obj, target.contains("msvc"), false);
285+
cmd.arg(&src);
286+
287+
let output = cmd.output()?;
288+
Ok(output.stderr.is_empty())
289+
}
290+
291+
/// Add an arbitrary flag to the invocation of the compiler if it supports it
292+
///
293+
/// # Example
294+
///
295+
/// ```no_run
296+
/// gcc::Config::new()
297+
/// .file("src/foo.c")
298+
/// .flag_if_supported("-Wlogical-op") // only supported by GCC
299+
/// .flag_if_supported("-Wunreachable-code") // only supported by clang
300+
/// .compile("foo");
301+
/// ```
302+
pub fn flag_if_supported(&mut self, flag: &str) -> &mut Config {
303+
if self.is_flag_supported(flag).unwrap_or(false) {
304+
self.flag(flag)
305+
} else {
306+
self
307+
}
308+
}
309+
263310
/// Set the `-shared` flag.
264311
///
265312
/// When enabled, the compiler will produce a shared object which can
@@ -599,15 +646,7 @@ impl Config {
599646
.to_string_lossy()
600647
.into_owned())
601648
};
602-
if msvc && is_asm {
603-
cmd.arg("/Fo").arg(dst);
604-
} else if msvc {
605-
let mut s = OsString::from("/Fo");
606-
s.push(&dst);
607-
cmd.arg(s);
608-
} else {
609-
cmd.arg("-o").arg(&dst);
610-
}
649+
command_add_output_file(&mut cmd, dst, msvc, is_asm);
611650
cmd.arg(if msvc { "/c" } else { "-c" });
612651
cmd.arg(file);
613652

@@ -1344,3 +1383,16 @@ fn fail(s: &str) -> ! {
13441383
println!("\n\n{}\n\n", s);
13451384
panic!()
13461385
}
1386+
1387+
1388+
fn command_add_output_file(cmd: &mut Command, dst: &Path, msvc: bool, is_asm: bool) {
1389+
if msvc && is_asm {
1390+
cmd.arg("/Fo").arg(dst);
1391+
} else if msvc {
1392+
let mut s = OsString::from("/Fo");
1393+
s.push(&dst);
1394+
cmd.arg(s);
1395+
} else {
1396+
cmd.arg("-o").arg(&dst);
1397+
}
1398+
}

tests/test.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,20 @@ fn gnu_shared() {
183183
.must_not_have("-static");
184184
}
185185

186+
#[test]
187+
fn gnu_flag_if_supported() {
188+
let test = Test::gnu();
189+
test.gcc()
190+
.file("foo.c")
191+
.flag_if_supported("-Wall")
192+
.flag_if_supported("-Wflag-does-not-exist")
193+
.compile("libfoo.a");
194+
195+
test.cmd(0)
196+
.must_have("-Wall")
197+
.must_not_have("-Wflag-does-not-exist");
198+
}
199+
186200
#[test]
187201
fn gnu_static() {
188202
let test = Test::gnu();

0 commit comments

Comments
 (0)