diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2020-01-13 11:15:36 -0800 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2020-01-22 23:39:33 +0200 |
commit | 730a7b296fdff8aca58e15829485b3b68262d3c0 (patch) | |
tree | 08d976f1a499520a520c09743904e268f5046d74 /mesonbuild/environment.py | |
parent | 958df63dac810246e84c2b8eaa32d22d19ace0ef (diff) | |
download | meson-730a7b296fdff8aca58e15829485b3b68262d3c0.zip meson-730a7b296fdff8aca58e15829485b3b68262d3c0.tar.gz meson-730a7b296fdff8aca58e15829485b3b68262d3c0.tar.bz2 |
environment: Replace LD with <LANG>LD
The rust code is ugly, because rust is annoying. It doesn't invoke a
linker directly (unless that linker is link.exe or lld-link.exe),
instead it invokes the C compiler (gcc or clang usually) to do it's
linking. Meson doesn't have good abstractions for this, though we
probably should because some of the D compilers do the same thing.
Either that or we should just call the c compiler directly, like vala
does.
This changes the public interface for meson, which we don't do unless we
absolutely have to. In this case I think we need to do it. A fair number
of projects have already been using 'ld' in their cross/native files to
get the ld binary and call it directly in custom_targets or generators,
and we broke that. While we could hit this problem again names like
`c_ld` and `cpp_ld` are far less likely to cause collisions than `ld`.
Additionally this gives a way to set the linker on a per-compiler basis,
which is probably in itself very useful.
Fixes #6442
Diffstat (limited to 'mesonbuild/environment.py')
-rw-r--r-- | mesonbuild/environment.py | 66 |
1 files changed, 40 insertions, 26 deletions
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 3d4f49a..122301f 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -749,7 +749,7 @@ class Environment: check_args += self.coredata.compiler_options[for_machine][comp_class.language + '_args'].value override = [] # type: T.List[str] - value = self.binaries[for_machine].lookup_entry('ld') + value = self.binaries[for_machine].lookup_entry(comp_class.language + 'ld') if value is not None: override = comp_class.use_linker_args(value[0]) check_args += override @@ -812,7 +812,7 @@ class Environment: check_args = comp_class.LINKER_PREFIX + ['--version'] + extra_args override = [] # type: T.List[str] - value = self.binaries[for_machine].lookup_entry('ld') + value = self.binaries[for_machine].lookup_entry(comp_class.language + 'ld') if value is not None: override = comp_class.use_linker_args(value[0]) check_args += override @@ -1355,6 +1355,7 @@ class Environment: cc = self.detect_c_compiler(for_machine) is_link_exe = isinstance(cc.linker, VisualStudioLikeLinkerMixin) + override = self.binaries[for_machine].lookup_entry('rustld') for compiler in compilers: if isinstance(compiler, str): @@ -1378,32 +1379,45 @@ class Environment: # 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)): + if override is None: + 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)]) + + # 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: + linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX, + always_args=always_args, version=cc.linker.version, + **extra_args) + elif 'link' in override[0]: + linker = self._guess_win_linker( + override, RustCompiler, for_machine, use_linker_prefix=False) + linker.direct = True + else: + # We're creating a new type of "C" compiler, that has rust + # as it's language. This is gross, but I can't figure out + # another way to handle this, because rustc is actually + # invoking the c compiler as it's linker. + b = type('b', (type(cc), ), {}) + b.language = RustCompiler.language + linker = self._guess_nix_linker(cc.exelist, b, for_machine) + + # Of course, we're not going to use any of that, we just + # need it to get the proper arguments to pass to rustc 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: - linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX, - always_args=always_args, version=cc.linker.version, - **extra_args) + compiler.extend(['-C', 'link-args={}'.format(' '.join(cc.use_linker_args(override[0])))]) return RustCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, |