Compare commits

...

4 Commits

Author SHA1 Message Date
Dylan Baker 3526b36a77 linkers: fully type annotate and fix mypy issues 4 years ago
Dylan Baker 4401668c9a linkers/compilers: Move an emscripten method to the compiler 4 years ago
Dylan Baker 67ab2880dd linkers: Make id a class variable for DynamicLinkers 4 years ago
Dylan Baker fc86df3d2c linkers: Fix argument error 4 years ago
  1. 7
      mesonbuild/compilers/mixins/emscripten.py
  2. 116
      mesonbuild/linkers.py
  3. 1
      run_mypy.py
  4. 4
      run_unittests.py

@ -41,6 +41,13 @@ class EmscriptenMixin:
def thread_flags(self, env: 'Environment') -> T.List[str]:
return ['-s', 'USE_PTHREADS=1']
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-s', 'USE_PTHREADS=1']
count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int
if count:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
def get_options(self):
opts = super().get_options()
opts.update({

@ -22,6 +22,7 @@ from .envconfig import get_env_var
if T.TYPE_CHECKING:
from .coredata import OptionDictType
from .envconfig import MachineChoice
from .environment import Environment
@ -327,6 +328,10 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
'custom': [],
} # type: T.Dict[str, T.List[str]]
@abc.abstractproperty
def id(self) -> str:
pass
def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]:
args = [arg] if isinstance(arg, str) else arg
if self.prefix_arg is None:
@ -338,13 +343,12 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
ret += self.prefix_arg + [arg]
return ret
def __init__(self, id_: str, exelist: T.List[str],
def __init__(self, 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
self.version = version
self.id = id_
self.prefix_arg = prefix_arg
self.always_args = always_args
@ -513,6 +517,10 @@ class GnuLikeDynamicLinkerMixin:
other linkers like GNU-ld.
"""
if T.TYPE_CHECKING:
for_machine = MachineChoice.HOST
def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ...
_BUILDTYPE_ARGS = {
'plain': [],
'debug': [],
@ -655,8 +663,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Apple's ld implementation."""
def __init__(self, *args, **kwargs):
super().__init__('ld64', *args, **kwargs)
id = 'ld64'
def get_asneeded_args(self) -> T.List[str]:
return self._apply_prefix('-dead_strip_dylibs')
@ -741,14 +748,12 @@ class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dynam
class GnuGoldDynamicLinker(GnuDynamicLinker):
def __init__(self, *args, **kwargs):
super().__init__('ld.gold', *args, **kwargs)
id = 'ld.gold'
class GnuBFDDynamicLinker(GnuDynamicLinker):
def __init__(self, *args, **kwargs):
super().__init__('ld.bfd', *args, **kwargs)
id = 'ld.bfd'
class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
@ -759,8 +764,12 @@ class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
linkers.
"""
def __init__(self, *args, **kwargs):
super().__init__('ld.lld', *args, **kwargs)
id = 'ld.lld'
def __init__(self, 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'):
super().__init__(exelist, for_machine, prefix_arg, always_args, version=version)
# Some targets don't seem to support this argument (windows, wasm, ...)
_, _, e = mesonlib.Popen_safe(self.exelist + self._apply_prefix('--allow-shlib-undefined'))
@ -776,15 +785,7 @@ class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
"""Emscripten's wasm-ld."""
def __init__(self, *args, **kwargs):
super().__init__('ld.wasm', *args, **kwargs)
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-s', 'USE_PTHREADS=1']
count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int
if count:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
id = 'ld.wasm'
def get_allow_undefined_args(self) -> T.List[str]:
return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0']
@ -810,9 +811,11 @@ class CcrxDynamicLinker(DynamicLinker):
"""Linker for Renesis CCrx compiler."""
id = 'rlink'
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__('rlink', ['rlink.exe'], for_machine, '', [],
super().__init__(['rlink.exe'], for_machine, '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@ -843,9 +846,11 @@ class Xc16DynamicLinker(DynamicLinker):
"""Linker for Microchip XC16 compiler."""
id = 'xc16-gcc'
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__('xc16-gcc', ['xc16-gcc.exe'], for_machine, '', [],
super().__init__(['xc16-gcc.exe'], for_machine, '', [],
version=version)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
@ -885,9 +890,11 @@ class CompCertDynamicLinker(DynamicLinker):
"""Linker for CompCert C compiler."""
id = 'ccomp'
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__('ccomp', ['ccomp'], for_machine, '', [],
super().__init__(['ccomp'], for_machine, '', [],
version=version)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
@ -908,7 +915,7 @@ class CompCertDynamicLinker(DynamicLinker):
return ['-o{}'.format(outputname)]
def get_search_args(self, dirname: str) -> T.List[str]:
return ['-L{}'.format(outputname)]
return ['-L{}'.format(dirname)]
def get_allow_undefined_args(self) -> T.List[str]:
return []
@ -927,9 +934,11 @@ class C2000DynamicLinker(DynamicLinker):
"""Linker for Texas Instruments C2000 compiler."""
id = 'cl2000'
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__('cl2000', ['cl2000.exe'], for_machine, '', [],
super().__init__(['cl2000.exe'], for_machine, '', [],
version=version)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
@ -963,9 +972,11 @@ class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Linker for the ARM compiler."""
id = 'armlink'
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
super().__init__('armlink', ['armlink'], for_machine, '', [],
super().__init__(['armlink'], for_machine, '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@ -993,18 +1004,17 @@ class ArmClangDynamicLinker(ArmDynamicLinker):
return ['--symdefs=' + implibname]
class QualcommLLVMDynamicLinker(LLVMDynamicLinker):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# ARM Linker from Snapdragon LLVM ARM Compiler
self.id = 'ld.qcld'
"""ARM Linker from Snapdragon LLVM ARM Compiler."""
id = 'ld.qcld'
class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""PGI linker."""
def __init__(self, *args, **kwargs):
super().__init__('pgi', *args, **kwargs)
id = 'pgi'
def get_allow_undefined_args(self) -> T.List[str]:
return []
@ -1049,6 +1059,12 @@ NvidiaHPC_StaticLinker = PGIStaticLinker
class VisualStudioLikeLinkerMixin:
"""Mixin class for for dynamic linkers that act like Microsoft's link.exe."""
if T.TYPE_CHECKING:
for_machine = MachineChoice.HOST
def _apply_prefix(self, arg: T.Union[str, T.List[str]]) -> T.List[str]: ...
_BUILDTYPE_ARGS = {
'plain': [],
'debug': [],
@ -1060,9 +1076,13 @@ class VisualStudioLikeLinkerMixin:
'custom': [],
} # type: T.Dict[str, T.List[str]]
def __init__(self, *args, direct: bool = True, machine: str = 'x86', **kwargs):
super().__init__(*args, **kwargs)
def __init__(self, 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', direct: bool = True, machine: str = 'x86'):
# There's no way I can find to make mypy understand what's going on here
super().__init__(exelist, for_machine, prefix_arg, always_args, version=version) # type: ignore
self.machine = machine
self.direct = direct
def get_buildtype_args(self, buildtype: str) -> T.List[str]:
return mesonlib.listify([self._apply_prefix(a) for a in self._BUILDTYPE_ARGS[buildtype]])
@ -1074,7 +1094,8 @@ class VisualStudioLikeLinkerMixin:
return self._apply_prefix(['/MACHINE:' + self.machine, '/OUT:' + outputname])
def get_always_args(self) -> T.List[str]:
return self._apply_prefix('/nologo') + super().get_always_args()
parent = super().get_always_args() # type: ignore
return self._apply_prefix('/nologo') + T.cast(T.List[str], parent)
def get_search_args(self, dirname: str) -> T.List[str]:
return self._apply_prefix('/LIBPATH:' + dirname)
@ -1114,12 +1135,14 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Microsoft's Link.exe."""
id = 'link'
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
exelist: T.Optional[T.List[str]] = None,
prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version',
direct: bool = True):
super().__init__('link', exelist or ['link.exe'], for_machine,
super().__init__(exelist or ['link.exe'], for_machine,
prefix, always_args, machine=machine, version=version, direct=direct)
def get_always_args(self) -> T.List[str]:
@ -1130,12 +1153,14 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Clang's lld-link.exe."""
id = 'lld-link'
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str], *,
exelist: T.Optional[T.List[str]] = None,
prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version',
direct: bool = True):
super().__init__('lld-link', exelist or ['lld-link.exe'], for_machine,
super().__init__(exelist or ['lld-link.exe'], for_machine,
prefix, always_args, machine=machine, version=version, direct=direct)
@ -1143,17 +1168,18 @@ class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Intel's Xilink.exe."""
id = 'xilink'
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str],
*, version: str = 'unknown version'):
super().__init__('xilink', ['xilink.exe'], for_machine, '', always_args, version=version)
super().__init__(['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)
id = 'ld.solaris'
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
if not args:
@ -1214,8 +1240,7 @@ class AIXDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Sys-V derived linker used on AIX"""
def __init__(self, *args, **kwargs):
super().__init__('ld.aix', *args, **kwargs)
id = 'ld.aix'
def get_always_args(self) -> T.List[str]:
return self._apply_prefix(['-bsvr4', '-bnoipath', '-bbigtoc']) + super().get_always_args()
@ -1246,11 +1271,13 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Digital Mars dynamic linker for windows."""
id = 'optlink'
def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
# Use optlink instead of link so we don't interfer with other link.exe
# implementations.
super().__init__('optlink', exelist, for_machine, '', [], version=version)
super().__init__(exelist, for_machine, '', [], version=version)
def get_allow_undefined_args(self) -> T.List[str]:
return []
@ -1266,11 +1293,10 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Cuda linker (nvlink)"""
def __init__(self, *args, **kwargs):
super().__init__('nvlink', *args, **kwargs)
id = 'nvlink'
@staticmethod
def parse_version():
def parse_version() -> str:
version_cmd = ['nvlink', '--version']
try:
_, out, _ = mesonlib.Popen_safe(version_cmd)

@ -21,6 +21,7 @@ modules = [
'mesonbuild/dependencies/mpi.py',
'mesonbuild/envconfig.py',
'mesonbuild/interpreterbase.py',
'mesonbuild/linkers.py',
'mesonbuild/mcompile.py',
'mesonbuild/mesonlib.py',
'mesonbuild/minit.py',

@ -465,7 +465,7 @@ class InternalTests(unittest.TestCase):
def test_compiler_args_class_gnuld(self):
## Test --start/end-group
linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,', [])
linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-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']
@ -493,7 +493,7 @@ class InternalTests(unittest.TestCase):
def test_compiler_args_remove_system(self):
## Test --start/end-group
linker = mesonbuild.linkers.GnuDynamicLinker([], MachineChoice.HOST, 'fake', '-Wl,', [])
linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-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