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_ci
175f9996aaSopenharmony_ciimport os
185f9996aaSopenharmony_ci
195f9996aaSopenharmony_cifrom resources.config import Config
205f9996aaSopenharmony_cifrom util.log_util import LogUtil
215f9996aaSopenharmony_cifrom util.io_util import IoUtil
225f9996aaSopenharmony_cifrom util.preloader.parse_vendor_product_config import get_vendor_parts_list
235f9996aaSopenharmony_ci
245f9996aaSopenharmony_ci
255f9996aaSopenharmony_ciclass Outputs:
265f9996aaSopenharmony_ci
275f9996aaSopenharmony_ci    def __init__(self, output_dir):
285f9996aaSopenharmony_ci        self.__post_init__(output_dir)
295f9996aaSopenharmony_ci
305f9996aaSopenharmony_ci    def __post_init__(self, output_dir):
315f9996aaSopenharmony_ci        os.makedirs(output_dir, exist_ok=True)
325f9996aaSopenharmony_ci        self.build_prop = os.path.join(output_dir, 'build.prop')
335f9996aaSopenharmony_ci        self.build_config_json = os.path.join(output_dir, 'build_config.json')
345f9996aaSopenharmony_ci        self.parts_json = os.path.join(output_dir, 'parts.json')
355f9996aaSopenharmony_ci        self.parts_config_json = os.path.join(output_dir, 'parts_config.json')
365f9996aaSopenharmony_ci        self.build_gnargs_prop = os.path.join(output_dir, 'build_gnargs.prop')
375f9996aaSopenharmony_ci        self.features_json = os.path.join(output_dir, 'features.json')
385f9996aaSopenharmony_ci        self.syscap_json = os.path.join(output_dir, 'syscap.json')
395f9996aaSopenharmony_ci        self.exclusion_modules_json = os.path.join(output_dir,
405f9996aaSopenharmony_ci                                                   'exclusion_modules.json')
415f9996aaSopenharmony_ci        self.subsystem_config_json = os.path.join(output_dir,
425f9996aaSopenharmony_ci                                                  'subsystem_config.json')
435f9996aaSopenharmony_ci        self.subsystem_config_overlay_json = os.path.join(output_dir,
445f9996aaSopenharmony_ci                                                  'subsystem_config_overlay.json')
455f9996aaSopenharmony_ci        self.platforms_build = os.path.join(output_dir, 'platforms.build')
465f9996aaSopenharmony_ci        self.systemcapability_json = os.path.join(
475f9996aaSopenharmony_ci            output_dir, 'SystemCapability.json')
485f9996aaSopenharmony_ci        self.compile_standard_whitelist_json = os.path.join(output_dir, 'compile_standard_whitelist.json')
495f9996aaSopenharmony_ci        self.compile_env_allowlist_json = os.path.join(output_dir, 'compile_env_allowlist.json')
505f9996aaSopenharmony_ci
515f9996aaSopenharmony_ci
525f9996aaSopenharmony_ciclass Dirs:
535f9996aaSopenharmony_ci
545f9996aaSopenharmony_ci    def __init__(self, config):
555f9996aaSopenharmony_ci        self.__post_init__(config)
565f9996aaSopenharmony_ci
575f9996aaSopenharmony_ci    def __post_init__(self, config):
585f9996aaSopenharmony_ci        self.source_root_dir = config.root_path
595f9996aaSopenharmony_ci        self.built_in_product_dir = config.built_in_product_path
605f9996aaSopenharmony_ci        self.productdefine_dir = os.path.join(
615f9996aaSopenharmony_ci            self.source_root_dir, 'productdefine/common')
625f9996aaSopenharmony_ci        self.built_in_base_dir = os.path.join(self.productdefine_dir, 'base')
635f9996aaSopenharmony_ci
645f9996aaSopenharmony_ci        # Configs of vendor specified products are stored in ${vendor_dir} directory.
655f9996aaSopenharmony_ci        self.vendor_dir = config.vendor_path
665f9996aaSopenharmony_ci        # Configs of device specified products are stored in ${device_dir} directory.
675f9996aaSopenharmony_ci        self.device_dir = os.path.join(config.root_path, 'device')
685f9996aaSopenharmony_ci
695f9996aaSopenharmony_ci        self.subsystem_config_json = os.path.join(
705f9996aaSopenharmony_ci            config.root_path, config.subsystem_config_json)
715f9996aaSopenharmony_ci        self.subsystem_config_overlay_json = os.path.join(config.product_path,
725f9996aaSopenharmony_ci                                                          'subsystem_config_overlay.json')
735f9996aaSopenharmony_ci        self.lite_components_dir = os.path.join(
745f9996aaSopenharmony_ci            config.root_path, 'build/lite/components')
755f9996aaSopenharmony_ci
765f9996aaSopenharmony_ci        self.preloader_output_dir = os.path.join(
775f9996aaSopenharmony_ci            config.root_path, 'out/preloader', config.product)
785f9996aaSopenharmony_ci
795f9996aaSopenharmony_ci
805f9996aaSopenharmony_ciclass Product():
815f9996aaSopenharmony_ci
825f9996aaSopenharmony_ci    def __init__(self, config_dirs: Dirs, ohos_config: Config):
835f9996aaSopenharmony_ci        self._ohos_config = None
845f9996aaSopenharmony_ci        self._dirs = None
855f9996aaSopenharmony_ci        self._name = ""
865f9996aaSopenharmony_ci        self._config = {}
875f9996aaSopenharmony_ci        self._build_vars = {}
885f9996aaSopenharmony_ci        self._parts = {}
895f9996aaSopenharmony_ci        self._syscap_info = {}
905f9996aaSopenharmony_ci        self._device_name = ""
915f9996aaSopenharmony_ci        self._device_info = {}
925f9996aaSopenharmony_ci        self._config_file = ""
935f9996aaSopenharmony_ci        self._version = ''
945f9996aaSopenharmony_ci        self.__post_init__(config_dirs, ohos_config)
955f9996aaSopenharmony_ci
965f9996aaSopenharmony_ci    def __post_init__(self, config_dirs: Dirs, config: Config):
975f9996aaSopenharmony_ci        self._ohos_config = config
985f9996aaSopenharmony_ci        self._dirs = config_dirs
995f9996aaSopenharmony_ci        self._name = config.product
1005f9996aaSopenharmony_ci        self._config_file = config.product_json
1015f9996aaSopenharmony_ci        self._config = self._get_full_product_config()
1025f9996aaSopenharmony_ci        self._version = self._config.get('version', '3.0')
1035f9996aaSopenharmony_ci        self._do_parse()
1045f9996aaSopenharmony_ci
1055f9996aaSopenharmony_ci    # parse product configuration, then generate parts list and build vars
1065f9996aaSopenharmony_ci    def _do_parse(self):
1075f9996aaSopenharmony_ci        self._update_syscap_info()
1085f9996aaSopenharmony_ci        self._update_device()
1095f9996aaSopenharmony_ci        self._update_parts()
1105f9996aaSopenharmony_ci        self._update_build_vars()
1115f9996aaSopenharmony_ci        self._remove_excluded_components()
1125f9996aaSopenharmony_ci
1135f9996aaSopenharmony_ci# update and remove
1145f9996aaSopenharmony_ci
1155f9996aaSopenharmony_ci    # Update the syscap info
1165f9996aaSopenharmony_ci    def _update_syscap_info(self):
1175f9996aaSopenharmony_ci        product_name = self._config.get('product_name')
1185f9996aaSopenharmony_ci        if product_name is None:
1195f9996aaSopenharmony_ci            product_name = ""
1205f9996aaSopenharmony_ci        os_level = self._config.get('type')
1215f9996aaSopenharmony_ci        if os_level is None:
1225f9996aaSopenharmony_ci            os_level = ""
1235f9996aaSopenharmony_ci        api_version = self._config.get('api_version')
1245f9996aaSopenharmony_ci        if api_version is None:
1255f9996aaSopenharmony_ci            api_version = 0
1265f9996aaSopenharmony_ci        manufacturer_id = self._config.get('manufacturer_id')
1275f9996aaSopenharmony_ci        if manufacturer_id is None:
1285f9996aaSopenharmony_ci            manufacturer_id = 0
1295f9996aaSopenharmony_ci        self._syscap_info = {'product': product_name, 'api_version': api_version,
1305f9996aaSopenharmony_ci                             'system_type': os_level, 'manufacturer_id': manufacturer_id}
1315f9996aaSopenharmony_ci
1325f9996aaSopenharmony_ci    # Update the _device_name and _device_info based on the product configuration in the vendor warehouse
1335f9996aaSopenharmony_ci    def _update_device(self):
1345f9996aaSopenharmony_ci        if self._version == "2.0":
1355f9996aaSopenharmony_ci            device_name = self._config.get('product_device')
1365f9996aaSopenharmony_ci            if device_name:
1375f9996aaSopenharmony_ci                self._device_name = device_name
1385f9996aaSopenharmony_ci                self._device_info = self._get_device_info_v2(
1395f9996aaSopenharmony_ci                    device_name, self._dirs.built_in_device_dir)
1405f9996aaSopenharmony_ci        else:
1415f9996aaSopenharmony_ci            device_name = self._config.get('board')
1425f9996aaSopenharmony_ci            if device_name:
1435f9996aaSopenharmony_ci                self._device_name = device_name
1445f9996aaSopenharmony_ci                self._device_info = self._get_device_info_v3(self._config)
1455f9996aaSopenharmony_ci        if self._ohos_config.target_cpu:
1465f9996aaSopenharmony_ci            self._device_info["target_cpu"] = self._ohos_config.target_cpu
1475f9996aaSopenharmony_ci        if self._ohos_config.target_os:
1485f9996aaSopenharmony_ci            self._device_info["target_os"] = self._ohos_config.target_os
1495f9996aaSopenharmony_ci        if self._ohos_config.compile_config:
1505f9996aaSopenharmony_ci            self._device_info[self._ohos_config["compile_config"]] = True
1515f9996aaSopenharmony_ci
1525f9996aaSopenharmony_ci    # Update the _parts based on the product configuration in the vendor warehouse
1535f9996aaSopenharmony_ci    def _update_parts(self):
1545f9996aaSopenharmony_ci        if self._version == "1.0":
1555f9996aaSopenharmony_ci            _parts = {}
1565f9996aaSopenharmony_ci            self._parts = _parts
1575f9996aaSopenharmony_ci        else:
1585f9996aaSopenharmony_ci            # 1. inherit parts information from base config
1595f9996aaSopenharmony_ci            if self._version == "2.0":
1605f9996aaSopenharmony_ci                os_level = self._config.get("type", "standard")
1615f9996aaSopenharmony_ci            else:
1625f9996aaSopenharmony_ci                os_level = self._config.get("type", "mini")
1635f9996aaSopenharmony_ci            # 2. product config based on default minimum system
1645f9996aaSopenharmony_ci            based_on_mininum_system = self._config.get(
1655f9996aaSopenharmony_ci                'based_on_mininum_system')
1665f9996aaSopenharmony_ci            if based_on_mininum_system == "true":
1675f9996aaSopenharmony_ci                self._parts = self._get_base_parts(
1685f9996aaSopenharmony_ci                    self._dirs.built_in_base_dir, os_level)
1695f9996aaSopenharmony_ci            # 3. inherit parts information from inherit config
1705f9996aaSopenharmony_ci            inherit = self._config.get('inherit')
1715f9996aaSopenharmony_ci            if inherit:
1725f9996aaSopenharmony_ci                self._parts.update(
1735f9996aaSopenharmony_ci                    self._get_inherit_parts(inherit, self._dirs.source_root_dir))
1745f9996aaSopenharmony_ci
1755f9996aaSopenharmony_ci            # 4. chipset products relate system parts config
1765f9996aaSopenharmony_ci            sys_info_path = self._config.get('system_component')
1775f9996aaSopenharmony_ci            if sys_info_path:
1785f9996aaSopenharmony_ci                sys_parts = self._get_sys_relate_parts(
1795f9996aaSopenharmony_ci                    sys_info_path, self._parts, self._dirs.source_root_dir)
1805f9996aaSopenharmony_ci                self._parts.update(sys_parts)
1815f9996aaSopenharmony_ci            all_parts = {}
1825f9996aaSopenharmony_ci            if self._version == "2.0":
1835f9996aaSopenharmony_ci                current_product_parts = self._config.get("parts")
1845f9996aaSopenharmony_ci                if current_product_parts:
1855f9996aaSopenharmony_ci                    all_parts.update(current_product_parts)
1865f9996aaSopenharmony_ci            else:
1875f9996aaSopenharmony_ci                all_parts.update(get_vendor_parts_list(self._config))
1885f9996aaSopenharmony_ci                all_parts.update(self._get_product_specific_parts())
1895f9996aaSopenharmony_ci
1905f9996aaSopenharmony_ci                device_name = self._config.get('board')
1915f9996aaSopenharmony_ci                if device_name:
1925f9996aaSopenharmony_ci                    all_parts.update(self._get_device_specific_parts())
1935f9996aaSopenharmony_ci            self._parts.update(all_parts)
1945f9996aaSopenharmony_ci
1955f9996aaSopenharmony_ci    # Update the _build_vars based on the product configuration in the vendor warehouse
1965f9996aaSopenharmony_ci    def _update_build_vars(self):
1975f9996aaSopenharmony_ci        config = self._config
1985f9996aaSopenharmony_ci        build_vars = {}
1995f9996aaSopenharmony_ci        if self._version == "1.0":
2005f9996aaSopenharmony_ci            build_vars = {"os_level": 'large'}
2015f9996aaSopenharmony_ci        else:
2025f9996aaSopenharmony_ci            if self._version == "2.0":
2035f9996aaSopenharmony_ci                build_vars['os_level'] = config.get("type", "standard")
2045f9996aaSopenharmony_ci                device_name = config.get('product_device')
2055f9996aaSopenharmony_ci                if device_name:
2065f9996aaSopenharmony_ci                    build_vars['device_name'] = device_name
2075f9996aaSopenharmony_ci                else:
2085f9996aaSopenharmony_ci                    build_vars['device_name'] = ''
2095f9996aaSopenharmony_ci                build_vars['product_company'] = config.get('product_company')
2105f9996aaSopenharmony_ci            else:
2115f9996aaSopenharmony_ci                build_vars['os_level'] = config.get('type', 'mini')
2125f9996aaSopenharmony_ci                build_vars['device_name'] = config.get('board')
2135f9996aaSopenharmony_ci                if config.get('product_company'):
2145f9996aaSopenharmony_ci                    build_vars['product_company'] = config.get(
2155f9996aaSopenharmony_ci                        'product_company')
2165f9996aaSopenharmony_ci                elif os.path.dirname(self._config_file) != self._dirs.built_in_product_dir:
2175f9996aaSopenharmony_ci                    relpath = os.path.relpath(
2185f9996aaSopenharmony_ci                        self._config_file, self._dirs.vendor_dir)
2195f9996aaSopenharmony_ci                    build_vars['product_company'] = relpath.split('/')[0]
2205f9996aaSopenharmony_ci                else:
2215f9996aaSopenharmony_ci                    build_vars['product_company'] = config.get(
2225f9996aaSopenharmony_ci                        'device_company')
2235f9996aaSopenharmony_ci            build_vars['product_name'] = config.get('product_name')
2245f9996aaSopenharmony_ci            if 'ext_root_proc_conf_path' in config:
2255f9996aaSopenharmony_ci                ext_root_proc_conf_path = os.path.join(
2265f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('ext_root_proc_conf_path'))
2275f9996aaSopenharmony_ci                if os.path.exists(ext_root_proc_conf_path):
2285f9996aaSopenharmony_ci                    build_vars['ext_root_proc_conf_path'] = ext_root_proc_conf_path
2295f9996aaSopenharmony_ci            if 'ext_critical_proc_conf_path' in config:
2305f9996aaSopenharmony_ci                ext_critical_proc_conf_path = os.path.join(
2315f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('ext_critical_proc_conf_path'))
2325f9996aaSopenharmony_ci                if os.path.exists(ext_critical_proc_conf_path):
2335f9996aaSopenharmony_ci                    build_vars['ext_critical_proc_conf_path'] = ext_critical_proc_conf_path
2345f9996aaSopenharmony_ci            if 'ext_sanitizer_check_list_path' in config:
2355f9996aaSopenharmony_ci                ext_sanitizer_check_list_path = os.path.join(
2365f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('ext_sanitizer_check_list_path'))
2375f9996aaSopenharmony_ci                if os.path.exists(ext_sanitizer_check_list_path):
2385f9996aaSopenharmony_ci                    build_vars['ext_sanitizer_check_list_path'] = ext_sanitizer_check_list_path
2395f9996aaSopenharmony_ci            _global_ext_var_file = os.path.join(
2405f9996aaSopenharmony_ci                self._dirs.source_root_dir, "out/products_ext", "global_ext_var_file.gni")
2415f9996aaSopenharmony_ci            if os.path.exists(_global_ext_var_file):
2425f9996aaSopenharmony_ci                build_vars['global_ext_var_file'] = _global_ext_var_file
2435f9996aaSopenharmony_ci            if 'enable_ramdisk' in config:
2445f9996aaSopenharmony_ci                build_vars['enable_ramdisk'] = config.get('enable_ramdisk')
2455f9996aaSopenharmony_ci            if 'enable_absystem' in config:
2465f9996aaSopenharmony_ci                build_vars['enable_absystem'] = config.get('enable_absystem')
2475f9996aaSopenharmony_ci            if 'build_selinux' in config:
2485f9996aaSopenharmony_ci                build_vars['build_selinux'] = config.get('build_selinux')
2495f9996aaSopenharmony_ci            if 'build_seccomp' in config:
2505f9996aaSopenharmony_ci                build_vars['build_seccomp'] = config.get('build_seccomp')
2515f9996aaSopenharmony_ci            if 'support_jsapi' in config:
2525f9996aaSopenharmony_ci                build_vars['support_jsapi'] = config.get('support_jsapi')
2535f9996aaSopenharmony_ci            if 'chipprod_config_path' in config:
2545f9996aaSopenharmony_ci                chipprod_config_path = os.path.join(
2555f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('chipprod_config_path'))
2565f9996aaSopenharmony_ci                if os.path.exists(chipprod_config_path):
2575f9996aaSopenharmony_ci                    build_vars['chipprod_config_path'] = chipprod_config_path
2585f9996aaSopenharmony_ci            if 'ext_sdk_config_file' in config:
2595f9996aaSopenharmony_ci                ext_sdk_config_file = os.path.join(
2605f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('ext_sdk_config_file'))
2615f9996aaSopenharmony_ci                if os.path.exists(ext_sdk_config_file):
2625f9996aaSopenharmony_ci                    build_vars['ext_sdk_config_file'] = ext_sdk_config_file
2635f9996aaSopenharmony_ci            if 'ext_ndk_config_file' in config:
2645f9996aaSopenharmony_ci                ext_ndk_config_file = os.path.join(
2655f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('ext_ndk_config_file'))
2665f9996aaSopenharmony_ci                if os.path.exists(ext_ndk_config_file):
2675f9996aaSopenharmony_ci                    build_vars['ext_ndk_config_file'] = ext_ndk_config_file
2685f9996aaSopenharmony_ci            if 'ext_sign_hap_py_path' in config:
2695f9996aaSopenharmony_ci                path = os.path.join(
2705f9996aaSopenharmony_ci                    self._dirs.source_root_dir, config.get('ext_sign_hap_py_path'))
2715f9996aaSopenharmony_ci                if os.path.exists(path):
2725f9996aaSopenharmony_ci                    build_vars['ext_sign_hap_py_path'] = path
2735f9996aaSopenharmony_ci
2745f9996aaSopenharmony_ci        build_vars.update(self._device_info)
2755f9996aaSopenharmony_ci        if build_vars['os_level'] == 'mini' or build_vars['os_level'] == 'small':
2765f9996aaSopenharmony_ci            toolchain_label = ""
2775f9996aaSopenharmony_ci        else:
2785f9996aaSopenharmony_ci            toolchain_label = '//build/toolchain/{0}:{0}_clang_{1}'.format(
2795f9996aaSopenharmony_ci                self._device_info.get('target_os'), self._device_info.get('target_cpu'))
2805f9996aaSopenharmony_ci        build_vars['product_toolchain_label'] = toolchain_label
2815f9996aaSopenharmony_ci        self._build_vars = build_vars
2825f9996aaSopenharmony_ci
2835f9996aaSopenharmony_ci    # Remove excluded components
2845f9996aaSopenharmony_ci    def _remove_excluded_components(self):
2855f9996aaSopenharmony_ci        items_to_remove = []
2865f9996aaSopenharmony_ci        for part, val in self._parts.items():
2875f9996aaSopenharmony_ci            if "exclude" in val and val["exclude"] == "true":
2885f9996aaSopenharmony_ci                items_to_remove.append(part)
2895f9996aaSopenharmony_ci        for item in items_to_remove:
2905f9996aaSopenharmony_ci            del self._parts[item]
2915f9996aaSopenharmony_ci
2925f9996aaSopenharmony_ci# get method
2935f9996aaSopenharmony_ci
2945f9996aaSopenharmony_ci    # Generate build_info needed for V2 configuration
2955f9996aaSopenharmony_ci    def _get_device_info_v2(self, device_name, config_dir) -> dict:
2965f9996aaSopenharmony_ci        device_config_file = os.path.join(config_dir,
2975f9996aaSopenharmony_ci                                          '{}.json'.format(device_name))
2985f9996aaSopenharmony_ci        device_info = IoUtil.read_json_file(device_config_file)
2995f9996aaSopenharmony_ci        if device_info and device_info.get('device_name') != device_name:
3005f9996aaSopenharmony_ci            raise Exception("device name configuration incorrect in '{}'".format(
3015f9996aaSopenharmony_ci                device_config_file))
3025f9996aaSopenharmony_ci        return device_info
3035f9996aaSopenharmony_ci
3045f9996aaSopenharmony_ci    # Generate build_info needed for V3 configuration
3055f9996aaSopenharmony_ci    def _get_device_info_v3(self, config) -> dict:
3065f9996aaSopenharmony_ci        # NOTE:
3075f9996aaSopenharmony_ci        # Product_name, device_company are necessary for
3085f9996aaSopenharmony_ci        # config.json, DON NOT use .get to replace []
3095f9996aaSopenharmony_ci        device_info = {
3105f9996aaSopenharmony_ci            'device_name': config['board'],
3115f9996aaSopenharmony_ci            'device_company': config['device_company']
3125f9996aaSopenharmony_ci        }
3135f9996aaSopenharmony_ci        if config.get('target_os'):
3145f9996aaSopenharmony_ci            device_info['target_os'] = config.get('target_os')
3155f9996aaSopenharmony_ci        else:
3165f9996aaSopenharmony_ci            device_info['target_os'] = 'ohos'
3175f9996aaSopenharmony_ci        if config.get('target_cpu'):
3185f9996aaSopenharmony_ci            device_info['target_cpu'] = config['target_cpu']
3195f9996aaSopenharmony_ci        else:
3205f9996aaSopenharmony_ci            # Target cpu is used to set default toolchain for standard system.
3215f9996aaSopenharmony_ci            LogUtil.hb_warning(
3225f9996aaSopenharmony_ci                "The target_cpu needs to be specified, default target_cpu=arm")
3235f9996aaSopenharmony_ci            device_info['target_cpu'] = 'arm'
3245f9996aaSopenharmony_ci        if config.get('kernel_version'):
3255f9996aaSopenharmony_ci            device_info['kernel_version'] = config.get('kernel_version')
3265f9996aaSopenharmony_ci        if config.get('device_build_path'):
3275f9996aaSopenharmony_ci            device_info['device_build_path'] = config.get('device_build_path')
3285f9996aaSopenharmony_ci        else:
3295f9996aaSopenharmony_ci            device_build_path = os.path.join(self._dirs.device_dir,
3305f9996aaSopenharmony_ci                                             config['device_company'],
3315f9996aaSopenharmony_ci                                             config['board'])
3325f9996aaSopenharmony_ci            if not os.path.exists(device_build_path):
3335f9996aaSopenharmony_ci                device_build_path = os.path.join(self._dirs.device_dir,
3345f9996aaSopenharmony_ci                                                 'board',
3355f9996aaSopenharmony_ci                                                 config['device_company'],
3365f9996aaSopenharmony_ci                                                 config['board'])
3375f9996aaSopenharmony_ci            device_info['device_build_path'] = device_build_path
3385f9996aaSopenharmony_ci        return device_info
3395f9996aaSopenharmony_ci
3405f9996aaSopenharmony_ci    def _get_device_specific_parts(self) -> dict:
3415f9996aaSopenharmony_ci        info = {}
3425f9996aaSopenharmony_ci        if self._device_info and self._device_info.get('device_build_path'):
3435f9996aaSopenharmony_ci            subsystem_name = 'device_{}'.format(self._device_name)
3445f9996aaSopenharmony_ci            part_name = subsystem_name
3455f9996aaSopenharmony_ci            info['{}:{}'.format(subsystem_name, part_name)] = {}
3465f9996aaSopenharmony_ci        return info
3475f9996aaSopenharmony_ci
3485f9996aaSopenharmony_ci    def _get_device_specific_subsystem(self) -> dict:
3495f9996aaSopenharmony_ci        info = {}
3505f9996aaSopenharmony_ci        subsystem_name = 'device_{}'.format(self._device_name)
3515f9996aaSopenharmony_ci        if self._device_info and self._device_info.get('device_build_path'):
3525f9996aaSopenharmony_ci            info[subsystem_name] = {
3535f9996aaSopenharmony_ci                'name': subsystem_name,
3545f9996aaSopenharmony_ci                'path': self._device_info.get('device_build_path')
3555f9996aaSopenharmony_ci            }
3565f9996aaSopenharmony_ci        return info
3575f9996aaSopenharmony_ci
3585f9996aaSopenharmony_ci    def _get_base_parts(self, base_config_dir, os_level) -> dict:
3595f9996aaSopenharmony_ci        system_base_config_file = os.path.join(base_config_dir,
3605f9996aaSopenharmony_ci                                               '{}_system.json'.format(os_level))
3615f9996aaSopenharmony_ci        if not os.path.exists(system_base_config_file):
3625f9996aaSopenharmony_ci            raise Exception("product configuration '{}' doesn't exist.".format(
3635f9996aaSopenharmony_ci                system_base_config_file))
3645f9996aaSopenharmony_ci        return IoUtil.read_json_file(system_base_config_file)
3655f9996aaSopenharmony_ci
3665f9996aaSopenharmony_ci    def _get_inherit_parts(self, inherit, source_root_dir) -> dict:
3675f9996aaSopenharmony_ci        inherit_parts = {}
3685f9996aaSopenharmony_ci        for _config in inherit:
3695f9996aaSopenharmony_ci            _file = os.path.join(source_root_dir, _config)
3705f9996aaSopenharmony_ci            _info = IoUtil.read_json_file(_file)
3715f9996aaSopenharmony_ci            parts = _info.get('parts')
3725f9996aaSopenharmony_ci            if parts:
3735f9996aaSopenharmony_ci                inherit_parts.update(parts)
3745f9996aaSopenharmony_ci            else:
3755f9996aaSopenharmony_ci                inherit_parts.update(get_vendor_parts_list(_info))
3765f9996aaSopenharmony_ci        return inherit_parts
3775f9996aaSopenharmony_ci
3785f9996aaSopenharmony_ci    def _get_sys_relate_parts(self, system_component_info, _parts, source_root_dir) -> dict:
3795f9996aaSopenharmony_ci        _info = IoUtil.read_json_file(os.path.join(
3805f9996aaSopenharmony_ci            source_root_dir, system_component_info))
3815f9996aaSopenharmony_ci        ret = {}
3825f9996aaSopenharmony_ci        parts = _info.get('parts')
3835f9996aaSopenharmony_ci        if not parts:
3845f9996aaSopenharmony_ci            parts = get_vendor_parts_list(_info)
3855f9996aaSopenharmony_ci        for part, featrue in parts.items():
3865f9996aaSopenharmony_ci            if not _parts.get(part):
3875f9996aaSopenharmony_ci                ret[part] = featrue
3885f9996aaSopenharmony_ci        return ret
3895f9996aaSopenharmony_ci
3905f9996aaSopenharmony_ci    def _get_product_specific_parts(self) -> dict:
3915f9996aaSopenharmony_ci        part_name = 'product_{}'.format(self._name)
3925f9996aaSopenharmony_ci        subsystem_name = part_name
3935f9996aaSopenharmony_ci        info = {}
3945f9996aaSopenharmony_ci        info['{}:{}'.format(subsystem_name, part_name)] = {}
3955f9996aaSopenharmony_ci        return info
3965f9996aaSopenharmony_ci
3975f9996aaSopenharmony_ci    def _get_product_specific_subsystem(self) -> dict:
3985f9996aaSopenharmony_ci        info = {}
3995f9996aaSopenharmony_ci        subsystem_name = 'product_{}'.format(self._name)
4005f9996aaSopenharmony_ci        product_build_path = self._config.get('product_build_path')
4015f9996aaSopenharmony_ci        if product_build_path:
4025f9996aaSopenharmony_ci            info[subsystem_name] = {
4035f9996aaSopenharmony_ci                'name': subsystem_name,
4045f9996aaSopenharmony_ci                'path': product_build_path
4055f9996aaSopenharmony_ci            }
4065f9996aaSopenharmony_ci        return info
4075f9996aaSopenharmony_ci
4085f9996aaSopenharmony_ci    def _get_full_product_config(self) -> dict:
4095f9996aaSopenharmony_ci        config = IoUtil.read_json_file(self._config_file)
4105f9996aaSopenharmony_ci        if config.get("version") != '2.0':
4115f9996aaSopenharmony_ci            if os.path.dirname(self._config_file) != self._dirs.built_in_product_dir \
4125f9996aaSopenharmony_ci                    and not hasattr(self._config, 'product_build_path'):
4135f9996aaSopenharmony_ci                config['product_build_path'] = os.path.relpath(
4145f9996aaSopenharmony_ci                    os.path.dirname(self._config_file), self._dirs.source_root_dir)
4155f9996aaSopenharmony_ci        return config
416