From 421c2104a537c1988a4ae226dfbb23421acd3185 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Fri, 10 Jan 2025 15:32:15 +0100 Subject: [PATCH] tool: Expose `family()` and deprecate `is_like_xxx()` wrappers Intead of adding a new `is_like_xxx()` function every time new information is needed, or new enumeration variants would be added, provide the (now `non_exhaustive`) `enum` directly to callers to match what they're interested in. Deprecate the existing functions to point users to the new pattern. --- dev-tools/cc-test/build.rs | 17 +++++++++------- src/lib.rs | 38 +++++++++++++++++++----------------- src/tool.rs | 40 ++++++++++++++++++++++++++++++-------- 3 files changed, 62 insertions(+), 33 deletions(-) diff --git a/dev-tools/cc-test/build.rs b/dev-tools/cc-test/build.rs index 4adb870cf..ea60d3abb 100644 --- a/dev-tools/cc-test/build.rs +++ b/dev-tools/cc-test/build.rs @@ -23,7 +23,10 @@ fn main() { run_forked_capture_output(&out, "metadata-off"); run_forked_capture_output(&out, "warnings-off"); - if cc::Build::new().get_compiler().is_like_msvc() { + if matches!( + cc::Build::new().get_compiler().family(), + cc::ToolFamily::Msvc { .. } + ) { // MSVC doesn't output warnings to stderr, so we can't capture them. // the test will use this env var to know whether to run the test. println!("cargo:rustc-env=TEST_WARNINGS_ON=0"); @@ -86,12 +89,12 @@ fn main() { } if target.contains("msvc") { - let cc_frontend = if compiler.is_like_msvc() { - "MSVC" - } else if compiler.is_like_clang() { - "CLANG" - } else { - unimplemented!("Unknown compiler that targets msvc but isn't clang-like or msvc-like") + let cc_frontend = match compiler.family() { + cc::ToolFamily::Clang { .. } => "CLANG", + cc::ToolFamily::Msvc { .. } => "MSVC", + f => unimplemented!( + "Unknown compiler `{f:?}` that targets msvc but isn't clang-like or msvc-like" + ), }; // Test that the `windows_registry` module will set PATH by looking for diff --git a/src/lib.rs b/src/lib.rs index 280ff7bb9..e8d8bc479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,8 +253,7 @@ mod command_helpers; use command_helpers::*; mod tool; -pub use tool::Tool; -use tool::ToolFamily; +pub use tool::{Tool, ToolFamily}; mod tempfile; @@ -701,7 +700,8 @@ impl Build { if compiler.family.verbose_stderr() { compiler.remove_arg("-v".into()); } - if compiler.is_like_clang() { + let clang = matches!(compiler.family(), ToolFamily::Clang { .. }); + if clang { // Avoid reporting that the arg is unsupported just because the // compiler complains that it wasn't used. compiler.push_cc_arg("-Wno-unused-command-line-argument".into()); @@ -709,17 +709,16 @@ impl Build { let mut cmd = compiler.to_command(); let is_arm = matches!(target.arch, "aarch64" | "arm"); - let clang = compiler.is_like_clang(); - let gnu = compiler.family == ToolFamily::Gnu; + let msvc = matches!(compiler.family(), ToolFamily::Msvc { .. }); command_add_output_file( &mut cmd, &obj, CmdAddOutputFileArgs { cuda: self.cuda, is_assembler_msvc: false, - msvc: compiler.is_like_msvc(), + msvc, clang, - gnu, + gnu: matches!(compiler.family(), ToolFamily::Gnu), is_asm: false, is_arm, }, @@ -733,7 +732,7 @@ impl Build { // On MSVC skip the CRT by setting the entry point to `main`. // This way we don't need to add the default library paths. - if compiler.is_like_msvc() { + if msvc { // Flags from _LINK_ are appended to the linker arguments. cmd.env("_LINK_", "-entry:main"); } @@ -1753,8 +1752,6 @@ impl Build { let target = self.get_target()?; let msvc = target.env == "msvc"; let compiler = self.try_get_compiler()?; - let clang = compiler.is_like_clang(); - let gnu = compiler.family == ToolFamily::Gnu; let is_assembler_msvc = msvc && asm_ext == Some(AsmFileExt::DotAsm); let (mut cmd, name) = if is_assembler_msvc { @@ -1782,9 +1779,9 @@ impl Build { CmdAddOutputFileArgs { cuda: self.cuda, is_assembler_msvc, - msvc: compiler.is_like_msvc(), - clang, - gnu, + msvc: matches!(compiler.family(), ToolFamily::Msvc { .. }), + clang: matches!(compiler.family(), ToolFamily::Clang { .. }), + gnu: matches!(compiler.family(), ToolFamily::Gnu), is_asm, is_arm, }, @@ -2036,15 +2033,16 @@ impl Build { } } ToolFamily::Gnu | ToolFamily::Clang { .. } => { + let clang = matches!(cmd.family, ToolFamily::Clang { .. }); // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does // not support '-Oz' - if opt_level == "z" && !cmd.is_like_clang() { + if opt_level == "z" && !clang { cmd.push_opt_unless_duplicate("-Os".into()); } else { cmd.push_opt_unless_duplicate(format!("-O{}", opt_level).into()); } - if cmd.is_like_clang() && target.os == "android" { + if clang && target.os == "android" { // For compatibility with code that doesn't use pre-defined `__ANDROID__` macro. // If compiler used via ndk-build or cmake (officially supported build methods) // this macros is defined. @@ -2141,7 +2139,9 @@ impl Build { family.add_force_frame_pointer(cmd); } - if !cmd.is_like_msvc() { + let msvc = matches!(cmd.family, ToolFamily::Msvc { .. }); + + if !msvc { if target.arch == "x86" { cmd.args.push("-m32".into()); } else if target.abi == "x32" { @@ -2653,7 +2653,8 @@ impl Build { // it does not support iOS in general), but we specify them anyhow in // case we actually have a Clang-like compiler disguised as a GNU-like // compiler, or in case GCC adds support for these in the future. - if !cmd.is_like_clang() { + let clang = matches!(cmd.family, ToolFamily::Clang { .. }); + if !clang { let min_version = self.apple_deployment_target(&target); cmd.args .push(target.apple_version_flag(&min_version).into()); @@ -3225,7 +3226,8 @@ impl Build { // And even extend it to gcc targets by searching for "ar" instead // of "llvm-ar"... let compiler = self.get_base_compiler().ok()?; - if compiler.is_like_clang() { + let clang = matches!(compiler.family, ToolFamily::Clang { .. }); + if clang { name = format!("llvm-{}", tool).into(); self.search_programs( &mut self.cmd(&compiler.path), diff --git a/src/tool.rs b/src/tool.rs index af43a918e..1b365bcd8 100644 --- a/src/tool.rs +++ b/src/tool.rs @@ -281,12 +281,17 @@ impl Tool { let mut chars = flag.chars(); // Only duplicate check compiler flags - if self.is_like_msvc() { - if chars.next() != Some('/') { - return false; + match self.family { + ToolFamily::Msvc { .. } => { + if chars.next() != Some('/') { + return false; + } + } + ToolFamily::Gnu | ToolFamily::Clang { .. } => { + if chars.next() != Some('-') { + return false; + } } - } else if (self.is_like_gnu() || self.is_like_clang()) && chars.next() != Some('-') { - return false; } // Check for existing optimization flags (-O, /O) @@ -395,12 +400,19 @@ impl Tool { flags } + /// The family of this tool, representing convention of arguments etc. + pub fn family(&self) -> ToolFamily { + self.family + } + /// Whether the tool is GNU Compiler Collection-like. + #[deprecated = "Consider matching against the ToolFamily returned by family() instead"] pub fn is_like_gnu(&self) -> bool { self.family == ToolFamily::Gnu } /// Whether the tool is Clang-like. + #[deprecated = "Consider matching against the ToolFamily returned by family() instead"] pub fn is_like_clang(&self) -> bool { matches!(self.family, ToolFamily::Clang { .. }) } @@ -417,11 +429,13 @@ impl Tool { } /// Whether the tool is MSVC-like. + #[deprecated = "Consider matching against the ToolFamily returned by family() instead"] pub fn is_like_msvc(&self) -> bool { matches!(self.family, ToolFamily::Msvc { .. }) } /// Whether the tool is `clang-cl`-based MSVC-like. + #[deprecated = "Consider matching against the ToolFamily returned by family() instead"] pub fn is_like_clang_cl(&self) -> bool { matches!(self.family, ToolFamily::Msvc { clang_cl: true }) } @@ -441,14 +455,24 @@ impl Tool { /// /// Detection of a family is done on best-effort basis and may not accurately reflect the tool. #[derive(Copy, Clone, Debug, PartialEq)] +#[non_exhaustive] pub enum ToolFamily { /// Tool is GNU Compiler Collection-like. + #[non_exhaustive] Gnu, /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags /// and its cross-compilation approach is different. - Clang { zig_cc: bool }, - /// Tool is the MSVC cl.exe. - Msvc { clang_cl: bool }, + #[non_exhaustive] + Clang { + /// Tool provided by zig + zig_cc: bool, + }, + /// Tool is the MSVC `cl.exe`. + #[non_exhaustive] + Msvc { + /// Whether this is `clang-cl` provided by LLVM + clang_cl: bool, + }, } impl ToolFamily {