diff options
-rw-r--r-- | mesonbuild/compilers/compilers.py | 30 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 5 |
2 files changed, 33 insertions, 2 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index c97b14a..3300a75 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -456,11 +456,13 @@ class CrossNoRunException(MesonException): class RunResult(HoldableObject): def __init__(self, compiled: bool, returncode: int = 999, - stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED'): + stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED', + cached: bool = False): self.compiled = compiled self.returncode = returncode self.stdout = stdout self.stderr = stderr + self.cached = cached class CompileResult(HoldableObject): @@ -689,6 +691,32 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) + # 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 + # run. + # For now we just accept code as a string, as that's what internal callers + # need anyway. If we wanted to accept files, the cache key would need to + # include mtime. + def cached_run(self, code: str, env: 'Environment', *, + extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, + dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: + run_check_cache = env.coredata.run_check_cache + args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode('link')) + key = (code, tuple(args)) + if key in run_check_cache: + p = run_check_cache[key] + p.cached = True + mlog.debug('Using cached run result:') + mlog.debug('Code:\n', code) + mlog.debug('Args:\n', extra_args) + mlog.debug('Cached run returncode:\n', p.returncode) + mlog.debug('Cached run stdout:\n', p.stdout) + mlog.debug('Cached run stderr:\n', p.stderr) + else: + p = self.run(code, env, extra_args=extra_args, dependencies=dependencies) + run_check_cache[key] = p + return p + def sizeof(self, typename: str, prefix: str, env: 'Environment', *, extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, dependencies: T.Optional[T.List['Dependency']] = None) -> int: diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index c90d48b..62c81ff 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -39,7 +39,7 @@ import typing as T if T.TYPE_CHECKING: from . import dependencies - from .compilers.compilers import Compiler, CompileResult + from .compilers.compilers import Compiler, CompileResult, RunResult from .dependencies.detect import TV_DepID from .environment import Environment from .mesonlib import OptionOverrideProxy, FileOrString @@ -49,6 +49,8 @@ if T.TYPE_CHECKING: MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]'] KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, OptionOverrideProxy] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], str] + # code, args + RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]] # typeshed StrOrBytesPath = T.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]] @@ -474,6 +476,7 @@ class CoreData: DependencyCache(self.options, MachineChoice.HOST)) self.compiler_check_cache: T.Dict['CompilerCheckCacheKey', 'CompileResult'] = OrderedDict() + self.run_check_cache: T.Dict['RunCheckCacheKey', 'RunResult'] = OrderedDict() # CMake cache self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache()) |