From a33c599f783d963ad2b04eb9bda76bdd38ad9234 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Mon, 21 Aug 2023 12:03:26 -0300 Subject: [PATCH 1/4] linkers: Fix detection of link arguments to Clang(-cl) + MSVC Currently, not only Meson lacks a way to induce a "--fatal-warnings" on LINK.exe, it is also unable to pass flags appropriately when using clang-cl or Microsoft's stock clang. This commit fixes it by implementing `fatal_warnings()` in the MSVCDynamicLinker and ClangCLDynamicLinker classes, and by implementing the requisite conversion steps in linker_to_compiler_args for ClangCompiler. --- mesonbuild/compilers/mixins/clang.py | 8 +++++++- mesonbuild/linkers/linkers.py | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index a57b9a9af..c7e3a13c8 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -11,7 +11,7 @@ import typing as T from ... import mesonlib from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ - MoldDynamicLinker + MoldDynamicLinker, MSVCDynamicLinker from ...mesonlib import OptionKey from ..compilers import CompileCheckMode from .gnu import GnuLikeCompiler @@ -155,6 +155,12 @@ class ClangCompiler(GnuLikeCompiler): args.extend(super().get_lto_compile_args(threads=threads)) return args + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + if isinstance(self.linker, (ClangClDynamicLinker, MSVCDynamicLinker)): + return [flag if flag.startswith('-Wl,') else f'-Wl,{flag}' for flag in args] + else: + return args + def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default', thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]: args = self.get_lto_compile_args(threads=threads, mode=mode) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index e4db0157f..a807b7b98 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -1313,6 +1313,9 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): def get_win_subsystem_args(self, value: str) -> T.List[str]: return self._apply_prefix([f'/SUBSYSTEM:{value.upper()}']) + def fatal_warnings(self) -> T.List[str]: + return ['-WX'] + class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): @@ -1342,6 +1345,9 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): def get_thinlto_cache_args(self, path: str) -> T.List[str]: return ["/lldltocache:" + path] + def fatal_warnings(self) -> T.List[str]: + return ['-WX'] + class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): From 3366756c0f959a5811f27d613f76d9371715c86a Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Thu, 24 Aug 2023 13:24:18 -0300 Subject: [PATCH 2/4] compilers: Forward Meson's preference of lld-link to clang-cl The latter prefers LINK.exe by default, which rejects GNU-like linker flags. --- mesonbuild/compilers/mixins/visualstudio.py | 12 ++++++++++++ mesonbuild/linkers/detect.py | 3 +++ 2 files changed, 15 insertions(+) diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 5dcebecef..13f8cfa0f 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -456,6 +456,18 @@ class ClangClCompiler(VisualStudioLikeCompiler): path = '.' return ['/clang:-isystem' + path] if is_system else ['-I' + path] + @classmethod + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: + # Clang additionally can use a linker specified as a path, unlike MSVC. + if linker == 'lld-link': + return ['-fuse-ld=lld-link'] + return super().use_linker_args(linker, version) + + def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: + # clang-cl forwards arguments span-wise with the /LINK flag + # therefore -Wl will be received by lld-link or LINK and rejected + return super().use_linker_args(self.linker.id, '') + super().linker_to_compiler_args([flag[4:] if flag.startswith('-Wl,') else flag for flag in args]) + def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: if dep.get_include_type() == 'system': converted: T.List[str] = [] diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 1bce413f4..bb391d171 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -55,6 +55,9 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty if value is not None: override = comp_class.use_linker_args(value[0], comp_version) check_args += override + elif 'lld-link' in compiler: + override = comp_class.use_linker_args('lld-link', comp_version) + check_args += override if extra_args is not None: check_args.extend(extra_args) From c5254429e4fdad4058104dc4c00531c0f7b109b6 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Tue, 5 Sep 2023 22:28:09 -0300 Subject: [PATCH 3/4] clang: Fix tests that use /DEF for MSVC LINK.exe --- mesonbuild/compilers/mixins/clang.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index c7e3a13c8..f982509f4 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -111,6 +111,13 @@ class ClangCompiler(GnuLikeCompiler): # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency. return [] + def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]: + if isinstance(self.linker, (MSVCDynamicLinker)): + # With MSVC, DLLs only export symbols that are explicitly exported, + # so if a module defs file is specified, we use that to export symbols + return ['-Wl,/DEF:' + defsfile] + return super().gen_vs_module_defs_args(defsfile) + @classmethod def use_linker_args(cls, linker: str, version: str) -> T.List[str]: # Clang additionally can use a linker specified as a path, which GCC From f3fad6cc5f948b0c7557bdce3959c71420183be9 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Thu, 24 Aug 2023 13:42:15 -0300 Subject: [PATCH 4/4] compilers: Add test for correct forwarding of flags to MSVC's Clang linkers --- .../common/180 has link arg/meson.build | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test cases/common/180 has link arg/meson.build b/test cases/common/180 has link arg/meson.build index 6bfbd59e7..111b0b9ea 100644 --- a/test cases/common/180 has link arg/meson.build +++ b/test cases/common/180 has link arg/meson.build @@ -45,3 +45,23 @@ endif assert(cc.has_multi_link_arguments(is_arg), 'Arg that should have worked does not work.') assert(cc.has_multi_link_arguments([useless, is_arg]), 'Arg that should have worked does not work.') + +# These are Visual Studio only flags +# Testing has_argument_syntax is incorrect as it skips Microsoft Clang +if cc.get_define('_MSC_FULL_VER') != '' + if cc.get_linker_id() == 'link' + is_only = '/OPT:REF' + is_shared = '/GUARD:CF' + else # ld-link + is_only = '--color-diagnostics' + is_shared = '-guard:cf' + endif + + # requires -Wl,xxx as it goes through the compiler + if cc.get_argument_syntax() != 'msvc' + is_only = '-Wl,@0@'.format(is_only) + is_shared = '-Wl,@0@'.format(is_shared) + endif + + assert(cc.has_multi_link_arguments([is_only, is_shared]), 'Arg that should have worked does not work.') +endif