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