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