diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2020-09-17 09:59:29 -0700 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2020-09-24 12:14:13 -0700 |
commit | d326c87fe22507b8c25078a7cd7ed88499ba7dc1 (patch) | |
tree | b58f159c6a1eee67c906bf38026649c64ce09b8f /mesonbuild | |
parent | 8fa0548e080dd006821ff985868fdef789935feb (diff) | |
download | meson-d326c87fe22507b8c25078a7cd7ed88499ba7dc1.zip meson-d326c87fe22507b8c25078a7cd7ed88499ba7dc1.tar.gz meson-d326c87fe22507b8c25078a7cd7ed88499ba7dc1.tar.bz2 |
compilers: Use a distinct type for compile/link results
Currently we do some crazy hackery where we add extra properties to a
Popen object and return that. That's crazy. Especially since some of our
hackery is to delete attributes off of the Popen we don't want. Instead,
let's just have a discrete type that has exactly the properties we want.
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/compilers/compilers.py | 52 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clike.py | 6 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/gnu.py | 7 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/visualstudio.py | 2 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 4 |
5 files changed, 42 insertions, 29 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index c4bd7c2..dc6dd5c 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -405,6 +405,29 @@ class RunResult: self.stderr = stderr +class CompileResult: + + """The result of Compiler.compiles (and friends).""" + + def __init__(self, stdo: T.Optional[str] = None, stde: T.Optional[str] = None, + args: T.Optional[T.List[str]] = None, + returncode: int = 999, pid: int = -1, + text_mode: bool = True, + input_name: T.Optional[str] = None, + output_name: T.Optional[str] = None, + command: T.Optional[T.List[str]] = None, cached: bool = False): + self.stdout = stdo + self.stderr = stde + self.input_name = input_name + self.output_name = output_name + self.command = command or [] + self.args = args or [] + self.cached = cached + self.returncode = returncode + self.pid = pid + self.text_mode = text_mode + + class Compiler(metaclass=abc.ABCMeta): # Libraries to ignore in find_library() since they are provided by the # compiler or the C library. Currently only used for MSVC. @@ -633,7 +656,7 @@ class Compiler(metaclass=abc.ABCMeta): return CompilerArgs(self, args) @contextlib.contextmanager - def compile(self, code: str, extra_args: list = None, *, mode: str = 'link', want_output: bool = False, temp_dir: str = None): + def compile(self, code: str, extra_args: list = None, *, mode: str = 'link', want_output: bool = False, temp_dir: str = None) -> T.Iterator[CompileResult]: if extra_args is None: extra_args = [] try: @@ -671,15 +694,14 @@ class Compiler(metaclass=abc.ABCMeta): os_env['LC_ALL'] = 'C' if no_ccache: os_env['CCACHE_DISABLE'] = '1' - p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname, env=os_env) - mlog.debug('Compiler stdout:\n', p.stdo) - mlog.debug('Compiler stderr:\n', p.stde) - p.commands = commands - p.input_name = srcname + p, stdo, stde = Popen_safe(commands, cwd=tmpdirname, env=os_env) + mlog.debug('Compiler stdout:\n', stdo) + mlog.debug('Compiler stderr:\n', stde) + + result = CompileResult(stdo, stde, list(commands), p.returncode, p.pid, input_name=srcname) if want_output: - p.output_name = output - p.cached = False # Make sure that the cached attribute always exists - yield p + result.output_name = output + yield result except OSError: # On Windows antivirus programs and the like hold on to files so # they can't be deleted. There's not much to do in this case. Also, @@ -687,7 +709,7 @@ class Compiler(metaclass=abc.ABCMeta): pass @contextlib.contextmanager - def cached_compile(self, code, cdata: coredata.CoreData, *, extra_args=None, mode: str = 'link', temp_dir=None): + def cached_compile(self, code, cdata: coredata.CoreData, *, extra_args=None, mode: str = 'link', temp_dir=None) -> T.Iterator[CompileResult]: assert(isinstance(cdata, coredata.CoreData)) # Calculate the key @@ -697,21 +719,13 @@ class Compiler(metaclass=abc.ABCMeta): # Check if not cached if key not in cdata.compiler_check_cache: with self.compile(code, extra_args=extra_args, mode=mode, want_output=False, temp_dir=temp_dir) as p: - # Remove all attributes except the following - # This way the object can be serialized - tokeep = ['args', 'commands', 'input_name', 'output_name', - 'pid', 'returncode', 'stdo', 'stde', 'text_mode'] - todel = [x for x in vars(p).keys() if x not in tokeep] - for i in todel: - delattr(p, i) - p.cached = False cdata.compiler_check_cache[key] = p yield p + p.cached = True return # Return cached p = cdata.compiler_check_cache[key] - p.cached = True mlog.debug('Using cached compile:') mlog.debug('Cached command line: ', ' '.join(p.commands), '\n') mlog.debug('Code:\n', code) diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index b2942d3..6a069b6 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -446,7 +446,7 @@ class CLikeCompiler: with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: return p.returncode == 0, p.cached - def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir: str = None) -> T.Tuple[bool, bool]: + def _build_wrapper(self, code: str, env, extra_args, dependencies=None, mode: str = 'compile', want_output: bool = False, disable_cache: bool = False, temp_dir: str = None) -> T.Iterator[compilers.CompileResult]: args = self._get_compiler_check_args(env, extra_args, dependencies, mode) if disable_cache or want_output: return self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) @@ -665,7 +665,7 @@ class CLikeCompiler: # Get the preprocessed value after the delimiter, # minus the extra newline at the end and # merge string literals. - return self.concatenate_string_literals(p.stdo.split(delim + '\n')[-1][:-1]), cached + return self.concatenate_string_literals(p.stdout.split(delim + '\n')[-1][:-1]), cached def get_return_value(self, fname, rtype, prefix, env, extra_args, dependencies): if rtype == 'string': @@ -889,7 +889,7 @@ class CLikeCompiler: with self._build_wrapper(code, env, extra_args=args, mode='compile', want_output=True, temp_dir=env.scratch_dir) as p: if p.returncode != 0: m = 'BUG: Unable to compile {!r} check: {}' - raise RuntimeError(m.format(n, p.stdo)) + raise RuntimeError(m.format(n, p.stdout)) if not os.path.isfile(p.output_name): m = 'BUG: Can\'t find compiled test code for {!r} check' raise RuntimeError(m.format(n)) diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 83f7047..538cc03 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -227,8 +227,7 @@ class GnuLikeCompiler(metaclass=abc.ABCMeta): with self._build_wrapper('', env, extra_args=extra_args, dependencies=None, mode='compile', want_output=True) as p: - stdo = p.stdo - return stdo + return p.stdout def _split_fetch_real_dirs(self, pathstr: str) -> T.List[str]: # We need to use the path separator used by the compiler for printing @@ -364,9 +363,9 @@ class GnuCompiler(GnuLikeCompiler): # another language, but still complete with exit_success with self._build_wrapper(code, env, args, None, mode) as p: result = p.returncode == 0 - if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stde: + if self.language in {'cpp', 'objcpp'} and 'is valid for C/ObjC' in p.stderr: result = False - if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stde: + if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stderr: result = False return result, p.cached diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 0ea03f0..74229e3 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -296,7 +296,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): with self._build_wrapper(code, env, extra_args=args, mode=mode) as p: if p.returncode != 0: return False, p.cached - return not(warning_text in p.stde or warning_text in p.stdo), p.cached + return not(warning_text in p.stderr or warning_text in p.stdout), p.cached def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: pdbarr = rel_obj.split('.')[:-1] diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a36bbe9..baae32b 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -32,7 +32,7 @@ import typing as T if T.TYPE_CHECKING: from . import dependencies - from .compilers import Compiler # noqa: F401 + from .compilers import Compiler, CompileResult # noqa: F401 from .environment import Environment OptionDictType = T.Dict[str, 'UserOption[T.Any]'] @@ -394,7 +394,7 @@ class CoreData: build_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD) host_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD) self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache] - self.compiler_check_cache = OrderedDict() + self.compiler_check_cache = OrderedDict() # type: T.MutableMapping[T.Tuple[T.Tuple[str, ...], str, str, T.Tuple[str, ...], str], CompileResult] # Only to print a warning if it changes between Meson invocations. self.config_files = self.__load_config_files(options, scratch_dir, 'native') |