Allow selecting the dynamic linker

This uses the normal meson mechanisms, an LD environment variable or via
cross/native files.

Fixes: #6057
pull/6207/head
Dylan Baker 5 years ago
parent 7658e67f92
commit ef9aeb188e
  1. 17
      docs/markdown/snippets/linker_override.md
  2. 6
      mesonbuild/compilers/compilers.py
  3. 4
      mesonbuild/compilers/mixins/gnu.py
  4. 4
      mesonbuild/compilers/mixins/visualstudio.py
  5. 6
      mesonbuild/compilers/rust.py
  6. 2
      mesonbuild/envconfig.py
  7. 206
      mesonbuild/environment.py
  8. 28
      mesonbuild/linkers.py
  9. 4
      run_unittests.py

@ -0,0 +1,17 @@
## Generic Overrider for Dynamic Linker selection
Previous to meson 0.52.0 you set the dynamic linker using compiler specific
flags passed via language flags and hoped things worked out. In meson 0.52.0
meson started detecting the linker and making intelligent decisions about
using it. Unfortunately this broke choosing a non-default linker.
Now there is a generic mechanism for doing this, you may use the LD
environment variable (with normal meson environment variable rules), or add
the following to a cross or native file:
```ini
[binaries]
ld = 'gold'
```
And meson will select the linker if possible.

