Merge pull request #7843 from dcbaker/submit/rustc-fixes

A few fixups for rust
pull/7988/head
Jussi Pakkanen 4 years ago committed by GitHub
commit 299a67781e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      mesonbuild/backend/ninjabackend.py
  2. 9
      mesonbuild/build.py
  3. 4
      mesonbuild/compilers/rust.py
  4. 67
      mesonbuild/environment.py
  5. 54
      run_unittests.py
  6. 2
      test cases/failing/76 link with shared module on osx/test.json

@ -1489,7 +1489,7 @@ int dummy;
self.create_target_source_introspection(target, valac, args, all_files, []) self.create_target_source_introspection(target, valac, args, all_files, [])
return other_src[0], other_src[1], vala_c_src return other_src[0], other_src[1], vala_c_src
def generate_rust_target(self, target): def generate_rust_target(self, target: build.BuildTarget) -> None:
rustc = target.compilers['rust'] rustc = target.compilers['rust']
# Rust compiler takes only the main file as input and # Rust compiler takes only the main file as input and
# figures out what other files are needed via import # figures out what other files are needed via import
@ -1539,7 +1539,8 @@ int dummy;
depfile = os.path.join(target.subdir, target.name + '.d') depfile = os.path.join(target.subdir, target.name + '.d')
args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link'] args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link']
args += target.get_extra_args('rust') args += target.get_extra_args('rust')
args += ['-o', os.path.join(target.subdir, target.get_filename())] args += rustc.get_output_args(os.path.join(target.subdir, target.get_filename()))
args += self.environment.coredata.get_external_args(target.for_machine, rustc.language)
orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets] orderdeps = [os.path.join(t.subdir, t.get_filename()) for t in target.link_targets]
linkdirs = OrderedDict() linkdirs = OrderedDict()
for d in target.link_targets: for d in target.link_targets:

