• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4#
5# Copyright (c) 2023 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19
20import sys
21import os
22from enum import Enum
23
24from containers.status import throw_exception
25from exceptions.ohos_exception import OHOSException
26from services.interface.build_file_generator_interface import BuildFileGeneratorInterface
27from resources.config import Config
28from containers.arg import Arg, ModuleType
29from util.system_util import SystemUtil
30from util.io_util import IoUtil
31from util.log_util import LogUtil
32
33
34class CMDTYPE(Enum):
35    GEN = 1
36    PATH = 2
37    DESC = 3
38    LS = 4
39    REFS = 5
40    FORMAT = 6
41    CLEAN = 7
42
43
44class Gn(BuildFileGeneratorInterface):
45
46    def __init__(self):
47        super().__init__()
48        self.config = Config()
49        self._regist_gn_path()
50
51    def run(self):
52        self.execute_gn_cmd(CMDTYPE.GEN)
53
54    @throw_exception
55    def execute_gn_cmd(self, cmd_type: int, **kwargs):
56        if cmd_type == CMDTYPE.GEN:
57            return self._execute_gn_gen_cmd()
58        elif cmd_type == CMDTYPE.PATH:
59            return self._execute_gn_path_cmd(**kwargs)
60        elif cmd_type == CMDTYPE.DESC:
61            return self._execute_gn_desc_cmd(**kwargs)
62        elif cmd_type == CMDTYPE.LS:
63            return self._execute_gn_ls_cmd(**kwargs)
64        elif cmd_type == CMDTYPE.REFS:
65            return self._execute_gn_refs_cmd(**kwargs)
66        elif cmd_type == CMDTYPE.FORMAT:
67            return self._execute_gn_format_cmd(**kwargs)
68        elif cmd_type == CMDTYPE.CLEAN:
69            return self._execute_gn_clean_cmd(**kwargs)
70        else:
71            raise OHOSException(
72                'You are tring to use an unsupported gn cmd type "{}"'.format(cmd_type), '3001')
73
74    '''Description: Get gn excutable path and regist it
75    @parameter: none
76    @return: Status
77    '''
78
79    @throw_exception
80    def _regist_gn_path(self):
81        gn_path = os.path.join(self.config.root_path, 'prebuilts/build-tools/{}-x86/bin/gn'
82                .format(sys.platform))
83        if os.path.exists(gn_path):
84            self.exec = gn_path
85        else:
86            raise OHOSException(
87                'There is no gn executable file at {}'.format(gn_path), '0001')
88
89    '''Description: Convert all registed args into a list
90    @parameter: none
91    @return: list of all registed args
92    '''
93
94    def _convert_args(self) -> list:
95        args_list = []
96
97        for key, value in self.args_dict.items():
98            if isinstance(value, bool):
99                args_list.append('{}={}'.format(key, str(value).lower()))
100
101            elif isinstance(value, str):
102                args_list.append('{}="{}"'.format(key, value))
103
104            elif isinstance(value, int):
105                args_list.append('{}={}'.format(key, value))
106
107            elif isinstance(value, list):
108                args_list.append('{}="{}"'.format(key, "&&".join(value)))
109
110        return args_list
111
112    '''Description: Convert all registed flags into a list
113    @parameter: none
114    @return: list of all registed flags
115    '''
116
117    def _convert_flags(self) -> list:
118        flags_list = []
119
120        for key, value in self.flags_dict.items():
121            if key == 'gn_flags' and isinstance(value, list):
122                flags_list += value
123            elif value == '':
124                flags_list.append('{}'.format(key))
125            else:
126                flags_list.append('{}={}'.format(key, str(value)).lower())
127
128        return flags_list
129
130    '''Description: Option validity check
131    @parameter: "option": Option to be checked
132                "args_file": Option config file
133    @return: Inspection result(True|False)
134    '''
135
136    def _check_options_validity(self, option: str, args_file: dict):
137        support_sub_options = args_file.get(
138            "arg_attribute").get("support_sub_options")
139        option_name = option.lstrip('-')
140        option_value = ""
141        if '=' in option:
142            option_name, option_value = option.lstrip('-').split('=')
143        if option_name in support_sub_options:
144            sub_optional_list = support_sub_options.get(
145                option_name).get("arg_attribute").get("optional")
146            if sub_optional_list and option_value not in sub_optional_list:
147                if not len(option_value):
148                    raise OHOSException('ERROR argument "--{}": Invalid choice "{}". '
149                                        'choose from {}'.format(option_name, option_value, sub_optional_list), '3006')
150                else:
151                    raise OHOSException('ERROR argument "--{}": Invalid choice "{}". '
152                                        'choose from {}'.format(option_name, option_value, sub_optional_list), '3003')
153        else:
154            raise OHOSException('ERROR argument "{}": Invalid choice "{}". '
155                                'choose from {}'.format(args_file.get("arg_name"),
156                                                        option, list(support_sub_options.keys())), '3003')
157
158    '''Description: Execute 'gn gen' command using registed args
159    @parameter: kwargs TBD
160    @return: None
161    '''
162
163    @throw_exception
164    def _execute_gn_gen_cmd(self, **kwargs):
165        gn_gen_cmd = [self.exec, 'gen',
166                      '--args={}'.format(' '.join(self._convert_args())),
167                      self.config.out_path] + self._convert_flags()
168        if self.config.os_level == 'mini' or self.config.os_level == 'small':
169            gn_gen_cmd.append(f'--script-executable={sys.executable}')
170        try:
171            LogUtil.write_log(self.config.log_path, 'Excuting gn command: {} {} --args="{}" {}'.format(
172                self.exec, 'gen',
173                ' '.join(self._convert_args()).replace('"', "\\\""),
174                ' '.join(gn_gen_cmd[3:])),
175                'info')
176            SystemUtil.exec_command(gn_gen_cmd, self.config.log_path)
177        except OHOSException:
178            raise OHOSException('GN phase failed', '3000')
179
180    '''Description: Execute 'gn path' command using registed args
181    @parameter: kwargs TBD
182    @return: None
183    '''
184
185    @throw_exception
186    def _execute_gn_path_cmd(self, **kwargs):
187        out_dir = kwargs.get("out_dir")
188        default_options = ['--all']
189        args_file = Arg.read_args_file(ModuleType.TOOL)['path']
190        if (os.path.exists(os.path.join(out_dir, "args.gn"))):
191            gn_path_cmd = [self.exec, 'path', out_dir]
192            for arg in kwargs.get('args_list'):
193                if arg.startswith('-'):
194                    self._check_options_validity(arg, args_file)
195                gn_path_cmd.append(arg)
196            gn_path_cmd.extend(default_options)
197            sort_index = gn_path_cmd.index
198            gn_path_cmd = list(set(gn_path_cmd))
199            gn_path_cmd.sort(key=sort_index)
200            SystemUtil.exec_command(gn_path_cmd)
201        else:
202            raise OHOSException(
203                '"{}" Not a build directory.'.format(out_dir), '3004')
204
205    '''Description: Execute 'gn desc' command using registed args
206    @parameter: kwargs TBD
207    @return: None
208    '''
209
210    @throw_exception
211    def _execute_gn_desc_cmd(self, **kwargs):
212        out_dir = kwargs.get("out_dir")
213        default_options = ['--tree', '--blame']
214        args_file = Arg.read_args_file(ModuleType.TOOL)['desc']
215        if (os.path.exists(os.path.join(out_dir, "args.gn"))):
216            gn_desc_cmd = [self.exec, 'desc', out_dir]
217            for arg in kwargs.get('args_list'):
218                if arg.startswith('-'):
219                    self._check_options_validity(arg, args_file)
220                gn_desc_cmd.append(arg)
221            gn_desc_cmd.extend(default_options)
222            sort_index = gn_desc_cmd.index
223            gn_desc_cmd = list(set(gn_desc_cmd))
224            gn_desc_cmd.sort(key=sort_index)
225            SystemUtil.exec_command(gn_desc_cmd)
226        else:
227            raise OHOSException(
228                '"{}" Not a build directory.'.format(out_dir), '3004')
229
230    '''Description: Execute 'gn ls' command using registed args
231    @parameter: kwargs TBD
232    @return: None
233    '''
234
235    @throw_exception
236    def _execute_gn_ls_cmd(self, **kwargs):
237        out_dir = kwargs.get("out_dir")
238        args_file = Arg.read_args_file(ModuleType.TOOL)['ls']
239        if (os.path.exists(os.path.join(out_dir, "args.gn"))):
240            gn_ls_cmd = [self.exec, 'ls', out_dir]
241            for arg in kwargs.get('args_list'):
242                if arg.startswith('-'):
243                    self._check_options_validity(arg, args_file)
244                gn_ls_cmd.append(arg)
245            SystemUtil.exec_command(gn_ls_cmd)
246        else:
247            raise OHOSException(
248                '"{}" Not a build directory.'.format(out_dir), '3004')
249
250    '''Description: Execute 'gn refs' command using registed args
251    @parameter: kwargs TBD
252    @return: None
253    '''
254
255    @throw_exception
256    def _execute_gn_refs_cmd(self, **kwargs):
257        out_dir = kwargs.get("out_dir")
258        args_file = Arg.read_args_file(ModuleType.TOOL)['refs']
259        if (os.path.exists(os.path.join(out_dir, "args.gn"))):
260            gn_refs_cmd = [self.exec, 'refs', out_dir]
261            for arg in kwargs.get('args_list'):
262                if arg.startswith('-'):
263                    self._check_options_validity(arg, args_file)
264                gn_refs_cmd.append(arg)
265            SystemUtil.exec_command(gn_refs_cmd)
266        else:
267            raise OHOSException(
268                '"{}" Not a build directory.'.format(out_dir), '3004')
269
270    '''Description: Execute 'gn format' command using registed args
271    @parameter: kwargs TBD
272    @return: None
273    '''
274
275    @throw_exception
276    def _execute_gn_format_cmd(self, **kwargs):
277        gn_format_cmd = [self.exec, 'format']
278        args_file = Arg.read_args_file(ModuleType.TOOL)['format']
279        for arg in kwargs.get("args_list"):
280            if (arg.endswith('.gn')):
281                if (os.path.exists(arg)):
282                    gn_format_cmd.append(arg)
283                else:
284                    raise OHOSException(
285                        "ERROR Couldn't read '{}'".format(arg), '3005')
286            else:
287                if arg.startswith('-'):
288                    self._check_options_validity(arg, args_file)
289                gn_format_cmd.append(arg)
290        SystemUtil.exec_command(gn_format_cmd)
291
292    '''Description: Execute 'gn clean' command using registed args
293    @parameter: kwargs TBD
294    @return: None
295    '''
296
297    @throw_exception
298    def _execute_gn_clean_cmd(self, **kwargs):
299        out_dir = kwargs.get("out_dir")
300        if (os.path.exists(os.path.join(out_dir, "args.gn"))):
301            gn_clean_cmd = [self.exec, 'clean', out_dir]
302            SystemUtil.exec_command(gn_clean_cmd)
303        else:
304            raise OHOSException('"{}" Not a build directory.'
305                                'Usage: "gn clean <out_dir>"'.format(out_dir), '3004')
306