linkers: Update the linker names to be more consistent

This makes two basic changes, 1 it moves the name of the linker into the
linker class, this should reduce the number of errors and typos, and
ensure that a linker always has one name. This then renames the linkers
to have more consistent names.

Posix/gnu linkers are called ld.<name>: ld.gold, ld.lld, ld.solaris.

Apple linkers are renamed ld64.
pull/6672/head
Dylan Baker 5 years ago committed by Nirbheek Chauhan
parent 9e7cca1472
commit 48f3e72493
  1. 13
      docs/markdown/Reference-tables.md
  2. 26
      mesonbuild/environment.py
  3. 50
      mesonbuild/linkers.py
  4. 16
      run_unittests.py

@ -38,17 +38,18 @@ These are return values of the `get_linker_id` method in a compiler object.
| Value | Linker family |
| ----- | --------------- |
| ld.bfd | The GNU linker |
| ld.gold | The GNU linker |
| lld | The LLVM linker, with the GNU interface |
| ld.gold | The GNU gold linker |
| ld.lld | The LLVM linker, with the GNU interface |
| ld.solaris | Solaris and illumos |
| ld64 | Apple ld64 |
| link | MSVC linker |
| pgi | Portland/Nvidia PGI |
| lld-link | The LLVM linker, with the MSVC interface |
| xilink | Used with Intel-cl only, MSVC like |
| optlink | optlink (used with DMD) |
| rlink | The Renesas linker, used with CCrx only |
| armlink | The ARM linker (arm and armclang compilers) |
| optlink | optlink |
| APPLE ld | Apple ld64 |
| solaris | Solaris and illumos |
| pgi | Portland/Nvidia PGI |
| nvlink | Nvidia Linker used with cuda |
For languages that don't have separate dynamic linkers such as C# and Java, the
`get_linker_id` will return the compiler name.

@ -47,7 +47,8 @@ from .linkers import (
CcrxDynamicLinker,
ClangClDynamicLinker,
DynamicLinker,
GnuDynamicLinker,
GnuBFDDynamicLinker,
GnuGoldDynamicLinker,
LLVMDynamicLinker,
MSVCDynamicLinker,
OptlinkDynamicLinker,
@ -767,7 +768,7 @@ class Environment:
if o.startswith('LLD'):
if '(compatible with GNU linkers)' in o:
return LLVMDynamicLinker(
compiler, for_machine, 'lld', comp_class.LINKER_PREFIX,
compiler, for_machine, comp_class.LINKER_PREFIX,
override, version=search_version(o))
if value is not None:
@ -830,7 +831,7 @@ class Environment:
v = search_version(o)
if o.startswith('LLD'):
linker = LLVMDynamicLinker(
compiler, for_machine, 'lld', comp_class.LINKER_PREFIX, override, version=v) # type: DynamicLinker
compiler, for_machine, comp_class.LINKER_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.
@ -846,30 +847,29 @@ class Environment:
_, o, e = Popen_safe([linker_cmd, '--version'])
v = search_version(o)
linker = LLVMDynamicLinker(compiler, for_machine, 'lld', comp_class.LINKER_PREFIX, override, version=v)
linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
# first is for apple clang, second is for real gcc, the third is icc
elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e:
if isinstance(comp_class.LINKER_PREFIX, str):
_, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
else:
_, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
i = 'APPLE ld'
for line in e.split('\n'):
if 'PROJECT:ld' in line:
v = line.split('-')[1]
break
else:
v = 'unknown version'
linker = AppleDynamicLinker(compiler, for_machine, i, comp_class.LINKER_PREFIX, override, version=v)
linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'GNU' in o:
if 'gold' in o:
i = 'GNU ld.gold'
cls = GnuGoldDynamicLinker
else:
i = 'GNU ld.bfd'
linker = GnuDynamicLinker(compiler, for_machine, i, comp_class.LINKER_PREFIX, override, version=v)
cls = GnuBFDDynamicLinker
linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'Solaris' in e or 'Solaris' in o:
linker = SolarisDynamicLinker(
compiler, for_machine, 'solaris', comp_class.LINKER_PREFIX, override,
compiler, for_machine, comp_class.LINKER_PREFIX, override,
version=search_version(e))
else:
raise EnvironmentException('Unable to determine dynamic linker')
@ -1061,7 +1061,7 @@ class Environment:
if 'PGI Compilers' in out:
cls = PGICCompiler if lang == 'c' else PGICPPCompiler
self.coredata.add_lang_args(cls.language, cls, for_machine, self)
linker = PGIDynamicLinker(compiler, for_machine, 'pgi', cls.LINKER_PREFIX, [], version=version)
linker = PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version)
return cls(
ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, linker=linker)
@ -1214,7 +1214,7 @@ class Environment:
if 'PGI Compilers' in out:
cls = PGIFortranCompiler
self.coredata.add_lang_args(cls.language, cls, for_machine, self)
linker = PGIDynamicLinker(compiler, for_machine, 'pgi',
linker = PGIDynamicLinker(compiler, for_machine,
cls.LINKER_PREFIX, [], version=version)
return cls(
compiler, version, for_machine, is_cross, info, exe_wrap,
@ -1413,7 +1413,7 @@ class Environment:
linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
version=cc.linker.version, **extra_args)
else:
linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX,
linker = type(cc.linker)(compiler, for_machine, cc.LINKER_PREFIX,
always_args=always_args, version=cc.linker.version,
**extra_args)
elif 'link' in override[0]:

@ -257,8 +257,8 @@ class DynamicLinker(metaclass=abc.ABCMeta):
ret += self.prefix_arg + [arg]
return ret
def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
id_: str, prefix_arg: T.Union[str, T.List[str]],
def __init__(self, id_: str, exelist: T.List[str],
for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]],
always_args: T.List[str], *, version: str = 'unknown version'):
self.exelist = exelist
self.for_machine = for_machine
@ -570,6 +570,9 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Apple's ld implementation."""
def __init__(self, *args, **kwargs):
super().__init__('ld64', *args, **kwargs)
def get_asneeded_args(self) -> T.List[str]:
return self._apply_prefix('-dead_strip_dylibs')
@ -649,18 +652,29 @@ class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dynam
"""Representation of GNU ld.bfd and ld.gold."""
pass
class GnuGoldDynamicLinker(GnuDynamicLinker):
def __init__(self, *args, **kwargs):
super().__init__('ld.gold', *args, **kwargs)
class GnuBFDDynamicLinker(GnuDynamicLinker):
def __init__(self, *args, **kwargs):
super().__init__('ld.bfd', *args, **kwargs)
class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
"""Representation of LLVM's lld (not lld-link) linker.
"""Representation of LLVM's ld.lld linker.
This is only the posix-like linker.
This is only the gnu-like linker, not the apple like or link.exe like
linkers.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
super().__init__('ld.lld', *args, **kwargs)
# Some targets don't seem to support this argument (windows, wasm, ...)
_, _, e = mesonlib.Popen_safe(self.exelist + self._apply_prefix('--allow-shlib-undefined'))
@ -672,14 +686,13 @@ class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
return []
class CcrxDynamicLinker(DynamicLinker):
"""Linker for Renesis CCrx compiler."""
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__(['rlink.exe'], for_machine, 'rlink', '', [],
super().__init__('rlink', ['rlink.exe'], for_machine, '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@ -712,7 +725,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', ['armlink'], for_machine, '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@ -744,6 +757,9 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""PGI linker."""
def __init__(self, *args, **kwargs):
super().__init__('pgi', *args, **kwargs)
def get_allow_undefined_args(self) -> T.List[str]:
return []
@ -857,7 +873,7 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version',
direct: bool = True):
super().__init__(exelist or ['link.exe'], for_machine, 'link',
super().__init__('link', exelist or ['link.exe'], for_machine,
prefix, always_args, machine=machine, version=version, direct=direct)
def get_always_args(self) -> T.List[str]:
@ -873,7 +889,7 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version',
direct: bool = True):
super().__init__(exelist or ['lld-link.exe'], for_machine, 'lld-link',
super().__init__('lld-link', exelist or ['lld-link.exe'], for_machine,
prefix, always_args, machine=machine, version=version, direct=direct)
@ -883,13 +899,16 @@ class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str],
*, version: str = 'unknown version'):
super().__init__(['xilink.exe'], for_machine, 'xilink', '', always_args, version=version)
super().__init__('xilink', ['xilink.exe'], for_machine, '', always_args, version=version)
class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Sys-V derived linker used on Solaris and OpenSolaris."""
def __init__(self, *args, **kwargs):
super().__init__('ld.solaris', *args, **kwargs)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
if not args:
return args
@ -940,13 +959,18 @@ 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', '', [], version=version)
super().__init__('optlink', ['optlink.exe'], for_machine, '', [], version=version)
def get_allow_undefined_args(self) -> T.List[str]:
return []
class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Cuda linker (nvlink)"""
def __init__(self, *args, **kwargs):
super().__init__('nvlink', *args, **kwargs)
@staticmethod
def parse_version():
version_cmd = ['nvlink', '--version']

