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, tempfile
17import itertools
18import typing as T
19from functools import lru_cache
20
21from .. import coredata
22from .. import mlog
23from .. import mesonlib
24from ..linkers import LinkerEnvVarsMixin
25from ..mesonlib import (
26    EnvironmentException, MachineChoice, MesonException,
27    Popen_safe, split_args
28)
29from ..envconfig import (
30    Properties, get_env_var
31)
32from ..arglist import CompilerArgs
33
34if T.TYPE_CHECKING:
35    from ..coredata import OptionDictType
36    from ..envconfig import MachineInfo
37    from ..environment import Environment
38    from ..linkers import DynamicLinker  # noqa: F401
39
40    CompilerType = T.TypeVar('CompilerType', bound=Compiler)
41
42"""This file contains the data files of all compilers Meson knows
43about. To support a new compiler, add its information below.
44Also add corresponding autodetection code in environment.py."""
45
46header_suffixes = ('h', 'hh', 'hpp', 'hxx', 'H', 'ipp', 'moc', 'vapi', 'di')
47obj_suffixes = ('o', 'obj', 'res')
48lib_suffixes = ('a', 'lib', 'dll', 'dll.a', 'dylib', 'so')
49# Mapping of language to suffixes of files that should always be in that language
50# This means we can't include .h headers here since they could be C, C++, ObjC, etc.
51lang_suffixes = {
52    'c': ('c',),
53    'cpp': ('cpp', 'cc', 'cxx', 'c++', 'hh', 'hpp', 'ipp', 'hxx', 'ino'),
54    'cuda': ('cu',),
55    # f90, f95, f03, f08 are for free-form fortran ('f90' recommended)
56    # f, for, ftn, fpp are for fixed-form fortran ('f' or 'for' recommended)
57    'fortran': ('f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp'),
58    'd': ('d', 'di'),
59    'objc': ('m',),
60    'objcpp': ('mm',),
61    'rust': ('rs',),
62    'vala': ('vala', 'vapi', 'gs'),
63    'cs': ('cs',),
64    'swift': ('swift',),
65    'java': ('java',),
66}
67all_languages = lang_suffixes.keys()
68cpp_suffixes = lang_suffixes['cpp'] + ('h',)
69c_suffixes = lang_suffixes['c'] + ('h',)
70# List of languages that by default consume and output libraries following the
71# C ABI; these can generally be used interchangebly
72clib_langs = ('objcpp', 'cpp', 'objc', 'c', 'fortran',)
73# List of languages that can be linked with C code directly by the linker
74# used in build.py:process_compilers() and build.py:get_dynamic_linker()
75clink_langs = ('d', 'cuda') + clib_langs
76clink_suffixes = ()
77for _l in clink_langs + ('vala',):
78    clink_suffixes += lang_suffixes[_l]
79clink_suffixes += ('h', 'll', 's')
80all_suffixes = set(itertools.chain(*lang_suffixes.values(), clink_suffixes))
81
82# Languages that should use LDFLAGS arguments when linking.
83languages_using_ldflags = {'objcpp', 'cpp', 'objc', 'c', 'fortran', 'd', 'cuda'}
84# Languages that should use CPPFLAGS arguments when linking.
85languages_using_cppflags = {'c', 'cpp', 'objc', 'objcpp'}
86soregex = re.compile(r'.*\.so(\.[0-9]+)?(\.[0-9]+)?(\.[0-9]+)?$')
87
88# Environment variables that each lang uses.
89cflags_mapping = {'c': 'CFLAGS',
90                  'cpp': 'CXXFLAGS',
91                  'cuda': 'CUFLAGS',
92                  'objc': 'OBJCFLAGS',
93                  'objcpp': 'OBJCXXFLAGS',
94                  'fortran': 'FFLAGS',
95                  'd': 'DFLAGS',
96                  'vala': 'VALAFLAGS',
97                  'rust': 'RUSTFLAGS'}
98
99# All these are only for C-linkable languages; see `clink_langs` above.
100
101def sort_clink(lang):
102    '''
103    Sorting function to sort the list of languages according to
104    reversed(compilers.clink_langs) and append the unknown langs in the end.
105    The purpose is to prefer C over C++ for files that can be compiled by
106    both such as assembly, C, etc. Also applies to ObjC, ObjC++, etc.
107    '''
108    if lang not in clink_langs:
109        return 1
110    return -clink_langs.index(lang)
111
112def is_header(fname):
113    if hasattr(fname, 'fname'):
114        fname = fname.fname
115    suffix = fname.split('.')[-1]
116    return suffix in header_suffixes
117
118def is_source(fname):
119    if hasattr(fname, 'fname'):
120        fname = fname.fname
121    suffix = fname.split('.')[-1].lower()
122    return suffix in clink_suffixes
123
124def is_assembly(fname):
125    if hasattr(fname, 'fname'):
126        fname = fname.fname
127    return fname.split('.')[-1].lower() == 's'
128
129def is_llvm_ir(fname):
130    if hasattr(fname, 'fname'):
131        fname = fname.fname
132    return fname.split('.')[-1] == 'll'
133
134@lru_cache(maxsize=None)
135def cached_by_name(fname):
136    suffix = fname.split('.')[-1]
137    return suffix in obj_suffixes
138
139def is_object(fname):
140    if hasattr(fname, 'fname'):
141        fname = fname.fname
142    return cached_by_name(fname)
143
144def is_library(fname):
145    if hasattr(fname, 'fname'):
146        fname = fname.fname
147
148    if soregex.match(fname):
149        return True
150
151    suffix = fname.split('.')[-1]
152    return suffix in lib_suffixes
153
154def is_known_suffix(fname):
155    if hasattr(fname, 'fname'):
156        fname = fname.fname
157    suffix = fname.split('.')[-1]
158
159    return suffix in all_suffixes
160
161cuda_buildtype_args = {'plain': [],
162                       'debug': [],
163                       'debugoptimized': [],
164                       'release': [],
165                       'minsize': [],
166                       }
167java_buildtype_args = {'plain': [],
168                       'debug': ['-g'],
169                       'debugoptimized': ['-g'],
170                       'release': [],
171                       'minsize': [],
172                       'custom': [],
173                       }
174
175rust_buildtype_args = {'plain': [],
176                       'debug': [],
177                       'debugoptimized': [],
178                       'release': [],
179                       'minsize': [],
180                       'custom': [],
181                       }
182
183d_gdc_buildtype_args = {'plain': [],
184                        'debug': [],
185                        'debugoptimized': ['-finline-functions'],
186                        'release': ['-finline-functions'],
187                        'minsize': [],
188                        'custom': [],
189                        }
190
191d_ldc_buildtype_args = {'plain': [],
192                        'debug': [],
193                        'debugoptimized': ['-enable-inlining', '-Hkeep-all-bodies'],
194                        'release': ['-enable-inlining', '-Hkeep-all-bodies'],
195                        'minsize': [],
196                        'custom': [],
197                        }
198
199d_dmd_buildtype_args = {'plain': [],
200                        'debug': [],
201                        'debugoptimized': ['-inline'],
202                        'release': ['-inline'],
203                        'minsize': [],
204                        'custom': [],
205                        }
206
207mono_buildtype_args = {'plain': [],
208                       'debug': [],
209                       'debugoptimized': ['-optimize+'],
210                       'release': ['-optimize+'],
211                       'minsize': [],
212                       'custom': [],
213                       }
214
215swift_buildtype_args = {'plain': [],
216                        'debug': [],
217                        'debugoptimized': [],
218                        'release': [],
219                        'minsize': [],
220                        'custom': [],
221                        }
222
223gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
224               '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
225
226msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
227                'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
228                'uuid.lib', 'comdlg32.lib', 'advapi32.lib']
229
230clike_optimization_args = {'0': [],
231                           'g': [],
232                           '1': ['-O1'],
233                           '2': ['-O2'],
234                           '3': ['-O3'],
235                           's': ['-Os'],
236                           }
237
238cuda_optimization_args = {'0': [],
239                          'g': ['-O0'],
240                          '1': ['-O1'],
241                          '2': ['-O2'],
242                          '3': ['-O3'],
243                          's': ['-O3']
244                          }
245
246cuda_debug_args = {False: [],
247                   True: ['-g']}
248
249clike_debug_args = {False: [],
250                    True: ['-g']}
251
252base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', True),
253                'b_lto': coredata.UserBooleanOption('Use link time optimization', False),
254                'b_sanitize': coredata.UserComboOption('Code sanitizer to use',
255                                                       ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'],
256                                                       'none'),
257                'b_lundef': coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True),
258                'b_asneeded': coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True),
259                'b_pgo': coredata.UserComboOption('Use profile guided optimization',
260                                                  ['off', 'generate', 'use'],
261                                                  'off'),
262                'b_coverage': coredata.UserBooleanOption('Enable coverage tracking.',
263                                                         False),
264                'b_colorout': coredata.UserComboOption('Use colored output',
265                                                       ['auto', 'always', 'never'],
266                                                       'always'),
267                'b_ndebug': coredata.UserComboOption('Disable asserts',
268                                                     ['true', 'false', 'if-release'], 'false'),
269                'b_staticpic': coredata.UserBooleanOption('Build static libraries as position independent',
270                                                          True),
271                'b_pie': coredata.UserBooleanOption('Build executables as position independent',
272                                                    False),
273                'b_bitcode': coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)',
274                                                        False),
275                'b_vscrt': coredata.UserComboOption('VS run-time library type to use.',
276                                                    ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype'],
277                                                    'from_buildtype'),
278                }
279
280def option_enabled(boptions, options, option):
281    try:
282        if option not in boptions:
283            return False
284        return options[option].value
285    except KeyError:
286        return False
287
288def get_base_compile_args(options, compiler):
289    args = []
290    try:
291        if options['b_lto'].value:
292            args.extend(compiler.get_lto_compile_args())
293    except KeyError:
294        pass
295    try:
296        args += compiler.get_colorout_args(options['b_colorout'].value)
297    except KeyError:
298        pass
299    try:
300        args += compiler.sanitizer_compile_args(options['b_sanitize'].value)
301    except KeyError:
302        pass
303    try:
304        pgo_val = options['b_pgo'].value
305        if pgo_val == 'generate':
306            args.extend(compiler.get_profile_generate_args())
307        elif pgo_val == 'use':
308            args.extend(compiler.get_profile_use_args())
309    except KeyError:
310        pass
311    try:
312        if options['b_coverage'].value:
313            args += compiler.get_coverage_args()
314    except KeyError:
315        pass
316    try:
317        if (options['b_ndebug'].value == 'true' or
318                (options['b_ndebug'].value == 'if-release' and
319                 options['buildtype'].value in {'release', 'plain'})):
320            args += compiler.get_disable_assert_args()
321    except KeyError:
322        pass
323    # This does not need a try...except
324    if option_enabled(compiler.base_options, options, 'b_bitcode'):
325        args.append('-fembed-bitcode')
326    try:
327        crt_val = options['b_vscrt'].value
328        buildtype = options['buildtype'].value
329        try:
330            args += compiler.get_crt_compile_args(crt_val, buildtype)
331        except AttributeError:
332            pass
333    except KeyError:
334        pass
335    return args
336
337def get_base_link_args(options, linker, is_shared_module):
338    args = []
339    try:
340        if options['b_lto'].value:
341            args.extend(linker.get_lto_link_args())
342    except KeyError:
343        pass
344    try:
345        args += linker.sanitizer_link_args(options['b_sanitize'].value)
346    except KeyError:
347        pass
348    try:
349        pgo_val = options['b_pgo'].value
350        if pgo_val == 'generate':
351            args.extend(linker.get_profile_generate_args())
352        elif pgo_val == 'use':
353            args.extend(linker.get_profile_use_args())
354    except KeyError:
355        pass
356    try:
357        if options['b_coverage'].value:
358            args += linker.get_coverage_link_args()
359    except KeyError:
360        pass
361
362    as_needed = option_enabled(linker.base_options, options, 'b_asneeded')
363    bitcode = option_enabled(linker.base_options, options, 'b_bitcode')
364    # Shared modules cannot be built with bitcode_bundle because
365    # -bitcode_bundle is incompatible with -undefined and -bundle
366    if bitcode and not is_shared_module:
367        args.extend(linker.bitcode_args())
368    elif as_needed:
369        # -Wl,-dead_strip_dylibs is incompatible with bitcode
370        args.extend(linker.get_asneeded_args())
371
372    # Apple's ld (the only one that supports bitcode) does not like -undefined
373    # arguments or -headerpad_max_install_names when bitcode is enabled
374    if not bitcode:
375        args.extend(linker.headerpad_args())
376        if (not is_shared_module and
377                option_enabled(linker.base_options, options, 'b_lundef')):
378            args.extend(linker.no_undefined_link_args())
379        else:
380            args.extend(linker.get_allow_undefined_link_args())
381
382    try:
383        crt_val = options['b_vscrt'].value
384        buildtype = options['buildtype'].value
385        try:
386            args += linker.get_crt_link_args(crt_val, buildtype)
387        except AttributeError:
388            pass
389    except KeyError:
390        pass
391    return args
392
393
394class CrossNoRunException(MesonException):
395    pass
396
397class RunResult:
398    def __init__(self, compiled, returncode=999, stdout='UNDEFINED', stderr='UNDEFINED'):
399        self.compiled = compiled
400        self.returncode = returncode
401        self.stdout = stdout
402        self.stderr = stderr
403
404
405class Compiler(metaclass=abc.ABCMeta):
406    # Libraries to ignore in find_library() since they are provided by the
407    # compiler or the C library. Currently only used for MSVC.
408    ignore_libs = ()
409    # Libraries that are internal compiler implementations, and must not be
410    # manually searched.
411    internal_libs = ()
412
413    LINKER_PREFIX = None  # type: T.Union[None, str, T.List[str]]
414    INVOKES_LINKER = True
415
416    def __init__(self, exelist, version, for_machine: MachineChoice, info: 'MachineInfo',
417                 linker: T.Optional['DynamicLinker'] = None, **kwargs):
418        if isinstance(exelist, str):
419            self.exelist = [exelist]
420        elif isinstance(exelist, list):
421            self.exelist = exelist
422        else:
423            raise TypeError('Unknown argument to Compiler')
424        # In case it's been overridden by a child class already
425        if not hasattr(self, 'file_suffixes'):
426            self.file_suffixes = lang_suffixes[self.language]
427        if not hasattr(self, 'can_compile_suffixes'):
428            self.can_compile_suffixes = set(self.file_suffixes)
429        self.default_suffix = self.file_suffixes[0]
430        self.version = version
431        if 'full_version' in kwargs:
432            self.full_version = kwargs['full_version']
433        else:
434            self.full_version = None
435        self.for_machine = for_machine
436        self.base_options = []
437        self.linker = linker
438        self.info = info
439
440    def __repr__(self):
441        repr_str = "<{0}: v{1} `{2}`>"
442        return repr_str.format(self.__class__.__name__, self.version,
443                               ' '.join(self.exelist))
444
445    @lru_cache(maxsize=None)
446    def can_compile(self, src) -> bool:
447        if hasattr(src, 'fname'):
448            src = src.fname
449        suffix = os.path.splitext(src)[1].lower()
450        if suffix and suffix[1:] in self.can_compile_suffixes:
451            return True
452        return False
453
454    def get_id(self) -> str:
455        return self.id
456
457    def get_linker_id(self) -> str:
458        # There is not guarantee that we have a dynamic linker instance, as
459        # some languages don't have separate linkers and compilers. In those
460        # cases return the compiler id
461        try:
462            return self.linker.id
463        except AttributeError:
464            return self.id
465
466    def get_version_string(self) -> str:
467        details = [self.id, self.version]
468        if self.full_version:
469            details += ['"%s"' % (self.full_version)]
470        return '(%s)' % (' '.join(details))
471
472    def get_language(self) -> str:
473        return self.language
474
475    @classmethod
476    def get_display_language(cls) -> str:
477        return cls.language.capitalize()
478
479    def get_default_suffix(self) -> str:
480        return self.default_suffix
481
482    def get_define(self, dname, prefix, env, extra_args, dependencies) -> T.Tuple[str, bool]:
483        raise EnvironmentException('%s does not support get_define ' % self.get_id())
484
485    def compute_int(self, expression, low, high, guess, prefix, env, extra_args, dependencies) -> int:
486        raise EnvironmentException('%s does not support compute_int ' % self.get_id())
487
488    def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
489        raise EnvironmentException('%s does not support compute_parameters_with_absolute_paths ' % self.get_id())
490
491    def has_members(self, typename, membernames, prefix, env, *,
492                    extra_args=None, dependencies=None) -> T.Tuple[bool, bool]:
493        raise EnvironmentException('%s does not support has_member(s) ' % self.get_id())
494
495    def has_type(self, typename, prefix, env, extra_args, *,
496                 dependencies=None) -> T.Tuple[bool, bool]:
497        raise EnvironmentException('%s does not support has_type ' % self.get_id())
498
499    def symbols_have_underscore_prefix(self, env) -> bool:
500        raise EnvironmentException('%s does not support symbols_have_underscore_prefix ' % self.get_id())
501
502    def get_exelist(self):
503        return self.exelist[:]
504
505    def get_linker_exelist(self) -> T.List[str]:
506        return self.linker.get_exelist()
507
508    def get_linker_output_args(self, outputname: str) -> T.List[str]:
509        return self.linker.get_output_args(outputname)
510
511    def get_builtin_define(self, *args, **kwargs):
512        raise EnvironmentException('%s does not support get_builtin_define.' % self.id)
513
514    def has_builtin_define(self, *args, **kwargs):
515        raise EnvironmentException('%s does not support has_builtin_define.' % self.id)
516
517    def get_always_args(self):
518        return []
519
520    def can_linker_accept_rsp(self) -> bool:
521        """
522        Determines whether the linker can accept arguments using the @rsp syntax.
523        """
524        return self.linker.get_accepts_rsp()
525
526    def get_linker_always_args(self) -> T.List[str]:
527        return self.linker.get_always_args()
528
529    def get_linker_lib_prefix(self):
530        return self.linker.get_lib_prefix()
531
532    def gen_import_library_args(self, implibname):
533        """
534        Used only on Windows for libraries that need an import library.
535        This currently means C, C++, Fortran.
536        """
537        return []
538
539    def get_linker_args_from_envvars(self,
540                                     for_machine: MachineChoice,
541                                     is_cross: bool) -> T.List[str]:
542        return self.linker.get_args_from_envvars(for_machine, is_cross)
543
544    def get_options(self) -> T.Dict[str, coredata.UserOption]:
545        return {}
546
547    def get_option_compile_args(self, options):
548        return []
549
550    def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
551        return self.linker.get_option_args(options)
552
553    def check_header(self, *args, **kwargs) -> T.Tuple[bool, bool]:
554        raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
555
556    def has_header(self, *args, **kwargs) -> T.Tuple[bool, bool]:
557        raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
558
559    def has_header_symbol(self, *args, **kwargs) -> T.Tuple[bool, bool]:
560        raise EnvironmentException('Language %s does not support header symbol checks.' % self.get_display_language())
561
562    def compiles(self, *args, **kwargs) -> T.Tuple[bool, bool]:
563        raise EnvironmentException('Language %s does not support compile checks.' % self.get_display_language())
564
565    def links(self, *args, **kwargs) -> T.Tuple[bool, bool]:
566        raise EnvironmentException('Language %s does not support link checks.' % self.get_display_language())
567
568    def run(self, *args, **kwargs) -> RunResult:
569        raise EnvironmentException('Language %s does not support run checks.' % self.get_display_language())
570
571    def sizeof(self, *args, **kwargs) -> int:
572        raise EnvironmentException('Language %s does not support sizeof checks.' % self.get_display_language())
573
574    def alignment(self, *args, **kwargs) -> int:
575        raise EnvironmentException('Language %s does not support alignment checks.' % self.get_display_language())
576
577    def has_function(self, *args, **kwargs) -> T.Tuple[bool, bool]:
578        raise EnvironmentException('Language %s does not support function checks.' % self.get_display_language())
579
580    @classmethod
581    def unix_args_to_native(cls, args):
582        "Always returns a copy that can be independently mutated"
583        return args[:]
584
585    @classmethod
586    def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
587        "Always returns a copy that can be independently mutated"
588        return args[:]
589
590    def find_library(self, *args, **kwargs):
591        raise EnvironmentException('Language {} does not support library finding.'.format(self.get_display_language()))
592
593    def get_library_dirs(self, *args, **kwargs):
594        return ()
595
596    def get_program_dirs(self, *args, **kwargs):
597        return []
598
599    def has_multi_arguments(self, args, env) -> T.Tuple[bool, bool]:
600        raise EnvironmentException(
601            'Language {} does not support has_multi_arguments.'.format(
602                self.get_display_language()))
603
604    def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
605        return self.linker.has_multi_arguments(args, env)
606
607    def _get_compile_output(self, dirname, mode):
608        # In pre-processor mode, the output is sent to stdout and discarded
609        if mode == 'preprocess':
610            return None
611        # Extension only matters if running results; '.exe' is
612        # guaranteed to be executable on every platform.
613        if mode == 'link':
614            suffix = 'exe'
615        else:
616            suffix = 'obj'
617        return os.path.join(dirname, 'output.' + suffix)
618
619    def get_compiler_args_for_mode(self, mode):
620        args = []
621        args += self.get_always_args()
622        if mode == 'compile':
623            args += self.get_compile_only_args()
624        if mode == 'preprocess':
625            args += self.get_preprocess_only_args()
626        return args
627
628    def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArgs:
629        """Return an appropriate CompilerArgs instance for this class."""
630        return CompilerArgs(self, args)
631
632    @contextlib.contextmanager
633    def compile(self, code: str, extra_args: list = None, *, mode: str = 'link', want_output: bool = False, temp_dir: str = None):
634        if extra_args is None:
635            extra_args = []
636        try:
637            with tempfile.TemporaryDirectory(dir=temp_dir) as tmpdirname:
638                no_ccache = False
639                if isinstance(code, str):
640                    srcname = os.path.join(tmpdirname,
641                                           'testfile.' + self.default_suffix)
642                    with open(srcname, 'w') as ofile:
643                        ofile.write(code)
644                    # ccache would result in a cache miss
645                    no_ccache = True
646                elif isinstance(code, mesonlib.File):
647                    srcname = code.fname
648
649                # Construct the compiler command-line
650                commands = self.compiler_args()
651                commands.append(srcname)
652                # Preprocess mode outputs to stdout, so no output args
653                if mode != 'preprocess':
654                    output = self._get_compile_output(tmpdirname, mode)
655                    commands += self.get_output_args(output)
656                commands.extend(self.get_compiler_args_for_mode(mode))
657                # extra_args must be last because it could contain '/link' to
658                # pass args to VisualStudio's linker. In that case everything
659                # in the command line after '/link' is given to the linker.
660                commands += extra_args
661                # Generate full command-line with the exelist
662                commands = self.get_exelist() + commands.to_native()
663                mlog.debug('Running compile:')
664                mlog.debug('Working directory: ', tmpdirname)
665                mlog.debug('Command line: ', ' '.join(commands), '\n')
666                mlog.debug('Code:\n', code)
667                os_env = os.environ.copy()
668                os_env['LC_ALL'] = 'C'
669                if no_ccache:
670                    os_env['CCACHE_DISABLE'] = '1'
671                p, p.stdo, p.stde = Popen_safe(commands, cwd=tmpdirname, env=os_env)
672                mlog.debug('Compiler stdout:\n', p.stdo)
673                mlog.debug('Compiler stderr:\n', p.stde)
674                p.commands = commands
675                p.input_name = srcname
676                if want_output:
677                    p.output_name = output
678                p.cached = False  # Make sure that the cached attribute always exists
679                yield p
680        except OSError:
681            # On Windows antivirus programs and the like hold on to files so
682            # they can't be deleted. There's not much to do in this case. Also,
683            # catch OSError because the directory is then no longer empty.
684            pass
685
686    @contextlib.contextmanager
687    def cached_compile(self, code, cdata: coredata.CoreData, *, extra_args=None, mode: str = 'link', temp_dir=None):
688        assert(isinstance(cdata, coredata.CoreData))
689
690        # Calculate the key
691        textra_args = tuple(extra_args) if extra_args is not None else None
692        key = (tuple(self.exelist), self.version, code, textra_args, mode)
693
694        # Check if not cached
695        if key not in cdata.compiler_check_cache:
696            with self.compile(code, extra_args=extra_args, mode=mode, want_output=False, temp_dir=temp_dir) as p:
697                # Remove all attributes except the following
698                # This way the object can be serialized
699                tokeep = ['args', 'commands', 'input_name', 'output_name',
700                          'pid', 'returncode', 'stdo', 'stde', 'text_mode']
701                todel = [x for x in vars(p).keys() if x not in tokeep]
702                for i in todel:
703                    delattr(p, i)
704                p.cached = False
705                cdata.compiler_check_cache[key] = p
706                yield p
707                return
708
709        # Return cached
710        p = cdata.compiler_check_cache[key]
711        p.cached = True
712        mlog.debug('Using cached compile:')
713        mlog.debug('Cached command line: ', ' '.join(p.commands), '\n')
714        mlog.debug('Code:\n', code)
715        mlog.debug('Cached compiler stdout:\n', p.stdo)
716        mlog.debug('Cached compiler stderr:\n', p.stde)
717        yield p
718
719    def get_colorout_args(self, colortype):
720        return []
721
722    # Some compilers (msvc) write debug info to a separate file.
723    # These args specify where it should be written.
724    def get_compile_debugfile_args(self, rel_obj, **kwargs):
725        return []
726
727    def get_link_debugfile_name(self, targetfile: str) -> str:
728        return self.linker.get_debugfile_name(targetfile)
729
730    def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
731        return self.linker.get_debugfile_args(targetfile)
732
733    def get_std_shared_lib_link_args(self) -> T.List[str]:
734        return self.linker.get_std_shared_lib_args()
735
736    def get_std_shared_module_link_args(self, options: 'OptionDictType') -> T.List[str]:
737        return self.linker.get_std_shared_module_args(options)
738
739    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
740        return self.linker.get_link_whole_for(args)
741
742    def get_allow_undefined_link_args(self) -> T.List[str]:
743        return self.linker.get_allow_undefined_args()
744
745    def no_undefined_link_args(self) -> T.List[str]:
746        return self.linker.no_undefined_args()
747
748    # Compiler arguments needed to enable the given instruction set.
749    # May be [] meaning nothing needed or None meaning the given set
750    # is not supported.
751    def get_instruction_set_args(self, instruction_set):
752        return None
753
754    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
755                         rpath_paths: str, build_rpath: str,
756                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
757        return self.linker.build_rpath_args(
758            env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
759
760    def thread_flags(self, env):
761        return []
762
763    def openmp_flags(self):
764        raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language())
765
766    def openmp_link_flags(self):
767        return self.openmp_flags()
768
769    def language_stdlib_only_link_flags(self):
770        return []
771
772    def gnu_symbol_visibility_args(self, vistype):
773        return []
774
775    def get_gui_app_args(self, value):
776        return []
777
778    def has_func_attribute(self, name, env):
779        raise EnvironmentException(
780            'Language {} does not support function attributes.'.format(self.get_display_language()))
781
782    def get_pic_args(self):
783        m = 'Language {} does not support position-independent code'
784        raise EnvironmentException(m.format(self.get_display_language()))
785
786    def get_pie_args(self):
787        m = 'Language {} does not support position-independent executable'
788        raise EnvironmentException(m.format(self.get_display_language()))
789
790    def get_pie_link_args(self) -> T.List[str]:
791        return self.linker.get_pie_args()
792
793    def get_argument_syntax(self):
794        """Returns the argument family type.
795
796        Compilers fall into families if they try to emulate the command line
797        interface of another compiler. For example, clang is in the GCC family
798        since it accepts most of the same arguments as GCC. ICL (ICC on
799        windows) is in the MSVC family since it accepts most of the same
800        arguments as MSVC.
801        """
802        return 'other'
803
804    def get_profile_generate_args(self):
805        raise EnvironmentException(
806            '%s does not support get_profile_generate_args ' % self.get_id())
807
808    def get_profile_use_args(self):
809        raise EnvironmentException(
810            '%s does not support get_profile_use_args ' % self.get_id())
811
812    def get_undefined_link_args(self) -> T.List[str]:
813        return self.linker.get_undefined_link_args()
814
815    def remove_linkerlike_args(self, args):
816        rm_exact = ('-headerpad_max_install_names',)
817        rm_prefixes = ('-Wl,', '-L',)
818        rm_next = ('-L', '-framework',)
819        ret = []
820        iargs = iter(args)
821        for arg in iargs:
822            # Remove this argument
823            if arg in rm_exact:
824                continue
825            # If the argument starts with this, but is not *exactly* this
826            # f.ex., '-L' should match ['-Lfoo'] but not ['-L', 'foo']
827            if arg.startswith(rm_prefixes) and arg not in rm_prefixes:
828                continue
829            # Ignore this argument and the one after it
830            if arg in rm_next:
831                next(iargs)
832                continue
833            ret.append(arg)
834        return ret
835
836    def get_lto_compile_args(self) -> T.List[str]:
837        return []
838
839    def get_lto_link_args(self) -> T.List[str]:
840        return self.linker.get_lto_args()
841
842    def sanitizer_compile_args(self, value: str) -> T.List[str]:
843        return []
844
845    def sanitizer_link_args(self, value: str) -> T.List[str]:
846        return self.linker.sanitizer_args(value)
847
848    def get_asneeded_args(self) -> T.List[str]:
849        return self.linker.get_asneeded_args()
850
851    def headerpad_args(self) -> T.List[str]:
852        return self.linker.headerpad_args()
853
854    def bitcode_args(self) -> T.List[str]:
855        return self.linker.bitcode_args()
856
857    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
858        return self.linker.get_buildtype_args(buildtype)
859
860    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
861                        suffix: str, soversion: str,
862                        darwin_versions: T.Tuple[str, str],
863                        is_shared_module: bool) -> T.List[str]:
864        return self.linker.get_soname_args(
865            env, prefix, shlib_name, suffix, soversion,
866            darwin_versions, is_shared_module)
867
868    def get_target_link_args(self, target):
869        return target.link_args
870
871    def get_dependency_compile_args(self, dep):
872        return dep.get_compile_args()
873
874    def get_dependency_link_args(self, dep):
875        return dep.get_link_args()
876
877    @classmethod
878    def use_linker_args(cls, linker: str) -> T.List[str]:
879        """Get a list of arguments to pass to the compiler to set the linker.
880        """
881        return []
882
883    def get_coverage_link_args(self) -> T.List[str]:
884        return self.linker.get_coverage_args()
885
886    def get_disable_assert_args(self) -> T.List[str]:
887        return []
888
889
890def get_largefile_args(compiler):
891    '''
892    Enable transparent large-file-support for 32-bit UNIX systems
893    '''
894    if not (compiler.get_argument_syntax() == 'msvc' or compiler.info.is_darwin()):
895        # Enable large-file support unconditionally on all platforms other
896        # than macOS and MSVC. macOS is now 64-bit-only so it doesn't
897        # need anything special, and MSVC doesn't have automatic LFS.
898        # You must use the 64-bit counterparts explicitly.
899        # glibc, musl, and uclibc, and all BSD libcs support this. On Android,
900        # support for transparent LFS is available depending on the version of
901        # Bionic: https://github.com/android/platform_bionic#32-bit-abi-bugs
902        # https://code.google.com/p/android/issues/detail?id=64613
903        #
904        # If this breaks your code, fix it! It's been 20+ years!
905        return ['-D_FILE_OFFSET_BITS=64']
906        # We don't enable -D_LARGEFILE64_SOURCE since that enables
907        # transitionary features and must be enabled by programs that use
908        # those features explicitly.
909    return []
910
911
912def get_args_from_envvars(lang: str,
913                          for_machine: MachineChoice,
914                          is_cross: bool,
915                          use_linker_args: bool) -> T.Tuple[T.List[str], T.List[str]]:
916    """
917    Returns a tuple of (compile_flags, link_flags) for the specified language
918    from the inherited environment
919    """
920    if lang not in cflags_mapping:
921        return [], []
922
923    compile_flags = []  # type: T.List[str]
924    link_flags = []     # type: T.List[str]
925
926    env_compile_flags = get_env_var(for_machine, is_cross, cflags_mapping[lang])
927    if env_compile_flags is not None:
928        compile_flags += split_args(env_compile_flags)
929
930    # Link flags (same for all languages)
931    if lang in languages_using_ldflags:
932        link_flags += LinkerEnvVarsMixin.get_args_from_envvars(for_machine, is_cross)
933    if use_linker_args:
934        # When the compiler is used as a wrapper around the linker (such as
935        # with GCC and Clang), the compile flags can be needed while linking
936        # too. This is also what Autotools does. However, we don't want to do
937        # this when the linker is stand-alone such as with MSVC C/C++, etc.
938        link_flags = compile_flags + link_flags
939
940    # Pre-processor flags for certain languages
941    if lang in languages_using_cppflags:
942        env_preproc_flags = get_env_var(for_machine, is_cross, 'CPPFLAGS')
943        if env_preproc_flags is not None:
944            compile_flags += split_args(env_preproc_flags)
945
946    return compile_flags, link_flags
947
948
949def get_global_options(lang: str,
950                       comp: T.Type[Compiler],
951                       for_machine: MachineChoice,
952                       is_cross: bool,
953                       properties: Properties) -> T.Dict[str, coredata.UserOption]:
954    """Retreive options that apply to all compilers for a given language."""
955    description = 'Extra arguments passed to the {}'.format(lang)
956    opts = {
957        'args': coredata.UserArrayOption(
958            description + ' compiler',
959            [], split_args=True, user_input=True, allow_dups=True),
960        'link_args': coredata.UserArrayOption(
961            description + ' linker',
962            [], split_args=True, user_input=True, allow_dups=True),
963    }
964
965    # Get from env vars.
966    compile_args, link_args = get_args_from_envvars(
967        lang,
968        for_machine,
969        is_cross,
970        comp.INVOKES_LINKER)
971
972    for k, o in opts.items():
973        user_k = lang + '_' + k
974        if user_k in properties:
975            # Get from configuration files.
976            o.set_value(properties[user_k])
977        elif k == 'args':
978            o.set_value(compile_args)
979        elif k == 'link_args':
980            o.set_value(link_args)
981
982    return opts
983