1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# 5# Copyright (c) 2020 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 18import os 19import platform 20from distutils.spawn import find_executable 21 22from hb_internal import CONFIG_JSON 23from hb_internal import CONFIG_STRUCT 24from hb_internal import BUILD_TOOLS_CFG 25from hb_internal.common.utils import read_json_file 26from hb_internal.common.utils import dump_json_file 27from hb_internal.common.utils import Singleton 28from hb_internal.common.utils import OHOSException 29from hb_internal.common.utils import download_tool 30from hb_internal.common.utils import makedirs 31 32 33class Config(metaclass=Singleton): 34 def __init__(self): 35 self.config_json = CONFIG_JSON 36 37 config_content = read_json_file(self.config_json) 38 self._root_path = config_content.get('root_path', None) 39 self._board = config_content.get('board', None) 40 self._kernel = config_content.get('kernel', None) 41 self._product = config_content.get('product', None) 42 self._product_path = config_content.get('product_path', None) 43 self._device_path = config_content.get('device_path', None) 44 self._device_company = config_content.get('device_company', None) 45 self._patch_cache = config_content.get('patch_cache', None) 46 self._version = config_content.get('version', '3.0') 47 self._os_level = config_content.get('os_level', 'small') 48 self._product_json = config_content.get('product_json', None) 49 self._target_cpu = config_content.get('target_cpu', None) 50 self._target_os = config_content.get('target_os', None) 51 self._out_path = config_content.get('out_path', None) 52 self.fs_attr = set() 53 self.platform = platform.system() 54 55 @property 56 def target_os(self): 57 return self._target_os 58 59 @target_os.setter 60 def target_os(self, value): 61 self._target_os = value 62 self.config_update('target_os', self._target_os) 63 64 @property 65 def target_cpu(self): 66 return self._target_cpu 67 68 @target_cpu.setter 69 def target_cpu(self, value): 70 self._target_cpu = value 71 self.config_update('target_cpu', self._target_cpu) 72 73 @property 74 def version(self): 75 return self._version 76 77 @version.setter 78 def version(self, value): 79 self._version = value 80 self.config_update('version', self._version) 81 82 @property 83 def os_level(self): 84 return self._os_level 85 86 @os_level.setter 87 def os_level(self, value): 88 self._os_level = value 89 self.config_update('os_level', self._os_level) 90 91 @property 92 def product_json(self): 93 return self._product_json 94 95 @product_json.setter 96 def product_json(self, value): 97 self._product_json = value 98 self.config_update('product_json', self._product_json) 99 100 @property 101 def root_path(self): 102 if self._root_path is None: 103 raise OHOSException('Failed to get root_path. ' 104 'Please run command "hb set" to ' 105 'init OHOS development environment') 106 107 return self._root_path 108 109 @root_path.setter 110 def root_path(self, value): 111 self._root_path = os.path.abspath(value) 112 if not os.path.isdir(self._root_path): 113 raise OHOSException(f'{self._root_path} is not a valid path') 114 115 config_path = os.path.join(self._root_path, 'ohos_config.json') 116 if not os.path.isfile(config_path): 117 self.config_create(config_path) 118 self.config_update('root_path', self._root_path) 119 120 @property 121 def board(self): 122 if self._board is None: 123 raise OHOSException('Failed to get board. ' 124 'Please run command "hb set" to ' 125 'init OHOS development environment') 126 return self._board 127 128 @board.setter 129 def board(self, value): 130 self._board = value 131 self.config_update('board', self._board) 132 133 @property 134 def device_company(self): 135 if self._device_company is None: 136 raise OHOSException('Failed to get device_company. ' 137 'Please run command "hb set" to ' 138 'init OHOS development environment') 139 return self._device_company 140 141 @device_company.setter 142 def device_company(self, value): 143 self._device_company = value 144 self.config_update('device_company', self._device_company) 145 146 @property 147 def kernel(self): 148 return self._kernel 149 150 @kernel.setter 151 def kernel(self, value): 152 self._kernel = value 153 self.config_update('kernel', self._kernel) 154 155 @property 156 def product(self): 157 if self._product is None: 158 raise OHOSException('Failed to get product. ' 159 'Please run command "hb set" to ' 160 'init OHOS development environment') 161 return self._product 162 163 @product.setter 164 def product(self, value): 165 self._product = value 166 self.config_update('product', self._product) 167 168 @property 169 def product_path(self): 170 if self._product_path is None: 171 raise OHOSException('Failed to get product_path. ' 172 'Please run command "hb set" to ' 173 'init OHOS development environment') 174 return self._product_path 175 176 @product_path.setter 177 def product_path(self, value): 178 self._product_path = value 179 self.config_update('product_path', self._product_path) 180 181 @property 182 def gn_product_path(self): 183 return self.product_path.replace(self.root_path, '/') 184 185 @property 186 def device_path(self): 187 if self._device_path is None: 188 raise OHOSException('Failed to get device_path. ' 189 'Please run command "hb set" to ' 190 'init OHOS development environment') 191 return self._device_path 192 193 @device_path.setter 194 def device_path(self, value): 195 self._device_path = value 196 self.config_update('device_path', self._device_path) 197 198 @property 199 def gn_device_path(self): 200 return self.device_path.replace(self.root_path, '/') 201 202 @property 203 def build_path(self): 204 _build_path = os.path.join(self.root_path, 'build', 'lite') 205 if not os.path.isdir(_build_path): 206 raise OHOSException(f'Invalid build path: {_build_path}') 207 return _build_path 208 209 @property 210 def out_path(self): 211 return self._out_path 212 213 @out_path.setter 214 def out_path(self, value): 215 self._out_path = value 216 self.config_update('out_path', self._out_path) 217 218 @property 219 def log_path(self): 220 if self.out_path is not None: 221 return os.path.join(self.out_path, 'build.log') 222 else: 223 raise OHOSException(f'Failed to get log_path') 224 225 @property 226 def vendor_path(self): 227 _vendor_path = os.path.join(self.root_path, 'vendor') 228 if not os.path.isdir(_vendor_path): 229 raise OHOSException(f'Invalid vendor path: {_vendor_path}') 230 return _vendor_path 231 232 @property 233 def built_in_product_path(self): 234 _built_in_product_path = os.path.join(self.root_path, 235 'productdefine/common/products') 236 if not os.path.isdir(_built_in_product_path): 237 raise OHOSException( 238 f'Invalid built-in product path: {_built_in_product_path}') 239 return _built_in_product_path 240 241 @property 242 def built_in_device_path(self): 243 _built_in_device_path = os.path.join(self.root_path, 244 'productdefine/common/device') 245 if not os.path.isdir(_built_in_device_path): 246 raise OHOSException( 247 f'Invalid built-in product path: {_built_in_device_path}') 248 return _built_in_device_path 249 250 @property 251 def build_tools_path(self): 252 try: 253 tools_path = BUILD_TOOLS_CFG[self.platform]['build_tools_path'] 254 return os.path.join(self.root_path, tools_path) 255 except KeyError: 256 raise OHOSException(f'unidentified platform: {self.platform}') 257 258 @property 259 def gn_path(self): 260 repo_gn_path = os.path.join(self.build_tools_path, 'gn') 261 # gn exist. 262 if os.path.isfile(repo_gn_path): 263 return repo_gn_path 264 265 # gn not install, download and extract it. 266 makedirs(self.build_tools_path, exist_ok=True) 267 268 gn_url = BUILD_TOOLS_CFG[self.platform].get('gn') 269 gn_dst = os.path.join(self.build_tools_path, 'gn_pkg') 270 download_tool(gn_url, gn_dst, tgt_dir=self.build_tools_path) 271 272 return repo_gn_path 273 274 @property 275 def ninja_path(self): 276 repo_ninja_path = os.path.join(self.build_tools_path, 'ninja') 277 # ninja exist. 278 if os.path.isfile(repo_ninja_path): 279 return repo_ninja_path 280 281 # ninja not install, download and extract. 282 makedirs(self.build_tools_path, exist_ok=True) 283 284 ninja_url = BUILD_TOOLS_CFG[self.platform].get('ninja') 285 ninja_dst = os.path.join(self.build_tools_path, 'ninja_pkg') 286 download_tool(ninja_url, ninja_dst, tgt_dir=self.build_tools_path) 287 288 return repo_ninja_path 289 290 @property 291 def clang_path(self): 292 repo_clang_path = os.path.join('prebuilts', 'clang', 'ohos', 293 'linux-x86_64', 'llvm') 294 # clang exist 295 if os.path.isdir(repo_clang_path): 296 return f'//{repo_clang_path}' 297 # clang installed manually or auto download 298 else: 299 # already installed manually 300 env_clang_bin_path = find_executable('clang') 301 if env_clang_bin_path is not None: 302 env_clang_path = os.path.abspath( 303 os.path.join(env_clang_bin_path, os.pardir, os.pardir)) 304 305 if os.path.basename(env_clang_path) == 'llvm': 306 return env_clang_path 307 308 # need auto download and extract clang. 309 clang_path = os.path.abspath( 310 os.path.join(repo_clang_path, os.pardir)) 311 makedirs(clang_path, exist_ok=True) 312 313 clang_url = BUILD_TOOLS_CFG[self.platform].get('clang') 314 clang_dst = os.path.join(clang_path, 'clang_pkg') 315 download_tool(clang_url, clang_dst, tgt_dir=clang_path) 316 return f'//{repo_clang_path}' 317 318 @property 319 def patch_cache(self): 320 return self._patch_cache 321 322 @patch_cache.setter 323 def patch_cache(self, value): 324 self._patch_cache = value 325 self.config_update('patch_cache', self._patch_cache) 326 327 def config_create(self, config_path): 328 dump_json_file(config_path, CONFIG_STRUCT) 329 self.config_json = config_path 330 331 def config_update(self, key, value): 332 config_content = read_json_file(self.config_json) 333 config_content[key] = value 334 dump_json_file(self.config_json, config_content) 335