diff --git a/docs/markdown/snippets/linker_override.md b/docs/markdown/snippets/linker_override.md new file mode 100644 index 000000000000..21cb072582de --- /dev/null +++ b/docs/markdown/snippets/linker_override.md @@ -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. diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 462349749362..87e2be0f9dca 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1176,6 +1176,12 @@ 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.List[str]: + """Get a list of arguments to pass to the compiler to set the linker. + """ + return [] + def get_largefile_args(compiler): ''' diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 64b0d3b0d6e6..668348607cff 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -299,6 +299,10 @@ 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]: + return ['-fuse-ld={}'.format(linker)] + class GnuCompiler(GnuLikeCompiler): """ diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 60b07c4678f4..4798bdca5498 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -381,3 +381,7 @@ def has_func_attribute(self, name: str, env: 'Environment') -> typing.Tuple[bool def get_argument_syntax(self) -> str: return 'msvc' + + @classmethod + def use_linker_args(cls, linker: str) -> typing.List[str]: + return [] diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 1adb08d9b67a..0f277a7bb257 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -309,7 +309,9 @@ def __init__( 'strip': 'STRIP', 'ar': 'AR', 'windres': 'WINDRES', + 'ld': 'LD', + # Other tools 'cmake': 'CMAKE', 'qmake': 'QMAKE', 'pkgconfig': 'PKG_CONFIG', diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 026ce5fe1110..0ae4fc6b79f7 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -733,33 +733,59 @@ def _handle_exceptions(self, exceptions, binaries, bintype='compiler'): 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: 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. @@ -774,14 +800,22 @@ def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice, :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 +831,7 @@ def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice, _, 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 +845,19 @@ def _guess_nix_linker(compiler: typing.List[str], for_machine: MachineChoice, 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 +932,7 @@ def sanitize(p): 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 +959,7 @@ def sanitize(p): 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 +978,7 @@ def sanitize(p): else: target = 'unknown target' cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler - linker = ClangClDynamicLinker(for_machine, version=version) + linker = self._guess_win_linker(['lld-link.exe'], cls, for_machine) return cls( compiler, version, for_machine, is_cross, info, exe_wrap, target, linker=linker) @@ -963,11 +997,11 @@ def sanitize(p): # 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 +1033,23 @@ def sanitize(p): 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.exe'], 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 +1147,7 @@ def detect_fortran_compiler(self, for_machine: MachineChoice): 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 +1155,7 @@ def detect_fortran_compiler(self, for_machine: MachineChoice): 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 +1163,7 @@ def detect_fortran_compiler(self, for_machine: MachineChoice): 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 +1171,14 @@ def detect_fortran_compiler(self, for_machine: MachineChoice): 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 +1198,21 @@ def detect_fortran_compiler(self, for_machine: MachineChoice): 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 +1251,7 @@ def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) 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 +1261,13 @@ def _detect_objc_or_objcpp_compiler(self, for_machine: MachineInfo, objc: bool) 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) @@ -1325,10 +1359,10 @@ def detect_rust_compiler(self, for_machine): # 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) + [], for_machine, 'Apple ld', RustCompiler.LINKER_PREFIX, []) else: linker = GnuDynamicLinker( - [], for_machine, 'GNU ld', RustCompiler.LINKER_PREFIX) + [], for_machine, 'GNU ld', RustCompiler.LINKER_PREFIX, []) return RustCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker) @@ -1375,26 +1409,25 @@ def detect_d_compiler(self, for_machine: MachineChoice): # 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.exe' if is_msvc else 'lld-link.exe'], + 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 +1436,17 @@ def detect_d_compiler(self, for_machine: MachineChoice): 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.exe'] elif arch == 'x86': - linker = OptlinkDynamicLinker(for_machine, version=full_version) + linker_cmd = ['optlink.exe'] 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.exe'] + 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 +1473,7 @@ def detect_swift_compiler(self, for_machine): # 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( diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 6c27d6ef532c..16ffffee7c2a 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -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 @@ 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 '' @@ -713,7 +717,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: @@ -851,33 +855,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): @@ -934,7 +938,7 @@ def __init__(self, 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.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 [] diff --git a/run_unittests.py b/run_unittests.py index 4e56c1d63c96..bf67729fccd1 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -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'] @@ -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']