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 os 21import sys 22import subprocess 23import json 24 25sys.path.append(os.path.dirname(os.path.abspath(__file__))) # ohos/build/hb dir 26sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # ohos/build dir 27sys.path.append( 28 os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'lite')) # ohos/build/lite dir 29 30from containers.arg import Arg, ModuleType 31from containers.status import throw_exception, judge_indep 32from resources.global_var import ARGS_DIR 33from resources.global_var import CURRENT_OHOS_ROOT 34from exceptions.ohos_exception import OHOSException 35 36from services.preloader import OHOSPreloader 37from services.loader import OHOSLoader 38from services.gn import Gn 39from services.ninja import Ninja 40from services.hpm import Hpm 41from services.indep_build import IndepBuild 42from services.hdc import Hdc 43 44from resolver.build_args_resolver import BuildArgsResolver 45from resolver.set_args_resolver import SetArgsResolver 46from resolver.clean_args_resolver import CleanArgsResolver 47from resolver.env_args_resolver import EnvArgsResolver 48from resolver.tool_args_resolver import ToolArgsResolver 49from resolver.indep_build_args_resolver import IndepBuildArgsResolver 50from resolver.install_args_resolver import InstallArgsResolver 51from resolver.package_args_resolver import PackageArgsResolver 52from resolver.publish_args_resolver import PublishArgsResolver 53from resolver.update_args_resolver import UpdateArgsResolver 54from resolver.push_args_resolver import PushArgsResolver 55 56from modules.interface.module_interface import ModuleInterface 57from modules.interface.build_module_interface import BuildModuleInterface 58from modules.interface.set_module_interface import SetModuleInterface 59from modules.interface.env_module_interface import EnvModuleInterface 60from modules.interface.clean_module_interface import CleanModuleInterface 61from modules.interface.tool_module_interface import ToolModuleInterface 62from modules.interface.indep_build_module_interface import IndepBuildModuleInterface 63from modules.interface.install_module_interface import InstallModuleInterface 64from modules.interface.package_module_interface import PackageModuleInterface 65from modules.interface.publish_module_interface import PublishModuleInterface 66from modules.interface.update_module_interface import UpdateModuleInterface 67from modules.interface.push_module_interface import PushModuleInterface 68 69from modules.ohos_build_module import OHOSBuildModule 70from modules.ohos_set_module import OHOSSetModule 71from modules.ohos_clean_module import OHOSCleanModule 72from modules.ohos_env_module import OHOSEnvModule 73from modules.ohos_tool_module import OHOSToolModule 74from modules.ohos_indep_build_module import OHOSIndepBuildModule 75from modules.ohos_install_module import OHOSInstallModule 76from modules.ohos_package_module import OHOSPackageModule 77from modules.ohos_publish_module import OHOSPublishModule 78from modules.ohos_update_module import OHOSUpdateModule 79from modules.ohos_push_module import OHOSPushModule 80 81from helper.separator import Separator 82from util.log_util import LogUtil 83from util.system_util import SystemUtil 84 85 86class Main(): 87 @staticmethod 88 @throw_exception 89 def main(): 90 main = Main() 91 module_initializers = { 92 'build': main._init_indep_build_module if main._is_indep_build() else main._init_build_module, 93 'init': main._init_hb_init_module, 94 'indep_build': main._init_indep_build_module, 95 'set': main._init_set_module, 96 'env': main._init_env_module, 97 'clean': main._init_clean_module, 98 'tool': main._init_tool_module, 99 'install': main._init_install_module, 100 'package': main._init_package_module, 101 'publish': main._init_publish_module, 102 'update': main._init_update_module, 103 'push': main._push_module 104 } 105 106 module_type = sys.argv[1] 107 if module_type == 'help': 108 for all_module_type in ModuleType: 109 LogUtil.hb_info(Separator.long_line) 110 LogUtil.hb_info(Arg.get_help(all_module_type)) 111 exit() 112 113 if module_type not in module_initializers: 114 raise OHOSException(f'There is no such option {module_type}', '0018') 115 116 start_time = SystemUtil.get_current_time() 117 module = module_initializers[module_type]() 118 try: 119 module.run() 120 if module_type == 'build': 121 LogUtil.hb_info('Cost Time: {}'.format(SystemUtil.get_current_time() - start_time)) 122 except KeyboardInterrupt: 123 for file in os.listdir(ARGS_DIR): 124 if file.endswith('.json') and os.path.exists(os.path.join(ARGS_DIR, file)): 125 os.remove(os.path.join(ARGS_DIR, file)) 126 print('User abort') 127 return -1 128 else: 129 return 0 130 131 def _set_path(self): 132 user_home = os.path.expanduser("~") 133 prebuilts_cache_path = os.path.join(user_home, '.prebuilts_cache', 'hpm', 'node_modules', '.bin') 134 nodejs_bin_path = os.path.join(CURRENT_OHOS_ROOT, 'prebuilts', 'build-tools', 'common', 'nodejs', 'current', 135 'bin') 136 os.environ['PATH'] = prebuilts_cache_path + os.pathsep + nodejs_bin_path + os.pathsep + os.environ['PATH'] 137 138 def _init_build_module(self) -> BuildModuleInterface: 139 args_dict = Arg.parse_all_args(ModuleType.BUILD) 140 141 if args_dict.get("product_name").arg_value != '': 142 set_args_dict = Arg.parse_all_args(ModuleType.SET) 143 set_args_resolver = SetArgsResolver(set_args_dict) 144 ohos_set_module = OHOSSetModule(set_args_dict, set_args_resolver, "") 145 ohos_set_module.set_product() 146 147 preloader = OHOSPreloader() 148 loader = OHOSLoader() 149 generate_ninja = Gn() 150 ninja = Ninja() 151 build_args_resolver = BuildArgsResolver(args_dict) 152 153 return OHOSBuildModule(args_dict, build_args_resolver, preloader, loader, generate_ninja, ninja) 154 155 def _init_hb_init_module(self): 156 subprocess.run([os.path.join(CURRENT_OHOS_ROOT, 'build', 'prebuilts_config.sh')]) 157 sys.exit() 158 159 def _init_set_module(self) -> SetModuleInterface: 160 Arg.clean_args_file() 161 args_dict = Arg.parse_all_args(ModuleType.SET) 162 set_args_resolver = SetArgsResolver(args_dict) 163 from services.menu import Menu 164 menu = Menu() 165 return OHOSSetModule(args_dict, set_args_resolver, menu) 166 167 def _init_env_module(self) -> EnvModuleInterface: 168 if len(sys.argv) > 2 and sys.argv[2] in ['--sshkey', '-s']: 169 self._set_path() 170 subprocess.run(['hpm', 'config', 'set', 'loginUser', str(sys.argv[3])]) 171 subprocess.run(['hpm', 'gen-keys']) 172 key_path = os.path.join(os.path.expanduser("~"), '.hpm', 'key', 'publicKey_' + sys.argv[3] + '.pem') 173 print(f'Please add the content of {key_path} to https://repo.harmonyos.com/#/cn/profile/sshkeys') 174 sys.exit() 175 args_dict = Arg.parse_all_args(ModuleType.ENV) 176 env_args_resolver = EnvArgsResolver(args_dict) 177 return OHOSEnvModule(args_dict, env_args_resolver) 178 179 def _init_clean_module(self) -> CleanModuleInterface: 180 args_dict = Arg.parse_all_args(ModuleType.CLEAN) 181 clean_args_resolever = CleanArgsResolver(args_dict) 182 return OHOSCleanModule(args_dict, clean_args_resolever) 183 184 def _init_tool_module(self) -> ToolModuleInterface: 185 Arg.clean_args_file() 186 args_dict = Arg.parse_all_args(ModuleType.TOOL) 187 generate_ninja = Gn() 188 tool_args_resolever = ToolArgsResolver(args_dict) 189 return OHOSToolModule(args_dict, tool_args_resolever, generate_ninja) 190 191 def _indep_build_command_format_check(self) -> bool: 192 return "-i" in sys.argv[2:-1] and sys.argv[sys.argv.index("-i") + 1][0] != '-' 193 194 def _init_indep_build_module(self) -> IndepBuildModuleInterface: 195 cwd = os.getcwd() 196 if not os.path.exists(os.path.join(cwd, 'build', 'indep_configs', 'build_indep.sh')): 197 print("ERROR: you are running hb build command in wrong dir!") 198 sys.exit() 199 self._set_path() 200 Arg.clean_args_file_by_type(ModuleType.INDEP_BUILD) 201 args_dict = Arg.parse_all_args(ModuleType.INDEP_BUILD) 202 hpm = Hpm() 203 indep_build = IndepBuild() 204 indep_build_args_resolver = IndepBuildArgsResolver(args_dict) 205 return OHOSIndepBuildModule(args_dict, indep_build_args_resolver, hpm, indep_build) 206 207 def _is_indep_build(self) -> bool: 208 if self._indep_build_command_format_check(): 209 print("ERROR: when use hb build command please add -i after component_name") 210 sys.exit() 211 if judge_indep(): 212 return True 213 env_args_dict = Arg.read_args_file(ModuleType.ENV) 214 return env_args_dict.get("indep_build").get("argDefault") 215 216 def _init_install_module(self) -> InstallModuleInterface: 217 self._set_path() 218 Arg.clean_args_file_by_type(ModuleType.INSTALL) 219 args_dict = Arg.parse_all_args(ModuleType.INSTALL) 220 hpm = Hpm() 221 install_args_resolver = InstallArgsResolver(args_dict) 222 return OHOSInstallModule(args_dict, install_args_resolver, hpm) 223 224 def _init_package_module(self) -> PackageModuleInterface: 225 self._set_path() 226 Arg.clean_args_file_by_type(ModuleType.PACKAGE) 227 args_dict = Arg.parse_all_args(ModuleType.PACKAGE) 228 hpm = Hpm() 229 package_args_resolver = PackageArgsResolver(args_dict) 230 return OHOSPackageModule(args_dict, package_args_resolver, hpm) 231 232 def _init_publish_module(self) -> PublishModuleInterface: 233 self._set_path() 234 args_dict = Arg.parse_all_args(ModuleType.PUBLISH) 235 hpm = Hpm() 236 publish_args_resolver = PublishArgsResolver(args_dict) 237 return OHOSPublishModule(args_dict, publish_args_resolver, hpm) 238 239 def _init_update_module(self) -> UpdateModuleInterface: 240 self._set_path() 241 Arg.clean_args_file_by_type(ModuleType.UPDATE) 242 args_dict = Arg.parse_all_args(ModuleType.UPDATE) 243 hpm = Hpm() 244 update_args_resolver = UpdateArgsResolver(args_dict) 245 return OHOSUpdateModule(args_dict, update_args_resolver, hpm) 246 247 def _init_push_module(self) -> PushModuleInterface: 248 args_dict = Arg.parse_all_args(ModuleType.PUSH) 249 hdc = Hdc() 250 update_args_resolver = PushArgsResolver(args_dict) 251 return OHOSPushModule(args_dict, update_args_resolver, hdc) 252 253 def _push_module(self): 254 if sys.argv[2] in ['-h', '-help', 'h', 'help']: 255 print('Please use the command "hb push" like this: hb push component_name -t device_num') 256 sys.exit() 257 check_hdc = subprocess.run(['hdc', '-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 258 if check_hdc.returncode != 0: 259 print("Error: Please make sure 'hdc' is installed and properly configured.") 260 sys.exit() 261 check_device = subprocess.run(['hdc', 'list', 'targets'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, 262 text=True) 263 if check_device.stdout.strip() == "[Empty]": 264 print("Error: Device is not connected.") 265 sys.exit() 266 if len(check_device.stdout.strip().split('\n')) == 1: 267 device = check_device.stdout.strip() 268 else: 269 device = sys.argv[4] 270 if device not in check_device.stdout: 271 print("Error: Wrong device number") 272 sys.exit() 273 subprocess.run(["hdc", "-t", str(device), "shell", "mount", "-o", "rw,remount", "/"], check=True, 274 stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 275 default = os.path.join(CURRENT_OHOS_ROOT, "out", "default") 276 with open(os.path.join(default, "build_configs", "component_mapping.json"), 'r') as r: 277 single_component_path = json.load(r).get("single_component_path") 278 part_path = next(iter(single_component_path.values())) 279 with open(os.path.join(CURRENT_OHOS_ROOT, part_path, "bundle.json"), 'r') as r: 280 bundle = json.load(r) 281 push_list = bundle.get("deployment") 282 if push_list: 283 if not isinstance(push_list, list): 284 print("Error: Deployment value format error, should be in list format!") 285 for one_push in push_list: 286 if one_push.get("src") and not os.path.exists(os.path.join(CURRENT_OHOS_ROOT, one_push.get("src"))): 287 print("Error: The path in src does not exist, please modify the src path!") 288 if one_push.get("src") and one_push.get("target"): 289 subprocess.run( 290 ["hdc", "-t", str(device), "file", "send", os.path.join(CURRENT_OHOS_ROOT, one_push.get("src")), 291 one_push.get("target")], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 292 print("hb push success!") 293 sys.exit() 294 295 296if __name__ == "__main__": 297 sys.exit(Main.main()) 298