From d31635c986ecc69ed479649add480499fa5f7f02 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 17 Apr 2024 10:49:12 -0700 Subject: [PATCH] compilers: Use a dataclass instead of tuple for cached results There's been a number of bugs where the code does something like: ```python def foo(...) -> T.Tuple[bool, bool]: ... if foo(): ... ``` Which will always resolve to True since a non-empty Tuple is truthy. To avoid that I've moved to a simple struct that implements a bool dunder, so that doing `if result:` does the expected thing. --- mesonbuild/compilers/c.py | 7 +- mesonbuild/compilers/compilers.py | 74 +++++----- mesonbuild/compilers/cpp.py | 21 +-- mesonbuild/compilers/cuda.py | 10 +- mesonbuild/compilers/d.py | 5 +- mesonbuild/compilers/fortran.py | 9 +- mesonbuild/compilers/mixins/clang.py | 3 +- mesonbuild/compilers/mixins/clike.py | 51 ++++--- mesonbuild/compilers/mixins/gnu.py | 6 +- mesonbuild/compilers/mixins/visualstudio.py | 14 +- mesonbuild/compilers/vala.py | 4 +- mesonbuild/dependencies/dev.py | 2 +- mesonbuild/dependencies/misc.py | 20 +-- mesonbuild/dependencies/python.py | 2 +- mesonbuild/dependencies/ui.py | 4 +- mesonbuild/interpreter/compiler.py | 146 ++++++++++---------- mesonbuild/linkers/linkers.py | 3 +- mesonbuild/modules/simd.py | 2 +- 18 files changed, 199 insertions(+), 184 deletions(-) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 819ef8bb8628..e6ed07d292d7 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -31,6 +31,7 @@ gnu_winlibs, msvc_winlibs, Compiler, + CompileCheckResult, ) if T.TYPE_CHECKING: @@ -79,7 +80,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: def has_header_symbol(self, hname: str, symbol: 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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} t = '''{prefix} #include <{header}> @@ -394,9 +395,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': # So we should explicitly fail at this case. def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: if funcname == 'lchmod': - return False, False + return CompileCheckResult(False) else: return super().has_function(funcname, prefix, env, extra_args=extra_args, diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index b9605ccaedcb..ded0961bf162 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -186,6 +186,19 @@ class CompileCheckMode(enum.Enum): LINK = 'link' +@dataclass +class CompileCheckResult: + + """The result of a Compiler check. + + :param result: Whether the check was successful or not + :param cached: Whether the result was retrieved from a cache, defaults to False + """ + + result: bool + cached: bool = False + + gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32', '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] @@ -530,12 +543,12 @@ def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], def has_members(self, typename: str, membernames: T.List[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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) def has_type(self, typename: str, prefix: str, env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: raise EnvironmentException('%s does not support has_type ' % self.get_id()) def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: @@ -604,19 +617,26 @@ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: def check_header(self, hname: 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) -> T.Tuple[bool, bool]: - """Check that header is usable. - - Returns a two item tuple of bools. The first bool is whether the - check succeeded, the second is whether the result was cached (True) - or run fresh (False). + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: + """Check that a header is actually usable. + + In contrast to :method:`has_header`, which checks that a header exists. + Tihs is useful for cases where a header contains an #error define. + + :param hname: the name of the header to check for + :param prefix: A preamble to add to the top of the generated test code + :param env: The Meson Environment + :param extra_args: Any extra arguments to pass to the check, defaults to None + :param dependencies: A list of Meson Dependency objects, defaults to None + :raises EnvironmentException: If the given compiler does not implement this check + :return: a :class:`CompileCheckResult` """ raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) def has_header(self, hname: 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, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: """Check that header is exists. This check will return true if the file exists, even if it contains: @@ -627,16 +647,14 @@ def has_header(self, hname: str, prefix: str, env: 'Environment', *, Use check_header if your header only works in some cases. - Returns a two item tuple of bools. The first bool is whether the - check succeeded, the second is whether the result was cached (True) - or run fresh (False). + :return: a :class:`CompileCheckResult` """ raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) def has_header_symbol(self, hname: str, symbol: 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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) def run(self, code: 'mesonlib.FileOrString', env: 'Environment', @@ -705,12 +723,10 @@ def alignment(self, typename: str, prefix: str, env: 'Environment', *, def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: """See if a function exists. - Returns a two item tuple of bools. The first bool is whether the - check succeeded, the second is whether the result was cached (True) - or run fresh (False). + :return: a :class:`CompileCheckResult` """ raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) @@ -740,23 +756,19 @@ def get_library_naming(self, env: 'Environment', libtype: LibType, def get_program_dirs(self, env: 'Environment') -> T.List[str]: return [] - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: """Checks if the compiler has all of the arguments. - :returns: - A tuple of (bool, bool). The first value is whether the check - succeeded, and the second is whether it was retrieved from a cache + :return: a :class:`CompileCheckResult` """ raise EnvironmentException( 'Language {} does not support has_multi_arguments.'.format( self.get_display_language())) - def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: """Checks if the linker has all of the arguments. - :returns: - A tuple of (bool, bool). The first value is whether the check - succeeded, and the second is whether it was retrieved from a cache + :return: a :class:`CompileCheckResult` """ return self.linker.has_multi_arguments(args, env) @@ -948,7 +960,7 @@ def get_win_subsystem_args(self, value: str) -> T.List[str]: # or does not target Windows return self.linker.get_win_subsystem_args(value) - def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: + def has_func_attribute(self, name: str, env: 'Environment') -> CompileCheckResult: raise EnvironmentException( f'Language {self.get_display_language()} does not support function attributes.') @@ -1295,21 +1307,19 @@ def compiles(self, code: 'mesonlib.FileOrString', env: 'Environment', *, extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, dependencies: T.Optional[T.List['Dependency']] = None, mode: CompileCheckMode = CompileCheckMode.COMPILE, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: """Run a compilation or link test to see if code can be compiled/linked. - :returns: - A tuple of (bool, bool). The first value is whether the check - succeeded, and the second is whether it was retrieved from a cache + :return: A :class:`CompileCheckResult` """ with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: - return p.returncode == 0, p.cached + return CompileCheckResult(p.returncode == 0, p.cached) def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, compiler: T.Optional['Compiler'] = None, extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, dependencies: T.Optional[T.List['Dependency']] = None, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: if compiler: with compiler._build_wrapper(code, env, dependencies=dependencies, want_output=True) as r: objfile = mesonlib.File.from_absolute_file(r.output_name) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index f9ebf08da8e8..ad6985f08b2b 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -17,6 +17,7 @@ msvc_winlibs, Compiler, CompileCheckMode, + CompileCheckResult, ) from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES from .mixins.apple import AppleCompilerMixin @@ -99,13 +100,13 @@ def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: def has_header_symbol(self, hname: str, symbol: 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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: # Check if it's a C-like symbol - found, cached = super().has_header_symbol(hname, symbol, prefix, env, - extra_args=extra_args, - dependencies=dependencies) - if found: - return True, cached + result = super().has_header_symbol(hname, symbol, prefix, env, + extra_args=extra_args, + dependencies=dependencies) + if result.result: + return result # Check if it's a class or a template if extra_args is None: extra_args = [] @@ -186,8 +187,8 @@ class _StdCPPLibMixin(CompilerMixinBase): def language_stdlib_provider(self, env: Environment) -> str: # https://stackoverflow.com/a/31658120 - header = 'version' if self.has_header('version', '', env)[0] else 'ciso646' - is_libcxx = self.has_header_symbol(header, '_LIBCPP_VERSION', '', env)[0] + header = 'version' if self.has_header('version', '', env).result else 'ciso646' + is_libcxx = self.has_header_symbol(header, '_LIBCPP_VERSION', '', env).result lib = 'c++' if is_libcxx else 'stdc++' return lib @@ -609,9 +610,9 @@ def get_options(self) -> 'MutableKeyedOptionDictType': # So we should explicitly fail at this case. def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: if funcname == 'lchmod': - return False, False + return CompileCheckResult(False) else: return super().has_function(funcname, prefix, env, extra_args=extra_args, diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 38a938f24aff..7e03f1c656f9 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -16,7 +16,7 @@ is_windows, LibType, version_compare ) from ..options import OptionKey -from .compilers import Compiler +from .compilers import Compiler, CompileCheckResult if T.TYPE_CHECKING: from .compilers import CompileCheckMode @@ -607,7 +607,7 @@ def sanity_check(self, work_dir: str, env: 'Environment') -> None: def has_header_symbol(self, hname: str, symbol: 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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: if extra_args is None: extra_args = [] fargs = {'prefix': prefix, 'header': hname, 'symbol': symbol} @@ -621,9 +621,9 @@ def has_header_symbol(self, hname: str, symbol: str, prefix: str, #endif return 0; }}''' - found, cached = self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies) - if found: - return True, cached + result = self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies) + if result.result: + return result # Check if it's a class or a template t = '''{prefix} #include <{header}> diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 8ee6ebf651c5..4f5ce2808cda 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -32,6 +32,7 @@ from ..environment import Environment from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice + from .compilers import CompileCheckResult CompilerMixinBase = Compiler else: @@ -547,7 +548,7 @@ def get_optimization_link_args(self, optimization_level: str) -> T.List[str]: def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> DCompilerArgs: return DCompilerArgs(self, args) - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: return self.compiles('int i;\n', env, extra_args=args) def _get_target_arch_args(self) -> T.List[str]: @@ -632,7 +633,7 @@ def alignment(self, typename: str, prefix: str, env: 'Environment', *, def has_header(self, hname: 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, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: extra_args = self._get_compile_extra_args(extra_args) code = f'''{prefix} diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index a99a95ce37ba..89c47b88cd0f 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -31,6 +31,7 @@ from ..environment import Environment from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice + from .compilers import CompileCheckResult class FortranCompiler(CLikeCompiler, Compiler): @@ -47,7 +48,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: raise MesonException('Fortran does not have "has_function" capability.\n' 'It is better to test if a Fortran capability is working like:\n\n' "meson.get_compiler('fortran').links('block; end block; end program')\n\n" @@ -105,10 +106,10 @@ def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str] code = 'stop; end program' return self._find_library_impl(libname, env, extra_dirs, code, libtype, lib_prefix_warning) - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: return self._has_multi_arguments(args, env, 'stop; end program') - def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: return self._has_multi_link_arguments(args, env, 'stop; end program') def get_options(self) -> 'MutableKeyedOptionDictType': @@ -181,7 +182,7 @@ def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: def has_header(self, hname: 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, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: ''' Derived from mixins/clike.py:has_header, but without C-style usage of __has_include which breaks with GCC-Fortran 10: diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index a0d3d5ffb069..2a317f4c1265 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -19,6 +19,7 @@ if T.TYPE_CHECKING: from ...environment import Environment from ...dependencies import Dependency # noqa: F401 + from ..compilers import CompileCheckResult clang_color_args: T.Dict[str, T.List[str]] = { 'auto': ['-fdiagnostics-color=auto'], @@ -112,7 +113,7 @@ def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: if extra_args is None: extra_args = [] # Starting with XCode 8, we need to pass this to force linker diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index e982ca023e41..a4e365462937 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -28,7 +28,7 @@ from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker from ...mesonlib import LibType from .. import compilers -from ..compilers import CompileCheckMode +from ..compilers import CompileCheckMode, CompileCheckResult from .visualstudio import VisualStudioLikeCompiler if T.TYPE_CHECKING: @@ -330,7 +330,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: def check_header(self, hname: 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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: code = f'''{prefix} #include <{hname}>''' return self.compiles(code, env, extra_args=extra_args, @@ -339,7 +339,7 @@ def check_header(self, hname: str, prefix: str, env: 'Environment', *, def has_header(self, hname: 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, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: code = f'''{prefix} #ifdef __has_include #if !__has_include("{hname}") @@ -354,7 +354,7 @@ def has_header(self, hname: str, prefix: str, env: 'Environment', *, def has_header_symbol(self, hname: str, symbol: 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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: t = f'''{prefix} #include <{hname}> int main(void) {{ @@ -465,7 +465,7 @@ def _compile_int(self, expression: str, prefix: str, env: 'Environment', #include int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}''' return self.compiles(t, env, extra_args=extra_args, - dependencies=dependencies)[0] + dependencies=dependencies).result def cross_compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], guess: T.Optional[int], prefix: str, env: 'Environment', @@ -549,7 +549,7 @@ def cross_sizeof(self, typename: str, prefix: str, env: 'Environment', *, return 0; }}''' if not self.compiles(t, env, extra_args=extra_args, - dependencies=dependencies)[0]: + dependencies=dependencies).result: return -1 return self.cross_compute_int(f'sizeof({typename})', None, None, None, prefix, env, extra_args, dependencies) @@ -588,8 +588,7 @@ def cross_alignment(self, typename: str, prefix: str, env: 'Environment', *, {typename} something; return 0; }}''' - if not self.compiles(t, env, extra_args=extra_args, - dependencies=dependencies)[0]: + if not self.compiles(t, env, extra_args=extra_args, dependencies=dependencies).result: return -1 t = f'''{prefix} #include @@ -765,7 +764,7 @@ def _have_prototype_templ() -> T.Tuple[str, str]: def has_function(self, funcname: str, prefix: str, env: 'Environment', *, extra_args: T.Optional[T.List[str]] = None, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: """Determine if a function exists. First, this function looks for the symbol in the default libraries @@ -784,7 +783,7 @@ def has_function(self, funcname: str, prefix: str, env: 'Environment', *, val = env.properties.host.get(varname, None) if val is not None: if isinstance(val, bool): - return val, False + return CompileCheckResult(val) raise mesonlib.EnvironmentException(f'Cross variable {varname} is not a boolean.') # TODO: we really need a protocol for this, @@ -818,14 +817,14 @@ def has_function(self, funcname: str, prefix: str, env: 'Environment', *, head, main = self._no_prototype_templ() templ = head + stubs_fail + main - res, cached = self.links(templ.format(**fargs), env, extra_args=extra_args, - dependencies=dependencies) - if res: - return True, cached + result = self.links(templ.format(**fargs), env, extra_args=extra_args, + dependencies=dependencies) + if result.result: + return result # MSVC does not have compiler __builtin_-s. if self.get_id() in {'msvc', 'intel-cl'}: - return False, False + return CompileCheckResult(False) # Detect function as a built-in # @@ -866,7 +865,7 @@ def has_function(self, funcname: str, prefix: str, env: 'Environment', *, def has_members(self, typename: str, membernames: T.List[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) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: if extra_args is None: extra_args = [] # Create code that accesses all members @@ -882,7 +881,7 @@ def has_members(self, typename: str, membernames: T.List[str], def has_type(self, typename: str, prefix: str, env: 'Environment', extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, - dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: + dependencies: T.Optional[T.List['Dependency']] = None) -> CompileCheckResult: t = f'''{prefix} void bar(void) {{ (void) sizeof({typename}); @@ -1125,7 +1124,7 @@ def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.Lis largs = self.get_linker_always_args() + self.get_allow_undefined_link_args() extra_args = cargs + self.linker_to_compiler_args(largs) - if self.links(code, env, extra_args=extra_args, disable_cache=True)[0]: + if self.links(code, env, extra_args=extra_args, disable_cache=True).result: return cargs # Don't do a manual search for internal libs if libname in self.internal_libs: @@ -1215,7 +1214,7 @@ def _find_framework_real(self, name: str, env: 'Environment', extra_dirs: T.List # then we must also pass -L/usr/lib to pick up libSystem.dylib extra_args = [] if allow_system else ['-Z', '-L/usr/lib'] link_args += ['-framework', name] - if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]: + if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True).result: return link_args return None @@ -1261,10 +1260,10 @@ def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]: return args.copy() def has_arguments(self, args: T.List[str], env: 'Environment', code: str, - mode: CompileCheckMode) -> T.Tuple[bool, bool]: + mode: CompileCheckMode) -> CompileCheckResult: return self.compiles(code, env, extra_args=args, mode=mode) - def _has_multi_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]: + def _has_multi_arguments(self, args: T.List[str], env: 'Environment', code: str) -> CompileCheckResult: new_args: T.List[str] = [] for arg in args: # some compilers, e.g. GCC, don't warn for unsupported warning-disable @@ -1285,10 +1284,10 @@ def _has_multi_arguments(self, args: T.List[str], env: 'Environment', code: str) new_args.append(arg) return self.has_arguments(new_args, env, code, mode=CompileCheckMode.COMPILE) - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: return self._has_multi_arguments(args, env, 'extern int i;\nint i;\n') - def _has_multi_link_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]: + def _has_multi_link_arguments(self, args: T.List[str], env: 'Environment', code: str) -> CompileCheckResult: # First time we check for link flags we need to first check if we have # --fatal-warnings, otherwise some linker checks could give some # false positive. @@ -1296,7 +1295,7 @@ def _has_multi_link_arguments(self, args: T.List[str], env: 'Environment', code: args = self.linker_to_compiler_args(args) return self.has_arguments(args, env, code, mode=CompileCheckMode.LINK) - def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: return self._has_multi_link_arguments(args, env, 'int main(void) { return 0; }\n') @staticmethod @@ -1315,13 +1314,13 @@ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: # mixins. return ['-Werror'] - def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: + def has_func_attribute(self, name: str, env: 'Environment') -> CompileCheckResult: # Just assume that if we're not on windows that dllimport and dllexport # don't work m = env.machines[self.for_machine] if not (m.is_windows() or m.is_cygwin()): if name in {'dllimport', 'dllexport'}: - return False, False + return CompileCheckResult(False) return self.compiles(self.attribute_check_func(name), env, extra_args=self.get_has_func_attribute_extra_args(name)) diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 62f55543a0a7..2e980584a175 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -17,7 +17,7 @@ from ... import mesonlib from ... import mlog from ...options import OptionKey -from mesonbuild.compilers.compilers import CompileCheckMode +from ..compilers import CompileCheckMode, CompileCheckResult if T.TYPE_CHECKING: from ..._typing import ImmutableListProtocol @@ -590,7 +590,7 @@ def openmp_flags(self, env: Environment) -> T.List[str]: return ['-fopenmp'] def has_arguments(self, args: T.List[str], env: 'Environment', code: str, - mode: CompileCheckMode) -> T.Tuple[bool, bool]: + mode: CompileCheckMode) -> CompileCheckResult: # For some compiler command line arguments, the GNU compilers will # emit a warning on stderr indicating that an option is valid for a # another language, but still complete with exit_success @@ -600,7 +600,7 @@ def has_arguments(self, args: T.List[str], env: 'Environment', code: str, result = False if self.language in {'c', 'objc'} and 'is valid for C++/ObjC++' in p.stderr: result = False - return result, p.cached + return CompileCheckResult(result, p.cached) def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: # GCC only warns about unknown or ignored attributes, so force an diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index b4677f4172ba..b6b44c293fa8 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -14,9 +14,9 @@ from ... import arglist from ... import mesonlib from ... import mlog -from mesonbuild.compilers.compilers import CompileCheckMode from ...options import OptionKey from mesonbuild.linkers.linkers import ClangClDynamicLinker +from ..compilers import CompileCheckMode, CompileCheckResult if T.TYPE_CHECKING: from ...environment import Environment @@ -297,12 +297,12 @@ def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], bu # Visual Studio is special. It ignores some arguments it does not # understand and you can't tell it to error out on those. # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t - def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: CompileCheckMode) -> T.Tuple[bool, bool]: + def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: CompileCheckMode) -> CompileCheckResult: warning_text = '4044' if mode == CompileCheckMode.LINK else '9002' 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.stderr or warning_text in p.stdout), p.cached + return CompileCheckResult(False, p.cached) + return CompileCheckResult(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] @@ -358,10 +358,10 @@ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: crt_val = self.get_crt_val(crt_val, buildtype) return self.crt_args[crt_val] - def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: + def has_func_attribute(self, name: str, env: 'Environment') -> CompileCheckResult: # MSVC doesn't have __attribute__ like Clang and GCC do, so just return # false without compiling anything - return name in {'dllimport', 'dllexport'}, False + return CompileCheckResult(name in {'dllimport', 'dllexport'}) @staticmethod def get_argument_syntax() -> str: @@ -452,7 +452,7 @@ def __init__(self, target: str): self.can_compile_suffixes.add('s') self.can_compile_suffixes.add('sx') - def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: CompileCheckMode) -> T.Tuple[bool, bool]: + def has_arguments(self, args: T.List[str], env: 'Environment', code: str, mode: CompileCheckMode) -> CompileCheckResult: if mode != CompileCheckMode.LINK: args = args + ['-Werror=unknown-argument', '-Werror=unknown-warning-option'] return super().has_arguments(args, env, code, mode) diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index a1d57b38cb8e..22fcd3391b92 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -10,7 +10,7 @@ from .. import mesonlib from ..mesonlib import EnvironmentException, version_compare, LibType from ..options import OptionKey -from .compilers import CompileCheckMode, Compiler +from .compilers import CompileCheckMode, CompileCheckResult, Compiler if T.TYPE_CHECKING: from ..arglist import CompilerArgs @@ -191,7 +191,7 @@ def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, compiler: T.Optional['Compiler'] = None, extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, dependencies: T.Optional[T.List['Dependency']] = None, - disable_cache: bool = False) -> T.Tuple[bool, bool]: + disable_cache: bool = False) -> CompileCheckResult: self.force_link = True if compiler: with compiler._build_wrapper(code, env, dependencies=dependencies, want_output=True) as r: diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py index de85516feb64..72f61fa9bb42 100644 --- a/mesonbuild/dependencies/dev.py +++ b/mesonbuild/dependencies/dev.py @@ -547,7 +547,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. for lib in libs: l = self.clib_compiler.find_library(lib, environment, [], self.libtype) h = self.clib_compiler.has_header('zlib.h', '', environment, dependencies=[self]) - if l and h[0]: + if l and h: self.is_found = True self.link_args = l break diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index b5c40984a8e7..70142561da5b 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -56,7 +56,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): super().__init__(name, env, kwargs) self.feature_since = ('0.62.0', "consider checking for `dlopen` with and without `find_library('dl')`") - if self.clib_compiler.has_function('dlopen', '#include ', env)[0]: + if self.clib_compiler.has_function('dlopen', '#include ', env): self.is_found = True @@ -68,7 +68,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): h = self.clib_compiler.has_header('dlfcn.h', '', env) self.link_args = self.clib_compiler.find_library('dl', env, [], self.libtype) - if h[0] and self.link_args: + if h and self.link_args: self.is_found = True @@ -132,7 +132,7 @@ def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> No # Flang has omp_lib.h header_names = ('omp.h', 'omp_lib.h') for name in header_names: - if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]: + if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True).result: self.is_found = True break else: @@ -344,7 +344,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): if l: for header in headers: h = self.clib_compiler.has_header(header, '', env) - if h[0]: + if h: self.is_found = True self.link_args = l # Not sure how to find version for non-ncurses curses @@ -380,7 +380,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): self.feature_since = ('0.60.0', "consider checking for `iconv_open` with and without `find_library('iconv')`") code = '''#include \n\nint main() {\n iconv_open("","");\n}''' # [ignore encoding] this is C, not python, Mr. Lint - if self.clib_compiler.links(code, env)[0]: + if self.clib_compiler.links(code, env): self.is_found = True @@ -392,7 +392,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): h = self.clib_compiler.has_header('iconv.h', '', env) self.link_args = self.clib_compiler.find_library('iconv', env, [], self.libtype) - if h[0] and self.link_args: + if h and self.link_args: self.is_found = True @@ -402,7 +402,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): self.feature_since = ('0.59.0', "consider checking for `ngettext` with and without `find_library('intl')`") code = '''#include \n\nint main() {\n gettext("Hello world");\n}''' - if self.clib_compiler.links(code, env)[0]: + if self.clib_compiler.links(code, env): self.is_found = True @@ -414,7 +414,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): h = self.clib_compiler.has_header('libintl.h', '', env) self.link_args = self.clib_compiler.find_library('intl', env, [], self.libtype) - if h[0] and self.link_args: + if h and self.link_args: self.is_found = True if self.static: @@ -430,7 +430,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): 'method': 'system', 'static': self.static, } - if not self.clib_compiler.has_header('openssl/ssl.h', '', env)[0]: + if not self.clib_compiler.has_header('openssl/ssl.h', '', env): return # openssl >= 3 only @@ -462,7 +462,7 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]): if self._add_sub_dependency(libcrypto_factory(env, self.for_machine, dependency_kwargs)): self.is_found = True elif name == 'libcrypto': - use_threads = self.clib_compiler.has_header_symbol('openssl/opensslconf.h', 'OPENSSL_THREADS', '', env, dependencies=[self])[0] + use_threads = self.clib_compiler.has_header_symbol('openssl/opensslconf.h', 'OPENSSL_THREADS', '', env, dependencies=[self]).result if not use_threads or self._add_sub_dependency(threads_factory(env, self.for_machine, {})): self.is_found = True # only relevant on platforms where it is distributed with the libc, in which case it always succeeds diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index fff4aaa9e849..3959f7dd84b6 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -363,7 +363,7 @@ def __init__(self, name: str, environment: 'Environment', if mesonlib.is_windows() and self.get_windows_python_arch().endswith('64') and mesonlib.version_compare(self.version, '<3.12'): self.compile_args += ['-DMS_WIN64='] - if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args)[0]: + if not self.clib_compiler.has_header('Python.h', '', environment, extra_args=self.compile_args): self.is_found = False @staticmethod diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index cc17377a649b..ca92030f1d5a 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -45,7 +45,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. return else: links = self.clib_compiler.find_library('GL', environment, []) - has_header = self.clib_compiler.has_header('GL/gl.h', '', environment)[0] + has_header = self.clib_compiler.has_header('GL/gl.h', '', environment).result if links and has_header: self.is_found = True self.link_args = links @@ -229,7 +229,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. else: # simply try to guess it, usually works on linux libs = self.clib_compiler.find_library('vulkan', environment, []) - if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment, disable_cache=True)[0]: + if libs is not None and self.clib_compiler.has_header('vulkan/vulkan.h', '', environment, disable_cache=True).result: self.is_found = True for lib in libs: self.link_args.append(lib) diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py index 90514446bb12..f19bad6763dd 100644 --- a/mesonbuild/interpreter/compiler.py +++ b/mesonbuild/interpreter/compiler.py @@ -367,20 +367,20 @@ def has_member_method(self, args: T.Tuple[str, str], kwargs: 'HasKW') -> bool: return False extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) - had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'], - self.environment, - extra_args=extra_args, - dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' - if required and not had: + result = self.compiler.has_members(typename, [membername], kwargs['prefix'], + self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if result.cached else '' + if required and not result.result: raise InterpreterException(f'{self.compiler.get_display_language()} member {membername!r} of type {typename!r} not usable') - elif had: + elif result.result: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking whether type', mlog.bold(typename, True), 'has member', mlog.bold(membername, True), msg, hadtxt, cached_msg) - return had + return result.result @typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1) @typed_kwargs('compiler.has_members', _HAS_REQUIRED_KW, *_COMMON_KWS) @@ -393,21 +393,21 @@ def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'HasKW') - return False extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) - had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'], - self.environment, - extra_args=extra_args, - dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' - if required and not had: + result = self.compiler.has_members(typename, membernames, kwargs['prefix'], + self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if result.cached else '' + if required and not result.result: # print members as array: ['member1', 'member2'] raise InterpreterException(f'{self.compiler.get_display_language()} members {membernames!r} of type {typename!r} not usable') - elif had: + elif result.result: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking whether type', mlog.bold(typename, True), 'has members', members, msg, hadtxt, cached_msg) - return had + return result.result @typed_pos_args('compiler.has_function', str) @typed_kwargs('compiler.has_function', _HAS_REQUIRED_KW, *_COMMON_KWS) @@ -419,18 +419,18 @@ def has_function_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: return False extra_args = self._determine_args(kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) - had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment, - extra_args=extra_args, - dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' - if required and not had: + result = self.compiler.has_function(funcname, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if result.cached else '' + if required and not result.result: raise InterpreterException(f'{self.compiler.get_display_language()} function {funcname!r} not usable') - elif had: + elif result.result: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt, cached_msg) - return had + return result.result @typed_pos_args('compiler.has_type', str) @typed_kwargs('compiler.has_type', _HAS_REQUIRED_KW, *_COMMON_KWS) @@ -442,17 +442,17 @@ def has_type_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool: return False extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) - had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment, - extra_args=extra_args, dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' - if required and not had: + result = self.compiler.has_type(typename, kwargs['prefix'], self.environment, + extra_args=extra_args, dependencies=deps) + cached_msg = mlog.blue('(cached)') if result.cached else '' + if required and not result.result: raise InterpreterException(f'{self.compiler.get_display_language()} type {typename!r} not usable') - elif had: + elif result.result: hadtxt = mlog.green('YES') else: hadtxt = mlog.red('NO') mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt, cached_msg) - return had + return result.result @FeatureNew('compiler.compute_int', '0.40.0') @typed_pos_args('compiler.compute_int', str) @@ -539,20 +539,20 @@ def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'Compi code.absolute_path(self.environment.source_dir, self.environment.build_dir)) extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None) - result, cached = self.compiler.compiles(code, self.environment, - extra_args=extra_args, - dependencies=deps) - if required and not result: + result = self.compiler.compiles(code, self.environment, + extra_args=extra_args, + dependencies=deps) + if required and not result.result: raise InterpreterException(f'Could not compile {testname}') if testname: - if result: + if result.result: h = mlog.green('YES') else: h = mlog.red('NO') - cached_msg = mlog.blue('(cached)') if cached else '' + cached_msg = mlog.blue('(cached)') if result.cached else '' mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h, cached_msg) - return result + return result.result @typed_pos_args('compiler.links', (str, mesonlib.File)) @typed_kwargs('compiler.links', *_COMPILES_KWS) @@ -588,21 +588,21 @@ def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileK extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False) - result, cached = self.compiler.links(code, self.environment, - compiler=compiler, - extra_args=extra_args, - dependencies=deps) - if required and not result: + result = self.compiler.links(code, self.environment, + compiler=compiler, + extra_args=extra_args, + dependencies=deps) + if required and not result.result: raise InterpreterException(f'Could not link {testname if testname else "code"}') if testname: - if result: + if result.result: h = mlog.green('YES') else: h = mlog.red('NO') - cached_msg = mlog.blue('(cached)') if cached else '' + cached_msg = mlog.blue('(cached)') if result.cached else '' mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached_msg) - return result + return result.result @FeatureNew('compiler.check_header', '0.47.0') @typed_pos_args('compiler.check_header', str) @@ -615,18 +615,18 @@ def check_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool: return False extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) - haz, cached = self.compiler.check_header(hname, kwargs['prefix'], self.environment, - extra_args=extra_args, - dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' - if required and not haz: + result = self.compiler.check_header(hname, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + cached_msg = mlog.blue('(cached)') if result.cached else '' + if required and not result.result: raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not usable') - elif haz: + elif result.result: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Check usable header', mlog.bold(hname, True), msg, h, cached_msg) - return haz + return result.result def _has_header_impl(self, hname: str, kwargs: 'HeaderKW') -> bool: disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) @@ -635,17 +635,17 @@ def _has_header_impl(self, hname: str, kwargs: 'HeaderKW') -> bool: return False extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) - haz, cached = self.compiler.has_header(hname, kwargs['prefix'], self.environment, - extra_args=extra_args, dependencies=deps) - cached_msg = mlog.blue('(cached)') if cached else '' - if required and not haz: + result = self.compiler.has_header(hname, kwargs['prefix'], self.environment, + extra_args=extra_args, dependencies=deps) + cached_msg = mlog.blue('(cached)') if result.cached else '' + if required and not result.result: raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not found') - elif haz: + elif result.result: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Has header', mlog.bold(hname, True), msg, h, cached_msg) - return haz + return result.result @typed_pos_args('compiler.has_header', str) @typed_kwargs('compiler.has_header', *_HEADER_KWS) @@ -662,18 +662,18 @@ def has_header_symbol_method(self, args: T.Tuple[str, str], kwargs: 'HeaderKW') return False extra_args = functools.partial(self._determine_args, kwargs) deps, msg = self._determine_dependencies(kwargs['dependencies']) - haz, cached = self.compiler.has_header_symbol(hname, symbol, kwargs['prefix'], self.environment, - extra_args=extra_args, - dependencies=deps) - if required and not haz: + result = self.compiler.has_header_symbol(hname, symbol, kwargs['prefix'], self.environment, + extra_args=extra_args, + dependencies=deps) + if required and not result.result: raise InterpreterException(f'{self.compiler.get_display_language()} symbol {symbol} not found in header {hname}') - elif haz: + elif result.result: h = mlog.green('YES') else: h = mlog.red('NO') - cached_msg = mlog.blue('(cached)') if cached else '' + cached_msg = mlog.blue('(cached)') if result.cached else '' mlog.log('Header', mlog.bold(hname, True), 'has symbol', mlog.bold(symbol, True), msg, h, cached_msg) - return haz + return result.result def notfound_library(self, libname: str) -> 'dependencies.ExternalLibrary': lib = dependencies.ExternalLibrary(libname, None, @@ -760,16 +760,16 @@ def _has_argument_impl(self, arguments: T.Union[str, T.List[str]], mlog.log(*logargs) return False test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments - result, cached = test(arguments, self.environment) - if required and not result: + result = test(arguments, self.environment) + if required and not result.result: logargs += ['not usable'] raise InterpreterException(*logargs) logargs += [ mlog.green('YES') if result else mlog.red('NO'), - mlog.blue('(cached)') if cached else '', + mlog.blue('(cached)') if result.cached else '', ] mlog.log(*logargs) - return result + return result.result @typed_pos_args('compiler.has_argument', str) @typed_kwargs('compiler.has_argument', _HAS_REQUIRED_KW) @@ -858,16 +858,16 @@ def _has_function_attribute_impl(self, attr: str, kwargs: T.Optional['ExtractReq logargs += ['skipped: feature', mlog.bold(feature), 'disabled'] mlog.log(*logargs) return False - had, cached = self.compiler.has_func_attribute(attr, self.environment) - if required and not had: + result = self.compiler.has_func_attribute(attr, self.environment) + if required and not result.result: logargs += ['not usable'] raise InterpreterException(*logargs) logargs += [ - mlog.green('YES') if had else mlog.red('NO'), - mlog.blue('(cached)') if cached else '' + mlog.green('YES') if result else mlog.red('NO'), + mlog.blue('(cached)') if result.cached else '' ] mlog.log(*logargs) - return had + return result.result @FeatureNew('compiler.has_function_attribute', '0.48.0') @typed_pos_args('compiler.has_function_attribute', str) diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index d011e67b9c54..371a0cfbf557 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -14,6 +14,7 @@ from ..arglist import CompilerArgs if T.TYPE_CHECKING: + from ..compilers.compilers import CompileCheckResult from ..coredata import KeyedOptionDictType from ..environment import Environment from ..mesonlib import MachineChoice @@ -174,7 +175,7 @@ def get_lib_prefix(self) -> str: def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]: return [] - def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: + def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> CompileCheckResult: raise EnvironmentException(f'Language {self.id} does not support has_multi_link_arguments.') def get_debugfile_name(self, targetfile: str) -> T.Optional[str]: diff --git a/mesonbuild/modules/simd.py b/mesonbuild/modules/simd.py index bfdc0c2dfc2d..034a21b49c5e 100644 --- a/mesonbuild/modules/simd.py +++ b/mesonbuild/modules/simd.py @@ -88,7 +88,7 @@ def check(self, state: ModuleState, args: T.Tuple[str], kwargs: CheckKw) -> T.Li mlog.log(f'Compiler supports {iset}:', mlog.red('NO')) continue - if not compiler.has_multi_arguments(compile_args, state.environment)[0]: + if not compiler.has_multi_arguments(compile_args, state.environment).result: mlog.log(f'Compiler supports {iset}:', mlog.red('NO')) continue mlog.log(f'Compiler supports {iset}:', mlog.green('YES'))