diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 9afed45e0b05..8e455d1ae26e 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1449,7 +1449,12 @@ def _sanity_check_compile_args(self, sourcename: str, binname: str OptionKey(f'{self.language}_args', machine=self.for_machine)))) largs = list(T.cast('T.List[str]', optstore.get_value_for( OptionKey(f'{self.language}_link_args', machine=self.for_machine)))) - return self.exelist_no_ccache + self.get_always_args() + self.get_output_args(binname) + [sourcename] + cargs, largs + return self.exelist_no_ccache \ + + self.get_always_args() \ + + self.get_compiler_check_args(CompileCheckMode.COMPILE) \ + + self.get_output_args(binname) \ + + [sourcename] \ + + cargs, largs @abc.abstractmethod def _sanity_check_source_code(self) -> str: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 620c1fa5126c..d0351e854f75 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -975,6 +975,10 @@ def get_cpp_modules_args(self) -> T.List[str]: # clang-cl does not support /interface. return ['-fmodules', '-fmodules-ts'] + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + # XXX: this is a hack because so much GnuLike stuff is in the base CPPCompiler class. + return ClangClCompiler.get_compiler_check_args(self, mode) + class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler): diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index be9bf11d2bd4..724b3fbc9c6c 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -469,14 +469,16 @@ def sanitizer_compile_args(self, target: T.Optional[BuildTarget], value: T.List[ args.append('/clang:-fno-omit-frame-pointer') return args - def has_arguments(self, args: T.List[str], code: str, mode: CompileCheckMode) -> T.Tuple[bool, bool]: + def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: + myargs: T.List[str] = [] if mode != CompileCheckMode.LINK: - args = args + [ + myargs.extend(( '-Werror=unknown-argument', '-Werror=unknown-warning-option', '-Werror=unused-command-line-argument', - ] - return super().has_arguments(args, code, mode) + )) + + return super().get_compiler_check_args(mode) + myargs def get_pch_base_name(self, header: str) -> str: return header diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 86eb5ee22529..b0570bae6baa 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -29,8 +29,9 @@ import mesonbuild.scripts.depfixer import mesonbuild.scripts.env2mfile from mesonbuild import coredata -from mesonbuild.compilers.c import ClangCCompiler, GnuCCompiler -from mesonbuild.compilers.compilers import Compiler, ManyInOneLinkerOptionStyle +from mesonbuild.compilers import Compiler +from mesonbuild.compilers.c import ClangCCompiler, ClangClCCompiler, GnuCCompiler +from mesonbuild.compilers.compilers import CompileCheckMode, ManyInOneLinkerOptionStyle from mesonbuild.compilers.cpp import VisualStudioCPPCompiler from mesonbuild.compilers.d import DmdDCompiler from mesonbuild.compilers.detect import detect_c_compiler @@ -435,6 +436,27 @@ def test_clike_sanity_check_drops_link_only_args_when_compile_only(self): self.assertEqual(largs, []) + def test_clang_family_compiler_check_args_contain_werror_unknown_warning(self): + env = get_fake_env() + mold = linkers.MoldDynamicLinker([], env, MachineChoice.HOST, '-Wl,', []) + lld_link = linkers.ClangClDynamicLinker(env, MachineChoice.HOST, []) + + compilers = { + 'clang': ClangCCompiler([], [], '14.0.0', MachineChoice.HOST, env, linker=mold), + 'clang-cl': ClangClCCompiler([], '14.0.0', MachineChoice.HOST, env, 'x64', linker=lld_link), + } + + for name, cc in compilers.items(): + with self.subTest(compiler=name): + self.assertIn('-Werror=unknown-warning-option', + cc.get_compiler_check_args(CompileCheckMode.COMPILE)) + # Both clang and clang-cl only apply this diagnostic when + # actually compiling; it's intentionally omitted for LINK to + # avoid failing on flags that are unused during linking. + self.assertNotIn('-Werror=unknown-warning-option', + cc.get_compiler_check_args(CompileCheckMode.LINK)) + + def test_msvc_unix_args_to_native(self): # joined self.assertEqual(MSVCCompiler.unix_args_to_native(['-isystemfoo']), ['/Ifoo']) diff --git a/unittests/linuxliketests.py b/unittests/linuxliketests.py index 193ff6b62fd5..06de9901350d 100644 --- a/unittests/linuxliketests.py +++ b/unittests/linuxliketests.py @@ -845,8 +845,13 @@ def test_cpp_std_override(self): self.assertNotIn('-std=c++98', plain_comp) self.assertNotIn('-std=c++11', plain_comp) # Now werror - self.assertIn('-Werror', plain_comp) - self.assertNotIn('-Werror', c98_comp) + self.assertIn('-Werror', plain_comp.split()) + self.assertNotIn('-Werror', c98_comp.split()) + + def test_sanity_check_fails_on_bad_c_args(self): + testdir = os.path.join(self.common_test_dir, '1 trivial') + with self.assertRaises((subprocess.CalledProcessError, RuntimeError)): + self.init(testdir, extra_args=['-Dc_args=-Wbad-flag-does-not-exist']) def test_run_installed(self): if is_cygwin() or is_osx():