From 52aa24e99733c2ad5da57f436823dbe56ca2164a Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 2 Dec 2019 12:40:13 -0800 Subject: linkers: Fix Apple and VS-like linkers always_args Which would not call the super() method, thus overriding the default behavior when it should have instead extended it. --- mesonbuild/linkers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 3251845..57760f7 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -595,7 +595,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker): return self._apply_prefix('-undefined,error') def get_always_args(self) -> typing.List[str]: - return self._apply_prefix('-headerpad_max_install_names') + return self._apply_prefix('-headerpad_max_install_names') + super().get_always_args() def bitcode_args(self) -> typing.List[str]: return self._apply_prefix('-bitcode_bundle') @@ -818,7 +818,7 @@ class VisualStudioLikeLinkerMixin: return self._apply_prefix('/MACHINE:' + self.machine) + self._apply_prefix('/OUT:' + outputname) def get_always_args(self) -> typing.List[str]: - return self._apply_prefix('/nologo') + return self._apply_prefix('/nologo') + super().get_always_args() def get_search_args(self, dirname: str) -> typing.List[str]: return self._apply_prefix('/LIBPATH:' + dirname) -- cgit v1.1 From 5a83cb0d33e96f19e05b2c83dae314a35ec9d5c1 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Nov 2019 15:00:32 -0800 Subject: Fix detection of D linker in MSVC environments Rather than trying to figure out if we're using MSVC based on environment variables, then trying to get the C compiler and test some attributes, get the C compiler and see if it's MSVC. This is much more reliable and we were already doing it anyway. --- mesonbuild/environment.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index d81f34f..8459d64 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -1339,10 +1339,11 @@ class Environment: info = self.machines[for_machine] # Detect the target architecture, required for proper architecture handling on Windows. - c_compiler = {} - is_msvc = mesonlib.is_windows() and 'VCINSTALLDIR' in os.environ - if is_msvc: - c_compiler = {'c': self.detect_c_compiler(for_machine)} # MSVC compiler is required for correct platform detection. + # MSVC compiler is required for correct platform detection. + c_compiler = {'c': self.detect_c_compiler(for_machine)} + is_msvc = isinstance(c_compiler['c'], VisualStudioCCompiler) + if not is_msvc: + c_compiler = {} arch = detect_cpu_family(c_compiler) if is_msvc and arch == 'x86': -- cgit v1.1 From 7658e67f92ba55e2d8e466f818293a001f34a65f Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 2 Dec 2019 12:52:42 -0800 Subject: backends/ninja: apply linker arguments when using rust This will be required to make switching the linker work with rust. --- mesonbuild/backend/ninjabackend.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'mesonbuild') diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 3c5cdf0..9ff6f74 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1293,6 +1293,8 @@ int dummy; else: raise InvalidArguments('Unknown target type for rustc.') args.append(cratetype) + if cratetype in {'bin', 'dylib'}: + args += rustc.linker.get_always_args() args += ['--crate-name', target.name] args += rustc.get_buildtype_args(self.get_option_for_target('buildtype', target)) args += rustc.get_debug_args(self.get_option_for_target('debug', target)) -- cgit v1.1 From ef9aeb188ea2bc7353e59916c18901cde90fa2b3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 19 Nov 2019 09:30:46 -0800 Subject: Allow selecting the dynamic linker This uses the normal meson mechanisms, an LD environment variable or via cross/native files. Fixes: #6057 --- mesonbuild/compilers/compilers.py | 6 + mesonbuild/compilers/mixins/gnu.py | 4 + mesonbuild/compilers/mixins/visualstudio.py | 4 + mesonbuild/compilers/rust.py | 6 +- mesonbuild/envconfig.py | 2 + mesonbuild/environment.py | 206 +++++++++++++++++----------- mesonbuild/linkers.py | 28 ++-- 7 files changed, 163 insertions(+), 93 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 52a2788..818c62c 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1178,6 +1178,12 @@ class Compiler: 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 64b0d3b..6683486 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -299,6 +299,10 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta): 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 60b07c4..4798bdc 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -381,3 +381,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): def get_argument_syntax(self) -> str: return 'msvc' + + @classmethod + def use_linker_args(cls, linker: str) -> typing.List[str]: + return [] diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index a17b697..405afea 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -32,7 +32,7 @@ rust_optimization_args = {'0': [], class RustCompiler(Compiler): - LINKER_PREFIX = '-Wl,' + # rustc doesn't invoke the compiler itself, it doesn't need a LINKER_PREFIX def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, info: 'MachineInfo', exe_wrapper=None, **kwargs): @@ -109,3 +109,7 @@ class RustCompiler(Compiler): def get_std_exe_link_args(self): return [] + + # Rust does not have a use_linker_args because it dispatches to a gcc-like + # C compiler for dynamic linking, as such we invoke the C compiler's + # use_linker_args method instead. diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 1adb08d..0f277a7 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -309,7 +309,9 @@ class BinaryTable(HasEnvVarFallback): '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 8459d64..b286eca 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -733,55 +733,85 @@ class Environment: 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: typing.Type[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. - :prefix: The prefix that the compiler uses to proxy arguments to the - linker, if required. This can be passed as a string or a list of - strings. If it is passed as a string then the arguments to be - proxied to the linker will be concatenated, if it is a list they - will be appended. This means that if a space is required (such as - with swift which wants `-Xlinker --version` and *not* - `-Xlinker=--version`) you must pass as a list. + :compiler: Invocation to use to get linker + :comp_class: The Compiler Type (uninstantiated) + :for_machine: which machine this linker targets :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 +827,7 @@ class Environment: _, 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 +841,19 @@ class Environment: 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 +928,7 @@ class Environment: 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 +955,7 @@ class Environment: 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 +974,7 @@ class Environment: else: target = 'unknown target' cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler - linker = ClangClDynamicLinker(for_machine, version=version) + linker = self._guess_win_linker(['lld-link'], cls, for_machine) return cls( compiler, version, for_machine, is_cross, info, exe_wrap, target, linker=linker) @@ -963,11 +993,11 @@ class Environment: # 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 +1029,23 @@ class Environment: 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'], 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 +1143,7 @@ class Environment: 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 +1151,7 @@ class Environment: 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 +1159,7 @@ class Environment: 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 +1167,14 @@ class Environment: 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 +1194,21 @@ class Environment: 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 +1247,7 @@ class Environment: 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 +1257,13 @@ class Environment: 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) @@ -1316,19 +1346,36 @@ class Environment: version = search_version(out) if 'rustc' in out: - # Chalk up another quirk for rust. There is no way (AFAICT) to - # figure out what linker rustc is using for a non-nightly compiler - # (On nightly you can pass -Z print-link-args). So we're going to - # hard code the linker based on the platform. - # Currently gnu ld is used for everything except apple by - # default, and apple ld is used on mac. - # 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) + if info.is_windows() or info.is_cygwin(): + # On windows rustc invokes link.exe + linker = self._guess_win_linker(['link'], for_machine) else: - linker = GnuDynamicLinker( - [], for_machine, 'GNU ld', RustCompiler.LINKER_PREFIX) + # On Linux and mac rustc will invoke gcc (clang for mac + # presumably), for dynamic linking. this means the easiest + # way to C compiler for dynamic linking. figure out what + # linker to use !windows it to just get the value of the C + # compiler and use that as the basis of the rust linker. + # However, there are two things we need to change, if CC is + # not the default use that, and second add the necessary + # arguments to rust to use -fuse-ld + cc = self.detect_c_compiler(for_machine) + + extra_args = [] + if not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or + isinstance(cc, GnuCCompiler)): + c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0] + extra_args.extend(['-C', 'linker={}'.format(c)]) + + value = self.binaries[for_machine].lookup_entry('ld') + if value is not None: + for a in cc.use_linker_args(value[0]): + extra_args.extend(['-C', 'link-arg={}'.format(a)]) + + # This trickery with type() gets us the class of the linker + # so we can initialize a new copy for the Rust Compiler + linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX, + always_args=extra_args, version=cc.linker.version) + return RustCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker) @@ -1375,26 +1422,25 @@ class Environment: # 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' if is_msvc else 'lld-link'], + 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 +1449,17 @@ class Environment: 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'] elif arch == 'x86': - linker = OptlinkDynamicLinker(for_machine, version=full_version) + linker_cmd = ['optlink'] 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'] + 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 +1486,7 @@ class Environment: # 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 57760f7..021134e 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 @@ class DynamicLinker(metaclass=abc.ABCMeta): 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 '' @@ -715,7 +719,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: @@ -853,33 +857,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): @@ -936,7 +940,7 @@ 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', prefix_arg='', version=version) + super().__init__(['optlink.exe'], for_machine, 'optlink', '', [], version=version) def get_allow_undefined_args(self) -> typing.List[str]: return [] -- cgit v1.1 From 8761ca7b7d0f7f8cc26be49329dd48b52da54d62 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 19 Nov 2019 09:41:46 -0800 Subject: environment: Remove duplicate argument from _guess_nix_linker Since we pass the whole compiler class (as a type()) we don't need to also pass it's LINKER_PREFIX attribute, we can just get it from the type we're passing. --- mesonbuild/environment.py | 59 ++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 32 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index b286eca..47fb9f1 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -734,9 +734,8 @@ class Environment: raise EnvironmentException(errmsg) 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': + for_machine: MachineChoice, *, + use_linker_prefix: bool = True) -> 'DynamicLinker': # Explicitly pass logo here so that we can get the version of link.exe if not use_linker_prefix or comp_class.LINKER_PREFIX is None: check_args = ['/logo', '--version'] @@ -785,8 +784,7 @@ class Environment: raise EnvironmentException('Unable to determine dynamic linker') def _guess_nix_linker(self, compiler: typing.List[str], comp_class: typing.Type[Compiler], - for_machine: MachineChoice, - prefix: typing.Union[str, typing.List[str]], *, + for_machine: MachineChoice, *, extra_args: typing.Optional[typing.List[str]] = None) -> 'DynamicLinker': """Helper for guessing what linker to use on Unix-Like OSes. @@ -797,10 +795,10 @@ class Environment: """ extra_args = typing.cast(typing.List[str], extra_args or []) - if isinstance(prefix, str): - check_args = [prefix + '--version'] + extra_args + if isinstance(comp_class.LINKER_PREFIX, str): + check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args else: - check_args = prefix + ['--version'] + extra_args + check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args override = [] # type: typing.List[str] value = self.binaries[for_machine].lookup_entry('ld') @@ -811,7 +809,7 @@ class Environment: _, o, e = Popen_safe(compiler + check_args) v = search_version(o) if o.startswith('LLD'): - linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, override, version=v) # type: DynamicLinker + linker = LLVMDynamicLinker(compiler, for_machine, 'lld', 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. @@ -827,13 +825,13 @@ class Environment: _, o, e = Popen_safe([linker_cmd, '--version']) v = search_version(o) - linker = LLVMDynamicLinker(compiler, for_machine, 'lld', prefix, override, version=v) + linker = LLVMDynamicLinker(compiler, for_machine, 'lld', comp_class.LINKER_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): - _, _, e = Popen_safe(compiler + [prefix + '-v'] + extra_args) + if isinstance(comp_class.LINKER_PREFIX, str): + _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args) else: - _, _, e = Popen_safe(compiler + prefix + ['-v'] + extra_args) + _, _, 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: @@ -841,16 +839,16 @@ class Environment: break else: v = 'unknown version' - linker = AppleDynamicLinker(compiler, for_machine, i, prefix, override, version=v) + linker = AppleDynamicLinker(compiler, for_machine, i, comp_class.LINKER_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, override, version=v) + linker = GnuDynamicLinker(compiler, for_machine, i, comp_class.LINKER_PREFIX, override, version=v) elif 'Solaris' in e or 'Solaris' in o: linker = SolarisDynamicLinker( - compiler, for_machine, 'solaris', prefix, override, + compiler, for_machine, 'solaris', comp_class.LINKER_PREFIX, override, version=search_version(e)) else: raise EnvironmentException('Unable to determine dynamic linker') @@ -928,7 +926,7 @@ class Environment: version = self.get_gnu_version_from_defines(defines) cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler - linker = self._guess_nix_linker(compiler, cls, for_machine, cls.LINKER_PREFIX) + linker = self._guess_nix_linker(compiler, cls, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, defines, full_version=full_version, @@ -993,11 +991,11 @@ class Environment: # 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, cls, for_machine, cls.LINKER_PREFIX) + linker = self._guess_win_linker(compiler, cls, for_machine) except MesonException: pass if linker is None: - linker = self._guess_nix_linker(compiler, cls, for_machine, cls.LINKER_PREFIX) + linker = self._guess_nix_linker(compiler, cls, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, @@ -1143,7 +1141,7 @@ class Environment: version = self.get_gnu_version_from_defines(defines) cls = GnuFortranCompiler linker = self._guess_nix_linker( - compiler, cls, for_machine, cls.LINKER_PREFIX) + compiler, cls, for_machine) return cls( compiler, version, for_machine, is_cross, info, exe_wrap, defines, full_version=full_version, @@ -1151,7 +1149,7 @@ class Environment: if 'G95' in out: linker = self._guess_nix_linker( - compiler, cls, for_machine, cls.LINKER_PREFIX) + compiler, cls, for_machine) return G95FortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -1159,7 +1157,7 @@ class Environment: if 'Sun Fortran' in err: version = search_version(err) linker = self._guess_nix_linker( - compiler, cls, for_machine, cls.LINKER_PREFIX) + compiler, cls, for_machine) return SunFortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -1194,21 +1192,21 @@ class Environment: if 'flang' in out or 'clang' in out: linker = self._guess_nix_linker( - compiler, FlangFortranCompiler, for_machine, FlangFortranCompiler.LINKER_PREFIX) + compiler, FlangFortranCompiler, for_machine) 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, Open64FortranCompiler, for_machine, Open64FortranCompiler.LINKER_PREFIX) + compiler, Open64FortranCompiler, for_machine) 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, NAGFortranCompiler, for_machine, NAGFortranCompiler.LINKER_PREFIX) + compiler, NAGFortranCompiler, for_machine) return NAGFortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -1247,7 +1245,7 @@ class Environment: continue version = self.get_gnu_version_from_defines(defines) comp = GnuObjCCompiler if objc else GnuObjCPPCompiler - linker = self._guess_nix_linker(compiler, comp, for_machine, comp.LINKER_PREFIX) + linker = self._guess_nix_linker(compiler, comp, for_machine) return comp( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, defines, linker=linker) @@ -1257,13 +1255,13 @@ class Environment: 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, comp, for_machine, comp.LINKER_PREFIX) + linker = self._guess_win_linker(compiler, comp, for_machine) except MesonException: pass if not linker: linker = self._guess_nix_linker( - compiler, comp, for_machine, comp.LINKER_PREFIX) + compiler, comp, for_machine) return comp( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker) @@ -1434,13 +1432,12 @@ class Environment: with tempfile.NamedTemporaryFile(suffix='.d') as f: linker = self._guess_nix_linker( 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, compilers.GnuDCompiler, for_machine, compilers.GnuDCompiler.LINKER_PREFIX) + linker = self._guess_nix_linker(exelist, compilers.GnuDCompiler, for_machine) return compilers.GnuDCompiler( exelist, version, for_machine, info, arch, is_cross, exe_wrap, full_version=full_version, linker=linker) @@ -1460,7 +1457,6 @@ class Environment: with tempfile.NamedTemporaryFile(suffix='.d') as f: linker = self._guess_nix_linker( exelist, compilers.DmdDCompiler, for_machine, - compilers.LLVMDCompiler.LINKER_PREFIX, extra_args=[f.name]) return compilers.DmdDCompiler( exelist, version, for_machine, info, arch, @@ -1487,7 +1483,6 @@ class Environment: with tempfile.NamedTemporaryFile(suffix='.swift') as f: linker = self._guess_nix_linker( exelist, compilers.SwiftCompiler, for_machine, - compilers.SwiftCompiler.LINKER_PREFIX, extra_args=[f.name]) return compilers.SwiftCompiler( exelist, version, for_machine, info, is_cross, linker=linker) -- cgit v1.1 From ab5ea9e8b60f043551a2920f70d6f3a1532d5bf8 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Nov 2019 12:29:12 -0800 Subject: environment: unify platform detection logic I noticed this while I was here, it's not much, just a small cleanup to the platform detection logic. --- mesonbuild/environment.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 47fb9f1..83c6935 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -1418,8 +1418,7 @@ class Environment: if 'LLVM D compiler' in out: # LDC seems to require a file - m = self.machines[for_machine] - if m.is_windows() or m.is_cygwin(): + if info.is_windows() or info.is_cygwin(): # 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 @@ -1443,8 +1442,7 @@ class Environment: full_version=full_version, linker=linker) elif 'The D Language Foundation' in out or 'Digital Mars' in out: # DMD seems to require a file - m = self.machines[for_machine] - if m.is_windows() or m.is_cygwin(): + if info.is_windows() or info.is_cygwin(): if is_msvc: linker_cmd = ['link'] elif arch == 'x86': -- cgit v1.1 From 0ae911d893485c4b4c5f90f9d6b5f820dc1f7672 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 26 Nov 2019 12:31:46 -0800 Subject: environment: Add a special error case for getting GNU link.exe Since I spent three days banging my head against this it seems reasonable that other people might also run into this problem. It can happen if you're trying to use microsoft's link.exe, but also have the dmd bin directory at the tail of your %PATH%, among other reasons. --- mesonbuild/environment.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'mesonbuild') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 83c6935..4c07e58 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -781,6 +781,11 @@ class Environment: for_machine, [], machine=target, exelist=compiler, prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [], version=search_version(out)) + elif 'GNU coreutils' in o: + raise EnvironmentException( + "Found GNU link.exe instead of MSVC link.exe. This link.exe " + "is not a linker. You may need to reorder entries to your " + "%PATH% variable to resolve this.") raise EnvironmentException('Unable to determine dynamic linker') def _guess_nix_linker(self, compiler: typing.List[str], comp_class: typing.Type[Compiler], -- cgit v1.1 From 8091b4c7448ca467bbfff22283beaa702533f177 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 2 Dec 2019 15:00:16 -0800 Subject: Intel: Dump worthless Xild abstractions This dumps xild on mac and linux. After a lot of reading and banging my head I've discovered we (meson) don't care about xild, xild is only useful if your invoke ld directly (not through icc/icpc) and you want to do ipo/lto/wpo. Instead just make icc report what it's actually doing, invoking ld or ld64 (for linux and mac respectively) directly. This allows us to get -fuse-ld working on linux. --- mesonbuild/environment.py | 13 ++++++------- mesonbuild/linkers.py | 29 +++++++---------------------- 2 files changed, 13 insertions(+), 29 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 4c07e58..f3f5e9e 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -53,8 +53,6 @@ from .linkers import ( PGIDynamicLinker, PGIStaticLinker, SolarisDynamicLinker, - XildAppleDynamicLinker, - XildLinuxDynamicLinker, XilinkDynamicLinker, CudaLinker, ) @@ -1046,9 +1044,9 @@ class Environment: 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 = AppleDynamicLinker(compiler, for_machine, 'APPLE ld', cls.LINKER_PREFIX, [], version=version) else: - l = XildLinuxDynamicLinker(compiler, for_machine, 'xild', cls.LINKER_PREFIX, [], version=version) + l = self._guess_nix_linker(compiler, cls, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=l) @@ -1176,8 +1174,7 @@ class Environment: info, exe_wrap, linker=linker) if 'ifort (IFORT)' in out: - linker = XildLinuxDynamicLinker( - compiler, for_machine, 'xild', IntelFortranCompiler.LINKER_PREFIX, [], version=version) + linker = self._guess_nix_linker(compiler, IntelFortranCompiler, for_machine) return IntelFortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -1376,8 +1373,10 @@ class Environment: # This trickery with type() gets us the class of the linker # so we can initialize a new copy for the Rust Compiler + linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX, - always_args=extra_args, version=cc.linker.version) + always_args=extra_args, version=cc.linker.version, + **extra_args) return RustCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 021134e..1c0dfff 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -399,6 +399,11 @@ class DynamicLinker(metaclass=abc.ABCMeta): install_rpath: str) -> typing.List[str]: return [] + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: typing.Tuple[str, str], + is_shared_module: bool) -> typing.List[str]: + return [] + class PosixDynamicLinkerMixin: @@ -423,8 +428,8 @@ class GnuLikeDynamicLinkerMixin: """Mixin class for dynamic linkers that provides gnu-like interface. - This acts as a base for the GNU linkers (bfd and gold), the Intel Xild - (which comes with ICC), LLVM's lld, and other linkers like GNU-ld. + This acts as a base for the GNU linkers (bfd and gold), LLVM's lld, and + other linkers like GNU-ld. """ _BUILDTYPE_ARGS = { @@ -660,26 +665,6 @@ class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna pass -class XildLinuxDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): - - """Representation of Intel's Xild linker. - - This is only the linux-like linker which dispatches to Gnu ld. - """ - - pass - - -class XildAppleDynamicLinker(AppleDynamicLinker): - - """Representation of Intel's Xild linker. - - This is the apple linker, which dispatches to Apple's ld. - """ - - pass - - class CcrxDynamicLinker(DynamicLinker): """Linker for Renesis CCrx compiler.""" -- cgit v1.1 From a1bfd22120c219a9190559b1fdc4ba29d8e59783 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 3 Dec 2019 11:25:26 -0800 Subject: linkers: Correct MSVC-like linkers invoke directly flag This is returning the inverse of the correct value, which happens to work out because in general the compilers that a link.exe-like linker is paired with accepts the same arguments. --- mesonbuild/linkers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 1c0dfff..09513e0 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -791,7 +791,7 @@ class VisualStudioLikeLinkerMixin: self.machine = machine def invoked_by_compiler(self) -> bool: - return self.direct + return not self.direct def get_debug_crt_args(self) -> typing.List[str]: """Arguments needed to select a debug crt for the linker. -- cgit v1.1 From d8561180061f271fde9a5d782853930d59280c06 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 3 Dec 2019 11:59:49 -0800 Subject: environment: Fix selecting the linker with rustc --- mesonbuild/backend/ninjabackend.py | 9 +++++- mesonbuild/environment.py | 65 ++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 29 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 9ff6f74..5630212 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1293,8 +1293,15 @@ int dummy; else: raise InvalidArguments('Unknown target type for rustc.') args.append(cratetype) + + # If we're dynamically linking, add those arguments + # + # Rust is super annoying, calling -C link-arg foo does not work, it has + # to be -C link-arg=foo if cratetype in {'bin', 'dylib'}: - args += rustc.linker.get_always_args() + for a in rustc.linker.get_always_args(): + args += ['-C', 'link-arg={}'.format(a)] + args += ['--crate-name', target.name] args += rustc.get_buildtype_args(self.get_option_for_target('buildtype', target)) args += rustc.get_debug_args(self.get_option_for_target('debug', target)) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index f3f5e9e..d4c1498 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -55,6 +55,7 @@ from .linkers import ( SolarisDynamicLinker, XilinkDynamicLinker, CudaLinker, + VisualStudioLikeLinkerMixin, ) from functools import lru_cache from .compilers import ( @@ -1333,6 +1334,10 @@ class Environment: compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine) is_cross = not self.machines.matches_build_machine(for_machine) info = self.machines[for_machine] + + cc = self.detect_c_compiler(for_machine) + is_link_exe = isinstance(cc.linker, VisualStudioLikeLinkerMixin) + for compiler in compilers: if isinstance(compiler, str): compiler = [compiler] @@ -1346,36 +1351,40 @@ class Environment: version = search_version(out) if 'rustc' in out: - if info.is_windows() or info.is_cygwin(): - # On windows rustc invokes link.exe - linker = self._guess_win_linker(['link'], for_machine) + # On Linux and mac rustc will invoke gcc (clang for mac + # presumably) and it can do this windows, for dynamic linking. + # this means the easiest way to C compiler for dynamic linking. + # figure out what linker to use is to just get the value of the + # C compiler and use that as the basis of the rust linker. + # However, there are two things we need to change, if CC is not + # the default use that, and second add the necessary arguments + # to rust to use -fuse-ld + + extra_args = {} + always_args = [] + if is_link_exe: + compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])]) + extra_args['direct'] = True + extra_args['machine'] = cc.linker.machine + elif not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or + isinstance(cc, GnuCCompiler)): + c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0] + compiler.extend(['-C', 'linker={}'.format(c)]) + + value = self.binaries[for_machine].lookup_entry('ld') + if value is not None: + for a in cc.use_linker_args(value[0]): + always_args.extend(['-C', 'link-arg={}'.format(a)]) + + # This trickery with type() gets us the class of the linker + # so we can initialize a new copy for the Rust Compiler + + if is_link_exe: + linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist, + version=cc.linker.version, **extra_args) else: - # On Linux and mac rustc will invoke gcc (clang for mac - # presumably), for dynamic linking. this means the easiest - # way to C compiler for dynamic linking. figure out what - # linker to use !windows it to just get the value of the C - # compiler and use that as the basis of the rust linker. - # However, there are two things we need to change, if CC is - # not the default use that, and second add the necessary - # arguments to rust to use -fuse-ld - cc = self.detect_c_compiler(for_machine) - - extra_args = [] - if not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or - isinstance(cc, GnuCCompiler)): - c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0] - extra_args.extend(['-C', 'linker={}'.format(c)]) - - value = self.binaries[for_machine].lookup_entry('ld') - if value is not None: - for a in cc.use_linker_args(value[0]): - extra_args.extend(['-C', 'link-arg={}'.format(a)]) - - # This trickery with type() gets us the class of the linker - # so we can initialize a new copy for the Rust Compiler - linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX, - always_args=extra_args, version=cc.linker.version, + always_args=always_args, version=cc.linker.version, **extra_args) return RustCompiler( -- cgit v1.1 From afe00f42177f865a7f1781c0ccac280b7cf0d746 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 3 Dec 2019 12:00:22 -0800 Subject: linkers: make constructor signature of VisualStudioLike linkers the same --- mesonbuild/linkers.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 09513e0..d69f688 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -845,9 +845,10 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): 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'): + machine: str = 'x86', version: str = 'unknown version', + direct: bool = True): super().__init__(exelist or ['link.exe'], for_machine, 'link', - prefix, always_args, machine=machine, version=version) + prefix, always_args, machine=machine, version=version, direct=direct) class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): @@ -857,9 +858,10 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): 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'): + machine: str = 'x86', version: str = 'unknown version', + direct: bool = True): super().__init__(exelist or ['lld-link.exe'], for_machine, 'lld-link', - prefix, always_args, version=version) + prefix, always_args, machine=machine, version=version, direct=direct) class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker): -- cgit v1.1