blob: 174c2685f135a953d8b78130570c457c3f75d97c [file] [log] [blame]
Dylan Bakerb30dddd2021-07-26 14:16:31 -07001# SPDX-Licnese-Identifier: Apache-2.0
2# Copyright 2012-2021 The Meson development team
Christian Claussa5020852021-10-01 00:03:23 +02003# Copyright © 2021 Intel Corporation
Dylan Bakerb30dddd2021-07-26 14:16:31 -07004
5import enum
Xavier Claessens558a7bc2021-04-01 08:18:44 -04006import functools
Dylan Bakerb30dddd2021-07-26 14:16:31 -07007import typing as T
Laurin-Luis Lehning281f5ab2021-06-22 07:59:08 +02008
Dylan Bakerb30dddd2021-07-26 14:16:31 -07009from .. import build
10from .. import coredata
11from .. import dependencies
Xavier Claessens558a7bc2021-04-01 08:18:44 -040012from .. import mesonlib
13from .. import mlog
Paolo Bonzini8596b3b2021-07-22 12:01:01 +020014from ..compilers import SUFFIX_TO_LANG
Dylan Bakerb30dddd2021-07-26 14:16:31 -070015from ..compilers.compilers import CompileCheckMode
16from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs,
17 FeatureNew, disablerIfNotFound,
18 InterpreterException)
19from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args
20from .interpreterobjects import (extract_required_kwarg, extract_search_dirs)
Dylan Baker11fbaf22021-08-27 11:47:12 -070021from .type_checking import REQUIRED_KW, in_set_validator, NoneType
Xavier Claessens558a7bc2021-04-01 08:18:44 -040022
Daniel Mensinger202e3452021-06-11 16:01:14 +020023if T.TYPE_CHECKING:
Daniel Mensinger7c757df2021-06-17 00:27:39 +020024 from ..interpreter import Interpreter
Daniel Mensinger202e3452021-06-11 16:01:14 +020025 from ..compilers import Compiler, RunResult
Dylan Bakerb30dddd2021-07-26 14:16:31 -070026 from ..interpreterbase import TYPE_var, TYPE_kwargs
27 from .kwargs import ExtractRequired, ExtractSearchDirs
28
29 from typing_extensions import TypedDict, Literal
30
31 class GetSupportedArgumentKw(TypedDict):
32
33 checked: Literal['warn', 'require', 'off']
34
35 class AlignmentKw(TypedDict):
36
37 prefix: str
38 args: T.List[str]
39 dependencies: T.List[dependencies.Dependency]
40
41 class CompileKW(TypedDict):
42
43 name: str
44 no_builtin_args: bool
45 include_directories: T.List[build.IncludeDirs]
46 args: T.List[str]
47 dependencies: T.List[dependencies.Dependency]
48
49 class CommonKW(TypedDict):
50
51 prefix: str
52 no_builtin_args: bool
53 include_directories: T.List[build.IncludeDirs]
54 args: T.List[str]
55 dependencies: T.List[dependencies.Dependency]
56
57 class CompupteIntKW(CommonKW):
58
59 guess: T.Optional[int]
60 high: T.Optional[int]
61 low: T.Optional[int]
62
63 class HeaderKW(CommonKW, ExtractRequired):
64 pass
65
66 class FindLibraryKW(ExtractRequired, ExtractSearchDirs):
67
68 disabler: bool
69 has_headers: T.List[str]
70 static: bool
71
72 # This list must be all of the `HeaderKW` values with `header_`
73 # prepended to the key
74 header_args: T.List[str]
75 header_dependencies: T.List[dependencies.Dependency]
76 header_include_directories: T.List[build.IncludeDirs]
77 header_no_builtin_args: bool
78 header_prefix: str
79 header_required: T.Union[bool, coredata.UserFeatureOption]
80
81
82class _TestMode(enum.Enum):
83
84 """Whether we're doing a compiler or linker check."""
85
86 COMPILER = 0
87 LINKER = 1
88
Daniel Mensinger202e3452021-06-11 16:01:14 +020089
90class TryRunResultHolder(ObjectHolder['RunResult']):
Daniel Mensinger7c757df2021-06-17 00:27:39 +020091 def __init__(self, res: 'RunResult', interpreter: 'Interpreter'):
92 super().__init__(res, interpreter)
Xavier Claessens558a7bc2021-04-01 08:18:44 -040093 self.methods.update({'returncode': self.returncode_method,
94 'compiled': self.compiled_method,
95 'stdout': self.stdout_method,
96 'stderr': self.stderr_method,
97 })
98
99 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700100 @noKwargs
Dylan Bakerbcb54002021-07-26 15:54:56 -0700101 def returncode_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> int:
Daniel Mensinger202e3452021-06-11 16:01:14 +0200102 return self.held_object.returncode
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400103
104 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700105 @noKwargs
Dylan Bakerbcb54002021-07-26 15:54:56 -0700106 def compiled_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
Daniel Mensinger202e3452021-06-11 16:01:14 +0200107 return self.held_object.compiled
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400108
109 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700110 @noKwargs
Dylan Bakerbcb54002021-07-26 15:54:56 -0700111 def stdout_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
Daniel Mensinger202e3452021-06-11 16:01:14 +0200112 return self.held_object.stdout
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400113
114 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700115 @noKwargs
Dylan Bakerbcb54002021-07-26 15:54:56 -0700116 def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
Daniel Mensinger202e3452021-06-11 16:01:14 +0200117 return self.held_object.stderr
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400118
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700119
120_ARGS_KW: KwargInfo[T.List[str]] = KwargInfo(
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400121 'args',
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700122 ContainerTypeInfo(list, str),
123 listify=True,
124 default=[],
125)
126_DEPENDENCIES_KW: KwargInfo[T.List['dependencies.Dependency']] = KwargInfo(
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400127 'dependencies',
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700128 ContainerTypeInfo(list, dependencies.Dependency),
129 listify=True,
130 default=[],
131)
132_INCLUDE_DIRS_KW: KwargInfo[T.List[build.IncludeDirs]] = KwargInfo(
133 'include_directories',
134 ContainerTypeInfo(list, build.IncludeDirs),
135 default=[],
136 listify=True,
137)
138_PREFIX_KW = KwargInfo('prefix', str, default='')
139_NO_BUILTIN_ARGS_KW = KwargInfo('no_builtin_args', bool, default=False)
140_NAME_KW = KwargInfo('name', str, default='')
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400141
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700142# Many of the compiler methods take this kwarg signature exactly, this allows
143# simplifying the `typed_kwargs` calls
144_COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _PREFIX_KW, _NO_BUILTIN_ARGS_KW]
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400145
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700146# Common methods of compiles, links, runs, and similar
147_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW]
148
149_HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS]
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400150
Daniel Mensinger202e3452021-06-11 16:01:14 +0200151class CompilerHolder(ObjectHolder['Compiler']):
Daniel Mensinger7c757df2021-06-17 00:27:39 +0200152 def __init__(self, compiler: 'Compiler', interpreter: 'Interpreter'):
153 super().__init__(compiler, interpreter)
154 self.environment = self.env
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400155 self.methods.update({'compiles': self.compiles_method,
156 'links': self.links_method,
157 'get_id': self.get_id_method,
158 'get_linker_id': self.get_linker_id_method,
159 'compute_int': self.compute_int_method,
160 'sizeof': self.sizeof_method,
161 'get_define': self.get_define_method,
162 'check_header': self.check_header_method,
163 'has_header': self.has_header_method,
164 'has_header_symbol': self.has_header_symbol_method,
165 'run': self.run_method,
166 'has_function': self.has_function_method,
167 'has_member': self.has_member_method,
168 'has_members': self.has_members_method,
169 'has_type': self.has_type_method,
170 'alignment': self.alignment_method,
171 'version': self.version_method,
172 'cmd_array': self.cmd_array_method,
173 'find_library': self.find_library_method,
174 'has_argument': self.has_argument_method,
175 'has_function_attribute': self.has_func_attribute_method,
176 'get_supported_function_attributes': self.get_supported_function_attributes_method,
177 'has_multi_arguments': self.has_multi_arguments_method,
178 'get_supported_arguments': self.get_supported_arguments_method,
179 'first_supported_argument': self.first_supported_argument_method,
180 'has_link_argument': self.has_link_argument_method,
181 'has_multi_link_arguments': self.has_multi_link_arguments_method,
182 'get_supported_link_arguments': self.get_supported_link_arguments_method,
183 'first_supported_link_argument': self.first_supported_link_argument_method,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400184 'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
185 'get_argument_syntax': self.get_argument_syntax_method,
186 })
187
Daniel Mensinger202e3452021-06-11 16:01:14 +0200188 @property
189 def compiler(self) -> 'Compiler':
190 return self.held_object
191
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700192 @staticmethod
193 def _dep_msg(deps: T.List['dependencies.Dependency'], endl: str) -> str:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400194 msg_single = 'with dependency {}'
195 msg_many = 'with dependencies {}'
196 if not deps:
197 return endl
198 if endl is None:
199 endl = ''
200 names = []
201 for d in deps:
202 if isinstance(d, dependencies.InternalDependency):
203 continue
204 if isinstance(d, dependencies.ExternalLibrary):
205 name = '-l' + d.name
206 else:
207 name = d.name
208 names.append(name)
209 if not names:
210 return None
211 tpl = msg_many if len(names) > 1 else msg_single
212 return tpl.format(', '.join(names)) + endl
213
214 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700215 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700216 def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400217 return self.compiler.version
218
219 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700220 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700221 def cmd_array_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400222 return self.compiler.exelist
223
Dylan Baker272674e2021-07-27 12:59:56 -0700224 def _determine_args(self, nobuiltins: bool,
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700225 incdirs: T.List[build.IncludeDirs],
226 extra_args: T.List[str],
227 mode: CompileCheckMode = CompileCheckMode.LINK) -> T.List[str]:
228 args: T.List[str] = []
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400229 for i in incdirs:
Daniel Mensinger7c757df2021-06-17 00:27:39 +0200230 for idir in i.to_string_list(self.environment.get_source_dir()):
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700231 args.extend(self.compiler.get_include_args(idir, False))
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400232 if not nobuiltins:
233 opts = self.environment.coredata.options
234 args += self.compiler.get_option_compile_args(opts)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700235 if mode is CompileCheckMode.LINK:
236 args.extend(self.compiler.get_option_link_args(opts))
237 args.extend(extra_args)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400238 return args
239
Dylan Baker272674e2021-07-27 12:59:56 -0700240 def _determine_dependencies(self, deps: T.List['dependencies.Dependency'], endl: str = ':') -> T.Tuple[T.List['dependencies.Dependency'], str]:
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700241 if deps:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400242 final_deps = []
243 while deps:
244 next_deps = []
Daniel Mensinger7c757df2021-06-17 00:27:39 +0200245 for d in mesonlib.listify(deps):
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400246 if not isinstance(d, dependencies.Dependency) or d.is_built():
247 raise InterpreterException('Dependencies must be external dependencies')
248 final_deps.append(d)
249 next_deps.extend(d.ext_deps)
250 deps = next_deps
251 deps = final_deps
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700252 else:
Christian Claussa5020852021-10-01 00:03:23 +0200253 # Ensure that we always return a new instance
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700254 deps = deps.copy()
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400255 return deps, self._dep_msg(deps, endl)
256
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700257 @typed_pos_args('compiler.alignment', str)
258 @typed_kwargs(
259 'compiler.alignment',
260 _PREFIX_KW,
261 _ARGS_KW,
262 _DEPENDENCIES_KW,
263 )
264 def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400265 typename = args[0]
Dylan Baker272674e2021-07-27 12:59:56 -0700266 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700267 result = self.compiler.alignment(typename, kwargs['prefix'], self.environment,
268 extra_args=kwargs['args'],
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400269 dependencies=deps)
270 mlog.log('Checking for alignment of', mlog.bold(typename, True), msg, result)
271 return result
272
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700273 @typed_pos_args('compiler.run', (str, mesonlib.File))
274 @typed_kwargs('compiler.run', *_COMPILES_KWS)
275 def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult':
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400276 code = args[0]
277 if isinstance(code, mesonlib.File):
278 code = mesonlib.File.from_absolute_file(
279 code.rel_to_builddir(self.environment.source_dir))
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700280 testname = kwargs['name']
Dylan Baker272674e2021-07-27 12:59:56 -0700281 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
282 deps, msg = self._determine_dependencies(kwargs['dependencies'], endl=None)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400283 result = self.compiler.run(code, self.environment, extra_args=extra_args,
284 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700285 if testname:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400286 if not result.compiled:
287 h = mlog.red('DID NOT COMPILE')
288 elif result.returncode == 0:
289 h = mlog.green('YES')
290 else:
291 h = mlog.red('NO (%d)' % result.returncode)
292 mlog.log('Checking if', mlog.bold(testname, True), msg, 'runs:', h)
Daniel Mensinger7c757df2021-06-17 00:27:39 +0200293 return result
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400294
295 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700296 @noKwargs
Dylan Baker7dda90f2021-07-26 14:58:24 -0700297 def get_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400298 return self.compiler.get_id()
299
300 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700301 @noKwargs
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400302 @FeatureNew('compiler.get_linker_id', '0.53.0')
Dylan Baker7dda90f2021-07-26 14:58:24 -0700303 def get_linker_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400304 return self.compiler.get_linker_id()
305
306 @noPosargs
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700307 @noKwargs
Dylan Baker7dda90f2021-07-26 14:58:24 -0700308 def symbols_have_underscore_prefix_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400309 '''
310 Check if the compiler prefixes _ (underscore) to global C symbols
311 See: https://en.wikipedia.org/wiki/Name_mangling#C
312 '''
313 return self.compiler.symbols_have_underscore_prefix(self.environment)
314
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700315 @typed_pos_args('compiler.has_member', str, str)
316 @typed_kwargs('compiler.has_member', *_COMMON_KWS)
317 def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400318 typename, membername = args
Dylan Baker272674e2021-07-27 12:59:56 -0700319 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
320 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700321 had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'],
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400322 self.environment,
323 extra_args=extra_args,
324 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700325 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400326 if had:
327 hadtxt = mlog.green('YES')
328 else:
329 hadtxt = mlog.red('NO')
330 mlog.log('Checking whether type', mlog.bold(typename, True),
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700331 'has member', mlog.bold(membername, True), msg, hadtxt, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400332 return had
333
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700334 @typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1)
335 @typed_kwargs('compiler.has_members', *_COMMON_KWS)
336 def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'CommonKW') -> bool:
337 typename, membernames = args
Dylan Baker272674e2021-07-27 12:59:56 -0700338 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
339 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700340 had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'],
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400341 self.environment,
342 extra_args=extra_args,
343 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700344 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400345 if had:
346 hadtxt = mlog.green('YES')
347 else:
348 hadtxt = mlog.red('NO')
349 members = mlog.bold(', '.join([f'"{m}"' for m in membernames]))
350 mlog.log('Checking whether type', mlog.bold(typename, True),
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700351 'has members', members, msg, hadtxt, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400352 return had
353
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700354 @typed_pos_args('compiler.has_function', str)
Daniel Mensingerc10e2282021-08-21 16:28:39 +0200355 @typed_kwargs('compiler.has_function', *_COMMON_KWS)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700356 def has_function_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400357 funcname = args[0]
Dylan Baker272674e2021-07-27 12:59:56 -0700358 extra_args = self._determine_args(kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
359 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700360 had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400361 extra_args=extra_args,
362 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700363 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400364 if had:
365 hadtxt = mlog.green('YES')
366 else:
367 hadtxt = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700368 mlog.log('Checking for function', mlog.bold(funcname, True), msg, hadtxt, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400369 return had
370
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700371 @typed_pos_args('compiler.has_type', str)
372 @typed_kwargs('compiler.has_type', *_COMMON_KWS)
373 def has_type_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400374 typename = args[0]
Dylan Baker272674e2021-07-27 12:59:56 -0700375 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
376 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700377 had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400378 extra_args=extra_args, dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700379 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400380 if had:
381 hadtxt = mlog.green('YES')
382 else:
383 hadtxt = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700384 mlog.log('Checking for type', mlog.bold(typename, True), msg, hadtxt, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400385 return had
386
387 @FeatureNew('compiler.compute_int', '0.40.0')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700388 @typed_pos_args('compiler.compute_int', str)
389 @typed_kwargs(
390 'compiler.compute_int',
Dylan Baker11fbaf22021-08-27 11:47:12 -0700391 KwargInfo('low', (int, NoneType)),
392 KwargInfo('high', (int, NoneType)),
393 KwargInfo('guess', (int, NoneType)),
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700394 *_COMMON_KWS,
395 )
396 def compute_int_method(self, args: T.Tuple[str], kwargs: 'CompupteIntKW') -> int:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400397 expression = args[0]
Dylan Baker272674e2021-07-27 12:59:56 -0700398 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
399 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700400 res = self.compiler.compute_int(expression, kwargs['low'], kwargs['high'],
401 kwargs['guess'], kwargs['prefix'],
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400402 self.environment, extra_args=extra_args,
403 dependencies=deps)
404 mlog.log('Computing int of', mlog.bold(expression, True), msg, res)
405 return res
406
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700407 @typed_pos_args('compiler.sizeof', str)
408 @typed_kwargs('compiler.sizeof', *_COMMON_KWS)
409 def sizeof_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> int:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400410 element = args[0]
Dylan Baker272674e2021-07-27 12:59:56 -0700411 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
412 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700413 esize = self.compiler.sizeof(element, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400414 extra_args=extra_args, dependencies=deps)
415 mlog.log('Checking for size of', mlog.bold(element, True), msg, esize)
416 return esize
417
418 @FeatureNew('compiler.get_define', '0.40.0')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700419 @typed_pos_args('compiler.get_define', str)
420 @typed_kwargs('compiler.get_define', *_COMMON_KWS)
421 def get_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> str:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400422 element = args[0]
Dylan Baker272674e2021-07-27 12:59:56 -0700423 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
424 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700425 value, cached = self.compiler.get_define(element, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400426 extra_args=extra_args,
427 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700428 cached_msg = mlog.blue('(cached)') if cached else ''
429 mlog.log('Fetching value of define', mlog.bold(element, True), msg, value, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400430 return value
431
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700432 @typed_pos_args('compiler.compiles', (str, mesonlib.File))
433 @typed_kwargs('compiler.compiles', *_COMPILES_KWS)
434 def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400435 code = args[0]
436 if isinstance(code, mesonlib.File):
437 code = mesonlib.File.from_absolute_file(
438 code.rel_to_builddir(self.environment.source_dir))
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700439 testname = kwargs['name']
Dylan Baker272674e2021-07-27 12:59:56 -0700440 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
441 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400442 result, cached = self.compiler.compiles(code, self.environment,
443 extra_args=extra_args,
444 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700445 if testname:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400446 if result:
447 h = mlog.green('YES')
448 else:
449 h = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700450 cached_msg = mlog.blue('(cached)') if cached else ''
451 mlog.log('Checking if', mlog.bold(testname, True), msg, 'compiles:', h, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400452 return result
453
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700454 @typed_pos_args('compiler.links', (str, mesonlib.File))
455 @typed_kwargs('compiler.links', *_COMPILES_KWS)
456 def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400457 code = args[0]
Paolo Bonzini8596b3b2021-07-22 12:01:01 +0200458 compiler = None
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400459 if isinstance(code, mesonlib.File):
460 code = mesonlib.File.from_absolute_file(
461 code.rel_to_builddir(self.environment.source_dir))
Paolo Bonzini8596b3b2021-07-22 12:01:01 +0200462 suffix = code.suffix
463 if suffix not in self.compiler.file_suffixes:
464 for_machine = self.compiler.for_machine
465 clist = self.interpreter.coredata.compilers[for_machine]
466 if suffix not in SUFFIX_TO_LANG:
467 # just pass it to the compiler driver
468 mlog.warning(f'Unknown suffix for test file {code}')
469 elif SUFFIX_TO_LANG[suffix] not in clist:
470 mlog.warning(f'Passed {SUFFIX_TO_LANG[suffix]} source to links method, not specified for {for_machine.get_lower_case_name()} machine.')
471 else:
472 compiler = clist[SUFFIX_TO_LANG[suffix]]
473
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700474 testname = kwargs['name']
Dylan Baker272674e2021-07-27 12:59:56 -0700475 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
476 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400477 result, cached = self.compiler.links(code, self.environment,
Paolo Bonzini8596b3b2021-07-22 12:01:01 +0200478 compiler=compiler,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400479 extra_args=extra_args,
480 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700481 cached_msg = mlog.blue('(cached)') if cached else ''
482 if testname:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400483 if result:
484 h = mlog.green('YES')
485 else:
486 h = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700487 mlog.log('Checking if', mlog.bold(testname, True), msg, 'links:', h, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400488 return result
489
490 @FeatureNew('compiler.check_header', '0.47.0')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700491 @typed_pos_args('compiler.check_header', str)
492 @typed_kwargs('compiler.check_header', *_HEADER_KWS)
493 def check_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400494 hname = args[0]
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400495 disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
496 if disabled:
497 mlog.log('Check usable header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
498 return False
Dylan Baker272674e2021-07-27 12:59:56 -0700499 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
500 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700501 haz, cached = self.compiler.check_header(hname, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400502 extra_args=extra_args,
503 dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700504 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400505 if required and not haz:
506 raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not usable')
507 elif haz:
508 h = mlog.green('YES')
509 else:
510 h = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700511 mlog.log('Check usable header', mlog.bold(hname, True), msg, h, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400512 return haz
513
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700514 def _has_header_impl(self, hname: str, kwargs: 'HeaderKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400515 disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
516 if disabled:
517 mlog.log('Has header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
518 return False
Dylan Baker272674e2021-07-27 12:59:56 -0700519 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
520 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700521 haz, cached = self.compiler.has_header(hname, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400522 extra_args=extra_args, dependencies=deps)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700523 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400524 if required and not haz:
525 raise InterpreterException(f'{self.compiler.get_display_language()} header {hname!r} not found')
526 elif haz:
527 h = mlog.green('YES')
528 else:
529 h = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700530 mlog.log('Has header', mlog.bold(hname, True), msg, h, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400531 return haz
532
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700533 @typed_pos_args('compiler.has_header', str)
534 @typed_kwargs('compiler.has_header', *_HEADER_KWS)
535 def has_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool:
536 return self._has_header_impl(args[0], kwargs)
537
538 @typed_pos_args('compiler.has_header_symbol', str, str)
539 @typed_kwargs('compiler.has_header_symbol', *_HEADER_KWS)
540 def has_header_symbol_method(self, args: T.Tuple[str, str], kwargs: 'HeaderKW') -> bool:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400541 hname, symbol = args
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400542 disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
543 if disabled:
544 mlog.log(f'Header <{hname}> has symbol', mlog.bold(symbol, True), 'skipped: feature', mlog.bold(feature), 'disabled')
545 return False
Dylan Baker272674e2021-07-27 12:59:56 -0700546 extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
547 deps, msg = self._determine_dependencies(kwargs['dependencies'])
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700548 haz, cached = self.compiler.has_header_symbol(hname, symbol, kwargs['prefix'], self.environment,
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400549 extra_args=extra_args,
550 dependencies=deps)
551 if required and not haz:
552 raise InterpreterException(f'{self.compiler.get_display_language()} symbol {symbol} not found in header {hname}')
553 elif haz:
554 h = mlog.green('YES')
555 else:
556 h = mlog.red('NO')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700557 cached_msg = mlog.blue('(cached)') if cached else ''
558 mlog.log(f'Header <{hname}> has symbol', mlog.bold(symbol, True), msg, h, cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400559 return haz
560
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700561 def notfound_library(self, libname: str) -> 'dependencies.ExternalLibrary':
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400562 lib = dependencies.ExternalLibrary(libname, None,
563 self.environment,
564 self.compiler.language,
565 silent=True)
Daniel Mensinger7c757df2021-06-17 00:27:39 +0200566 return lib
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400567
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400568 @disablerIfNotFound
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700569 @typed_pos_args('compiler.find_library', str)
570 @typed_kwargs(
571 'compiler.find_library',
572 KwargInfo('required', (bool, coredata.UserFeatureOption), default=True),
573 KwargInfo('has_headers', ContainerTypeInfo(list, str), listify=True, default=[], since='0.50.0'),
Dylan Baker11fbaf22021-08-27 11:47:12 -0700574 KwargInfo('static', (bool, NoneType), since='0.51.0'),
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700575 KwargInfo('disabler', bool, default=False, since='0.49.0'),
576 KwargInfo('dirs', ContainerTypeInfo(list, str), listify=True, default=[]),
Eli Schwartze8a85fa2021-08-15 11:08:26 -0400577 *(k.evolve(name=f'header_{k.name}') for k in _HEADER_KWS)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700578 )
579 def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'dependencies.ExternalLibrary':
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400580 # TODO add dependencies support?
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400581 libname = args[0]
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400582
583 disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
584 if disabled:
585 mlog.log('Library', mlog.bold(libname), 'skipped: feature', mlog.bold(feature), 'disabled')
586 return self.notfound_library(libname)
587
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700588 # This could be done with a comprehension, but that confuses the type
589 # checker, and having it check this seems valuable
590 has_header_kwargs: 'HeaderKW' = {
591 'required': required,
592 'args': kwargs['header_args'],
593 'dependencies': kwargs['header_dependencies'],
594 'include_directories': kwargs['header_include_directories'],
595 'prefix': kwargs['header_prefix'],
596 'no_builtin_args': kwargs['header_no_builtin_args'],
597 }
598 for h in kwargs['has_headers']:
599 if not self._has_header_impl(h, has_header_kwargs):
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400600 return self.notfound_library(libname)
601
602 search_dirs = extract_search_dirs(kwargs)
603
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700604 if kwargs['static'] is True:
605 libtype = mesonlib.LibType.STATIC
606 elif kwargs['static'] is False:
607 libtype = mesonlib.LibType.SHARED
608 else:
609 libtype = mesonlib.LibType.PREFER_SHARED
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400610 linkargs = self.compiler.find_library(libname, self.environment, search_dirs, libtype)
611 if required and not linkargs:
612 if libtype == mesonlib.LibType.PREFER_SHARED:
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700613 libtype_s = 'shared or static'
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400614 else:
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700615 libtype_s = libtype.name.lower()
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400616 raise InterpreterException('{} {} library {!r} not found'
617 .format(self.compiler.get_display_language(),
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700618 libtype_s, libname))
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400619 lib = dependencies.ExternalLibrary(libname, linkargs, self.environment,
620 self.compiler.language)
Daniel Mensinger7c757df2021-06-17 00:27:39 +0200621 return lib
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400622
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700623 def _has_argument_impl(self, arguments: T.Union[str, T.List[str]],
624 mode: _TestMode = _TestMode.COMPILER) -> bool:
Christian Claussa5020852021-10-01 00:03:23 +0200625 """Shared implementation for methods checking compiler and linker arguments."""
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700626 # This simplifies the callers
627 if isinstance(arguments, str):
628 arguments = [arguments]
629 test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments
630 result, cached = test(arguments, self.environment)
631 cached_msg = mlog.blue('(cached)') if cached else ''
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400632 mlog.log(
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700633 'Compiler for',
634 self.compiler.get_display_language(),
635 'supports{}'.format(' link' if mode is _TestMode.LINKER else ''),
636 'arguments {}:'.format(' '.join(arguments)),
637 mlog.green('YES') if result else mlog.red('NO'),
638 cached_msg)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400639 return result
640
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700641 @noKwargs
642 @typed_pos_args('compiler.has_argument', str)
643 def has_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
644 return self._has_argument_impl([args[0]])
645
646 @noKwargs
647 @typed_pos_args('compiler.has_multi_arguments', varargs=str)
Daniel Mensingerc10e2282021-08-21 16:28:39 +0200648 @FeatureNew('compiler.has_multi_arguments', '0.37.0')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700649 def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool:
650 return self._has_argument_impl(args[0])
651
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400652 @FeatureNew('compiler.get_supported_arguments', '0.43.0')
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700653 @typed_pos_args('compiler.get_supported_arguments', varargs=str)
Laurin-Luis Lehning281f5ab2021-06-22 07:59:08 +0200654 @typed_kwargs(
655 'compiler.get_supported_arguments',
656 KwargInfo('checked', str, default='off', since='0.59.0',
Dylan Bakeraa895b32021-08-23 14:07:57 -0700657 validator=in_set_validator({'warn', 'require', 'off'})),
Laurin-Luis Lehning281f5ab2021-06-22 07:59:08 +0200658 )
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700659 def get_supported_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'GetSupportedArgumentKw') -> T.List[str]:
660 supported_args: T.List[str] = []
661 checked = kwargs['checked']
Laurin-Luis Lehningd5ed8f62021-06-18 01:42:57 +0200662
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700663 for arg in args[0]:
664 if not self._has_argument_impl([arg]):
Laurin-Luis Lehningd5ed8f62021-06-18 01:42:57 +0200665 msg = f'Compiler for {self.compiler.get_display_language()} does not support "{arg}"'
666 if checked == 'warn':
667 mlog.warning(msg)
668 elif checked == 'require':
669 raise mesonlib.MesonException(msg)
670 else:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400671 supported_args.append(arg)
672 return supported_args
673
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700674 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700675 @typed_pos_args('compiler.first_supported_argument', varargs=str)
676 def first_supported_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
677 for arg in args[0]:
678 if self._has_argument_impl([arg]):
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400679 mlog.log('First supported argument:', mlog.bold(arg))
680 return [arg]
681 mlog.log('First supported argument:', mlog.red('None'))
682 return []
683
684 @FeatureNew('compiler.has_link_argument', '0.46.0')
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700685 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700686 @typed_pos_args('compiler.has_link_argument', str)
687 def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
688 return self._has_argument_impl([args[0]], mode=_TestMode.LINKER)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400689
690 @FeatureNew('compiler.has_multi_link_argument', '0.46.0')
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700691 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700692 @typed_pos_args('compiler.has_multi_link_argument', varargs=str)
693 def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool:
694 return self._has_argument_impl(args[0], mode=_TestMode.LINKER)
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400695
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700696 @FeatureNew('compiler.get_supported_link_arguments', '0.46.0')
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700697 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700698 @typed_pos_args('compiler.get_supported_link_arguments', varargs=str)
699 def get_supported_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
700 supported_args: T.List[str] = []
701 for arg in args[0]:
702 if self._has_argument_impl([arg], mode=_TestMode.LINKER):
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400703 supported_args.append(arg)
704 return supported_args
705
706 @FeatureNew('compiler.first_supported_link_argument_method', '0.46.0')
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700707 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700708 @typed_pos_args('compiler.first_supported_link_argument', varargs=str)
709 def first_supported_link_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
710 for arg in args[0]:
711 if self._has_argument_impl([arg], mode=_TestMode.LINKER):
712 mlog.log('First supported link argument:', mlog.bold(arg))
713 return [arg]
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400714 mlog.log('First supported link argument:', mlog.red('None'))
715 return []
716
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700717 def _has_function_attribute_impl(self, attr: str) -> bool:
718 """Common helper for function attribute testing."""
719 result, cached = self.compiler.has_func_attribute(attr, self.environment)
720 cached_msg = mlog.blue('(cached)') if cached else ''
721 h = mlog.green('YES') if result else mlog.red('NO')
Eli Schwartzd06cc042021-07-08 00:06:10 -0400722 mlog.log(f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:', h, cached_msg)
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700723 return result
724
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400725 @FeatureNew('compiler.has_function_attribute', '0.48.0')
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700726 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700727 @typed_pos_args('compiler.has_function_attribute', str)
728 def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
729 return self._has_function_attribute_impl(args[0])
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400730
731 @FeatureNew('compiler.get_supported_function_attributes', '0.48.0')
Dylan Baker32d3b5c2021-07-22 09:21:57 -0700732 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700733 @typed_pos_args('compiler.get_supported_function_attributes', varargs=str)
734 def get_supported_function_attributes_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
735 return [a for a in args[0] if self._has_function_attribute_impl(a)]
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400736
737 @FeatureNew('compiler.get_argument_syntax_method', '0.49.0')
738 @noPosargs
739 @noKwargs
Dylan Bakerb30dddd2021-07-26 14:16:31 -0700740 def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
Xavier Claessens558a7bc2021-04-01 08:18:44 -0400741 return self.compiler.get_argument_syntax()