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 os.path, subprocess
16import typing as T
17
18from ..mesonlib import EnvironmentException
19
20from .compilers import Compiler, MachineChoice, mono_buildtype_args
21from .mixins.islinker import BasicLinkerIsCompilerMixin
22
23if T.TYPE_CHECKING:
24    from ..envconfig import MachineInfo
25
26cs_optimization_args = {'0': [],
27                        'g': [],
28                        '1': ['-optimize+'],
29                        '2': ['-optimize+'],
30                        '3': ['-optimize+'],
31                        's': ['-optimize+'],
32                        }
33
34
35class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
36
37    language = 'cs'
38
39    def __init__(self, exelist, version, for_machine: MachineChoice,
40                 info: 'MachineInfo', comp_id, runner=None):
41        super().__init__(exelist, version, for_machine, info)
42        self.id = comp_id
43        self.is_cross = False
44        self.runner = runner
45
46    @classmethod
47    def get_display_language(cls):
48        return 'C sharp'
49
50    def get_always_args(self):
51        return ['/nologo']
52
53    def get_linker_always_args(self):
54        return ['/nologo']
55
56    def get_output_args(self, fname):
57        return ['-out:' + fname]
58
59    def get_link_args(self, fname):
60        return ['-r:' + fname]
61
62    def get_werror_args(self):
63        return ['-warnaserror']
64
65    def split_shlib_to_parts(self, fname):
66        return None, fname
67
68    def get_dependency_gen_args(self, outtarget, outfile):
69        return []
70
71    def get_linker_exelist(self):
72        return self.exelist[:]
73
74    def get_compile_only_args(self):
75        return []
76
77    def get_coverage_args(self):
78        return []
79
80    def get_std_exe_link_args(self):
81        return []
82
83    def get_include_args(self, path):
84        return []
85
86    def get_pic_args(self):
87        return []
88
89    def compute_parameters_with_absolute_paths(self, parameter_list, build_dir):
90        for idx, i in enumerate(parameter_list):
91            if i[:2] == '-L':
92                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
93            if i[:5] == '-lib:':
94                parameter_list[idx] = i[:5] + os.path.normpath(os.path.join(build_dir, i[5:]))
95
96        return parameter_list
97
98    def name_string(self):
99        return ' '.join(self.exelist)
100
101    def get_pch_use_args(self, pch_dir, header):
102        return []
103
104    def get_pch_name(self, header_name):
105        return ''
106
107    def sanity_check(self, work_dir, environment):
108        src = 'sanity.cs'
109        obj = 'sanity.exe'
110        source_name = os.path.join(work_dir, src)
111        with open(source_name, 'w') as ofile:
112            ofile.write('''public class Sanity {
113    static public void Main () {
114    }
115}
116''')
117        pc = subprocess.Popen(self.exelist + self.get_always_args() + [src], cwd=work_dir)
118        pc.wait()
119        if pc.returncode != 0:
120            raise EnvironmentException('Mono compiler %s can not compile programs.' % self.name_string())
121        if self.runner:
122            cmdlist = [self.runner, obj]
123        else:
124            cmdlist = [os.path.join(work_dir, obj)]
125        pe = subprocess.Popen(cmdlist, cwd=work_dir)
126        pe.wait()
127        if pe.returncode != 0:
128            raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string())
129
130    def needs_static_linker(self):
131        return False
132
133    def get_buildtype_args(self, buildtype):
134        return mono_buildtype_args[buildtype]
135
136    def get_debug_args(self, is_debug):
137        return ['-debug'] if is_debug else []
138
139    def get_optimization_args(self, optimization_level):
140        return cs_optimization_args[optimization_level]
141
142
143class MonoCompiler(CsCompiler):
144    def __init__(self, exelist, version, for_machine: MachineChoice,
145                 info: 'MachineInfo'):
146        super().__init__(exelist, version, for_machine, info, 'mono',
147                         runner='mono')
148
149
150class VisualStudioCsCompiler(CsCompiler):
151    def __init__(self, exelist, version, for_machine: MachineChoice,
152                 info: 'MachineInfo'):
153        super().__init__(exelist, version, for_machine, info, 'csc')
154
155    def get_buildtype_args(self, buildtype):
156        res = mono_buildtype_args[buildtype]
157        if not self.info.is_windows():
158            tmp = []
159            for flag in res:
160                if flag == '-debug':
161                    flag = '-debug:portable'
162                tmp.append(flag)
163            res = tmp
164        return res
165