From 15f4444d5a6916a5880309d42ec38890f19da9a5 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 16 Nov 2022 20:20:47 -0500 Subject: [PATCH] Add `Build::asm_flag` The method allows flags to be specified that are only applied to assembly input files, not C files. This is helpful with clang, which only accepts certain assembly options if the input file is asm, not C. --- src/lib.rs | 38 +++++++++++++++++++++++++++++++++++++- tests/test.rs | 14 ++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 469b0f893..486d67e0b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,6 +97,7 @@ pub struct Build { flags_supported: Vec, known_flag_support_status: Arc>>, ar_flags: Vec, + asm_flags: Vec, no_default_flags: bool, files: Vec, cpp: bool, @@ -299,6 +300,7 @@ impl Build { flags_supported: Vec::new(), known_flag_support_status: Arc::new(Mutex::new(HashMap::new())), ar_flags: Vec::new(), + asm_flags: Vec::new(), no_default_flags: false, files: Vec::new(), shared_flag: None, @@ -434,6 +436,25 @@ impl Build { self } + /// Add a flag that will only be used with assembly files. + /// + /// The flag will be applied to input files with either a `.s` or + /// `.asm` extension (case insensitive). + /// + /// # Example + /// + /// ```no_run + /// cc::Build::new() + /// .asm_flag("-Wa,-defsym,abc=1") + /// .file("src/foo.S") // The asm flag will be applied here + /// .file("src/bar.c") // The asm flag will not be applied here + /// .compile("foo"); + /// ``` + pub fn asm_flag(&mut self, flag: &str) -> &mut Build { + self.asm_flags.push(flag.to_string()); + self + } + fn ensure_check_file(&self) -> Result { let out_dir = self.get_out_dir()?; let src = if self.cuda { @@ -1318,7 +1339,7 @@ impl Build { } fn compile_object(&self, obj: &Object) -> Result<(), Error> { - let is_asm = obj.src.extension().and_then(|s| s.to_str()) == Some("asm"); + let is_asm = is_asm(&obj.src); let target = self.get_target()?; let msvc = target.contains("msvc"); let compiler = self.try_get_compiler()?; @@ -1349,6 +1370,9 @@ impl Build { if self.cuda && self.files.len() > 1 { cmd.arg("--device-c"); } + if is_asm { + cmd.args(&self.asm_flags); + } if compiler.family == (ToolFamily::Msvc { clang_cl: true }) && !is_asm { // #513: For `clang-cl`, separate flags/options from the input file. // When cross-compiling macOS -> Windows, this avoids interpreting @@ -3471,3 +3495,15 @@ fn which(tool: &Path) -> Option { return if check_exe(&mut exe) { Some(exe) } else { None }; }) } + +/// Check if the file's extension is either "asm" or "s", case insensitive. +fn is_asm(file: &Path) -> bool { + if let Some(ext) = file.extension() { + if let Some(ext) = ext.to_str() { + let ext = ext.to_lowercase(); + return ext == "asm" || ext == "s"; + } + } + + false +} diff --git a/tests/test.rs b/tests/test.rs index 98a03e851..8ef5d8867 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -442,3 +442,17 @@ fn msvc_no_dash_dash() { test.cmd(0).must_not_have("--"); } + +#[test] +fn asm_flags() { + let test = Test::gnu(); + test.gcc() + .file("foo.c") + .file("x86_64.asm") + .file("x86_64.S") + .asm_flag("--abc") + .compile("foo"); + test.cmd(0).must_not_have("--abc"); + test.cmd(1).must_have("--abc"); + test.cmd(2).must_have("--abc"); +}