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/6679/head
Dylan Baker 5 years ago committed by Nirbheek Chauhan
parent c5e66dd69c
commit c708c52ca2
  1. 30
      docs/markdown/Reference-tables.md
  2. 26
      mesonbuild/environment.py
  3. 50
      mesonbuild/linkers.py
  4. 16
      run_unittests.py

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

@ -47,7 +47,8 @@ from .linkers import (
CcrxDynamicLinker, CcrxDynamicLinker,
ClangClDynamicLinker, ClangClDynamicLinker,
DynamicLinker, DynamicLinker,
GnuDynamicLinker, GnuBFDDynamicLinker,
GnuGoldDynamicLinker,
LLVMDynamicLinker, LLVMDynamicLinker,
MSVCDynamicLinker, MSVCDynamicLinker,
OptlinkDynamicLinker, OptlinkDynamicLinker,
@ -766,7 +767,7 @@ class Environment:
if o.startswith('LLD'): if o.startswith('LLD'):
if '(compatible with GNU linkers)' in o: if '(compatible with GNU linkers)' in o:
return LLVMDynamicLinker( return LLVMDynamicLinker(
compiler, for_machine, 'lld', comp_class.LINKER_PREFIX, compiler, for_machine, comp_class.LINKER_PREFIX,
override, version=search_version(o)) override, version=search_version(o))
if value is not None: if value is not None:
@ -829,7 +830,7 @@ class Environment:
v = search_version(o) v = search_version(o)
if o.startswith('LLD'): if o.startswith('LLD'):
linker = LLVMDynamicLinker( 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: '): elif e.startswith('lld-link: '):
# Toolchain wrapper got in the way; this happens with e.g. https://github.com/mstorsjo/llvm-mingw # 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. # Let's try to extract the linker invocation command to grab the version.
@ -845,30 +846,29 @@ class Environment:
_, o, e = Popen_safe([linker_cmd, '--version']) _, o, e = Popen_safe([linker_cmd, '--version'])
v = search_version(o) 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 # 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: 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): if isinstance(comp_class.LINKER_PREFIX, str):
_, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args) _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
else: else:
_, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args) _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
i = 'APPLE ld'
for line in e.split('\n'): for line in e.split('\n'):
if 'PROJECT:ld' in line: if 'PROJECT:ld' in line:
v = line.split('-')[1] v = line.split('-')[1]
break break
else: else:
v = 'unknown version' 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: elif 'GNU' in o:
if 'gold' in o: if 'gold' in o:
i = 'GNU ld.gold' cls = GnuGoldDynamicLinker
else: else:
i = 'GNU ld.bfd' cls = GnuBFDDynamicLinker
linker = GnuDynamicLinker(compiler, for_machine, i, comp_class.LINKER_PREFIX, override, version=v) linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'Solaris' in e or 'Solaris' in o: elif 'Solaris' in e or 'Solaris' in o:
linker = SolarisDynamicLinker( linker = SolarisDynamicLinker(
compiler, for_machine, 'solaris', comp_class.LINKER_PREFIX, override, compiler, for_machine, comp_class.LINKER_PREFIX, override,
version=search_version(e)) version=search_version(e))
else: else:
raise EnvironmentException('Unable to determine dynamic linker') raise EnvironmentException('Unable to determine dynamic linker')
@ -1060,7 +1060,7 @@ class Environment:
if 'PGI Compilers' in out: if 'PGI Compilers' in out:
cls = PGICCompiler if lang == 'c' else PGICPPCompiler cls = PGICCompiler if lang == 'c' else PGICPPCompiler
self.coredata.add_lang_args(cls.language, cls, for_machine, self) 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( return cls(
ccache + compiler, version, for_machine, is_cross, ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, linker=linker) info, exe_wrap, linker=linker)
@ -1213,7 +1213,7 @@ class Environment:
if 'PGI Compilers' in out: if 'PGI Compilers' in out:
cls = PGIFortranCompiler cls = PGIFortranCompiler
self.coredata.add_lang_args(cls.language, cls, for_machine, self) 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) cls.LINKER_PREFIX, [], version=version)
return cls( return cls(
compiler, version, for_machine, is_cross, info, exe_wrap, compiler, version, for_machine, is_cross, info, exe_wrap,
@ -1410,7 +1410,7 @@ class Environment:
linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist, linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
version=cc.linker.version, **extra_args) version=cc.linker.version, **extra_args)
else: 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, always_args=always_args, version=cc.linker.version,
**extra_args) **extra_args)
elif 'link' in override[0]: elif 'link' in override[0]:

