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 exceptions.ohos_exception import OHOSException 20from scripts.util.file_utils import read_json_file, write_json_file # noqa: E402 21from containers.status import throw_exception 22from . import merge_platform_build 23 24 25class PlatformsLoader: 26 def __init__(self, platforms_config_file, source_root_dir, root_build_dir, 27 target_arch, scalable_build): 28 self._platforms_config_file = platforms_config_file 29 self._source_root_dir = source_root_dir 30 self._root_build_dir = root_build_dir 31 self._platforms_info = {} 32 self._all_parts = {} 33 self._all_stubs = {} 34 self._is_load = False 35 self._target_arch = target_arch 36 self._scalable_build = scalable_build 37 38 @throw_exception 39 def _read_platforms_config(self): 40 if not os.path.exists(self._platforms_config_file): 41 raise OHOSException("config file '{}' doesn't exist.".format( 42 self._platforms_config_file), "2012") 43 config_info = read_json_file(self._platforms_config_file) 44 if config_info is None: 45 raise OHOSException("read file '{}' failed.".format( 46 self._platforms_config_file), "2012") 47 config_version = config_info.get('version') 48 platforms_info = config_info.get('platforms') 49 50 platforms_config = {} 51 for _name, _platform_infos in platforms_info.items(): 52 if config_version >= 2: 53 _info = _platform_infos 54 target_os = _info.get('target_os') 55 target_cpu = _info.get('target_cpu') 56 if target_os is None or target_cpu is None: 57 error_info = "platform '{}' config incorrect,"\ 58 "target_os or target_cpu is None." 59 raise OHOSException(error_info.format(_name), "2012") 60 arch = "{}_{}".format(target_os, target_cpu) 61 if arch in platforms_config: 62 _infos = platforms_config.get(arch) 63 else: 64 _infos = {} 65 _infos[_name] = _info 66 platforms_config[arch] = _infos 67 else: 68 for _info in _platform_infos: 69 target_os = _info.get('target_os') 70 target_cpu = _info.get('target_cpu') 71 if target_os is None or target_cpu is None: 72 error_info = "platform '{}' config incorrect,"\ 73 "target_os or target_cpu is None." 74 raise OHOSException(error_info.format(_name), "2012") 75 arch = "{}_{}".format(target_os, target_cpu) 76 if arch in platforms_config: 77 _infos = platforms_config.get(arch) 78 else: 79 _infos = {} 80 _infos[_name] = _info 81 platforms_config[arch] = _infos 82 return platforms_config 83 84 @staticmethod 85 def _load_platform_config(platform_config_file): 86 if not os.path.exists(platform_config_file): 87 raise Exception( 88 "config file '{}' doesn't exist.".format(platform_config_file)) 89 _platform_config = read_json_file(platform_config_file) 90 if _platform_config is None: 91 raise Exception( 92 "read file '{}' failed.".format(platform_config_file)) 93 if 'parts' in _platform_config: 94 parts = _platform_config.get('parts') 95 else: 96 parts = [] 97 if 'stub_parts' in _platform_config: 98 stub_parts = _platform_config.get('stub_parts') 99 else: 100 stub_parts = [] 101 return parts, stub_parts 102 103 @throw_exception 104 def _loading(self): 105 if self._is_load: 106 return 107 all_platforms_config = self._read_platforms_config() 108 _platforms_info = all_platforms_config.get(self._target_arch) 109 config_base_dir = os.path.dirname(self._platforms_config_file) 110 all_parts = {} 111 all_stubs = {} 112 if _platforms_info is None: 113 raise OHOSException( 114 'this product do not support thish arch', '2001') 115 for _platform_name, _info in _platforms_info.items(): 116 if self._scalable_build is False: 117 _file_name = _info.get('parts_config') 118 if _file_name is None: 119 _file_name = os.path.join( 120 'target_platforms', "{}.build".format(_platform_name)) 121 _platform_config_file = os.path.join(config_base_dir, 122 _file_name) 123 else: 124 required_build_file = os.path.join( 125 config_base_dir, _info.get('base_parts_config')) 126 optional_build_file = os.path.join( 127 config_base_dir, _info.get('optional_parts_config')) 128 stub_build_file = os.path.join(config_base_dir, 129 _info.get('stub_parts_config')) 130 _platform_config_file = '{}.build'.format(_platform_name) 131 132 merge_platform_build.do_merge(required_build_file, 133 optional_build_file, 134 stub_build_file, 135 _platform_config_file) 136 137 parts, stubs = self._load_platform_config(_platform_config_file) 138 all_parts[_platform_name] = parts 139 all_stubs[_platform_name] = stubs 140 141 self._platforms_info = _platforms_info 142 self._all_parts = all_parts 143 self._all_stubs = all_stubs 144 self._is_load = True 145 146 def get_all_parts(self): 147 self._loading() 148 all_parts = {} 149 for _platform, _parts in self._all_parts.items(): 150 part_list = [] 151 for part_def in _parts: 152 _part_name = part_def.split(':')[1] 153 part_list.append(_part_name) 154 all_parts[_platform] = part_list 155 return all_parts 156 157 def get_all_stubs(self): 158 self._loading() 159 all_parts = {} 160 for _platform, _parts in self._all_stubs.items(): 161 part_list = [] 162 for part_def in _parts: 163 _part_name = part_def.split(':')[1] 164 part_list.append(_part_name) 165 all_parts[_platform] = part_list 166 return all_parts 167 168 def platforms_toolchain(self): 169 self._loading() 170 platform_toolchain = {} 171 toolchain_platform = {} 172 for key, val in self._platforms_info.items(): 173 _toolchain = val.get('toolchain') 174 platform_toolchain[key] = _toolchain 175 toolchain_platform[_toolchain] = key 176 _result = { 177 "platform_toolchain": platform_toolchain, 178 "toolchain_platform": toolchain_platform 179 } 180 return _result 181 182 183def get_platforms_info(platforms_config_file, source_root_dir, root_build_dir, 184 target_arch, config_output_relpath, scalable_build): 185 platform_loader = PlatformsLoader(platforms_config_file, source_root_dir, 186 root_build_dir, target_arch, 187 scalable_build) 188 189 platforms_info_output_dir = 'platforms_info' 190 all_parts = platform_loader.get_all_parts() 191 all_parts_file = os.path.join(source_root_dir, config_output_relpath, 192 platforms_info_output_dir, "all_parts.json") 193 write_json_file(all_parts_file, all_parts) 194 LogUtil.hb_info( 195 "generate all parts of platforms info to '{}'".format(all_parts_file)) 196 197 # variant to toolchain and toolchain to variant 198 toolchain_to_variant_dict = platform_loader.platforms_toolchain() 199 toolchain_variant_info_file = os.path.join(source_root_dir, 200 config_output_relpath, 201 platforms_info_output_dir, 202 "toolchain_to_variant.json") 203 write_json_file(toolchain_variant_info_file, 204 toolchain_to_variant_dict, 205 check_changes=True) 206 LogUtil.hb_info("generate toolchain to variant of platforms info to '{}'".format( 207 toolchain_variant_info_file)) 208 209 result = {} 210 result['all_parts'] = all_parts 211 result['all_stubs'] = platform_loader.get_all_stubs() 212 result['variant_toolchain_info'] = toolchain_to_variant_dict 213 return result 214