• 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
19import os
20import argparse
21import sys
22
23from enum import Enum
24from resources.global_var import CURRENT_ARGS_DIR
25from resources.global_var import CURRENT_BUILD_ARGS
26from resources.global_var import DEFAULT_BUILD_ARGS
27from resources.global_var import CURRENT_SET_ARGS
28from resources.global_var import DEFAULT_SET_ARGS
29from resources.global_var import CURRENT_CLEAN_ARGS
30from resources.global_var import DEFAULT_CLEAN_ARGS
31from resources.global_var import DEFAULT_ENV_ARGS
32from resources.global_var import CURRENT_ENV_ARGS
33from resources.global_var import DEFAULT_TOOL_ARGS
34from resources.global_var import CURRENT_TOOL_ARGS
35from resources.global_var import DEFAULT_INDEP_BUILD_ARGS
36from resources.global_var import CURRENT_INDEP_BUILD_ARGS
37from resources.global_var import DEFAULT_INSTALL_ARGS
38from resources.global_var import CURRENT_INSTALL_ARGS
39from resources.global_var import DEFAULT_PACKAGE_ARGS
40from resources.global_var import CURRENT_PACKAGE_ARGS
41from resources.global_var import DEFAULT_PUBLISH_ARGS
42from resources.global_var import CURRENT_PUBLISH_ARGS
43from resources.global_var import DEFAULT_UPDATE_ARGS
44from resources.global_var import CURRENT_UPDATE_ARGS
45from resources.global_var import DEFAULT_PUSH_ARGS
46from resources.global_var import CURRENT_PUSH_ARGS
47from resources.global_var import ARGS_DIR
48from exceptions.ohos_exception import OHOSException
49from util.log_util import LogUtil
50from util.io_util import IoUtil
51from util.type_check_util import TypeCheckUtil
52from resolver.args_factory import ArgsFactory
53from containers.status import throw_exception
54
55
56class ModuleType(Enum):
57
58    BUILD = 0
59    SET = 1
60    ENV = 2
61    CLEAN = 3
62    TOOL = 4
63    INDEP_BUILD = 5
64    INSTALL = 6
65    PACKAGE = 7
66    PUBLISH = 8
67    UPDATE = 9
68    PUSH = 10
69
70class ArgType():
71
72    NONE = 0
73    BOOL = 1
74    INT = 2
75    STR = 3
76    LIST = 4
77    DICT = 5
78    SUBPARSERS = 6
79
80    @staticmethod
81    def get_type(value: str):
82        if value == 'bool':
83            return ArgType.BOOL
84        elif value == "int":
85            return ArgType.INT
86        elif value == 'str':
87            return ArgType.STR
88        elif value == "list":
89            return ArgType.LIST
90        elif value == 'dict':
91            return ArgType.DICT
92        elif value == 'subparsers':
93            return ArgType.SUBPARSERS
94        else:
95            return ArgType.NONE
96
97
98class BuildPhase():
99
100    NONE = 0
101    PRE_BUILD = 1
102    PRE_LOAD = 2
103    LOAD = 3
104    PRE_TARGET_GENERATE = 4
105    TARGET_GENERATE = 5
106    POST_TARGET_GENERATE = 6
107    PRE_TARGET_COMPILATION = 7
108    TARGET_COMPILATION = 8
109    POST_TARGET_COMPILATION = 9
110    POST_BUILD = 10
111
112    @staticmethod
113    def get_type(value: str):
114        if value == 'prebuild':
115            return BuildPhase.PRE_BUILD
116        elif value == "preload":
117            return BuildPhase.PRE_LOAD
118        elif value == 'load':
119            return BuildPhase.LOAD
120        elif value == "preTargetGenerate":
121            return BuildPhase.PRE_TARGET_GENERATE
122        elif value == 'targetGenerate':
123            return BuildPhase.TARGET_GENERATE
124        elif value == 'postTargetGenerate':
125            return BuildPhase.POST_TARGET_GENERATE
126        elif value == 'preTargetCompilation':
127            return BuildPhase.PRE_TARGET_COMPILATION
128        elif value == 'targetCompilation':
129            return BuildPhase.TARGET_COMPILATION
130        elif value == 'postTargetCompilation':
131            return BuildPhase.POST_TARGET_COMPILATION
132        elif value == 'postbuild':
133            return BuildPhase.POST_BUILD
134        else:
135            return BuildPhase.NONE
136
137
138class CleanPhase():
139
140    REGULAR = 0
141    DEEP = 1
142    NONE = 2
143
144    @staticmethod
145    def get_type(value: str):
146        if value == 'regular':
147            return CleanPhase.REGULAR
148        elif value == 'deep':
149            return CleanPhase.DEEP
150        else:
151            return CleanPhase.NONE
152
153
154class Arg():
155
156    def __init__(self, name: str, helps: str, phase: str,
157                 attribute: dict, argtype: ArgType, value,
158                 resolve_function: str):
159        self._arg_name = name
160        self._arg_help = helps
161        self._arg_phase = phase
162        self._arg_attribute = attribute
163        self._arg_type = argtype
164        self._arg_value = value
165        self._resolve_function = resolve_function
166
167    @property
168    def arg_name(self):
169        return self._arg_name
170
171    @property
172    def arg_value(self):
173        return self._arg_value
174
175    @arg_value.setter
176    def arg_value(self, value):
177        self._arg_value = value
178
179    @property
180    def arg_help(self):
181        return self._arg_help
182
183    @property
184    def arg_attribute(self):
185        return self._arg_attribute
186
187    @property
188    def arg_phase(self):
189        return self._arg_phase
190
191    @property
192    def arg_type(self):
193        return self._arg_type
194
195    @property
196    def resolve_function(self):
197        return self._resolve_function
198
199    @resolve_function.setter
200    def resolve_function(self, value):
201        self._resolve_function = value
202
203    @staticmethod
204    @throw_exception
205    def create_instance_by_dict(data: dict):
206        arg_name = str(data['arg_name']).replace("-", "_")[2:]
207        arg_help = str(data['arg_help'])
208        arg_phase = BuildPhase.get_type(str(data['arg_phase']))
209        arg_attibute = dict(data['arg_attribute'])
210        arg_type = ArgType.get_type(data['arg_type'])
211        arg_value = ''
212        if arg_type == ArgType.BOOL:
213            arg_value = data['argDefault']
214        elif arg_type == ArgType.INT:
215            arg_value = int(data['argDefault'])
216        elif arg_type == ArgType.STR:
217            arg_value = data['argDefault']
218        elif arg_type == ArgType.LIST:
219            arg_value = list(data['argDefault'])
220        elif arg_type == ArgType.DICT:
221            arg_value = dict(data['argDefault'])
222        elif arg_type == ArgType.SUBPARSERS:
223            arg_value = list(data['argDefault'])
224        else:
225            raise OHOSException('Unknown arg type "{}" for arg "{}"'.format(
226                arg_type, arg_name), "0003")
227        resolve_function = data['resolve_function']
228        return Arg(arg_name, arg_help, arg_phase, arg_attibute, arg_type, arg_value, resolve_function)
229
230    @staticmethod
231    def get_help(module_type: ModuleType) -> str:
232        parser = argparse.ArgumentParser()
233        all_args = Arg.read_args_file(module_type)
234
235        for arg in all_args.values():
236            arg = dict(arg)
237            ArgsFactory.genetic_add_option(parser, arg)
238
239        parser.usage = 'hb {} [option]'.format(module_type.name.lower())
240        parser.parse_known_args(sys.argv[2:])
241
242        return parser.format_help()
243
244    @staticmethod
245    def parse_all_args(module_type: ModuleType) -> dict:
246        args_dict = {}
247        parser = argparse.ArgumentParser()
248        all_args = Arg.read_args_file(module_type)
249
250        for arg in all_args.values():
251            arg = dict(arg)
252            ArgsFactory.genetic_add_option(parser, arg)
253            oh_arg = Arg.create_instance_by_dict(arg)
254            args_dict[oh_arg.arg_name] = oh_arg
255
256        parser.usage = 'hb {} [option]'.format(module_type.name.lower())
257        parser_args = parser.parse_known_args(sys.argv[2:])
258
259        for oh_arg in args_dict.values():
260            if isinstance(oh_arg, Arg):
261                assigned_value = parser_args[0].__dict__[oh_arg.arg_name]
262                if oh_arg.arg_type == ArgType.LIST:
263                    convert_assigned_value = TypeCheckUtil.tile_list(assigned_value)
264                    convert_assigned_value = list(set(convert_assigned_value))
265                elif oh_arg.arg_type == ArgType.SUBPARSERS:
266                    convert_assigned_value = TypeCheckUtil.tile_list(assigned_value)
267                    if len(convert_assigned_value):
268                        convert_assigned_value = list(set(convert_assigned_value))
269                        convert_assigned_value.extend(parser_args[1])
270                        convert_assigned_value.sort(key=sys.argv[2:].index)
271                elif oh_arg.arg_type == ArgType.BOOL:
272                    if str(assigned_value).lower() == 'false':
273                        convert_assigned_value = False
274                    elif str(assigned_value).lower() == 'true' or assigned_value is None:
275                        convert_assigned_value = True
276                else:
277                    convert_assigned_value = assigned_value
278
279                if oh_arg.arg_attribute.get('deprecated', None) and oh_arg.arg_value != convert_assigned_value:
280                    LogUtil.hb_warning(
281                        'compile option "{}" will be deprecated, \
282                            please consider use other options'.format(oh_arg.arg_name))
283                oh_arg.arg_value = convert_assigned_value
284                Arg.write_args_file(
285                    oh_arg.arg_name, oh_arg.arg_value, module_type)
286
287        return args_dict
288
289    @staticmethod
290    @throw_exception
291    def write_args_file(key: str, value, module_type: ModuleType):
292        args_file_path = ''
293        if module_type == ModuleType.BUILD:
294            args_file_path = CURRENT_BUILD_ARGS
295        elif module_type == ModuleType.SET:
296            args_file_path = CURRENT_SET_ARGS
297        elif module_type == ModuleType.CLEAN:
298            args_file_path = CURRENT_CLEAN_ARGS
299        elif module_type == ModuleType.ENV:
300            args_file_path = CURRENT_ENV_ARGS
301        elif module_type == ModuleType.TOOL:
302            args_file_path = CURRENT_TOOL_ARGS
303        elif module_type == ModuleType.INDEP_BUILD:
304            args_file_path = CURRENT_INDEP_BUILD_ARGS
305        elif module_type == ModuleType.INSTALL:
306            args_file_path = CURRENT_INSTALL_ARGS
307        elif module_type == ModuleType.PACKAGE:
308            args_file_path = CURRENT_PACKAGE_ARGS
309        elif module_type == ModuleType.PUBLISH:
310            args_file_path = CURRENT_PUBLISH_ARGS
311        elif module_type == ModuleType.UPDATE:
312            args_file_path = CURRENT_UPDATE_ARGS
313        elif module_type == ModuleType.PUSH:
314            args_file_path = CURRENT_PUSH_ARGS
315        else:
316            raise OHOSException(
317                'You are trying to write args file, but there is no corresponding module "{}" args file'
318                .format(module_type), "0002")
319        args_file = Arg.read_args_file(module_type)
320        args_file[key]["argDefault"] = value
321        IoUtil.dump_json_file(args_file_path, args_file)
322
323    @staticmethod
324    @throw_exception
325    def read_args_file(module_type: ModuleType):
326        args_file_path = ''
327        default_file_path = ''
328        if module_type == ModuleType.BUILD:
329            args_file_path = CURRENT_BUILD_ARGS
330            default_file_path = DEFAULT_BUILD_ARGS
331        elif module_type == ModuleType.SET:
332            args_file_path = CURRENT_SET_ARGS
333            default_file_path = DEFAULT_SET_ARGS
334        elif module_type == ModuleType.CLEAN:
335            args_file_path = CURRENT_CLEAN_ARGS
336            default_file_path = DEFAULT_CLEAN_ARGS
337        elif module_type == ModuleType.ENV:
338            args_file_path = CURRENT_ENV_ARGS
339            default_file_path = DEFAULT_ENV_ARGS
340        elif module_type == ModuleType.TOOL:
341            args_file_path = CURRENT_TOOL_ARGS
342            default_file_path = DEFAULT_TOOL_ARGS
343        elif module_type == ModuleType.INDEP_BUILD:
344            args_file_path = CURRENT_INDEP_BUILD_ARGS
345            default_file_path = DEFAULT_INDEP_BUILD_ARGS
346        elif module_type == ModuleType.INSTALL:
347            args_file_path = CURRENT_INSTALL_ARGS
348            default_file_path = DEFAULT_INSTALL_ARGS
349        elif module_type == ModuleType.PACKAGE:
350            args_file_path = CURRENT_PACKAGE_ARGS
351            default_file_path = DEFAULT_PACKAGE_ARGS
352        elif module_type == ModuleType.PUBLISH:
353            args_file_path = CURRENT_PUBLISH_ARGS
354            default_file_path = DEFAULT_PUBLISH_ARGS
355        elif module_type == ModuleType.UPDATE:
356            args_file_path = CURRENT_UPDATE_ARGS
357            default_file_path = DEFAULT_UPDATE_ARGS
358        elif module_type == ModuleType.PUSH:
359            args_file_path = CURRENT_PUSH_ARGS
360            default_file_path = DEFAULT_PUSH_ARGS
361        else:
362            raise OHOSException(
363                'You are trying to read args file, but there is no corresponding module "{}" args file'
364                .format(module_type.name.lower()), "0018")
365        if not os.path.exists(CURRENT_ARGS_DIR):
366            os.makedirs(CURRENT_ARGS_DIR, exist_ok=True)
367        if not os.path.exists(args_file_path):
368            IoUtil.copy_file(src=default_file_path, dst=args_file_path)
369        return IoUtil.read_json_file(args_file_path)
370
371    @staticmethod
372    def clean_args_file():
373        if os.path.exists(CURRENT_ARGS_DIR):
374            for file in os.listdir(CURRENT_ARGS_DIR):
375                if file.endswith('.json') and os.path.exists(os.path.join(CURRENT_ARGS_DIR, file)):
376                    os.remove(os.path.join(CURRENT_ARGS_DIR, file))
377
378    @staticmethod
379    def clean_args_file_by_type(module_type: ModuleType):
380        args_file_path = ''
381        if module_type == ModuleType.INSTALL:
382            args_file_path = CURRENT_INSTALL_ARGS
383        elif module_type == ModuleType.PACKAGE:
384            args_file_path = CURRENT_PACKAGE_ARGS
385        elif module_type == ModuleType.UPDATE:
386            args_file_path = CURRENT_UPDATE_ARGS
387        elif module_type == ModuleType.ENV:
388            args_file_path = CURRENT_ENV_ARGS
389        elif module_type == ModuleType.INDEP_BUILD:
390            args_file_path = CURRENT_INDEP_BUILD_ARGS
391        elif module_type == ModuleType.PUSH:
392            args_file_path = CURRENT_PUSH_ARGS
393        if os.path.exists(args_file_path):
394            os.remove(args_file_path)
395