1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2023 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import sys 17import os 18from util.log_util import LogUtil 19from resources.config import Config 20from exceptions.ohos_exception import OHOSException 21from scripts.util.file_utils import read_json_file, write_json_file # noqa: E402 22from containers.status import throw_exception 23from . import merge_platform_build 24 25 26class PlatformsLoader: 27 def __init__(self, platforms_config_file, source_root_dir, root_build_dir, 28 target_arch, scalable_build): 29 self._platforms_config_file = platforms_config_file 30 self._source_root_dir = source_root_dir 31 self._root_build_dir = root_build_dir 32 self._platforms_info = {} 33 self._all_parts = {} 34 self._all_stubs = {} 35 self._is_load = False 36 self._target_arch = target_arch 37 self._scalable_build = scalable_build 38 39 @staticmethod 40 def _load_platform_config(platform_config_file): 41 if not os.path.exists(platform_config_file): 42 raise Exception( 43 "config file '{}' doesn't exist.".format(platform_config_file)) 44 _platform_config = read_json_file(platform_config_file) 45 if _platform_config is None: 46 raise Exception( 47 "read file '{}' failed.".format(platform_config_file)) 48 if 'parts' in _platform_config: 49 parts = _platform_config.get('parts') 50 else: 51 parts = [] 52 if 'stub_parts' in _platform_config: 53 stub_parts = _platform_config.get('stub_parts') 54 else: 55 stub_parts = [] 56 return parts, stub_parts 57 58 @throw_exception 59 def _read_platforms_config(self): 60 if not os.path.exists(self._platforms_config_file): 61 raise OHOSException("config file '{}' doesn't exist.".format( 62 self._platforms_config_file), "2012") 63 config_info = read_json_file(self._platforms_config_file) 64 if config_info is None: 65 raise OHOSException("read file '{}' failed.".format( 66 self._platforms_config_file), "2012") 67 config_version = config_info.get('version') 68 platforms_info = config_info.get('platforms') 69 70 platforms_config = {} 71 for _name, _platform_infos in platforms_info.items(): 72 if config_version >= 2: 73 _info = _platform_infos 74 target_os = _info.get('target_os') 75 target_cpu = _info.get('target_cpu') 76 if target_os is None or target_cpu is None: 77 error_info = "platform '{}' config incorrect,"\ 78 "target_os or target_cpu is None." 79 raise OHOSException(error_info.format(_name), "2012") 80 arch = "{}_{}".format(target_os, target_cpu) 81 if arch in platforms_config: 82 _infos = platforms_config.get(arch) 83 else: 84 _infos = {} 85 _infos[_name] = _info 86 platforms_config[arch] = _infos 87 else: 88 for _info in _platform_infos: 89 target_os = _info.get('target_os') 90 target_cpu = _info.get('target_cpu') 91 if target_os is None or target_cpu is None: 92 error_info = "platform '{}' config incorrect,"\ 93 "target_os or target_cpu is None." 94 raise OHOSException(error_info.format(_name), "2012") 95 arch = "{}_{}".format(target_os, target_cpu) 96 if arch in platforms_config: 97 _infos = platforms_config.get(arch) 98 else: 99 _infos = {} 100 _infos[_name] = _info 101 platforms_config[arch] = _infos 102 return platforms_config 103 104 @throw_exception 105 def _loading(self): 106 if self._is_load: 107 return 108 all_platforms_config = self._read_platforms_config() 109 _platforms_info = all_platforms_config.get(self._target_arch) 110 config_base_dir = os.path.dirname(self._platforms_config_file) 111 all_parts = {} 112 all_stubs = {} 113 if _platforms_info is None: 114 raise OHOSException( 115 'this product do not support thish arch', '2001') 116 for _platform_name, _info in _platforms_info.items(): 117 if self._scalable_build is False: 118 _file_name = _info.get('parts_config') 119 if _file_name is None: 120 _file_name = os.path.join( 121 'target_platforms', "{}.build".format(_platform_name)) 122 _platform_config_file = os.path.join(config_base_dir, 123 _file_name) 124 else: 125 required_build_file = os.path.join( 126 config_base_dir, _info.get('base_parts_config')) 127 optional_build_file = os.path.join( 128 config_base_dir, _info.get('optional_parts_config')) 129 stub_build_file = os.path.join(config_base_dir, 130 _info.get('stub_parts_config')) 131 _platform_config_file = '{}.build'.format(_platform_name) 132 133 merge_platform_build.do_merge(required_build_file, 134 optional_build_file, 135 stub_build_file, 136 _platform_config_file) 137 138 parts, stubs = self._load_platform_config(_platform_config_file) 139 all_parts[_platform_name] = parts 140 all_stubs[_platform_name] = stubs 141 142 self._platforms_info = _platforms_info 143 self._all_parts = all_parts 144 self._all_stubs = all_stubs 145 self._is_load = True 146 147 def get_all_parts(self): 148 self._loading() 149 all_parts = {} 150 for _platform, _parts in self._all_parts.items(): 151 part_list = [] 152 for part_def in _parts: 153 _part_name = part_def.split(':')[1] 154 part_list.append(_part_name) 155 all_parts[_platform] = part_list 156 return all_parts 157 158 def get_all_stubs(self): 159 self._loading() 160 all_parts = {} 161 for _platform, _parts in self._all_stubs.items(): 162 part_list = [] 163 for part_def in _parts: 164 _part_name = part_def.split(':')[1] 165 part_list.append(_part_name) 166 all_parts[_platform] = part_list 167 return all_parts 168 169 def platforms_toolchain(self): 170 self._loading() 171 platform_toolchain = {} 172 toolchain_platform = {} 173 for key, val in self._platforms_info.items(): 174 _toolchain = val.get('toolchain') 175 platform_toolchain[key] = _toolchain 176 toolchain_platform[_toolchain] = key 177 _result = { 178 "platform_toolchain": platform_toolchain, 179 "toolchain_platform": toolchain_platform 180 } 181 return _result 182 183 184def get_platforms_info(platforms_config_file, source_root_dir, root_build_dir, 185 target_arch, config_output_relpath, scalable_build): 186 platform_loader = PlatformsLoader(platforms_config_file, source_root_dir, 187 root_build_dir, target_arch, 188 scalable_build) 189 190 platforms_info_output_dir = 'platforms_info' 191 all_parts = platform_loader.get_all_parts() 192 all_parts_file = os.path.join(source_root_dir, config_output_relpath, 193 platforms_info_output_dir, "all_parts.json") 194 write_json_file(all_parts_file, all_parts) 195 LogUtil.hb_info( 196 "generate all parts of platforms info to '{}'".format(all_parts_file), mode=Config.log_mode) 197 198 # variant to toolchain and toolchain to variant 199 toolchain_to_variant_dict = platform_loader.platforms_toolchain() 200 toolchain_variant_info_file = os.path.join(source_root_dir, 201 config_output_relpath, 202 platforms_info_output_dir, 203 "toolchain_to_variant.json") 204 write_json_file(toolchain_variant_info_file, 205 toolchain_to_variant_dict, 206 check_changes=True) 207 LogUtil.hb_info("generate toolchain to variant of platforms info to '{}'".format( 208 toolchain_variant_info_file), mode=Config.log_mode) 209 210 result = {} 211 result['all_parts'] = all_parts 212 result['all_stubs'] = platform_loader.get_all_stubs() 213 result['variant_toolchain_info'] = toolchain_to_variant_dict 214 return result 215