15f9996aaSopenharmony_ci#!/usr/bin/env python
25f9996aaSopenharmony_ci# -*- coding: utf-8 -*-
35f9996aaSopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd.
45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License.
65f9996aaSopenharmony_ci# You may obtain a copy of the License at
75f9996aaSopenharmony_ci#
85f9996aaSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
95f9996aaSopenharmony_ci#
105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and
145f9996aaSopenharmony_ci# limitations under the License.
155f9996aaSopenharmony_ci
165f9996aaSopenharmony_ciimport sys
175f9996aaSopenharmony_ciimport os
185f9996aaSopenharmony_cifrom util.log_util import LogUtil
195f9996aaSopenharmony_cifrom resources.config import Config
205f9996aaSopenharmony_cifrom exceptions.ohos_exception import OHOSException
215f9996aaSopenharmony_cifrom scripts.util.file_utils import read_json_file, write_json_file  # noqa: E402
225f9996aaSopenharmony_cifrom containers.status import throw_exception
235f9996aaSopenharmony_cifrom . import merge_platform_build
245f9996aaSopenharmony_ci
255f9996aaSopenharmony_ci
265f9996aaSopenharmony_ciclass PlatformsLoader:
275f9996aaSopenharmony_ci    def __init__(self, platforms_config_file, source_root_dir, root_build_dir,
285f9996aaSopenharmony_ci                 target_arch, scalable_build):
295f9996aaSopenharmony_ci        self._platforms_config_file = platforms_config_file
305f9996aaSopenharmony_ci        self._source_root_dir = source_root_dir
315f9996aaSopenharmony_ci        self._root_build_dir = root_build_dir
325f9996aaSopenharmony_ci        self._platforms_info = {}
335f9996aaSopenharmony_ci        self._all_parts = {}
345f9996aaSopenharmony_ci        self._all_stubs = {}
355f9996aaSopenharmony_ci        self._is_load = False
365f9996aaSopenharmony_ci        self._target_arch = target_arch
375f9996aaSopenharmony_ci        self._scalable_build = scalable_build
385f9996aaSopenharmony_ci
395f9996aaSopenharmony_ci    @staticmethod
405f9996aaSopenharmony_ci    def _load_platform_config(platform_config_file):
415f9996aaSopenharmony_ci        if not os.path.exists(platform_config_file):
425f9996aaSopenharmony_ci            raise Exception(
435f9996aaSopenharmony_ci                "config file '{}' doesn't exist.".format(platform_config_file))
445f9996aaSopenharmony_ci        _platform_config = read_json_file(platform_config_file)
455f9996aaSopenharmony_ci        if _platform_config is None:
465f9996aaSopenharmony_ci            raise Exception(
475f9996aaSopenharmony_ci                "read file '{}' failed.".format(platform_config_file))
485f9996aaSopenharmony_ci        if 'parts' in _platform_config:
495f9996aaSopenharmony_ci            parts = _platform_config.get('parts')
505f9996aaSopenharmony_ci        else:
515f9996aaSopenharmony_ci            parts = []
525f9996aaSopenharmony_ci        if 'stub_parts' in _platform_config:
535f9996aaSopenharmony_ci            stub_parts = _platform_config.get('stub_parts')
545f9996aaSopenharmony_ci        else:
555f9996aaSopenharmony_ci            stub_parts = []
565f9996aaSopenharmony_ci        return parts, stub_parts
575f9996aaSopenharmony_ci
585f9996aaSopenharmony_ci    @throw_exception
595f9996aaSopenharmony_ci    def _read_platforms_config(self):
605f9996aaSopenharmony_ci        if not os.path.exists(self._platforms_config_file):
615f9996aaSopenharmony_ci            raise OHOSException("config file '{}' doesn't exist.".format(
625f9996aaSopenharmony_ci                self._platforms_config_file), "2012")
635f9996aaSopenharmony_ci        config_info = read_json_file(self._platforms_config_file)
645f9996aaSopenharmony_ci        if config_info is None:
655f9996aaSopenharmony_ci            raise OHOSException("read file '{}' failed.".format(
665f9996aaSopenharmony_ci                self._platforms_config_file), "2012")
675f9996aaSopenharmony_ci        config_version = config_info.get('version')
685f9996aaSopenharmony_ci        platforms_info = config_info.get('platforms')
695f9996aaSopenharmony_ci
705f9996aaSopenharmony_ci        platforms_config = {}
715f9996aaSopenharmony_ci        for _name, _platform_infos in platforms_info.items():
725f9996aaSopenharmony_ci            if config_version >= 2:
735f9996aaSopenharmony_ci                _info = _platform_infos
745f9996aaSopenharmony_ci                target_os = _info.get('target_os')
755f9996aaSopenharmony_ci                target_cpu = _info.get('target_cpu')
765f9996aaSopenharmony_ci                if target_os is None or target_cpu is None:
775f9996aaSopenharmony_ci                    error_info = "platform '{}' config incorrect,"\
785f9996aaSopenharmony_ci                        "target_os or target_cpu is None."
795f9996aaSopenharmony_ci                    raise OHOSException(error_info.format(_name), "2012")
805f9996aaSopenharmony_ci                arch = "{}_{}".format(target_os, target_cpu)
815f9996aaSopenharmony_ci                if arch in platforms_config:
825f9996aaSopenharmony_ci                    _infos = platforms_config.get(arch)
835f9996aaSopenharmony_ci                else:
845f9996aaSopenharmony_ci                    _infos = {}
855f9996aaSopenharmony_ci                _infos[_name] = _info
865f9996aaSopenharmony_ci                platforms_config[arch] = _infos
875f9996aaSopenharmony_ci            else:
885f9996aaSopenharmony_ci                for _info in _platform_infos:
895f9996aaSopenharmony_ci                    target_os = _info.get('target_os')
905f9996aaSopenharmony_ci                    target_cpu = _info.get('target_cpu')
915f9996aaSopenharmony_ci                    if target_os is None or target_cpu is None:
925f9996aaSopenharmony_ci                        error_info = "platform '{}' config incorrect,"\
935f9996aaSopenharmony_ci                            "target_os or target_cpu is None."
945f9996aaSopenharmony_ci                        raise OHOSException(error_info.format(_name), "2012")
955f9996aaSopenharmony_ci                    arch = "{}_{}".format(target_os, target_cpu)
965f9996aaSopenharmony_ci                    if arch in platforms_config:
975f9996aaSopenharmony_ci                        _infos = platforms_config.get(arch)
985f9996aaSopenharmony_ci                    else:
995f9996aaSopenharmony_ci                        _infos = {}
1005f9996aaSopenharmony_ci                    _infos[_name] = _info
1015f9996aaSopenharmony_ci                    platforms_config[arch] = _infos
1025f9996aaSopenharmony_ci        return platforms_config
1035f9996aaSopenharmony_ci
1045f9996aaSopenharmony_ci    @throw_exception
1055f9996aaSopenharmony_ci    def _loading(self):
1065f9996aaSopenharmony_ci        if self._is_load:
1075f9996aaSopenharmony_ci            return
1085f9996aaSopenharmony_ci        all_platforms_config = self._read_platforms_config()
1095f9996aaSopenharmony_ci        _platforms_info = all_platforms_config.get(self._target_arch)
1105f9996aaSopenharmony_ci        config_base_dir = os.path.dirname(self._platforms_config_file)
1115f9996aaSopenharmony_ci        all_parts = {}
1125f9996aaSopenharmony_ci        all_stubs = {}
1135f9996aaSopenharmony_ci        if _platforms_info is None:
1145f9996aaSopenharmony_ci            raise OHOSException(
1155f9996aaSopenharmony_ci                'this product do not support thish arch', '2001')
1165f9996aaSopenharmony_ci        for _platform_name, _info in _platforms_info.items():
1175f9996aaSopenharmony_ci            if self._scalable_build is False:
1185f9996aaSopenharmony_ci                _file_name = _info.get('parts_config')
1195f9996aaSopenharmony_ci                if _file_name is None:
1205f9996aaSopenharmony_ci                    _file_name = os.path.join(
1215f9996aaSopenharmony_ci                        'target_platforms', "{}.build".format(_platform_name))
1225f9996aaSopenharmony_ci                _platform_config_file = os.path.join(config_base_dir,
1235f9996aaSopenharmony_ci                                                     _file_name)
1245f9996aaSopenharmony_ci            else:
1255f9996aaSopenharmony_ci                required_build_file = os.path.join(
1265f9996aaSopenharmony_ci                    config_base_dir, _info.get('base_parts_config'))
1275f9996aaSopenharmony_ci                optional_build_file = os.path.join(
1285f9996aaSopenharmony_ci                    config_base_dir, _info.get('optional_parts_config'))
1295f9996aaSopenharmony_ci                stub_build_file = os.path.join(config_base_dir,
1305f9996aaSopenharmony_ci                                               _info.get('stub_parts_config'))
1315f9996aaSopenharmony_ci                _platform_config_file = '{}.build'.format(_platform_name)
1325f9996aaSopenharmony_ci
1335f9996aaSopenharmony_ci                merge_platform_build.do_merge(required_build_file,
1345f9996aaSopenharmony_ci                                              optional_build_file,
1355f9996aaSopenharmony_ci                                              stub_build_file,
1365f9996aaSopenharmony_ci                                              _platform_config_file)
1375f9996aaSopenharmony_ci
1385f9996aaSopenharmony_ci            parts, stubs = self._load_platform_config(_platform_config_file)
1395f9996aaSopenharmony_ci            all_parts[_platform_name] = parts
1405f9996aaSopenharmony_ci            all_stubs[_platform_name] = stubs
1415f9996aaSopenharmony_ci
1425f9996aaSopenharmony_ci        self._platforms_info = _platforms_info
1435f9996aaSopenharmony_ci        self._all_parts = all_parts
1445f9996aaSopenharmony_ci        self._all_stubs = all_stubs
1455f9996aaSopenharmony_ci        self._is_load = True
1465f9996aaSopenharmony_ci
1475f9996aaSopenharmony_ci    def get_all_parts(self):
1485f9996aaSopenharmony_ci        self._loading()
1495f9996aaSopenharmony_ci        all_parts = {}
1505f9996aaSopenharmony_ci        for _platform, _parts in self._all_parts.items():
1515f9996aaSopenharmony_ci            part_list = []
1525f9996aaSopenharmony_ci            for part_def in _parts:
1535f9996aaSopenharmony_ci                _part_name = part_def.split(':')[1]
1545f9996aaSopenharmony_ci                part_list.append(_part_name)
1555f9996aaSopenharmony_ci            all_parts[_platform] = part_list
1565f9996aaSopenharmony_ci        return all_parts
1575f9996aaSopenharmony_ci
1585f9996aaSopenharmony_ci    def get_all_stubs(self):
1595f9996aaSopenharmony_ci        self._loading()
1605f9996aaSopenharmony_ci        all_parts = {}
1615f9996aaSopenharmony_ci        for _platform, _parts in self._all_stubs.items():
1625f9996aaSopenharmony_ci            part_list = []
1635f9996aaSopenharmony_ci            for part_def in _parts:
1645f9996aaSopenharmony_ci                _part_name = part_def.split(':')[1]
1655f9996aaSopenharmony_ci                part_list.append(_part_name)
1665f9996aaSopenharmony_ci            all_parts[_platform] = part_list
1675f9996aaSopenharmony_ci        return all_parts
1685f9996aaSopenharmony_ci
1695f9996aaSopenharmony_ci    def platforms_toolchain(self):
1705f9996aaSopenharmony_ci        self._loading()
1715f9996aaSopenharmony_ci        platform_toolchain = {}
1725f9996aaSopenharmony_ci        toolchain_platform = {}
1735f9996aaSopenharmony_ci        for key, val in self._platforms_info.items():
1745f9996aaSopenharmony_ci            _toolchain = val.get('toolchain')
1755f9996aaSopenharmony_ci            platform_toolchain[key] = _toolchain
1765f9996aaSopenharmony_ci            toolchain_platform[_toolchain] = key
1775f9996aaSopenharmony_ci        _result = {
1785f9996aaSopenharmony_ci            "platform_toolchain": platform_toolchain,
1795f9996aaSopenharmony_ci            "toolchain_platform": toolchain_platform
1805f9996aaSopenharmony_ci        }
1815f9996aaSopenharmony_ci        return _result
1825f9996aaSopenharmony_ci
1835f9996aaSopenharmony_ci
1845f9996aaSopenharmony_cidef get_platforms_info(platforms_config_file, source_root_dir, root_build_dir,
1855f9996aaSopenharmony_ci                       target_arch, config_output_relpath, scalable_build):
1865f9996aaSopenharmony_ci    platform_loader = PlatformsLoader(platforms_config_file, source_root_dir,
1875f9996aaSopenharmony_ci                                      root_build_dir, target_arch,
1885f9996aaSopenharmony_ci                                      scalable_build)
1895f9996aaSopenharmony_ci
1905f9996aaSopenharmony_ci    platforms_info_output_dir = 'platforms_info'
1915f9996aaSopenharmony_ci    all_parts = platform_loader.get_all_parts()
1925f9996aaSopenharmony_ci    all_parts_file = os.path.join(source_root_dir, config_output_relpath,
1935f9996aaSopenharmony_ci                                  platforms_info_output_dir, "all_parts.json")
1945f9996aaSopenharmony_ci    write_json_file(all_parts_file, all_parts)
1955f9996aaSopenharmony_ci    LogUtil.hb_info(
1965f9996aaSopenharmony_ci        "generate all parts of platforms info to '{}'".format(all_parts_file), mode=Config.log_mode)
1975f9996aaSopenharmony_ci
1985f9996aaSopenharmony_ci    # variant to toolchain and toolchain to variant
1995f9996aaSopenharmony_ci    toolchain_to_variant_dict = platform_loader.platforms_toolchain()
2005f9996aaSopenharmony_ci    toolchain_variant_info_file = os.path.join(source_root_dir,
2015f9996aaSopenharmony_ci                                               config_output_relpath,
2025f9996aaSopenharmony_ci                                               platforms_info_output_dir,
2035f9996aaSopenharmony_ci                                               "toolchain_to_variant.json")
2045f9996aaSopenharmony_ci    write_json_file(toolchain_variant_info_file,
2055f9996aaSopenharmony_ci                    toolchain_to_variant_dict,
2065f9996aaSopenharmony_ci                    check_changes=True)
2075f9996aaSopenharmony_ci    LogUtil.hb_info("generate toolchain to variant of platforms info to '{}'".format(
2085f9996aaSopenharmony_ci        toolchain_variant_info_file), mode=Config.log_mode)
2095f9996aaSopenharmony_ci
2105f9996aaSopenharmony_ci    result = {}
2115f9996aaSopenharmony_ci    result['all_parts'] = all_parts
2125f9996aaSopenharmony_ci    result['all_stubs'] = platform_loader.get_all_stubs()
2135f9996aaSopenharmony_ci    result['variant_toolchain_info'] = toolchain_to_variant_dict
2145f9996aaSopenharmony_ci    return result
215