1# Copyright 2012-2019 The Meson development team 2 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6 7# http://www.apache.org/licenses/LICENSE-2.0 8 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import abc 16import contextlib, os.path, re 17import enum 18import itertools 19import typing as T 20from functools import lru_cache 21 22from .. import coredata 23from .. import mlog 24from .. import mesonlib 25from ..mesonlib import ( 26 HoldableObject, 27 EnvironmentException, MachineChoice, MesonException, 28 Popen_safe, LibType, TemporaryDirectoryWinProof, OptionKey, 29) 30 31from ..arglist import CompilerArgs 32 33if T.TYPE_CHECKING: 34 from ..build import BuildTarget 35 from ..coredata import KeyedOptionDictType 36 from ..envconfig import MachineInfo 37 from ..environment import Environment 38 from ..linkers import DynamicLinker, RSPFileSyntax 39 from ..dependencies import Dependency 40 41 CompilerType = T.TypeVar('CompilerType', bound='Compiler') 42 _T = T.TypeVar('_T') 43 44"""This file contains the data files of all compilers Meson knows 45about. To support a new compiler, add its information below. 46Also add corresponding autodetection code in environment.py.""" 47 48header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di') # type: T.Tuple[str, ...] 49obj_suffixes = ('o', 'obj', 'res') # type: T.Tuple[str, ...] 50# To the emscripten compiler, .js files are libraries 51lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so', 'js') # type: T.Tuple[str, ...] 52# Mapping of language to suffixes of files that should always be in that language 53# This means we can't include .h headers here since they could be C, C++, ObjC, etc. 54lang_suffixes = { 55 'c': ('c',), 56 'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino', 'ixx', 'C'), 57 'cuda': ('cu',), 58 # f90, f95, f03, f08 are for free-form fortran ('f90' recommended) 59 # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended) 60 'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'), 61 'd': ('d', 'di'), 62 'objc': ('m',), 63 'objcpp': ('mm',), 64 'rust': ('rs',), 65 'vala': ('vala', 'vapi', 'gs'), 66 'cs': ('cs',), 67 'swift': ('swift',), 68 'java': ('java',), 69 'cython': ('pyx', ), 70} # type: T.Dict[str, T.Tuple[str, ...]] 71all_languages = lang_suffixes.keys() 72cpp_suffixes = lang_suffixes['cpp'] + ('h',) # type: T.Tuple[str, ...] 73c_suffixes = lang_suffixes['c'] + ('h',) # type: T.Tuple[str, ...] 74# List of languages that by default consume and output libraries following the 75# C ABI; these can generally be used interchangeably 76clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',) # type: T.Tuple[str, ...] 77# List of assembler suffixes that can be linked with C code directly by the linker 78assembler_suffixes: T.Tuple[str, ...] = ('s', 'S') 79# List of languages that can be linked with C code directly by the linker 80# used in build.py:process_compilers() and build.py:get_dynamic_linker() 81clink_langs = ('d', 'cuda') + clib_langs # type: T.Tuple[str, ...] 82clink_suffixes = tuple() # type: T.Tuple[str, ...] 83for _l in clink_langs + ('vala',): 84 clink_suffixes += lang_suffixes[_l] 85clink_suffixes += ('h', 'll', 's') 86all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes)) # type: T.Set[str] 87SUFFIX_TO_LANG = dict(itertools.chain(*( 88 [(suffix, lang) for suffix in v] for lang, v in lang_suffixes.items()))) # type: T.Dict[str, str] 89 90# Languages that should use LDFLAGS arguments when linking. 91LANGUAGES_USING_LDFLAGS = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'} # type: T.Set[str] 92# Languages that should use CPPFLAGS arguments when linking. 93LANGUAGES_USING_CPPFLAGS = {'c', 'cpp', 'objc', 'objcpp'} # type: T.Set[str] 94soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$') 95 96# Environment variables that each lang uses. 97CFLAGS_MAPPING: T.Mapping[str, str] = { 98 'c': 'CFLAGS', 99 'cpp': 'CXXFLAGS', 100 'cuda': 'CUFLAGS', 101 'objc': 'OBJCFLAGS', 102 'objcpp': 'OBJCXXFLAGS', 103 'fortran': 'FFLAGS', 104 'd': 'DFLAGS', 105 'vala': 'VALAFLAGS', 106 'rust': 'RUSTFLAGS', 107 'cython': 'CYTHONFLAGS', 108} 109 110CEXE_MAPPING: T.Mapping = { 111 'c': 'CC', 112 'cpp': 'CXX', 113} 114 115# All these are only for C-linkable languages; see `clink_langs` above. 116 117def sort_clink(lang: str) -> int: 118 ''' 119 Sorting function to sort the list of languages according to 120 reversed(compilers.clink_langs) and append the unknown langs in the end. 121 The purpose is to prefer C over C++ for files that can be compiled by 122 both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc. 123 ''' 124 if lang not in clink_langs: 125 return 1 126 return -clink_langs.index(lang) 127 128def is_header(fname: 'mesonlib.FileOrString') -> bool: 129 if isinstance(fname, mesonlib.File): 130 fname = fname.fname 131 suffix = fname.split('.')[-1] 132 return suffix in header_suffixes 133 134def is_source(fname: 'mesonlib.FileOrString') -> bool: 135 if isinstance(fname, mesonlib.File): 136 fname = fname.fname 137 suffix = fname.split('.')[-1].lower() 138 return suffix in clink_suffixes 139 140def is_assembly(fname: 'mesonlib.FileOrString') -> bool: 141 if isinstance(fname, mesonlib.File): 142 fname = fname.fname 143 return fname.split('.')[-1].lower() == 's' 144 145def is_llvm_ir(fname: 'mesonlib.FileOrString') -> bool: 146 if isinstance(fname, mesonlib.File): 147 fname = fname.fname 148 return fname.split('.')[-1] == 'll' 149 150@lru_cache(maxsize=None) 151def cached_by_name(fname: 'mesonlib.FileOrString') -> bool: 152 suffix = fname.split('.')[-1] 153 return suffix in obj_suffixes 154 155def is_object(fname: 'mesonlib.FileOrString') -> bool: 156 if isinstance(fname, mesonlib.File): 157 fname = fname.fname 158 return cached_by_name(fname) 159 160def is_library(fname: 'mesonlib.FileOrString') -> bool: 161 if isinstance(fname, mesonlib.File): 162 fname = fname.fname 163 164 if soregex.match(fname): 165 return True 166 167 suffix = fname.split('.')[-1] 168 return suffix in lib_suffixes 169 170def is_known_suffix(fname: 'mesonlib.FileOrString') -> bool: 171 if isinstance(fname, mesonlib.File): 172 fname = fname.fname 173 suffix = fname.split('.')[-1] 174 175 return suffix in all_suffixes 176 177 178class CompileCheckMode(enum.Enum): 179 180 PREPROCESS = 'preprocess' 181 COMPILE = 'compile' 182 LINK = 'link' 183 184 185cuda_buildtype_args = {'plain': [], 186 'debug': ['-g', '-G'], 187 'debugoptimized': ['-g', '-lineinfo'], 188 'release': [], 189 'minsize': [], 190 'custom': [], 191 } # type: T.Dict[str, T.List[str]] 192java_buildtype_args = {'plain': [], 193 'debug': ['-g'], 194 'debugoptimized': ['-g'], 195 'release': [], 196 'minsize': [], 197 'custom': [], 198 } # type: T.Dict[str, T.List[str]] 199 200rust_buildtype_args = {'plain': [], 201 'debug': [], 202 'debugoptimized': [], 203 'release': [], 204 'minsize': [], 205 'custom': [], 206 } # type: T.Dict[str, T.List[str]] 207 208d_gdc_buildtype_args = {'plain': [], 209 'debug': [], 210 'debugoptimized': ['-finline-functions'], 211 'release': ['-finline-functions'], 212 'minsize': [], 213 'custom': [], 214 } # type: T.Dict[str, T.List[str]] 215 216d_ldc_buildtype_args = {'plain': [], 217 'debug': [], 218 'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'], 219 'release': ['-enable-inlining', '-Hkeep-all-bodies'], 220 'minsize': [], 221 'custom': [], 222 } # type: T.Dict[str, T.List[str]] 223 224d_dmd_buildtype_args = {'plain': [], 225 'debug': [], 226 'debugoptimized': ['-inline'], 227 'release': ['-inline'], 228 'minsize': [], 229 'custom': [], 230 } # type: T.Dict[str, T.List[str]] 231 232mono_buildtype_args = {'plain': [], 233 'debug': [], 234 'debugoptimized': ['-optimize+'], 235 'release': ['-optimize+'], 236 'minsize': [], 237 'custom': [], 238 } # type: T.Dict[str, T.List[str]] 239 240swift_buildtype_args = {'plain': [], 241 'debug': [], 242 'debugoptimized': [], 243 'release': [], 244 'minsize': [], 245 'custom': [], 246 } # type: T.Dict[str, T.List[str]] 247 248gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32', 249 '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32'] # type: T.List[str] 250 251msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib', 252 'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib', 253 'uuid.lib', 'comdlg32.lib', 'advapi32.lib'] # type: T.List[str] 254 255clike_optimization_args = {'0': [], 256 'g': [], 257 '1': ['-O1'], 258 '2': ['-O2'], 259 '3': ['-O3'], 260 's': ['-Os'], 261 } # type: T.Dict[str, T.List[str]] 262 263cuda_optimization_args = {'0': [], 264 'g': ['-O0'], 265 '1': ['-O1'], 266 '2': ['-O2'], 267 '3': ['-O3'], 268 's': ['-O3'] 269 } # type: T.Dict[str, T.List[str]] 270 271cuda_debug_args = {False: [], 272 True: ['-g']} # type: T.Dict[bool, T.List[str]] 273 274clike_debug_args = {False: [], 275 True: ['-g']} # type: T.Dict[bool, T.List[str]] 276 277base_options: 'KeyedOptionDictType' = { 278 OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True), 279 OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), 280 OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), 281 OptionKey('b_lto_threads'): coredata.UserIntegerOption('Use multiple threads for Link Time Optimization', (None, None, 0)), 282 OptionKey('b_lto_mode'): coredata.UserComboOption('Select between different LTO modes.', 283 ['default', 'thin'], 284 'default'), 285 OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use', 286 ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'], 287 'none'), 288 OptionKey('b_lundef'): coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True), 289 OptionKey('b_asneeded'): coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True), 290 OptionKey('b_pgo'): coredata.UserComboOption('Use profile guided optimization', 291 ['off', 'generate', 'use'], 292 'off'), 293 OptionKey('b_coverage'): coredata.UserBooleanOption('Enable coverage tracking.', False), 294 OptionKey('b_colorout'): coredata.UserComboOption('Use colored output', 295 ['auto', 'always', 'never'], 296 'always'), 297 OptionKey('b_ndebug'): coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'), 298 OptionKey('b_staticpic'): coredata.UserBooleanOption('Build static libraries as position independent', True), 299 OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False), 300 OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False), 301 OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.', 302 ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype', 'static_from_buildtype'], 303 'from_buildtype'), 304} 305 306def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType', 307 option: OptionKey) -> bool: 308 try: 309 if option not in boptions: 310 return False 311 ret = options[option].value 312 assert isinstance(ret, bool), 'must return bool' # could also be str 313 return ret 314 except KeyError: 315 return False 316 317 318def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '_T') -> '_T': 319 """Get the value of an option, or the fallback value.""" 320 try: 321 v: '_T' = options[opt].value 322 except KeyError: 323 return fallback 324 325 assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}' 326 # Mypy doesn't understand that the above assert ensures that v is type _T 327 return v 328 329 330def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]: 331 args = [] # type T.List[str] 332 try: 333 if options[OptionKey('b_lto')].value: 334 args.extend(compiler.get_lto_compile_args( 335 threads=get_option_value(options, OptionKey('b_lto_threads'), 0), 336 mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'))) 337 except KeyError: 338 pass 339 try: 340 args += compiler.get_colorout_args(options[OptionKey('b_colorout')].value) 341 except KeyError: 342 pass 343 try: 344 args += compiler.sanitizer_compile_args(options[OptionKey('b_sanitize')].value) 345 except KeyError: 346 pass 347 try: 348 pgo_val = options[OptionKey('b_pgo')].value 349 if pgo_val == 'generate': 350 args.extend(compiler.get_profile_generate_args()) 351 elif pgo_val == 'use': 352 args.extend(compiler.get_profile_use_args()) 353 except KeyError: 354 pass 355 try: 356 if options[OptionKey('b_coverage')].value: 357 args += compiler.get_coverage_args() 358 except KeyError: 359 pass 360 try: 361 if (options[OptionKey('b_ndebug')].value == 'true' or 362 (options[OptionKey('b_ndebug')].value == 'if-release' and 363 options[OptionKey('buildtype')].value in {'release', 'plain'})): 364 args += compiler.get_disable_assert_args() 365 except KeyError: 366 pass 367 # This does not need a try...except 368 if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')): 369 args.append('-fembed-bitcode') 370 try: 371 crt_val = options[OptionKey('b_vscrt')].value 372 buildtype = options[OptionKey('buildtype')].value 373 try: 374 args += compiler.get_crt_compile_args(crt_val, buildtype) 375 except AttributeError: 376 pass 377 except KeyError: 378 pass 379 return args 380 381def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler', 382 is_shared_module: bool) -> T.List[str]: 383 args = [] # type: T.List[str] 384 try: 385 if options[OptionKey('b_lto')].value: 386 args.extend(linker.get_lto_link_args( 387 threads=get_option_value(options, OptionKey('b_lto_threads'), 0), 388 mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'))) 389 except KeyError: 390 pass 391 try: 392 args += linker.sanitizer_link_args(options[OptionKey('b_sanitize')].value) 393 except KeyError: 394 pass 395 try: 396 pgo_val = options[OptionKey('b_pgo')].value 397 if pgo_val == 'generate': 398 args.extend(linker.get_profile_generate_args()) 399 elif pgo_val == 'use': 400 args.extend(linker.get_profile_use_args()) 401 except KeyError: 402 pass 403 try: 404 if options[OptionKey('b_coverage')].value: 405 args += linker.get_coverage_link_args() 406 except KeyError: 407 pass 408 409 as_needed = option_enabled(linker.base_options, options, OptionKey('b_asneeded')) 410 bitcode = option_enabled(linker.base_options, options, OptionKey('b_bitcode')) 411 # Shared modules cannot be built with bitcode_bundle because 412 # -bitcode_bundle is incompatible with -undefined and -bundle 413 if bitcode and not is_shared_module: 414 args.extend(linker.bitcode_args()) 415 elif as_needed: 416 # -Wl,-dead_strip_dylibs is incompatible with bitcode 417 args.extend(linker.get_asneeded_args()) 418 419 # Apple's ld (the only one that supports bitcode) does not like -undefined 420 # arguments or -headerpad_max_install_names when bitcode is enabled 421 if not bitcode: 422 args.extend(linker.headerpad_args()) 423 if (not is_shared_module and 424 option_enabled(linker.base_options, options, OptionKey('b_lundef'))): 425 args.extend(linker.no_undefined_link_args()) 426 else: 427 args.extend(linker.get_allow_undefined_link_args()) 428 429 try: 430 crt_val = options[OptionKey('b_vscrt')].value 431 buildtype = options[OptionKey('buildtype')].value 432 try: 433 args += linker.get_crt_link_args(crt_val, buildtype) 434 except AttributeError: 435 pass 436 except KeyError: 437 pass 438 return args 439 440 441class CrossNoRunException(MesonException): 442 pass 443 444class RunResult(HoldableObject): 445 def __init__(self, compiled: bool, returncode: int = 999, 446 stdout: str = 'UNDEFINED', stderr: str = 'UNDEFINED'): 447 self.compiled = compiled 448 self.returncode = returncode 449 self.stdout = stdout 450 self.stderr = stderr 451 452 453class CompileResult(HoldableObject): 454 455 """The result of Compiler.compiles (and friends).""" 456 457 def __init__(self, stdo: T.Optional[str] = None, stde: T.Optional[str] = None, 458 args: T.Optional[T.List[str]] = None, 459 returncode: int = 999, pid: int = -1, 460 text_mode: bool = True, 461 input_name: T.Optional[str] = None, 462 output_name: T.Optional[str] = None, 463 command: T.Optional[T.List[str]] = None, cached: bool = False): 464 self.stdout = stdo 465 self.stderr = stde 466 self.input_name = input_name 467 self.output_name = output_name 468 self.command = command or [] 469 self.args = args or [] 470 self.cached = cached 471 self.returncode = returncode 472 self.pid = pid 473 self.text_mode = text_mode 474 475 476class Compiler(HoldableObject, metaclass=abc.ABCMeta): 477 # Libraries to ignore in find_library() since they are provided by the 478 # compiler or the C library. Currently only used for MSVC. 479 ignore_libs = [] # type: T.List[str] 480 # Libraries that are internal compiler implementations, and must not be 481 # manually searched. 482 internal_libs = [] # type: T.List[str] 483 484 LINKER_PREFIX = None # type: T.Union[None, str, T.List[str]] 485 INVOKES_LINKER = True 486 487 # TODO: these could be forward declarations once we drop 3.5 support 488 if T.TYPE_CHECKING: 489 language = 'unset' 490 id = '' 491 warn_args = {} # type: T.Dict[str, T.List[str]] 492 493 def __init__(self, exelist: T.List[str], version: str, 494 for_machine: MachineChoice, info: 'MachineInfo', 495 linker: T.Optional['DynamicLinker'] = None, 496 full_version: T.Optional[str] = None, is_cross: bool = False): 497 self.exelist = exelist 498 # In case it's been overridden by a child class already 499 if not hasattr(self, 'file_suffixes'): 500 self.file_suffixes = lang_suffixes[self.language] 501 if not hasattr(self, 'can_compile_suffixes'): 502 self.can_compile_suffixes = set(self.file_suffixes) 503 self.default_suffix = self.file_suffixes[0] 504 self.version = version 505 self.full_version = full_version 506 self.for_machine = for_machine 507 self.base_options: T.Set[OptionKey] = set() 508 self.linker = linker 509 self.info = info 510 self.is_cross = is_cross 511 512 def __repr__(self) -> str: 513 repr_str = "<{0}: v{1} `{2}`>" 514 return repr_str.format(self.__class__.__name__, self.version, 515 ' '.join(self.exelist)) 516 517 @lru_cache(maxsize=None) 518 def can_compile(self, src: 'mesonlib.FileOrString') -> bool: 519 if isinstance(src, mesonlib.File): 520 src = src.fname 521 suffix = os.path.splitext(src)[1] 522 if suffix != '.C': 523 suffix = suffix.lower() 524 return bool(suffix) and suffix[1:] in self.can_compile_suffixes 525 526 def get_id(self) -> str: 527 return self.id 528 529 def get_linker_id(self) -> str: 530 # There is not guarantee that we have a dynamic linker instance, as 531 # some languages don't have separate linkers and compilers. In those 532 # cases return the compiler id 533 try: 534 return self.linker.id 535 except AttributeError: 536 return self.id 537 538 def get_version_string(self) -> str: 539 details = [self.id, self.version] 540 if self.full_version: 541 details += ['"%s"' % (self.full_version)] 542 return '(%s)' % (' '.join(details)) 543 544 def get_language(self) -> str: 545 return self.language 546 547 @classmethod 548 def get_display_language(cls) -> str: 549 return cls.language.capitalize() 550 551 def get_default_suffix(self) -> str: 552 return self.default_suffix 553 554 def get_define(self, dname: str, prefix: str, env: 'Environment', 555 extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], 556 dependencies: T.List['Dependency'], 557 disable_cache: bool = False) -> T.Tuple[str, bool]: 558 raise EnvironmentException('%s does not support get_define ' % self.get_id()) 559 560 def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int], 561 guess: T.Optional[int], prefix: str, env: 'Environment', *, 562 extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], 563 dependencies: T.Optional[T.List['Dependency']]) -> int: 564 raise EnvironmentException('%s does not support compute_int ' % self.get_id()) 565 566 def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], 567 build_dir: str) -> T.List[str]: 568 raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id()) 569 570 def has_members(self, typename: str, membernames: T.List[str], 571 prefix: str, env: 'Environment', *, 572 extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, 573 dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: 574 raise EnvironmentException('%s does not support has_member(s) ' % self.get_id()) 575 576 def has_type(self, typename: str, prefix: str, env: 'Environment', 577 extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *, 578 dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: 579 raise EnvironmentException('%s does not support has_type ' % self.get_id()) 580 581 def symbols_have_underscore_prefix(self, env: 'Environment') -> bool: 582 raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id()) 583 584 def get_exelist(self) -> T.List[str]: 585 return self.exelist.copy() 586 587 def get_linker_exelist(self) -> T.List[str]: 588 return self.linker.get_exelist() 589 590 @abc.abstractmethod 591 def get_output_args(self, outputname: str) -> T.List[str]: 592 pass 593 594 def get_linker_output_args(self, outputname: str) -> T.List[str]: 595 return self.linker.get_output_args(outputname) 596 597 def get_linker_search_args(self, dirname: str) -> T.List[str]: 598 return self.linker.get_search_args(dirname) 599 600 def get_builtin_define(self, define: str) -> T.Optional[str]: 601 raise EnvironmentException('%s does not support get_builtin_define.' % self.id) 602 603 def has_builtin_define(self, define: str) -> bool: 604 raise EnvironmentException('%s does not support has_builtin_define.' % self.id) 605 606 def get_always_args(self) -> T.List[str]: 607 return [] 608 609 def can_linker_accept_rsp(self) -> bool: 610 """ 611 Determines whether the linker can accept arguments using the @rsp syntax. 612 """ 613 return self.linker.get_accepts_rsp() 614 615 def get_linker_always_args(self) -> T.List[str]: 616 return self.linker.get_always_args() 617 618 def get_linker_lib_prefix(self) -> str: 619 return self.linker.get_lib_prefix() 620 621 def gen_import_library_args(self, implibname: str) -> T.List[str]: 622 """ 623 Used only on Windows for libraries that need an import library. 624 This currently means C, C++, Fortran. 625 """ 626 return [] 627 628 def get_options(self) -> 'KeyedOptionDictType': 629 return {} 630 631 def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 632 return [] 633 634 def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 635 return self.linker.get_option_args(options) 636 637 def check_header(self, hname: str, prefix: str, env: 'Environment', *, 638 extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, 639 dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: 640 """Check that header is usable. 641 642 Returns a two item tuple of bools. The first bool is whether the 643 check succeeded, the second is whether the result was cached (True) 644 or run fresh (False). 645 """ 646 raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) 647 648 def has_header(self, hname: str, prefix: str, env: 'Environment', *, 649 extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, 650 dependencies: T.Optional[T.List['Dependency']] = None, 651 disable_cache: bool = False) -> T.Tuple[bool, bool]: 652 """Check that header is exists. 653 654 This check will return true if the file exists, even if it contains: 655 656 ```c 657 # error "You thought you could use this, LOLZ!" 658 ``` 659 660 Use check_header if your header only works in some cases. 661 662 Returns a two item tuple of bools. The first bool is whether the 663 check succeeded, the second is whether the result was cached (True) 664 or run fresh (False). 665 """ 666 raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language()) 667 668 def has_header_symbol(self, hname: str, symbol: str, prefix: str, 669 env: 'Environment', *, 670 extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, 671 dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: 672 raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language()) 673 674 def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *, 675 extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None, 676 dependencies: T.Optional[T.List['Dependency']] = None) -> RunResult: 677 raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language()) 678 679 def sizeof(self, typename: str, prefix: str, env: 'Environment', *, 680 extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, 681 dependencies: T.Optional[T.List['Dependency']] = None) -> int: 682 raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language()) 683 684 def alignment(self, typename: str, prefix: str, env: 'Environment', *, 685 extra_args: T.Optional[T.List[str]] = None, 686 dependencies: T.Optional[T.List['Dependency']] = None) -> int: 687 raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language()) 688 689 def has_function(self, funcname: str, prefix: str, env: 'Environment', *, 690 extra_args: T.Optional[T.List[str]] = None, 691 dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]: 692 """See if a function exists. 693 694 Returns a two item tuple of bools. The first bool is whether the 695 check succeeded, the second is whether the result was cached (True) 696 or run fresh (False). 697 """ 698 raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language()) 699 700 def unix_args_to_native(self, args: T.List[str]) -> T.List[str]: 701 "Always returns a copy that can be independently mutated" 702 return args.copy() 703 704 @classmethod 705 def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]: 706 "Always returns a copy that can be independently mutated" 707 return args.copy() 708 709 def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str], 710 libtype: LibType = LibType.PREFER_SHARED) -> T.Optional[T.List[str]]: 711 raise EnvironmentException(f'Language {self.get_display_language()} does not support library finding.') 712 713 def get_library_naming(self, env: 'Environment', libtype: LibType, 714 strict: bool = False) -> T.Optional[T.Tuple[str, ...]]: 715 raise EnvironmentException( 716 'Language {} does not support get_library_naming.'.format( 717 self.get_display_language())) 718 719 def get_program_dirs(self, env: 'Environment') -> T.List[str]: 720 return [] 721 722 def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: 723 raise EnvironmentException( 724 'Language {} does not support has_multi_arguments.'.format( 725 self.get_display_language())) 726 727 def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]: 728 return self.linker.has_multi_arguments(args, env) 729 730 def _get_compile_output(self, dirname: str, mode: str) -> str: 731 # TODO: mode should really be an enum 732 # In pre-processor mode, the output is sent to stdout and discarded 733 if mode == 'preprocess': 734 return None 735 # Extension only matters if running results; '.exe' is 736 # guaranteed to be executable on every platform. 737 if mode == 'link': 738 suffix = 'exe' 739 else: 740 suffix = 'obj' 741 return os.path.join(dirname, 'output.' + suffix) 742 743 def get_compiler_args_for_mode(self, mode: CompileCheckMode) -> T.List[str]: 744 # TODO: mode should really be an enum 745 args = [] # type: T.List[str] 746 args += self.get_always_args() 747 if mode is CompileCheckMode.COMPILE: 748 args += self.get_compile_only_args() 749 elif mode is CompileCheckMode.PREPROCESS: 750 args += self.get_preprocess_only_args() 751 else: 752 assert mode is CompileCheckMode.LINK 753 return args 754 755 def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs: 756 """Return an appropriate CompilerArgs instance for this class.""" 757 return CompilerArgs(self, args) 758 759 @contextlib.contextmanager 760 def compile(self, code: 'mesonlib.FileOrString', 761 extra_args: T.Union[None, CompilerArgs, T.List[str]] = None, 762 *, mode: str = 'link', want_output: bool = False, 763 temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: 764 # TODO: there isn't really any reason for this to be a contextmanager 765 if extra_args is None: 766 extra_args = [] 767 768 with TemporaryDirectoryWinProof(dir=temp_dir) as tmpdirname: 769 no_ccache = False 770 if isinstance(code, str): 771 srcname = os.path.join(tmpdirname, 772 'testfile.' + self.default_suffix) 773 with open(srcname, 'w', encoding='utf-8') as ofile: 774 ofile.write(code) 775 # ccache would result in a cache miss 776 no_ccache = True 777 contents = code 778 else: 779 srcname = code.fname 780 if not is_object(code.fname): 781 with open(code.fname, encoding='utf-8') as f: 782 contents = f.read() 783 else: 784 contents = '<binary>' 785 786 # Construct the compiler command-line 787 commands = self.compiler_args() 788 commands.append(srcname) 789 790 # Preprocess mode outputs to stdout, so no output args 791 output = self._get_compile_output(tmpdirname, mode) 792 if mode != 'preprocess': 793 commands += self.get_output_args(output) 794 commands.extend(self.get_compiler_args_for_mode(CompileCheckMode(mode))) 795 796 # extra_args must be last because it could contain '/link' to 797 # pass args to VisualStudio's linker. In that case everything 798 # in the command line after '/link' is given to the linker. 799 if extra_args: 800 commands += extra_args 801 # Generate full command-line with the exelist 802 command_list = self.get_exelist() + commands.to_native() 803 mlog.debug('Running compile:') 804 mlog.debug('Working directory: ', tmpdirname) 805 mlog.debug('Command line: ', ' '.join(command_list), '\n') 806 mlog.debug('Code:\n', contents) 807 os_env = os.environ.copy() 808 os_env['LC_ALL'] = 'C' 809 if no_ccache: 810 os_env['CCACHE_DISABLE'] = '1' 811 p, stdo, stde = Popen_safe(command_list, cwd=tmpdirname, env=os_env) 812 mlog.debug('Compiler stdout:\n', stdo) 813 mlog.debug('Compiler stderr:\n', stde) 814 815 result = CompileResult(stdo, stde, list(commands), p.returncode, p.pid, input_name=srcname) 816 if want_output: 817 result.output_name = output 818 yield result 819 820 @contextlib.contextmanager 821 def cached_compile(self, code: 'mesonlib.FileOrString', cdata: coredata.CoreData, *, 822 extra_args: T.Union[None, T.List[str], CompilerArgs] = None, 823 mode: str = 'link', 824 temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]: 825 # TODO: There's isn't really any reason for this to be a context manager 826 827 # Calculate the key 828 textra_args = tuple(extra_args) if extra_args is not None else tuple() # type: T.Tuple[str, ...] 829 key = (tuple(self.exelist), self.version, code, textra_args, mode) # type: coredata.CompilerCheckCacheKey 830 831 # Check if not cached, and generate, otherwise get from the cache 832 if key in cdata.compiler_check_cache: 833 p = cdata.compiler_check_cache[key] # type: CompileResult 834 p.cached = True 835 mlog.debug('Using cached compile:') 836 mlog.debug('Cached command line: ', ' '.join(p.command), '\n') 837 mlog.debug('Code:\n', code) 838 mlog.debug('Cached compiler stdout:\n', p.stdout) 839 mlog.debug('Cached compiler stderr:\n', p.stderr) 840 yield p 841 else: 842 with self.compile(code, extra_args=extra_args, mode=mode, want_output=False, temp_dir=temp_dir) as p: 843 cdata.compiler_check_cache[key] = p 844 yield p 845 846 def get_colorout_args(self, colortype: str) -> T.List[str]: 847 # TODO: colortype can probably be an emum 848 return [] 849 850 # Some compilers (msvc) write debug info to a separate file. 851 # These args specify where it should be written. 852 def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> T.List[str]: 853 return [] 854 855 def get_link_debugfile_name(self, targetfile: str) -> str: 856 return self.linker.get_debugfile_name(targetfile) 857 858 def get_link_debugfile_args(self, targetfile: str) -> T.List[str]: 859 return self.linker.get_debugfile_args(targetfile) 860 861 def get_std_shared_lib_link_args(self) -> T.List[str]: 862 return self.linker.get_std_shared_lib_args() 863 864 def get_std_shared_module_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: 865 return self.linker.get_std_shared_module_args(options) 866 867 def get_link_whole_for(self, args: T.List[str]) -> T.List[str]: 868 return self.linker.get_link_whole_for(args) 869 870 def get_allow_undefined_link_args(self) -> T.List[str]: 871 return self.linker.get_allow_undefined_args() 872 873 def no_undefined_link_args(self) -> T.List[str]: 874 return self.linker.no_undefined_args() 875 876 def get_instruction_set_args(self, instruction_set: str) -> T.Optional[T.List[str]]: 877 """Compiler arguments needed to enable the given instruction set. 878 879 Return type ay be an empty list meaning nothing needed or None 880 meaning the given set is not supported. 881 """ 882 return None 883 884 def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str, 885 rpath_paths: str, build_rpath: str, 886 install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]: 887 return self.linker.build_rpath_args( 888 env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath) 889 890 def thread_flags(self, env: 'Environment') -> T.List[str]: 891 return [] 892 893 def thread_link_flags(self, env: 'Environment') -> T.List[str]: 894 return self.linker.thread_flags(env) 895 896 def openmp_flags(self) -> T.List[str]: 897 raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language()) 898 899 def openmp_link_flags(self) -> T.List[str]: 900 return self.openmp_flags() 901 902 def language_stdlib_only_link_flags(self, env: 'Environment') -> T.List[str]: 903 return [] 904 905 def gnu_symbol_visibility_args(self, vistype: str) -> T.List[str]: 906 return [] 907 908 def get_gui_app_args(self, value: bool) -> T.List[str]: 909 # Only used on Windows 910 return self.linker.get_gui_app_args(value) 911 912 def get_win_subsystem_args(self, value: str) -> T.List[str]: 913 # By default the dynamic linker is going to return an empty 914 # array in case it either doesn't support Windows subsystems 915 # or does not target Windows 916 return self.linker.get_win_subsystem_args(value) 917 918 def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]: 919 raise EnvironmentException( 920 f'Language {self.get_display_language()} does not support function attributes.') 921 922 def get_pic_args(self) -> T.List[str]: 923 m = 'Language {} does not support position-independent code' 924 raise EnvironmentException(m.format(self.get_display_language())) 925 926 def get_pie_args(self) -> T.List[str]: 927 m = 'Language {} does not support position-independent executable' 928 raise EnvironmentException(m.format(self.get_display_language())) 929 930 def get_pie_link_args(self) -> T.List[str]: 931 return self.linker.get_pie_args() 932 933 def get_argument_syntax(self) -> str: 934 """Returns the argument family type. 935 936 Compilers fall into families if they try to emulate the command line 937 interface of another compiler. For example, clang is in the GCC family 938 since it accepts most of the same arguments as GCC. ICL (ICC on 939 windows) is in the MSVC family since it accepts most of the same 940 arguments as MSVC. 941 """ 942 return 'other' 943 944 def get_profile_generate_args(self) -> T.List[str]: 945 raise EnvironmentException( 946 '%s does not support get_profile_generate_args ' % self.get_id()) 947 948 def get_profile_use_args(self) -> T.List[str]: 949 raise EnvironmentException( 950 '%s does not support get_profile_use_args ' % self.get_id()) 951 952 def remove_linkerlike_args(self, args: T.List[str]) -> T.List[str]: 953 rm_exact = ('-headerpad_max_install_names',) 954 rm_prefixes = ('-Wl,', '-L',) 955 rm_next = ('-L', '-framework',) 956 ret = [] # T.List[str] 957 iargs = iter(args) 958 for arg in iargs: 959 # Remove this argument 960 if arg in rm_exact: 961 continue 962 # If the argument starts with this, but is not *exactly* this 963 # f.ex., '-L' should match ['-Lfoo'] but not ['-L', 'foo'] 964 if arg.startswith(rm_prefixes) and arg not in rm_prefixes: 965 continue 966 # Ignore this argument and the one after it 967 if arg in rm_next: 968 next(iargs) 969 continue 970 ret.append(arg) 971 return ret 972 973 def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: 974 return [] 975 976 def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: 977 return self.linker.get_lto_args() 978 979 def sanitizer_compile_args(self, value: str) -> T.List[str]: 980 return [] 981 982 def sanitizer_link_args(self, value: str) -> T.List[str]: 983 return self.linker.sanitizer_args(value) 984 985 def get_asneeded_args(self) -> T.List[str]: 986 return self.linker.get_asneeded_args() 987 988 def headerpad_args(self) -> T.List[str]: 989 return self.linker.headerpad_args() 990 991 def bitcode_args(self) -> T.List[str]: 992 return self.linker.bitcode_args() 993 994 def get_buildtype_args(self, buildtype: str) -> T.List[str]: 995 raise EnvironmentException(f'{self.id} does not implement get_buildtype_args') 996 997 def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: 998 return self.linker.get_buildtype_args(buildtype) 999 1000 def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, 1001 suffix: str, soversion: str, 1002 darwin_versions: T.Tuple[str, str]) -> T.List[str]: 1003 return self.linker.get_soname_args( 1004 env, prefix, shlib_name, suffix, soversion, 1005 darwin_versions) 1006 1007 def get_target_link_args(self, target: 'BuildTarget') -> T.List[str]: 1008 return target.link_args 1009 1010 def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]: 1011 return dep.get_compile_args() 1012 1013 def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]: 1014 return dep.get_link_args() 1015 1016 @classmethod 1017 def use_linker_args(cls, linker: str) -> T.List[str]: 1018 """Get a list of arguments to pass to the compiler to set the linker. 1019 """ 1020 return [] 1021 1022 def get_coverage_args(self) -> T.List[str]: 1023 return [] 1024 1025 def get_coverage_link_args(self) -> T.List[str]: 1026 return self.linker.get_coverage_args() 1027 1028 def get_disable_assert_args(self) -> T.List[str]: 1029 return [] 1030 1031 def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]: 1032 raise EnvironmentException('This compiler does not support Windows CRT selection') 1033 1034 def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]: 1035 raise EnvironmentException('This compiler does not support Windows CRT selection') 1036 1037 def get_compile_only_args(self) -> T.List[str]: 1038 return [] 1039 1040 def get_preprocess_only_args(self) -> T.List[str]: 1041 raise EnvironmentException('This compiler does not have a preprocessor') 1042 1043 def get_default_include_dirs(self) -> T.List[str]: 1044 # TODO: This is a candidate for returning an immutable list 1045 return [] 1046 1047 def get_largefile_args(self) -> T.List[str]: 1048 '''Enable transparent large-file-support for 32-bit UNIX systems''' 1049 if not (self.get_argument_syntax() == 'msvc' or self.info.is_darwin()): 1050 # Enable large-file support unconditionally on all platforms other 1051 # than macOS and MSVC. macOS is now 64-bit-only so it doesn't 1052 # need anything special, and MSVC doesn't have automatic LFS. 1053 # You must use the 64-bit counterparts explicitly. 1054 # glibc, musl, and uclibc, and all BSD libcs support this. On Android, 1055 # support for transparent LFS is available depending on the version of 1056 # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs 1057 # https://code.google.com/p/android/issues/detail?id=64613 1058 # 1059 # If this breaks your code, fix it! It's been 20+ years! 1060 return ['-D_FILE_OFFSET_BITS=64'] 1061 # We don't enable -D_LARGEFILE64_SOURCE since that enables 1062 # transitionary features and must be enabled by programs that use 1063 # those features explicitly. 1064 return [] 1065 1066 def get_library_dirs(self, env: 'Environment', 1067 elf_class: T.Optional[int] = None) -> T.List[str]: 1068 return [] 1069 1070 def get_return_value(self, 1071 fname: str, 1072 rtype: str, 1073 prefix: str, 1074 env: 'Environment', 1075 extra_args: T.Optional[T.List[str]], 1076 dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]: 1077 raise EnvironmentException(f'{self.id} does not support get_return_value') 1078 1079 def find_framework(self, 1080 name: str, 1081 env: 'Environment', 1082 extra_dirs: T.List[str], 1083 allow_system: bool = True) -> T.Optional[T.List[str]]: 1084 raise EnvironmentException(f'{self.id} does not support find_framework') 1085 1086 def find_framework_paths(self, env: 'Environment') -> T.List[str]: 1087 raise EnvironmentException(f'{self.id} does not support find_framework_paths') 1088 1089 def attribute_check_func(self, name: str) -> str: 1090 raise EnvironmentException(f'{self.id} does not support attribute checks') 1091 1092 def get_pch_suffix(self) -> str: 1093 raise EnvironmentException(f'{self.id} does not support pre compiled headers') 1094 1095 def get_pch_name(self, name: str) -> str: 1096 raise EnvironmentException(f'{self.id} does not support pre compiled headers') 1097 1098 def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: 1099 raise EnvironmentException(f'{self.id} does not support pre compiled headers') 1100 1101 def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: 1102 raise EnvironmentException(f'{self.id} does not support function attributes') 1103 1104 def name_string(self) -> str: 1105 return ' '.join(self.exelist) 1106 1107 @abc.abstractmethod 1108 def sanity_check(self, work_dir: str, environment: 'Environment') -> None: 1109 """Check that this compiler actually works. 1110 1111 This should provide a simple compile/link test. Something as simple as: 1112 ```python 1113 main(): return 0 1114 ``` 1115 is good enough here. 1116 """ 1117 1118 def split_shlib_to_parts(self, fname: str) -> T.Tuple[T.Optional[str], str]: 1119 return None, fname 1120 1121 def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: 1122 return [] 1123 1124 def get_std_exe_link_args(self) -> T.List[str]: 1125 # TODO: is this a linker property? 1126 return [] 1127 1128 def get_include_args(self, path: str, is_system: bool) -> T.List[str]: 1129 return [] 1130 1131 def depfile_for_object(self, objfile: str) -> str: 1132 return objfile + '.' + self.get_depfile_suffix() 1133 1134 def get_depfile_suffix(self) -> str: 1135 raise EnvironmentException(f'{self.id} does not implement get_depfile_suffix') 1136 1137 def get_no_stdinc_args(self) -> T.List[str]: 1138 """Arguments to turn off default inclusion of standard libraries.""" 1139 return [] 1140 1141 def get_warn_args(self, level: str) -> T.List[str]: 1142 return [] 1143 1144 def get_werror_args(self) -> T.List[str]: 1145 return [] 1146 1147 @abc.abstractmethod 1148 def get_optimization_args(self, optimization_level: str) -> T.List[str]: 1149 pass 1150 1151 def get_module_incdir_args(self) -> T.Tuple[str, ...]: 1152 raise EnvironmentException(f'{self.id} does not implement get_module_incdir_args') 1153 1154 def get_module_outdir_args(self, path: str) -> T.List[str]: 1155 raise EnvironmentException(f'{self.id} does not implement get_module_outdir_args') 1156 1157 def module_name_to_filename(self, module_name: str) -> str: 1158 raise EnvironmentException(f'{self.id} does not implement module_name_to_filename') 1159 1160 def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: 1161 """Arguments to pass the compiler and/or linker for checks. 1162 1163 The default implementation turns off optimizations. 1164 1165 Examples of things that go here: 1166 - extra arguments for error checking 1167 - Arguments required to make the compiler exit with a non-zero status 1168 when something is wrong. 1169 """ 1170 return self.get_no_optimization_args() 1171 1172 def get_no_optimization_args(self) -> T.List[str]: 1173 """Arguments to the compiler to turn off all optimizations.""" 1174 return [] 1175 1176 def build_wrapper_args(self, env: 'Environment', 1177 extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], 1178 dependencies: T.Optional[T.List['Dependency']], 1179 mode: CompileCheckMode = CompileCheckMode.COMPILE) -> CompilerArgs: 1180 """Arguments to pass the build_wrapper helper. 1181 1182 This generally needs to be set on a per-language baises. It provides 1183 a hook for languages to handle dependencies and extra args. The base 1184 implementation handles the most common cases, namely adding the 1185 check_arguments, unwrapping dependencies, and appending extra args. 1186 """ 1187 if callable(extra_args): 1188 extra_args = extra_args(mode) 1189 if extra_args is None: 1190 extra_args = [] 1191 if dependencies is None: 1192 dependencies = [] 1193 1194 # Collect compiler arguments 1195 args = self.compiler_args(self.get_compiler_check_args(mode)) 1196 for d in dependencies: 1197 # Add compile flags needed by dependencies 1198 args += d.get_compile_args() 1199 if mode is CompileCheckMode.LINK: 1200 # Add link flags needed to find dependencies 1201 args += d.get_link_args() 1202 1203 if mode is CompileCheckMode.COMPILE: 1204 # Add DFLAGS from the env 1205 args += env.coredata.get_external_args(self.for_machine, self.language) 1206 elif mode is CompileCheckMode.LINK: 1207 # Add LDFLAGS from the env 1208 args += env.coredata.get_external_link_args(self.for_machine, self.language) 1209 # extra_args must override all other arguments, so we add them last 1210 args += extra_args 1211 return args 1212 1213 @contextlib.contextmanager 1214 def _build_wrapper(self, code: 'mesonlib.FileOrString', env: 'Environment', 1215 extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None, 1216 dependencies: T.Optional[T.List['Dependency']] = None, 1217 mode: str = 'compile', want_output: bool = False, 1218 disable_cache: bool = False, 1219 temp_dir: str = None) -> T.Iterator[T.Optional[CompileResult]]: 1220 """Helper for getting a cacched value when possible. 1221 1222 This method isn't meant to be called externally, it's mean to be 1223 wrapped by other methods like compiles() and links(). 1224 """ 1225 args = self.build_wrapper_args(env, extra_args, dependencies, CompileCheckMode(mode)) 1226 if disable_cache or want_output: 1227 with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r: 1228 yield r 1229 else: 1230 with self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) as r: 1231 yield r 1232 1233 def compiles(self, code: 'mesonlib.FileOrString', env: 'Environment', *, 1234 extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, 1235 dependencies: T.Optional[T.List['Dependency']] = None, 1236 mode: str = 'compile', 1237 disable_cache: bool = False) -> T.Tuple[bool, bool]: 1238 with self._build_wrapper(code, env, extra_args, dependencies, mode, disable_cache=disable_cache) as p: 1239 return p.returncode == 0, p.cached 1240 1241 def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *, 1242 compiler: T.Optional['Compiler'] = None, 1243 extra_args: T.Union[None, T.List[str], CompilerArgs, T.Callable[[CompileCheckMode], T.List[str]]] = None, 1244 dependencies: T.Optional[T.List['Dependency']] = None, 1245 mode: str = 'compile', 1246 disable_cache: bool = False) -> T.Tuple[bool, bool]: 1247 if compiler: 1248 with compiler._build_wrapper(code, env, dependencies=dependencies, want_output=True) as r: 1249 objfile = mesonlib.File.from_absolute_file(r.output_name) 1250 return self.compiles(objfile, env, extra_args=extra_args, 1251 dependencies=dependencies, mode='link', disable_cache=True) 1252 1253 return self.compiles(code, env, extra_args=extra_args, 1254 dependencies=dependencies, mode='link', disable_cache=disable_cache) 1255 1256 def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]: 1257 """Used by D for extra language features.""" 1258 # TODO: using a TypeDict here would improve this 1259 raise EnvironmentException(f'{self.id} does not implement get_feature_args') 1260 1261 def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]: 1262 raise EnvironmentException(f'{self.id} does not know how to do prelinking.') 1263 1264 def rsp_file_syntax(self) -> 'RSPFileSyntax': 1265 """The format of the RSP file that this compiler supports. 1266 1267 If `self.can_linker_accept_rsp()` returns True, then this needs to 1268 be implemented 1269 """ 1270 return self.linker.rsp_file_syntax() 1271 1272 def get_debug_args(self, is_debug: bool) -> T.List[str]: 1273 """Arguments required for a debug build.""" 1274 return [] 1275 1276 def get_no_warn_args(self) -> T.List[str]: 1277 """Arguments to completely disable warnings.""" 1278 return [] 1279 1280 1281def get_global_options(lang: str, 1282 comp: T.Type[Compiler], 1283 for_machine: MachineChoice, 1284 env: 'Environment') -> 'KeyedOptionDictType': 1285 """Retrieve options that apply to all compilers for a given language.""" 1286 description = f'Extra arguments passed to the {lang}' 1287 argkey = OptionKey('args', lang=lang, machine=for_machine) 1288 largkey = argkey.evolve('link_args') 1289 envkey = argkey.evolve('env_args') 1290 1291 comp_key = argkey if argkey in env.options else envkey 1292 1293 comp_options = env.options.get(comp_key, []) 1294 link_options = env.options.get(largkey, []) 1295 1296 cargs = coredata.UserArrayOption( 1297 description + ' compiler', 1298 comp_options, split_args=True, user_input=True, allow_dups=True) 1299 1300 largs = coredata.UserArrayOption( 1301 description + ' linker', 1302 link_options, split_args=True, user_input=True, allow_dups=True) 1303 1304 if comp.INVOKES_LINKER and comp_key == envkey: 1305 # If the compiler acts as a linker driver, and we're using the 1306 # environment variable flags for both the compiler and linker 1307 # arguments, then put the compiler flags in the linker flags as well. 1308 # This is how autotools works, and the env vars freature is for 1309 # autotools compatibility. 1310 largs.extend_value(comp_options) 1311 1312 opts: 'KeyedOptionDictType' = {argkey: cargs, largkey: largs} 1313 1314 return opts 1315