1# Copyright 2012-2017 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 typing as T
16
17from .. import coredata
18from ..mesonlib import MachineChoice, OptionKey
19
20from .mixins.clike import CLikeCompiler
21from .compilers import Compiler
22from .mixins.gnu import GnuCompiler
23from .mixins.clang import ClangCompiler
24
25if T.TYPE_CHECKING:
26    from ..programs import ExternalProgram
27    from ..envconfig import MachineInfo
28    from ..environment import Environment
29    from ..linkers import DynamicLinker
30
31class ObjCPPCompiler(CLikeCompiler, Compiler):
32
33    language = 'objcpp'
34
35    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
36                 is_cross: bool, info: 'MachineInfo',
37                 exe_wrap: T.Optional['ExternalProgram'],
38                 linker: T.Optional['DynamicLinker'] = None,
39                 full_version: T.Optional[str] = None):
40        Compiler.__init__(self, exelist, version, for_machine, info,
41                          is_cross=is_cross, full_version=full_version,
42                          linker=linker)
43        CLikeCompiler.__init__(self, exe_wrap)
44
45    @staticmethod
46    def get_display_language() -> str:
47        return 'Objective-C++'
48
49    def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
50        code = '#import<stdio.h>\nclass MyClass;int main(void) { return 0; }\n'
51        return self._sanity_check_impl(work_dir, environment, 'sanitycheckobjcpp.mm', code)
52
53
54class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler):
55    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
56                 is_cross: bool, info: 'MachineInfo',
57                 exe_wrapper: T.Optional['ExternalProgram'] = None,
58                 defines: T.Optional[T.Dict[str, str]] = None,
59                 linker: T.Optional['DynamicLinker'] = None,
60                 full_version: T.Optional[str] = None):
61        ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
62                                info, exe_wrapper, linker=linker, full_version=full_version)
63        GnuCompiler.__init__(self, defines)
64        default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
65        self.warn_args = {'0': [],
66                          '1': default_warn_args,
67                          '2': default_warn_args + ['-Wextra'],
68                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}
69
70
71class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
72
73    def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoice,
74                 is_cross: bool, info: 'MachineInfo',
75                 exe_wrapper: T.Optional['ExternalProgram'] = None,
76                 defines: T.Optional[T.Dict[str, str]] = None,
77                 linker: T.Optional['DynamicLinker'] = None,
78                 full_version: T.Optional[str] = None):
79        ObjCPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
80                                info, exe_wrapper, linker=linker, full_version=full_version)
81        ClangCompiler.__init__(self, defines)
82        default_warn_args = ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor']
83        self.warn_args = {'0': [],
84                          '1': default_warn_args,
85                          '2': default_warn_args + ['-Wextra'],
86                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}
87
88    def get_options(self) -> 'coredata.KeyedOptionDictType':
89        opts = super().get_options()
90        opts.update({
91            OptionKey('std', machine=self.for_machine, lang='cpp'): coredata.UserComboOption(
92                'C++ language standard to use',
93                ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17'],
94                'none',
95            )
96        })
97        return opts
98
99    def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
100        args = []
101        std = options[OptionKey('std', machine=self.for_machine, lang='cpp')]
102        if std.value != 'none':
103            args.append('-std=' + std.value)
104        return args
105
106
107class AppleClangObjCPPCompiler(ClangObjCPPCompiler):
108
109    """Handle the differences between Apple's clang and vanilla clang."""
110