compilers: Every compiler can run code

Compiling and linking code is part of the Compiler base class, there is
no reason it cannot also run executables.
pull/12983/head
Xavier Claessens 1 year ago committed by Xavier Claessens
parent 3afbe042af
commit f41a95ddf2
  1. 4
      docs/markdown/snippets/compiler_run.md
  2. 25
      mesonbuild/compilers/compilers.py
  3. 26
      mesonbuild/compilers/d.py
  4. 26
      mesonbuild/compilers/mixins/clike.py
  5. 3
      mesonbuild/interpreter/compiler.py
  6. 3
      test cases/rust/1 basic/meson.build

@ -0,0 +1,4 @@
## compiler.run() method is now available for all languages
It used to be only implemented for C-like and D languages, but it is now available
for all languages.

@ -623,10 +623,31 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language())
def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, def run(self, code: 'mesonlib.FileOrString', env: 'Environment',
extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult:
raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
if need_exe_wrapper and self.exe_wrapper is None:
raise CrossNoRunException('Can not run test applications in this cross environment.')
with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p:
if p.returncode != 0:
mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n')
return RunResult(False)
if need_exe_wrapper:
cmdlist = self.exe_wrapper.get_command() + [p.output_name]
else:
cmdlist = [p.output_name]
try:
pe, so, se = mesonlib.Popen_safe(cmdlist)
except Exception as e:
mlog.debug(f'Could not run: {cmdlist} (error: {e})\n')
return RunResult(False)
mlog.debug('Program stdout:\n')
mlog.debug(so)
mlog.debug('Program stderr:\n')
mlog.debug(se)
return RunResult(True, pe.returncode, so, se)
# Caching run() in general seems too risky (no way to know what the program # Caching run() in general seems too risky (no way to know what the program
# depends on), but some callers know more about the programs they intend to # depends on), but some callers know more about the programs they intend to

@ -9,7 +9,6 @@ import subprocess
import typing as T import typing as T
from .. import mesonlib from .. import mesonlib
from .. import mlog
from ..arglist import CompilerArgs from ..arglist import CompilerArgs
from ..linkers import RSPFileSyntax from ..linkers import RSPFileSyntax
from ..mesonlib import ( from ..mesonlib import (
@ -571,32 +570,11 @@ class DCompiler(Compiler):
args.append(extra_args) args.append(extra_args)
return args return args
def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, def run(self, code: 'mesonlib.FileOrString', env: 'Environment',
extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult: dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult:
need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
if need_exe_wrapper and self.exe_wrapper is None:
raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
extra_args = self._get_compile_extra_args(extra_args) extra_args = self._get_compile_extra_args(extra_args)
with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p: return super().run(code, env, extra_args, dependencies)
if p.returncode != 0:
mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n')
return compilers.RunResult(False)
if need_exe_wrapper:
cmdlist = self.exe_wrapper.get_command() + [p.output_name]
else:
cmdlist = [p.output_name]
try:
pe, so, se = mesonlib.Popen_safe(cmdlist)
except Exception as e:
mlog.debug(f'Could not run: {cmdlist} (error: {e})\n')
return compilers.RunResult(False)
mlog.debug('Program stdout:\n')
mlog.debug(so)
mlog.debug('Program stderr:\n')
mlog.debug(se)
return compilers.RunResult(True, pe.returncode, so, se)
def sizeof(self, typename: str, prefix: str, env: 'Environment', *, def sizeof(self, typename: str, prefix: str, env: 'Environment', *,
extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,

@ -459,32 +459,6 @@ class CLikeCompiler(Compiler):
args = cargs + extra_args + largs args = cargs + extra_args + largs
return args return args
def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *,
extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None,
dependencies: T.Optional[T.List['Dependency']] = None) -> compilers.RunResult:
need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
if need_exe_wrapper and self.exe_wrapper is None:
raise compilers.CrossNoRunException('Can not run test applications in this cross environment.')
with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p:
if p.returncode != 0:
mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n')
return compilers.RunResult(False)
if need_exe_wrapper:
cmdlist = self.exe_wrapper.get_command() + [p.output_name]
else:
cmdlist = [p.output_name]
try:
pe, so, se = mesonlib.Popen_safe(cmdlist)
except Exception as e:
mlog.debug(f'Could not run: {cmdlist} (error: {e})\n')
return compilers.RunResult(False)
mlog.debug('Program stdout:\n')
mlog.debug(so)
mlog.debug('Program stderr:\n')
mlog.debug(se)
return compilers.RunResult(True, pe.returncode, so, se)
def _compile_int(self, expression: str, prefix: str, env: 'Environment', def _compile_int(self, expression: str, prefix: str, env: 'Environment',
extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]],
dependencies: T.Optional[T.List['Dependency']]) -> bool: dependencies: T.Optional[T.List['Dependency']]) -> bool:

@ -302,6 +302,9 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.run', (str, mesonlib.File)) @typed_pos_args('compiler.run', (str, mesonlib.File))
@typed_kwargs('compiler.run', *_COMPILES_KWS) @typed_kwargs('compiler.run', *_COMPILES_KWS)
def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult': def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult':
if self.compiler.language not in {'d', 'c', 'cpp', 'objc', 'objcpp'}:
FeatureNew.single_use(f'compiler.run for {self.compiler.get_display_language()} language',
'1.5.0', self.subproject, location=self.current_node)
code = args[0] code = args[0]
if isinstance(code, mesonlib.File): if isinstance(code, mesonlib.File):
self.interpreter.add_build_def_file(code) self.interpreter.add_build_def_file(code)

@ -18,3 +18,6 @@ test(
), ),
should_fail : true, should_fail : true,
) )
rustc = meson.get_compiler('rust')
assert(rustc.run('fn main(){}').returncode() == 0)

Loading…
Cancel
Save