diff options
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 5 | ||||
-rw-r--r-- | mesonbuild/build.py | 9 | ||||
-rw-r--r-- | mesonbuild/compilers/rust.py | 4 | ||||
-rw-r--r-- | mesonbuild/environment.py | 67 | ||||
-rwxr-xr-x | run_unittests.py | 54 | ||||
-rw-r--r-- | test cases/failing/76 link with shared module on osx/test.json | 2 |
6 files changed, 89 insertions, 52 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1ed742b..c3c5705 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1489,7 +1489,7 @@ int dummy; self.create_target_source_introspection(target, valac, args, all_files, []) 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'] # Rust compiler takes only the main file as input and # figures out what other files are needed via import @@ -1539,7 +1539,8 @@ int dummy; depfile = os.path.join(target.subdir, target.name + '.d') args += ['--emit', 'dep-info={}'.format(depfile), '--emit', 'link'] 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] linkdirs = OrderedDict() for d in target.link_targets: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 78292f2..36d4e19 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1359,11 +1359,12 @@ You probably should put it in link_with instead.''') for link_target in self.link_targets: if isinstance(link_target, SharedModule): if self.environment.machines[self.for_machine].is_darwin(): - raise MesonException('''target links against shared modules. -This is not permitted on OSX''') + raise MesonException( + 'target links against shared modules. This is not permitted on OSX') else: - mlog.warning('''target links against shared modules. This is not -recommended as it is not supported on some platforms''') + mlog.warning('target links against shared modules. This ' + 'is not recommended as it is not supported on some ' + 'platforms') return class Generator: diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 1be0cd8..312b3b6 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -125,6 +125,10 @@ class RustCompiler(Compiler): def get_output_args(self, outputname: str) -> T.List[str]: 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 # C compiler for dynamic linking, as such we invoke the C compiler's # use_linker_args method instead. diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 588005b..7194d03 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -129,6 +129,9 @@ from .compilers import ( VisualStudioCPPCompiler, ) +if T.TYPE_CHECKING: + from .dependencies import ExternalProgram + build_filename = 'meson.build' CompilersDict = T.Dict[str, Compiler] @@ -869,7 +872,7 @@ class Environment: defines[rest[0]] = rest[1] 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 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) 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 = {} 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) info = self.machines[for_machine] @@ -1619,9 +1630,9 @@ class Environment: return comp_class(exelist, version, for_machine, info, is_cross) raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"') - def detect_rust_compiler(self, for_machine): - popen_exceptions = {} - compilers, ccache, exe_wrap = self._get_compilers('rust', for_machine) + def detect_rust_compiler(self, for_machine: MachineChoice) -> RustCompiler: + popen_exceptions = {} # type: T.Dict[str, Exception] + compilers, _, exe_wrap = self._get_compilers('rust', for_machine) is_cross = self.is_cross_build(for_machine) info = self.machines[for_machine] @@ -1634,7 +1645,7 @@ class Environment: compiler = [compiler] arg = ['--version'] try: - p, out = Popen_safe(compiler + arg)[0:2] + out = Popen_safe(compiler + arg)[1] except OSError as e: popen_exceptions[' '.join(compiler + arg)] = e continue @@ -1651,17 +1662,30 @@ class Environment: # the default use that, and second add the necessary arguments # 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: extra_args = {} always_args = [] 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['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)]) + else: + exelist = cc.linker.exelist.copy() + if 'ccache' in exelist[0]: + 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 # so we can initialize a new copy for the Rust Compiler @@ -1675,21 +1699,22 @@ class Environment: elif 'link' in override[0]: linker = self._guess_win_linker( override, RustCompiler, for_machine, use_linker_prefix=False) + # rustc takes linker arguments without a prefix, and + # inserts the correct prefix itself. linker.direct = True + compiler.extend(RustCompiler.use_linker_args(linker.exelist[0])) 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) + # On linux and macos rust will invoke the c compiler for + # linking, on windows it will use lld-link or link.exe. + # we will simply ask for the C compiler that coresponds to + # it, and use that. + cc = self._detect_c_or_cpp_compiler('c', for_machine, override_compiler=override) + linker = cc.linker # 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)]) - compiler.extend(['-C', 'link-args={}'.format(' '.join(cc.use_linker_args(override[0])))]) + c = linker.exelist[1] if linker.exelist[0].endswith('ccache') else linker.exelist[0] + compiler.extend(RustCompiler.use_linker_args(c)) self.coredata.add_lang_args(RustCompiler.language, RustCompiler, for_machine, self) return RustCompiler( diff --git a/run_unittests.py b/run_unittests.py index 97110bc..7f7df36 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -2943,20 +2943,22 @@ class AllPlatformTests(BasePlatformTests): # the source tree leads to all kinds of trouble. with tempfile.TemporaryDirectory() as project_dir: with open(os.path.join(project_dir, 'meson.build'), 'w') as ofile: - ofile.write('''project('disttest', 'c', version : '1.4.3') -e = executable('distexe', 'distexe.c') -test('dist test', e) -subproject('vcssub', required : false) -subproject('tarballsub', required : false) -''') + ofile.write(textwrap.dedent('''\ + project('disttest', 'c', version : '1.4.3') + e = executable('distexe', 'distexe.c') + test('dist test', e) + subproject('vcssub', required : false) + subproject('tarballsub', required : false) + ''')) 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) { - printf("I am a distribution test.\\n"); - return 0; -} -''') + int main(int argc, char **argv) { + printf("I am a distribution test.\\n"); + return 0; + } + ''')) xz_distfile = os.path.join(self.distdir, 'disttest-1.4.3.tar.xz') xz_checksumfile = xz_distfile + '.sha256sum' 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') out = self.init(tdir) - msg = ('''WARNING: target links against shared modules. This is not -recommended as it is not supported on some platforms''') + msg = ('WARNING: target links against shared modules. This is not ' + 'recommended as it is not supported on some platforms') self.assertIn(msg, out) 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') nativefile = tempfile.NamedTemporaryFile(mode='w') - nativefile.write('''[binaries] -c = ['{0}'] -'''.format(os.path.join(testdir, 'build_wrapper.py'))) + nativefile.write(textwrap.dedent('''\ + [binaries] + c = ['{0}'] + '''.format(os.path.join(testdir, 'build_wrapper.py')))) nativefile.flush() self.meson_native_file = nativefile.name crossfile = tempfile.NamedTemporaryFile(mode='w') - crossfile.write('''[binaries] -c = ['{0}'] -'''.format(os.path.join(testdir, 'host_wrapper.py'))) + crossfile.write(textwrap.dedent('''\ + [binaries] + c = ['{0}'] + '''.format(os.path.join(testdir, 'host_wrapper.py')))) crossfile.flush() self.meson_cross_file = crossfile.name @@ -7287,9 +7291,10 @@ c = ['{0}'] 'CC_FOR_BUILD': '"' + os.path.join(testdir, 'build_wrapper.py') + '"', } crossfile = tempfile.NamedTemporaryFile(mode='w') - crossfile.write('''[binaries] -c = ['{0}'] -'''.format(os.path.join(testdir, 'host_wrapper.py'))) + crossfile.write(textwrap.dedent('''\ + [binaries] + c = ['{0}'] + '''.format(os.path.join(testdir, 'host_wrapper.py')))) crossfile.flush() self.meson_cross_file = crossfile.name # 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') @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): - 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): self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold') diff --git a/test cases/failing/76 link with shared module on osx/test.json b/test cases/failing/76 link with shared module on osx/test.json index 4e2856f..0a32674 100644 --- a/test cases/failing/76 link with shared module on osx/test.json +++ b/test cases/failing/76 link with shared module on osx/test.json @@ -1,7 +1,7 @@ { "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" } ] } |