Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion mesonbuild/compilers/mixins/clang.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

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
Expand Down Expand Up @@ -111,6 +111,13 @@ def openmp_flags(self) -> T.List[str]:
# 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
Expand Down Expand Up @@ -155,6 +162,12 @@ def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.
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)
Expand Down
12 changes: 12 additions & 0 deletions mesonbuild/compilers/mixins/visualstudio.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,18 @@ def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
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] = []
Expand Down
3 changes: 3 additions & 0 deletions mesonbuild/linkers/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions mesonbuild/linkers/linkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,9 @@ def get_always_args(self) -> T.List[str]:
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):

Expand Down Expand Up @@ -1342,6 +1345,9 @@ def get_win_subsystem_args(self, value: str) -> T.List[str]:
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):

Expand Down
20 changes: 20 additions & 0 deletions test cases/common/180 has link arg/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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