@ -6061,30 +6061,30 @@ c = ['{0}']
self.assertEqual(comp.linker.id, expected)
def test_ld_environment_variable_bfd(self):
self._check_ld('ld.bfd', 'bfd', 'c', 'GNU ld.bfd')
self._check_ld('ld.bfd', 'bfd', 'c', 'ld.bfd')
def test_ld_environment_variable_gold(self):
self._check_ld('ld.gold', 'gold', 'c', 'GNU ld.gold')
self._check_ld('ld.gold', 'gold', 'c', 'ld.gold')
def test_ld_environment_variable_lld(self):
self._check_ld('ld.lld', 'lld', 'c', 'lld')
self._check_ld('ld.lld', 'lld', 'c', 'ld.lld')
@skipIfNoExecutable('rustc')
def test_ld_environment_variable_rust(self):
self._check_ld('ld.gold', 'gold', 'rust', 'GNU ld.gold')
self._check_ld('ld.gold', 'gold', 'rust', 'ld.gold')
def test_ld_environment_variable_cpp(self):
self._check_ld('ld.gold', 'gold', 'cpp', 'GNU ld.gold')
self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold')
def test_ld_environment_variable_objc(self):
self._check_ld('ld.gold', 'gold', 'objc', 'GNU ld.gold')
self._check_ld('ld.gold', 'gold', 'objc', 'ld.gold')
def test_ld_environment_variable_objcpp(self):
self._check_ld('ld.gold', 'gold', 'objcpp', 'GNU ld.gold')
self._check_ld('ld.gold', 'gold', 'objcpp', 'ld.gold')
@skipIfNoExecutable('gfortran')
def test_ld_environment_variable_fortran(self):
self._check_ld('ld.gold', 'gold', 'fortran', 'GNU ld.gold')
self._check_ld('ld.gold', 'gold', 'fortran', 'ld.gold')
def compute_sha256(self, filename):
with open(filename, 'rb') as f:

Loading…
Cancel
Save