@ -1359,11 +1359,12 @@ You probably should put it in link_with instead.''')
for link_target in self.link_targets: for link_target in self.link_targets:
if isinstance(link_target, SharedModule): if isinstance(link_target, SharedModule):
if self.environment.machines[self.for_machine].is_darwin(): if self.environment.machines[self.for_machine].is_darwin():
raise MesonException('''target links against shared modules. raise MesonException(
This is not permitted on OSX''') 'target links against shared modules. This is not permitted on OSX')
else: else:
mlog.warning('''target links against shared modules. This is not mlog.warning('target links against shared modules. This '
recommended as it is not supported on some platforms''') 'is not recommended as it is not supported on some '
'platforms')
return return
class Generator: class Generator:

@ -125,6 +125,10 @@ class RustCompiler(Compiler):
def get_output_args(self, outputname: str) -> T.List[str]: def get_output_args(self, outputname: str) -> T.List[str]:
return ['-o', outputname] return ['-o', outputname]
@classmethod
def use_linker_args(cls, linker: str) -> T.List[str]:
return ['-C', 'linker={}'.format(linker)]
# Rust does not have a use_linker_args because it dispatches to a gcc-like # 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 # C compiler for dynamic linking, as such we invoke the C compiler's
# use_linker_args method instead. # use_linker_args method instead.

@ -129,6 +129,9 @@ from .compilers import (
VisualStudioCPPCompiler, VisualStudioCPPCompiler,
) )
if T.TYPE_CHECKING:
from .dependencies import ExternalProgram
build_filename = 'meson.build' build_filename = 'meson.build'
CompilersDict = T.Dict[str, Compiler] CompilersDict = T.Dict[str, Compiler]
@ -869,7 +872,7 @@ class Environment:
defines[rest[0]] = rest[1] defines[rest[0]] = rest[1]
return defines return defines
def _get_compilers(self, lang, for_machine): def _get_compilers(self, lang: str, for_machine: MachineChoice) -> T.Tuple[T.List[T.List[str]], T.List[str], T.Optional['ExternalProgram']]:
''' '''
The list of compilers is detected in the exact same way for The list of compilers is detected in the exact same way for
C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here.
@ -1062,9 +1065,17 @@ class Environment:
self.__failed_to_detect_linker(compiler, check_args, o, e) self.__failed_to_detect_linker(compiler, check_args, o, e)
return linker return linker
def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice) -> Compiler: def _detect_c_or_cpp_compiler(self, lang: str, for_machine: MachineChoice, *, override_compiler: T.Optional[T.List[str]] = None) -> Compiler:
"""Shared implementation for finding the C or C++ compiler to use.
the override_compiler option is provided to allow compilers which use
the compiler (GCC or Clang usually) as their shared linker, to find
the linker they need.
"""
popen_exceptions = {} popen_exceptions = {}
compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine) compilers, ccache, exe_wrap = self._get_compilers(lang, for_machine)
if override_compiler is not None:
compilers = [override_compiler]
is_cross = self.is_cross_build(for_machine) is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine] info = self.machines[for_machine]
@ -1619,9 +1630,9 @@ class Environment:
return comp_class(exelist, version, for_machine, info, is_cross) return comp_class(exelist, version, for_machine, info, is_cross)
raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
def detect_rust_compiler(self, for_machine): def detect_rust_compiler(self, for_machine: MachineChoice) -> RustCompiler:
popen_exceptions = {} popen_exceptions = {} # type: T.Dict[str, Exception]
compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine) compilers, _, exe_wrap = self._get_compilers('rust', for_machine)
is_cross = self.is_cross_build(for_machine) is_cross = self.is_cross_build(for_machine)
info = self.machines[for_machine] info = self.machines[for_machine]
@ -1634,7 +1645,7 @@ class Environment:
compiler = [compiler] compiler = [compiler]
arg = ['--version'] arg = ['--version']
try: try:
p, out = Popen_safe(compiler + arg)[0:2] out = Popen_safe(compiler + arg)[1]
except OSError as e: except OSError as e:
popen_exceptions[' '.join(compiler + arg)] = e popen_exceptions[' '.join(compiler + arg)] = e
continue continue
@ -1651,17 +1662,30 @@ class Environment:
# the default use that, and second add the necessary arguments # the default use that, and second add the necessary arguments
# to rust to use -fuse-ld # to rust to use -fuse-ld
if any(a.startswith('linker=') for a in compiler):
mlog.warning(
'Please do not put -C linker= in your compiler '
'command, set rust_ld=command in your cross file '
'or use the RUST_LD environment variable. meson '
'will override your seletion otherwise.')
if override is None: if override is None:
extra_args = {} extra_args = {}
always_args = [] always_args = []
if is_link_exe: if is_link_exe:
compiler.extend(['-C', 'linker={}'.format(cc.linker.exelist[0])]) compiler.extend(RustCompiler.use_linker_args(cc.linker.exelist[0]))
extra_args['direct'] = True extra_args['direct'] = True
extra_args['machine'] = cc.linker.machine extra_args['machine'] = cc.linker.machine
elif not ((info.is_darwin() and isinstance(cc, AppleClangCCompiler)) or else:
isinstance(cc, GnuCCompiler)): exelist = cc.linker.exelist.copy()
c = cc.exelist[1] if cc.exelist[0].endswith('ccache') else cc.exelist[0] if 'ccache' in exelist[0]:
compiler.extend(['-C', 'linker={}'.format(c)]) del exelist[0]
c = exelist.pop(0)
compiler.extend(RustCompiler.use_linker_args(c))
# Also ensure that we pass any extra arguments to the linker
for l in exelist:
compiler.extend(['-C', 'link-arg={}'.format(l)])
# This trickery with type() gets us the class of the linker # This trickery with type() gets us the class of the linker
# so we can initialize a new copy for the Rust Compiler # so we can initialize a new copy for the Rust Compiler
@ -1675,21 +1699,22 @@ class Environment:
elif 'link' in override[0]: elif 'link' in override[0]:
linker = self._guess_win_linker( linker = self._guess_win_linker(
override, RustCompiler, for_machine, use_linker_prefix=False) override, RustCompiler, for_machine, use_linker_prefix=False)
# rustc takes linker arguments without a prefix, and
# inserts the correct prefix itself.
linker.direct = True linker.direct = True
compiler.extend(RustCompiler.use_linker_args(linker.exelist[0]))
else: else:
# We're creating a new type of "C" compiler, that has rust # On linux and macos rust will invoke the c compiler for
# as it's language. This is gross, but I can't figure out # linking, on windows it will use lld-link or link.exe.
# another way to handle this, because rustc is actually # we will simply ask for the C compiler that coresponds to
# invoking the c compiler as it's linker. # it, and use that.
b = type('b', (type(cc), ), {}) cc = self._detect_c_or_cpp_compiler('c', for_machine, override_compiler=override)
b.language = RustCompiler.language linker = cc.linker
linker = self._guess_nix_linker(cc.exelist, b, for_machine)
# Of course, we're not going to use any of that, we just # Of course, we're not going to use any of that, we just
# need it to get the proper arguments to pass to rustc # 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] c = linker.exelist[1] if linker.exelist[0].endswith('ccache') else linker.exelist[0]
compiler.extend(['-C', 'linker={}'.format(c)]) compiler.extend(RustCompiler.use_linker_args(c))
compiler.extend(['-C', 'link-args={}'.format(' '.join(cc.use_linker_args(override[0])))])
self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self) self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self)
return RustCompiler( return RustCompiler(

@ -2943,20 +2943,22 @@ class AllPlatformTests(BasePlatformTests):
# the source tree leads to all kinds of trouble. # the source tree leads to all kinds of trouble.
with tempfile.TemporaryDirectory() as project_dir: with tempfile.TemporaryDirectory() as project_dir:
with open(os.path.join(project_dir, 'meson.build'), 'w') as ofile: with open(os.path.join(project_dir, 'meson.build'), 'w') as ofile:
ofile.write('''project('disttest', 'c', version : '1.4.3') ofile.write(textwrap.dedent('''\
e = executable('distexe', 'distexe.c') project('disttest', 'c', version : '1.4.3')
test('dist test', e) e = executable('distexe', 'distexe.c')
subproject('vcssub', required : false) test('dist test', e)
subproject('tarballsub', required : false) subproject('vcssub', required : false)
''') subproject('tarballsub', required : false)
'''))
with open(os.path.join(project_dir, 'distexe.c'), 'w') as ofile: with open(os.path.join(project_dir, 'distexe.c'), 'w') as ofile:
ofile.write('''#include<stdio.h> ofile.write(textwrap.dedent('''\
#include<stdio.h>
int main(int argc, char **argv) { int main(int argc, char **argv) {
printf("I am a distribution test.\\n"); printf("I am a distribution test.\\n");
return 0; return 0;
} }
''') '''))
xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz')
xz_checksumfile = xz_distfile + '.sha256sum' xz_checksumfile = xz_distfile + '.sha256sum'
zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip') zip_distfile = os.path.join(self.distdir, 'disttest-1.4.3.zip')
@ -3615,8 +3617,8 @@ int main(int argc, char **argv) {
""" """
tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking') tdir = os.path.join(self.unit_test_dir, '30 shared_mod linking')
out = self.init(tdir) out = self.init(tdir)
msg = ('''WARNING: target links against shared modules. This is not msg = ('WARNING: target links against shared modules. This is not '
recommended as it is not supported on some platforms''') 'recommended as it is not supported on some platforms')
self.assertIn(msg, out) self.assertIn(msg, out)
def test_ndebug_if_release_disabled(self): def test_ndebug_if_release_disabled(self):
@ -7265,16 +7267,18 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.unit_test_dir, '61 identity cross') testdir = os.path.join(self.unit_test_dir, '61 identity cross')
nativefile = tempfile.NamedTemporaryFile(mode='w') nativefile = tempfile.NamedTemporaryFile(mode='w')
nativefile.write('''[binaries] nativefile.write(textwrap.dedent('''\
c = ['{0}'] [binaries]
'''.format(os.path.join(testdir, 'build_wrapper.py'))) c = ['{0}']
'''.format(os.path.join(testdir, 'build_wrapper.py'))))
nativefile.flush() nativefile.flush()
self.meson_native_file = nativefile.name self.meson_native_file = nativefile.name
crossfile = tempfile.NamedTemporaryFile(mode='w') crossfile = tempfile.NamedTemporaryFile(mode='w')
crossfile.write('''[binaries] crossfile.write(textwrap.dedent('''\
c = ['{0}'] [binaries]
'''.format(os.path.join(testdir, 'host_wrapper.py'))) c = ['{0}']
'''.format(os.path.join(testdir, 'host_wrapper.py'))))
crossfile.flush() crossfile.flush()
self.meson_cross_file = crossfile.name self.meson_cross_file = crossfile.name
@ -7287,9 +7291,10 @@ c = ['{0}']
'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"', 'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"',
} }
crossfile = tempfile.NamedTemporaryFile(mode='w') crossfile = tempfile.NamedTemporaryFile(mode='w')
crossfile.write('''[binaries] crossfile.write(textwrap.dedent('''\
c = ['{0}'] [binaries]
'''.format(os.path.join(testdir, 'host_wrapper.py'))) c = ['{0}']
'''.format(os.path.join(testdir, 'host_wrapper.py'))))
crossfile.flush() crossfile.flush()
self.meson_cross_file = crossfile.name self.meson_cross_file = crossfile.name
# TODO should someday be explicit about build platform only here # TODO should someday be explicit about build platform only here
@ -7355,8 +7360,9 @@ c = ['{0}']
self._check_ld('ld.lld', 'lld', 'c', 'ld.lld') self._check_ld('ld.lld', 'lld', 'c', 'ld.lld')
@skip_if_not_language('rust') @skip_if_not_language('rust')
@skipIfNoExecutable('ld.gold') # need an additional check here because _check_ld checks for gcc
def test_ld_environment_variable_rust(self): def test_ld_environment_variable_rust(self):
self._check_ld('ld.gold', 'gold', 'rust', 'ld.gold') self._check_ld('gcc', 'gcc -fuse-ld=gold', 'rust', 'ld.gold')
def test_ld_environment_variable_cpp(self): def test_ld_environment_variable_cpp(self):
self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold') self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold')

@ -1,7 +1,7 @@
{ {
"stdout": [ "stdout": [
{ {
"line": "test cases/failing/76 link with shared module on osx/meson.build:8:0: ERROR: target links against shared modules." "line": "test cases/failing/76 link with shared module on osx/meson.build:8:0: ERROR: target links against shared modules. This is not permitted on OSX"
} }
] ]
} }

Loading…
Cancel
Save