Merge pull request #12144 from amyspark/fix-msvc-clangcl-linker-flag-detection

linkers: Fix detection of link arguments to Clang(-cl) + MSVC
pull/12691/head
Jussi Pakkanen 8 months ago committed by GitHub
commit 30c38e2bd6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 15
      mesonbuild/compilers/mixins/clang.py
  2. 12
      mesonbuild/compilers/mixins/visualstudio.py
  3. 3
      mesonbuild/linkers/detect.py
  4. 6
      mesonbuild/linkers/linkers.py
  5. 20
      test cases/common/180 has link arg/meson.build

@ -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
@ -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
@ -155,6 +162,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)

@ -460,6 +460,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] = []

@ -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)

@ -1319,6 +1319,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):
@ -1348,6 +1351,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):

@ -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

Loading…
Cancel
Save