@ -257,8 +257,8 @@ class DynamicLinker(metaclass=abc.ABCMeta):
ret += self.prefix_arg + [arg] ret += self.prefix_arg + [arg]
return ret return ret
def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice, def __init__(self, id_: str, exelist: T.List[str],
id_: str, prefix_arg: T.Union[str, T.List[str]], for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]],
always_args: T.List[str], *, version: str = 'unknown version'): always_args: T.List[str], *, version: str = 'unknown version'):
self.exelist = exelist self.exelist = exelist
self.for_machine = for_machine self.for_machine = for_machine
@ -570,6 +570,9 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Apple's ld implementation.""" """Apple's ld implementation."""
def __init__(self, *args, **kwargs):
super().__init__('ld64', *args, **kwargs)
def get_asneeded_args(self) -> T.List[str]: def get_asneeded_args(self) -> T.List[str]:
return self._apply_prefix('-dead_strip_dylibs') return self._apply_prefix('-dead_strip_dylibs')
@ -649,17 +652,29 @@ class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dynam
"""Representation of GNU ld.bfd and ld.gold.""" """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): 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.
""" """
pass def __init__(self, *args, **kwargs):
super().__init__('ld.lld', *args, **kwargs)
class CcrxDynamicLinker(DynamicLinker): class CcrxDynamicLinker(DynamicLinker):
@ -668,7 +683,7 @@ class CcrxDynamicLinker(DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice, def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'): *, version: str = 'unknown version'):
super().__init__(['rlink.exe'], for_machine, 'rlink', '', [], super().__init__('rlink', ['rlink.exe'], for_machine, '', [],
version=version) version=version)
def get_accepts_rsp(self) -> bool: def get_accepts_rsp(self) -> bool:
@ -701,7 +716,7 @@ class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice, def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'): *, version: str = 'unknown version'):
super().__init__(['armlink'], for_machine, 'armlink', '', [], super().__init__('armlink', ['armlink'], for_machine, '', [],
version=version) version=version)
def get_accepts_rsp(self) -> bool: def get_accepts_rsp(self) -> bool:
@ -733,6 +748,9 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""PGI linker.""" """PGI linker."""
def __init__(self, *args, **kwargs):
super().__init__('pgi', *args, **kwargs)
def get_allow_undefined_args(self) -> T.List[str]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
@ -846,7 +864,7 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
prefix: T.Union[str, T.List[str]] = '', prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version', machine: str = 'x86', version: str = 'unknown version',
direct: bool = True): 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) prefix, always_args, machine=machine, version=version, direct=direct)
def get_always_args(self) -> T.List[str]: def get_always_args(self) -> T.List[str]:
@ -862,7 +880,7 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
prefix: T.Union[str, T.List[str]] = '', prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version', machine: str = 'x86', version: str = 'unknown version',
direct: bool = True): 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) prefix, always_args, machine=machine, version=version, direct=direct)
@ -872,13 +890,16 @@ class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str],
*, version: str = 'unknown version'): *, 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): class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Sys-V derived linker used on Solaris and OpenSolaris.""" """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]: def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
if not args: if not args:
return args return args
@ -929,13 +950,18 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
*, version: str = 'unknown version'): *, version: str = 'unknown version'):
# Use optlink instead of link so we don't interfer with other link.exe # Use optlink instead of link so we don't interfer with other link.exe
# implementations. # 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]: def get_allow_undefined_args(self) -> T.List[str]:
return [] return []
class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker): class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Cuda linker (nvlink)""" """Cuda linker (nvlink)"""
def __init__(self, *args, **kwargs):
super().__init__('nvlink', *args, **kwargs)
@staticmethod @staticmethod
def parse_version(): def parse_version():
version_cmd = ['nvlink', '--version'] version_cmd = ['nvlink', '--version']

@ -5942,30 +5942,30 @@ c = ['{0}']
self.assertEqual(comp.linker.id, expected) self.assertEqual(comp.linker.id, expected)
def test_ld_environment_variable_bfd(self): 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): 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): 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') @skipIfNoExecutable('rustc')
def test_ld_environment_variable_rust(self): 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): 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): 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): 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') @skipIfNoExecutable('gfortran')
def test_ld_environment_variable_fortran(self): 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): def compute_sha256(self, filename):
with open(filename, 'rb') as f: with open(filename, 'rb') as f:

Loading…
Cancel
Save