Skip to content

Commit

Permalink
Allow selecting the dynamic linker
Browse files Browse the repository at this point in the history
This uses the normal meson mechanisms, an LD environment variable or via
cross/native files.

Fixes: mesonbuild#6057
  • Loading branch information
dcbaker committed Nov 19, 2019
1 parent 24cdb4a commit 260be5b
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 49 deletions.
17 changes: 17 additions & 0 deletions docs/markdown/snippets/linker_override.md
Original file line number Diff line number Diff line change
@@ -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.
10 changes: 10 additions & 0 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,16 @@ def get_dependency_compile_args(self, dep):
def get_dependency_link_args(self, dep):
return dep.get_link_args()

@classmethod
def use_linker_args(cls, linker: str) -> typing.Optional[typing.List[str]]:
"""Get a list of arguments to pass to the compiler to set the linker.
Returns None if the compiler does not invoke the linker.
:raises MesonException: When meson doesn't know how to map a specific
linker to a compiler
"""
raise mesonlib.MesonException('Cannot use linker {} with {}'.format(linker, self.id))


def get_largefile_args(compiler):
'''
Expand Down
6 changes: 6 additions & 0 deletions mesonbuild/compilers/mixins/gnu.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ def get_include_args(self, path: str, is_system: bool) -> typing.List[str]:
return ['-isystem' + path]
return ['-I' + path]

@classmethod
def use_linker_args(cls, linker: str) -> typing.List[str]:
if linker not in {'bfd', 'gold', 'lld'}:
return super().use_linker_args(linker)
return ['-fuse-ld={}'.format(linker)]


class GnuCompiler(GnuLikeCompiler):
"""
Expand Down
2 changes: 2 additions & 0 deletions mesonbuild/envconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ def __init__(
'strip': 'STRIP',
'ar': 'AR',
'windres': 'WINDRES',
'ld': 'LD',

# Other tools
'cmake': 'CMAKE',
'qmake': 'QMAKE',
'pkgconfig': 'PKG_CONFIG',
Expand Down
98 changes: 61 additions & 37 deletions mesonbuild/environment.py

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions mesonbuild/linkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,14 @@ def _apply_prefix(self, arg: str) -> typing.List[str]:
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))
Expand All @@ -276,7 +278,7 @@ def get_accepts_rsp(self) -> bool:
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 ''
Expand Down Expand Up @@ -713,7 +715,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:
Expand Down Expand Up @@ -851,33 +853,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, machine=machine, 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):
Expand Down
4 changes: 2 additions & 2 deletions run_unittests.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ def test_compiler_args_class(self):
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']
Expand Down Expand Up @@ -474,7 +474,7 @@ def test_compiler_args_class_gnuld(self):
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']
Expand Down

0 comments on commit 260be5b

Please sign in to comment.