@ -1178,6 +1178,12 @@ class Compiler:
def get_dependency_link_args(self, dep):
return dep.get_link_args()
@classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]:
"""Get a list of arguments to pass to the compiler to set the linker.
"""
return []
def get_largefile_args(compiler):
'''

@ -299,6 +299,10 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta):
return ['-isystem' + path]
return ['-I' + path]
@classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]:
return ['-fuse-ld={}'.format(linker)]
class GnuCompiler(GnuLikeCompiler):
"""

@ -381,3 +381,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
def get_argument_syntax(self) -> str:
return 'msvc'
@classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]:
return []

@ -32,7 +32,7 @@ rust_optimization_args = {'0': [],
class RustCompiler(Compiler):
LINKER_PREFIX = '-Wl,'
# rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs):
@ -109,3 +109,7 @@ class RustCompiler(Compiler):
def get_std_exe_link_args(self):
return []
# Rust does not have a use_linker_args because it dispatches to a gcc-like
# C compiler for dynamic linking, as such we invoke the C compiler's
# use_linker_args method instead.

@ -309,7 +309,9 @@ class BinaryTable(HasEnvVarFallback):
'strip': 'STRIP',
'ar': 'AR',
'windres': 'WINDRES',
'ld': 'LD',
# Other tools
'cmake': 'CMAKE',
'qmake': 'QMAKE',
'pkgconfig': 'PKG_CONFIG',

@ -733,55 +733,85 @@ class Environment:
errmsg += '\nRunning "{0}" gave "{1}"'.format(c, e)
raise EnvironmentException(errmsg)
@staticmethod
def _guess_win_linker(compiler: typing.List[str], for_machine: MachineChoice,
prefix: typing.Union[str, typing.List[str]]) -> 'DynamicLinker':
def _guess_win_linker(self, compiler: typing.List[str], comp_class: Compiler,
for_machine: MachineChoice,
prefix: typing.Union[str, typing.List[str]],
*, use_linker_prefix: bool = True) -> 'DynamicLinker':
# Explicitly pass logo here so that we can get the version of link.exe
if isinstance(prefix, str):
check_args = [prefix + '/logo', prefix + '--version']
else:
check_args = prefix + ['/logo'] + prefix + ['--version']
if not use_linker_prefix or comp_class.LINKER_PREFIX is None:
check_args = ['/logo', '--version']
elif isinstance(comp_class.LINKER_PREFIX, str):
check_args = [comp_class.LINKER_PREFIX + '/logo', comp_class.LINKER_PREFIX + '--version']
elif isinstance(comp_class.LINKER_PREFIX, list):
check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
override = [] # type: typing.List[str]
value = self.binaries[for_machine].lookup_entry('ld')
if value is not None:
override = comp_class.use_linker_args(value[0])
check_args += override
p, o, _ = Popen_safe(compiler + check_args)
if o.startswith('LLD'):
if '(compatible with GNU linkers)' in o:
return LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, version=search_version(o))
else:
return ClangClDynamicLinker(for_machine, exelist=compiler, prefix=prefix, version=search_version(o))
elif o.startswith('Microsoft'):
match = re.search(r'.*(X86|X64|ARM|ARM64).*', o)
return LLVMDynamicLinker(
compiler, for_machine, 'lld', comp_class.LINKER_PREFIX,
override, version=search_version(o))
if value is not None:
compiler = value
p, o, e = Popen_safe(compiler + check_args)
if o.startswith('LLD'):
return ClangClDynamicLinker(
for_machine, [],
prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
exelist=compiler, version=search_version(o))
elif 'OPTLINK' in o:
# Opltink's stdout *may* beging with a \r character.
return OptlinkDynamicLinker(for_machine, version=search_version(o))
elif o.startswith('Microsoft') or e.startswith('Microsoft'):
out = o or e
match = re.search(r'.*(X86|X64|ARM|ARM64).*', out)
if match:
target = str(match.group(1))
else:
target = 'x86'
return MSVCDynamicLinker(
for_machine, machine=target, exelist=compiler, prefix=prefix,
version=search_version(o))
raise MesonException('Cannot guess dynamic linker')
for_machine, [], machine=target, exelist=compiler,
prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
version=search_version(out))
raise EnvironmentException('Unable to determine dynamic linker')
@staticmethod
def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice,
def _guess_nix_linker(self, compiler: typing.List[str], comp_class: typing.Type[Compiler],
for_machine: MachineChoice,
prefix: typing.Union[str, typing.List[str]], *,
extra_args: typing.Optional[typing.List[str]] = None) -> 'DynamicLinker':
"""Helper for guessing what linker to use on Unix-Like OSes.
:prefix: The prefix that the compiler uses to proxy arguments to the
linker, if required. This can be passed as a string or a list of
strings. If it is passed as a string then the arguments to be
proxied to the linker will be concatenated, if it is a list they
will be appended. This means that if a space is required (such as
with swift which wants `-Xlinker --version` and *not*
`-Xlinker=--version`) you must pass as a list.
:compiler: Invocation to use to get linker
:comp_class: The Compiler Type (uninstantiated)
:for_machine: which machine this linker targets
:extra_args: Any additional arguments required (such as a source file)
"""
extra_args = typing.cast(typing.List[str], extra_args or [])
if isinstance(prefix, str):
check_args = [prefix + '--version'] + extra_args
else:
check_args = prefix + ['--version'] + extra_args
override = [] # type: typing.List[str]
value = self.binaries[for_machine].lookup_entry('ld')
if value is not None:
override = comp_class.use_linker_args(value[0])
check_args += override
_, o, e = Popen_safe(compiler + check_args)
v = search_version(o)
if o.startswith('LLD'):
linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, version=v) # type: DynamicLinker
linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, override, version=v) # type: DynamicLinker
elif e.startswith('lld-link: '):
# Toolchain wrapper got in the way; this happens with e.g. https://github.com/mstorsjo/llvm-mingw
# Let's try to extract the linker invocation command to grab the version.
@ -797,7 +827,7 @@ class Environment:
_, o, e = Popen_safe([linker_cmd, '--version'])
v = search_version(o)
linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, version=v)
linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, override, version=v)
# first is for apple clang, second is for real gcc
elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e:
if isinstance(prefix, str):
@ -811,19 +841,19 @@ class Environment:
break
else:
v = 'unknown version'
linker = AppleDynamicLinker(compiler, for_machine, i, prefix, version=v)
linker = AppleDynamicLinker(compiler, for_machine, i, prefix, override, version=v)
elif 'GNU' in o:
if 'gold' in o:
i = 'GNU ld.gold'
else:
i = 'GNU ld.bfd'
linker = GnuDynamicLinker(compiler, for_machine, i, prefix, version=v)
linker = GnuDynamicLinker(compiler, for_machine, i, prefix, override, version=v)
elif 'Solaris' in e or 'Solaris' in o:
linker = SolarisDynamicLinker(
compiler, for_machine, 'solaris', prefix,
compiler, for_machine, 'solaris', prefix, override,
version=search_version(e))
else:
raise MesonException('Unable to determine dynamic linker.')
raise EnvironmentException('Unable to determine dynamic linker')
return linker
def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice) -> Compiler:
@ -898,7 +928,7 @@ class Environment:
version = self.get_gnu_version_from_defines(defines)
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX)
linker = self._guess_nix_linker(compiler, cls, for_machine, cls.LINKER_PREFIX)
return cls(
ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, defines, full_version=full_version,
@ -925,7 +955,7 @@ class Environment:
version = search_version(arm_ver_str)
full_version = arm_ver_str
cls = ArmclangCCompiler if lang == 'c' else ArmclangCPPCompiler
linker = ArmClangDynamicLinker(for_machine, version=version)
linker = ArmClangDynamicLinker(for_machine, [], version=version)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
@ -944,7 +974,7 @@ class Environment:
else:
target = 'unknown target'
cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler
linker = ClangClDynamicLinker(for_machine, version=version)
linker = self._guess_win_linker(['lld-link'], cls, for_machine)
return cls(
compiler, version, for_machine, is_cross, info, exe_wrap,
target, linker=linker)
@ -963,11 +993,11 @@ class Environment:
# style ld, but for clang on "real" windows we'll use
# either link.exe or lld-link.exe
try:
linker = self._guess_win_linker(compiler, for_machine, cls.LINKER_PREFIX)
linker = self._guess_win_linker(compiler, cls, for_machine, cls.LINKER_PREFIX)
except MesonException:
pass
if linker is None:
linker = self._guess_nix_linker(compiler, for_machine, cls.LINKER_PREFIX)
linker = self._guess_nix_linker(compiler, cls, for_machine, cls.LINKER_PREFIX)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
@ -999,23 +1029,23 @@ class Environment:
else:
m = 'Failed to detect MSVC compiler target architecture: \'cl /?\' output is\n{}'
raise EnvironmentException(m.format(cl_signature))
linker = MSVCDynamicLinker(for_machine, version=version)
cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler
linker = self._guess_win_linker(['link'], cls, for_machine)
return cls(
compiler, version, for_machine, is_cross, info, exe_wrap,
target, linker=linker)
if 'PGI Compilers' in out:
cls = PGICCompiler if lang == 'c' else PGICPPCompiler
linker = PGIDynamicLinker(compiler, for_machine, 'pgi', cls.LINKER_PREFIX, version=version)
linker = PGIDynamicLinker(compiler, for_machine, 'pgi', cls.LINKER_PREFIX, [], version=version)
return cls(
ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, linker=linker)
if '(ICC)' in out:
cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler
if self.machines[for_machine].is_darwin():
l = XildAppleDynamicLinker(compiler, for_machine, 'xild', cls.LINKER_PREFIX, version=version)
l = XildAppleDynamicLinker(compiler, for_machine, 'xild', cls.LINKER_PREFIX, [], version=version)
else:
l = XildLinuxDynamicLinker(compiler, for_machine, 'xild', cls.LINKER_PREFIX, version=version)
l = XildLinuxDynamicLinker(compiler, for_machine, 'xild', cls.LINKER_PREFIX, [], version=version)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=l)
@ -1113,7 +1143,7 @@ class Environment:
version = self.get_gnu_version_from_defines(defines)
cls = GnuFortranCompiler
linker = self._guess_nix_linker(
compiler, for_machine, cls.LINKER_PREFIX)
compiler, cls, for_machine, cls.LINKER_PREFIX)
return cls(
compiler, version, for_machine, is_cross, info,
exe_wrap, defines, full_version=full_version,
@ -1121,7 +1151,7 @@ class Environment:
if 'G95' in out:
linker = self._guess_nix_linker(
compiler, for_machine, cls.LINKER_PREFIX)
compiler, cls, for_machine, cls.LINKER_PREFIX)
return G95FortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
@ -1129,7 +1159,7 @@ class Environment:
if 'Sun Fortran' in err:
version = search_version(err)
linker = self._guess_nix_linker(
compiler, for_machine, cls.LINKER_PREFIX)
compiler, cls, for_machine, cls.LINKER_PREFIX)
return SunFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
@ -1137,14 +1167,14 @@ class Environment:
if 'Intel(R) Visual Fortran' in err:
version = search_version(err)
target = 'x86' if 'IA-32' in err else 'x86_64'
linker = XilinkDynamicLinker(for_machine, version=version)
linker = XilinkDynamicLinker(for_machine, [], version=version)
return IntelClFortranCompiler(
compiler, version, for_machine, is_cross, target,
info, exe_wrap, linker=linker)
if 'ifort (IFORT)' in out:
linker = XildLinuxDynamicLinker(
compiler, for_machine, 'xild', IntelFortranCompiler.LINKER_PREFIX, version=version)
compiler, for_machine, 'xild', IntelFortranCompiler.LINKER_PREFIX, [], version=version)
return IntelFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
@ -1164,21 +1194,21 @@ class Environment:
if 'flang' in out or 'clang' in out:
linker = self._guess_nix_linker(
compiler, for_machine, FlangFortranCompiler.LINKER_PREFIX)
compiler, FlangFortranCompiler, for_machine, FlangFortranCompiler.LINKER_PREFIX)
return FlangFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
if 'Open64 Compiler Suite' in err:
linker = self._guess_nix_linker(
compiler, for_machine, Open64FortranCompiler.LINKER_PREFIX)
compiler, Open64FortranCompiler, for_machine, Open64FortranCompiler.LINKER_PREFIX)
return Open64FortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
if 'NAG Fortran' in err:
linker = self._guess_nix_linker(
compiler, for_machine, NAGFortranCompiler.LINKER_PREFIX)
compiler, NAGFortranCompiler, for_machine, NAGFortranCompiler.LINKER_PREFIX)
return NAGFortranCompiler(
compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
@ -1217,7 +1247,7 @@ class Environment:
continue
version = self.get_gnu_version_from_defines(defines)
comp = GnuObjCCompiler if objc else GnuObjCPPCompiler
linker = self._guess_nix_linker(compiler, for_machine, comp.LINKER_PREFIX)
linker = self._guess_nix_linker(compiler, comp, for_machine, comp.LINKER_PREFIX)
return comp(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, defines, linker=linker)
@ -1227,13 +1257,13 @@ class Environment:
if 'windows' in out or self.machines[for_machine].is_windows():
# If we're in a MINGW context this actually will use a gnu style ld
try:
linker = self._guess_win_linker(compiler, for_machine, comp.LINKER_PREFIX)
linker = self._guess_win_linker(compiler, comp, for_machine, comp.LINKER_PREFIX)
except MesonException:
pass
if not linker:
linker = self._guess_nix_linker(
compiler, for_machine, comp.LINKER_PREFIX)
compiler, comp, for_machine, comp.LINKER_PREFIX)
return comp(
ccache + compiler, version, for_machine,
is_cross, info, exe_wrap, linker=linker)
@ -1316,19 +1346,36 @@ class Environment:
version = search_version(out)
if 'rustc' in out:
# Chalk up another quirk for rust. There is no way (AFAICT) to
# figure out what linker rustc is using for a non-nightly compiler
# (On nightly you can pass -Z print-link-args). So we're going to
# hard code the linker based on the platform.
# Currently gnu ld is used for everything except apple by
# default, and apple ld is used on mac.
# TODO: find some better way to figure this out.
if self.machines[for_machine].is_darwin():
linker = AppleDynamicLinker(
[], for_machine, 'Apple ld', RustCompiler.LINKER_PREFIX)
if info.is_windows() or info.is_cygwin():
# On windows rustc invokes link.exe
linker = self._guess_win_linker(['link'], for_machine)
else:
linker = GnuDynamicLinker(
[], for_machine, 'GNU ld', RustCompiler.LINKER_PREFIX)
# On Linux and mac rustc will invoke gcc (clang for mac
# presumably), for dynamic linking. this means the easiest
# way to C compiler for dynamic linking. figure out what
# linker to use !windows it to just get the value of the C
# compiler and use that as the basis of the rust linker.
# However, there are two things we need to change, if CC is
# not the default use that, and second add the necessary
# arguments to rust to use -fuse-ld
cc = self.detect_c_compiler(for_machine)
extra_args = []
if not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or
isinstance(cc, GnuCCompiler)):
c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0]
extra_args.extend(['-C', 'linker={}'.format(c)])
value = self.binaries[for_machine].lookup_entry('ld')
if value is not None:
for a in cc.use_linker_args(value[0]):
extra_args.extend(['-C', 'link-arg={}'.format(a)])
# This trickery with type() gets us the class of the linker
# so we can initialize a new copy for the Rust Compiler
linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX,
always_args=extra_args, version=cc.linker.version)
return RustCompiler(
compiler, version, for_machine, is_cross, info, exe_wrap,
linker=linker)
@ -1375,26 +1422,25 @@ class Environment:
# LDC seems to require a file
m = self.machines[for_machine]
if m.is_windows() or m.is_cygwin():
if is_msvc:
linker = MSVCDynamicLinker(for_machine, version=version)
else:
# Getting LDC on windows to give useful linker output when not
# doing real work is painfully hard. It ships with a version of
# lld-link, so just assume that we're going to use lld-link
# with it.
_, o, _ = Popen_safe(['lld-link.exe', '--version'])
linker = ClangClDynamicLinker(for_machine, version=search_version(o))
# Getting LDC on windows to give useful linker output when
# not doing real work is painfully hard. It ships with a
# version of lld-link, so unless we think the user wants
# link.exe, just assume that we're going to use lld-link
# with it.
linker = self._guess_win_linker(
['link' if is_msvc else 'lld-link'],
compilers.LLVMDCompiler, for_machine, use_linker_prefix=False)
else:
with tempfile.NamedTemporaryFile(suffix='.d') as f:
linker = self._guess_nix_linker(
exelist, for_machine,
exelist, compilers.LLVMDCompiler, for_machine,
compilers.LLVMDCompiler.LINKER_PREFIX,
extra_args=[f.name])
return compilers.LLVMDCompiler(
exelist, version, for_machine, info, arch,
full_version=full_version, linker=linker)
elif 'gdc' in out:
linker = self._guess_nix_linker(exelist, for_machine, compilers.GnuDCompiler.LINKER_PREFIX)
linker = self._guess_nix_linker(exelist, compilers.GnuDCompiler, for_machine, compilers.GnuDCompiler.LINKER_PREFIX)
return compilers.GnuDCompiler(
exelist, version, for_machine, info, arch, is_cross, exe_wrap,
full_version=full_version, linker=linker)
@ -1403,17 +1449,17 @@ class Environment:
m = self.machines[for_machine]
if m.is_windows() or m.is_cygwin():
if is_msvc:
linker = MSVCDynamicLinker(for_machine, version=version)
linker_cmd = ['link']
elif arch == 'x86':
linker = OptlinkDynamicLinker(for_machine, version=full_version)
linker_cmd = ['optlink']
else:
# DMD ships with lld-link
_, o, _ = Popen_safe(['lld-link.exe', '--version'])
linker = ClangClDynamicLinker(for_machine, version=search_version(o))
linker_cmd = ['lld-link']
linker = self._guess_win_linker(linker_cmd, compilers.DmdDCompiler, for_machine,
use_linker_prefix=False)
else:
with tempfile.NamedTemporaryFile(suffix='.d') as f:
linker = self._guess_nix_linker(
exelist, for_machine,
exelist, compilers.DmdDCompiler, for_machine,
compilers.LLVMDCompiler.LINKER_PREFIX,
extra_args=[f.name])
return compilers.DmdDCompiler(
@ -1440,7 +1486,7 @@ class Environment:
# As for 5.0.1 swiftc *requires* a file to check the linker:
with tempfile.NamedTemporaryFile(suffix='.swift') as f:
linker = self._guess_nix_linker(
exelist, for_machine,
exelist, compilers.SwiftCompiler, for_machine,
compilers.SwiftCompiler.LINKER_PREFIX,
extra_args=[f.name])
return compilers.SwiftCompiler(

@ -247,17 +247,21 @@ class DynamicLinker(metaclass=abc.ABCMeta):
} # type: typing.Dict[str, typing.List[str]]
def _apply_prefix(self, arg: str) -> typing.List[str]:
if isinstance(self.prefix_arg, str):
if self.prefix_arg is None:
return [arg]
elif isinstance(self.prefix_arg, str):
return [self.prefix_arg + arg]
return self.prefix_arg + [arg]
def __init__(self, exelist: typing.List[str], for_machine: mesonlib.MachineChoice,
id_: str, prefix_arg: typing.Union[str, typing.List[str]], *, version: str = 'unknown version'):
id_: str, prefix_arg: typing.Union[str, typing.List[str]],
always_args: typing.List[str], *, version: str = 'unknown version'):
self.exelist = exelist
self.for_machine = for_machine
self.version = version
self.id = id_
self.prefix_arg = prefix_arg
self.always_args = always_args
def __repr__(self) -> str:
return '<{}: v{} `{}`>'.format(type(self).__name__, self.version, ' '.join(self.exelist))
@ -276,7 +280,7 @@ class DynamicLinker(metaclass=abc.ABCMeta):
return mesonlib.is_windows()
def get_always_args(self) -> typing.List[str]:
return []
return self.always_args.copy()
def get_lib_prefix(self) -> str:
return ''
@ -715,7 +719,7 @@ class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__(['armlink'], for_machine, 'armlink', '',
super().__init__(['armlink'], for_machine, 'armlink', '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@ -853,33 +857,33 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Microsoft's Link.exe."""
def __init__(self, for_machine: mesonlib.MachineChoice, *,
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: typing.List[str], *,
exelist: typing.Optional[typing.List[str]] = None,
prefix: typing.Union[str, typing.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version'):
super().__init__(exelist or ['link.exe'], for_machine, 'link',
prefix, machine=machine, version=version)
prefix, always_args, machine=machine, version=version)
class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Clang's lld-link.exe."""
def __init__(self, for_machine: mesonlib.MachineChoice, *,
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: typing.List[str], *,
exelist: typing.Optional[typing.List[str]] = None,
prefix: typing.Union[str, typing.List[str]] = '',
version: str = 'unknown version'):
super().__init__(exelist or ['lld-link.exe'], for_machine,
'lld-link', prefix, version=version)
super().__init__(exelist or ['lld-link.exe'], for_machine, 'lld-link',
prefix, always_args, version=version)
class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Intel's Xilink.exe."""
def __init__(self, for_machine: mesonlib.MachineChoice,
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: typing.List[str],
*, version: str = 'unknown version'):
super().__init__(['xilink.exe'], for_machine, 'xilink', '', version=version)
super().__init__(['xilink.exe'], for_machine, 'xilink', '', always_args, version=version)
class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
@ -936,7 +940,7 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
*, version: str = 'unknown version'):
# Use optlink instead of link so we don't interfer with other link.exe
# implementations.
super().__init__(['optlink.exe'], for_machine, 'optlink', prefix_arg='', version=version)
super().__init__(['optlink.exe'], for_machine, 'optlink', '', [], version=version)
def get_allow_undefined_args(self) -> typing.List[str]:
return []

@ -445,7 +445,7 @@ class InternalTests(unittest.TestCase):
def test_compiler_args_class_gnuld(self):
cargsfunc = mesonbuild.compilers.CompilerArgs
## Test --start/end-group
linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,')
linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,', [])
gcc = mesonbuild.compilers.GnuCCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker)
## Ensure that the fake compiler is never called by overriding the relevant function
gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include']
@ -474,7 +474,7 @@ class InternalTests(unittest.TestCase):
def test_compiler_args_remove_system(self):
cargsfunc = mesonbuild.compilers.CompilerArgs
## Test --start/end-group
linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,')
linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,', [])
gcc = mesonbuild.compilers.GnuCCompiler([], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker)
## Ensure that the fake compiler is never called by overriding the relevant function
gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include']

Loading…
Cancel
Save