• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2021 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 os
17import sys
18import load_bundle_file
19
20sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
21from scripts.util.file_utils import read_json_file, write_json_file, write_file  # noqa: E402, E501  pylint: disable=C0413, E0611
22
23import_list = """
24# import("//build/ohos.gni")
25# import("//build/ohos_var.gni")
26import("//build/ohos/ohos_part.gni")
27import("//build/ohos/ohos_kits.gni")
28import("//build/ohos/ohos_test.gni")
29"""
30
31part_template = """
32ohos_part("{}") {{
33  subsystem_name = "{}"
34  module_list = [
35    {}
36  ]
37  origin_name = "{}"
38  variant = "{}"
39}}"""
40
41inner_kits_template = """
42ohos_inner_kits("{0}_inner_kits") {{
43  sdk_libs = [
44{1}
45  ]
46  part_name = "{0}"
47  origin_name = "{2}"
48  variant = "{3}"
49}}"""
50
51system_kits_template = """
52ohos_system_kits("{0}_system_kits") {{
53  sdk_libs = [
54{1}
55  ]
56  part_name = "{0}"
57  origin_name = "{2}"
58  variant = "{3}"
59}}"""
60
61test_template = """
62ohos_part_test("{0}_test") {{
63  testonly = true
64  test_packages = [
65    {1}
66  ]
67  deps = [":{0}"]
68  part_name = "{0}"
69  subsystem_name = "{2}"
70}}"""
71
72
73def _normalize(label, path):
74    if not label.startswith('//'):
75        label = '//{}/{}'.format(path, label)
76    return label
77
78def get_syscap_from_bundle(bundle_file):
79    if not os.path.exists(bundle_file):
80        raise Exception(
81            "config file '{}' doesn't exist.".format(bundle_file))
82    bundle_config = read_json_file(bundle_file)
83    if bundle_config is None:
84        raise Exception("read file '{}' failed.".format(bundle_file))
85    part_name = bundle_config.get('component').get('name')
86    part_syscap = bundle_config.get('component').get('syscap')
87    return part_name, part_syscap
88
89def read_build_file(ohos_build_file):
90    if not os.path.exists(ohos_build_file):
91        raise Exception(
92            "config file '{}' doesn't exist.".format(ohos_build_file))
93    subsystem_config = read_json_file(ohos_build_file)
94    if subsystem_config is None:
95        raise Exception("read file '{}' failed.".format(ohos_build_file))
96    return subsystem_config
97
98
99class PartObject(object):
100    """"part object info, description part variant."""
101
102    def __init__(self, part_name, variant_name, part_config, toolchain,
103                 subsystem_name, target_arch):
104        self._origin_name = part_name
105        if variant_name != 'phone':
106            _real_name = '{}_{}'.format(part_name, variant_name)
107        else:
108            _real_name = part_name
109        self._part_name = _real_name
110        self._variant_name = variant_name
111        self._subsystem_name = subsystem_name
112        self._feature_list = []
113        self._toolchain = toolchain
114        self._inner_kits_info = {}
115        self._kits = []
116        self._target_arch = target_arch
117        self._system_capabilities = []
118        self._parsing_config(self._part_name, part_config, subsystem_name)
119
120    @classmethod
121    def _parsing_kits_lib(cls, kit_lib, is_inner_kits=False):
122        lib_config = []
123        lib_type = kit_lib.get('type')
124        if lib_type is None:
125            lib_type = 'so' if is_inner_kits else 'jar'
126        label = kit_lib.get('name')
127        if label is None:
128            raise Exception("kits lib config incorrect, required for name.")
129        lib_config.append('      type = "{}"'.format(lib_type))
130        lib_config.append('      name = "{}"'.format(label))
131        if lib_type == 'so' and 'header' in kit_lib:
132            header = kit_lib.get('header')
133            header_files = header.get('header_files')
134            lib_config.append('      header = {')
135            lib_config.append('        header_files = [')
136            for h_file in header_files:
137                lib_config.append('          "{}",'.format(h_file))
138            lib_config.append('        ]')
139            header_base = header.get('header_base')
140            lib_config.append('        header_base = "{}"'.format(header_base))
141            lib_config.append('      }')
142        if is_inner_kits is False and 'javadoc' in kit_lib:
143            javadoc_val = kit_lib.get('javadoc')
144            lib_config.append('      javadoc = {')
145            resource_dir = javadoc_val.get('resource_dir')
146            lib_config.append(
147                '        resource_dir = "{}"'.format(resource_dir))
148            lib_config.append('      }')
149        return lib_config
150
151    def _parsing_inner_kits(self, part_name, inner_kits_info, build_gn_content,
152                            target_arch):
153        inner_kits_libs_gn = []
154        for inner_kits_lib in inner_kits_info:
155            inner_kits_libs_gn.append('    {')
156            inner_kits_libs_gn.extend(
157                self._parsing_kits_lib(inner_kits_lib, True))
158            inner_kits_libs_gn.append('    },')
159
160        inner_kits_libs_gn_line = '\n'.join(inner_kits_libs_gn)
161        inner_kits_def = inner_kits_template.format(part_name,
162                                                    inner_kits_libs_gn_line,
163                                                    self._origin_name,
164                                                    self._variant_name)
165        build_gn_content.append(inner_kits_def)
166        # output inner kits info to resolve external deps
167        _libs_info = {}
168        for inner_kits_lib in inner_kits_info:
169            info = {'part_name': part_name}
170            label = inner_kits_lib.get('name')
171            lib_name = label.split(':')[1]
172            info['label'] = label
173            info['name'] = lib_name
174            lib_type = inner_kits_lib.get('type')
175            if lib_type is None:
176                lib_type = 'so'
177            info['type'] = lib_type
178            prebuilt = inner_kits_lib.get('prebuilt_enable')
179            if prebuilt:
180                info['prebuilt_enable'] = prebuilt
181                prebuilt_source_libs = inner_kits_lib.get('prebuilt_source')
182                prebuilt_source = prebuilt_source_libs.get(target_arch)
183                info['prebuilt_source'] = prebuilt_source
184            else:
185                info['prebuilt_enable'] = False
186            # header files
187            if lib_type == 'so':
188                header = inner_kits_lib.get('header')
189                if header is None:
190                    raise Exception(
191                        "header not configuration, part_name = '{}'".format(
192                            part_name))
193                header_base = header.get('header_base')
194                if header_base is None:
195                    raise Exception(
196                        "header base not configuration, part_name = '{}'".
197                        format(part_name))
198                info['header_base'] = header_base
199                info['header_files'] = header.get('header_files')
200            _libs_info[lib_name] = info
201        self._inner_kits_info = _libs_info
202
203    def _parsing_system_kits(self, part_name, system_kits_info,
204                             build_gn_content):
205        system_kits_libs_gn = []
206        kits = []
207        for _kits_lib in system_kits_info:
208            system_kits_libs_gn.append('    {')
209            system_kits_libs_gn.extend(self._parsing_kits_lib(
210                _kits_lib, False))
211            kits.append('"{}"'.format(_kits_lib.get('name')))
212            system_kits_libs_gn.append('    },')
213        _kits_libs_gn_line = '\n'.join(system_kits_libs_gn)
214        system_kits_def = system_kits_template.format(part_name,
215                                                      _kits_libs_gn_line,
216                                                      self._origin_name,
217                                                      self._variant_name)
218        build_gn_content.append(system_kits_def)
219        self._kits = kits
220
221    def _parsing_config(self, part_name, part_config, subsystem_name):
222        self._part_target_list = []
223        build_gn_content = []
224        build_gn_content.append(import_list)
225
226        # ohos part
227        if 'module_list' not in part_config:
228            raise Exception(
229                "ohos.build incorrect, part name: '{}'".format(part_name))
230        module_list = part_config.get('module_list')
231        if len(module_list) == 0:
232            module_list_line = ''
233        else:
234            module_list_line = '"{}",'.format('",\n    "'.join(module_list))
235        parts_definition = part_template.format(part_name, subsystem_name,
236                                                module_list_line,
237                                                self._origin_name,
238                                                self._variant_name)
239        build_gn_content.append(parts_definition)
240
241        # part inner kits
242        if part_config.get('inner_kits'):
243            self._part_target_list.append('inner_kits')
244            inner_kits_info = part_config.get('inner_kits')
245            self._parsing_inner_kits(part_name, inner_kits_info,
246                                     build_gn_content, self._target_arch)
247        # part system kits
248        if part_config.get('system_kits'):
249            self._part_target_list.append('system_kits')
250            system_kits_info = part_config.get('system_kits')
251            self._parsing_system_kits(part_name, system_kits_info,
252                                      build_gn_content)
253        # part test list
254        if part_config.get('test_list'):
255            self._part_target_list.append('test')
256            test_list = part_config.get('test_list')
257            test_list_line = '"{}",'.format('",\n    "'.join(test_list))
258            test_def = test_template.format(part_name, test_list_line,
259                                            subsystem_name)
260            build_gn_content.append(test_def)
261        self._build_gn_content = build_gn_content
262        # feature
263        if part_config.get('feature_list'):
264            self._feature_list = part_config.get('feature_list')
265            # check feature
266            for _feature_name in self._feature_list:
267                if not _feature_name.startswith('{}_'.format(
268                        self._origin_name)):
269                    raise Exception(
270                        "part feature list config incorrect,"
271                        " part_name='{}', feature_name='{}'".format(
272                            self._origin_name, _feature_name))
273
274        # system_capabilities is a list attribute of a part in ohos.build
275        if part_config.get('system_capabilities'):
276            self._system_capabilities = part_config.get('system_capabilities')
277
278    def part_name(self):
279        """part name."""
280        return self._part_name
281
282    def part_variant(self):
283        """part variant."""
284        return self._variant_name
285
286    def toolchain(self):
287        """current part variant toolchain."""
288        return self._toolchain
289
290    def part_inner_kits(self):
291        """part inner kits."""
292        return self._inner_kits_info
293
294    def part_kits(self):
295        """part kits."""
296        return self._kits
297
298    def write_build_gn(self, config_output_dir):
299        """output build gn."""
300        part_gn_file = os.path.join(config_output_dir, self._part_name,
301                                    'BUILD.gn')
302        write_file(part_gn_file, '\n'.join(self._build_gn_content))
303
304    def get_target_label(self, config_output_relpath):
305        """target label."""
306        if config_output_relpath.startswith('/'):
307            raise Exception("args config output relative path is incorrect.")
308        if self._toolchain == '':
309            return "//{0}/{1}:{1}".format(config_output_relpath,
310                                          self._part_name)
311        else:
312            return "//{0}/{1}:{1}({2})".format(config_output_relpath,
313                                               self._part_name,
314                                               self._toolchain)
315
316    def part_group_targets(self, config_output_relpath):
317        """part group target."""
318        if config_output_relpath.startswith('/'):
319            raise Exception("args config output relative path is incorrect.")
320        _labels = {}
321        _labels['part'] = self.get_target_label(config_output_relpath)
322        for group_label in self._part_target_list:
323            if group_label == 'phony':
324                _labels[group_label] = "//{0}/{1}:{1}_{2}".format(
325                    config_output_relpath, self._part_name, group_label)
326                continue
327            if self._toolchain == '':
328                _labels[group_label] = "//{0}/{1}:{1}_{2}".format(
329                    config_output_relpath, self._part_name, group_label)
330            else:
331                _labels[group_label] = "//{0}/{1}:{1}_{2}({3})".format(
332                    config_output_relpath, self._part_name, group_label,
333                    self._toolchain)
334        return _labels
335
336    def part_info(self):
337        """part info."""
338        _info = {}
339        _info['part_name'] = self._part_name
340        _info['origin_part_name'] = self._origin_name
341        _info['toolchain_label'] = self._toolchain
342        _info['variant_name'] = self._variant_name
343        _info['subsystem_name'] = self._subsystem_name
344        _info['system_capabilities'] = self._system_capabilities
345
346        if self._feature_list:
347            _info['feature_list'] = self._feature_list
348        if self._variant_name != 'phone':
349            toolchain_name = self._toolchain.split(':')[1]
350            _build_out_dir = toolchain_name
351        else:
352            _build_out_dir = '.'
353        _info['build_out_dir'] = _build_out_dir
354        return _info
355
356
357class LoadBuildConfig(object):
358    """load build config file and parse configuration info."""
359
360    def __init__(self, source_root_dir, subsystem_build_info,
361                 config_output_dir, variant_toolchains, subsystem_name,
362                 target_arch, ignored_subsystems,
363                 exclusion_modules_config_file, load_test_config):
364        self._source_root_dir = source_root_dir
365        self._build_info = subsystem_build_info
366        self._config_output_relpath = config_output_dir
367        self._is_load = False
368        self._parts_variants = {}
369        self._part_list = {}
370        self._part_targets_label = {}
371        self._variant_toolchains = variant_toolchains
372        self._subsystem_name = subsystem_name
373        self._target_arch = target_arch
374        self._ignored_subsystems = ignored_subsystems
375        self._parts_info_dict = {}
376        self._phony_targets = {}
377        self._parts_path_dict = {}
378        self._part_hisysevent_config = {}
379        self._parts_module_list = {}
380        self._exclusion_modules_config_file = exclusion_modules_config_file
381        self._load_test_config = load_test_config
382
383    def _parsing_config(self, parts_config):
384        _parts_info_dict = {}
385        _variant_phony_targets = {}
386        for part_name, value in parts_config.items():
387            if 'variants' in value:
388                variants = value.get('variants')
389                if len(variants) == 0:
390                    variants = ['phone']
391            else:
392                variants = ['phone']
393            _build_target = {}
394            _targets_label = {}
395            _parts_info = []
396            for variant in variants:
397                toolchain = self._variant_toolchains.get(variant)
398                if toolchain is None:
399                    continue
400                part_obj = PartObject(part_name, variant, value, toolchain,
401                                      self._subsystem_name, self._target_arch)
402                real_part_name = part_obj.part_name()
403                self._part_list[real_part_name] = part_obj
404
405                subsystem_config_dir = os.path.join(
406                    self._config_output_relpath, self._subsystem_name)
407                part_obj.write_build_gn(
408                    os.path.join(self._source_root_dir, subsystem_config_dir))
409
410                _target_label = part_obj.get_target_label(subsystem_config_dir)
411                _build_target[variant] = _target_label
412                _targets_label[real_part_name] = part_obj.part_group_targets(
413                    subsystem_config_dir)
414                _parts_info.append(part_obj.part_info())
415                if variant != 'phone':
416                    _variant_phony_targets[real_part_name] = _target_label
417            self._part_targets_label.update(_targets_label)
418            self._parts_variants[part_name] = _build_target
419            if 'hisysevent_config' in value:
420                _config_files = value.get('hisysevent_config')
421                for _config_file in _config_files:
422                    if not _config_file.startswith('//'):
423                        raise Exception(
424                            "part '{}' hisysevent config incorrest.".format(
425                                part_name))
426                self._part_hisysevent_config[part_name] = _config_files
427            _parts_info_dict[part_name] = _parts_info
428        self._parts_info_dict = _parts_info_dict
429        self._phony_targets = _variant_phony_targets
430
431    def _merge_build_config(self):
432        _build_files = self._build_info.get('build_files')
433        is_thirdparty_subsystem = False
434        if _build_files[0].startswith(self._source_root_dir + 'third_party'):
435            is_thirdparty_subsystem = True
436        subsystem_name = None
437        parts_info = {}
438        parts_path_dict = {}
439        for _build_file in _build_files:
440            if _build_file.endswith('bundle.json'):
441                bundle_part_obj = load_bundle_file.BundlePartObj(
442                    _build_file, self._exclusion_modules_config_file,
443                    self._load_test_config)
444                _parts_config = bundle_part_obj.to_ohos_build()
445            else:
446                _parts_config = read_build_file(_build_file)
447            _subsystem_name = _parts_config.get('subsystem')
448            if not is_thirdparty_subsystem and subsystem_name and _subsystem_name != subsystem_name:
449                raise Exception(
450                    "subsystem name config incorrect in '{}'.".format(
451                        _build_file))
452            subsystem_name = _subsystem_name
453            _curr_parts_info = _parts_config.get('parts')
454            for _pname in _curr_parts_info.keys():
455                parts_path_dict[_pname] = os.path.relpath(
456                    os.path.dirname(_build_file), self._source_root_dir)
457            parts_info.update(_curr_parts_info)
458        subsystem_config = {}
459        subsystem_config['subsystem'] = subsystem_name
460        subsystem_config['parts'] = parts_info
461        return subsystem_config, parts_path_dict
462
463    def parse_syscap_info(self):
464        _build_files = self._build_info.get('build_files')
465        subsystem_syscap = []
466        for _build_file in _build_files:
467            if _build_file.endswith('bundle.json'):
468                part_name, part_syscap = get_syscap_from_bundle(_build_file)
469                subsystem_syscap.append({'component': part_name, 'syscap': part_syscap})
470        return subsystem_syscap
471
472    def parse(self):
473        """parse part info from build config file."""
474        if self._is_load:
475            return
476        subsystem_config, parts_path_dict = self._merge_build_config()
477        parts_config = subsystem_config.get('parts')
478        self._parts_module_list.update(parts_config)
479        self._parsing_config(parts_config)
480        self._parts_path_dict = parts_path_dict
481        self._is_load = True
482
483    def parts_variants(self):
484        """parts varinats info."""
485        self.parse()
486        return self._parts_variants
487
488    def parts_inner_kits_info(self):
489        """parts inner kits info."""
490        self.parse()
491        _parts_inner_kits = {}
492        for part_obj in self._part_list.values():
493            _parts_inner_kits[
494                part_obj.part_name()] = part_obj.part_inner_kits()
495        return _parts_inner_kits
496
497    def parts_build_targets(self):
498        """parts build target label."""
499        self.parse()
500        return self._part_targets_label
501
502    def parts_name_list(self):
503        """parts name list."""
504        self.parse()
505        return list(self._part_list.keys())
506
507    def parts_info(self):
508        """parts info."""
509        self.parse()
510        return self._parts_info_dict
511
512    def parts_phony_target(self):
513        """parts phony target info"""
514        self.parse()
515        return self._phony_targets
516
517    def parts_kits_info(self):
518        """parts kits info."""
519        self.parse()
520        _parts_kits = {}
521        for part_obj in self._part_list.values():
522            _parts_kits[part_obj.part_name()] = part_obj.part_kits()
523        return _parts_kits
524
525    def parts_path_info(self):
526        """parts to path info."""
527        self.parse()
528        return self._parts_path_dict
529
530    def parts_hisysevent_config(self):
531        self.parse()
532        return self._part_hisysevent_config
533
534    def parts_modules_info(self):
535        self.parse()
536        return self._parts_module_list
537
538    def parts_info_filter(self, save_part):
539        if save_part is None:
540            raise Exception
541        self._parts_variants = {key : value for key, value in self._parts_variants.items() if save_part == key}
542        self._part_list = {key : value for key, value in self._part_list.items() if save_part == key}
543        self._part_targets_label = {key : value for key, value in self._part_targets_label.items() if save_part == key}
544        self._parts_info_dict = {key : value for key, value in self._parts_info_dict.items() if save_part == key}
545        self._phony_targets = {key : value for key, value in self._phony_targets.items() if save_part == key}
546        self._parts_path_dict = {key : value for key, value in self._parts_path_dict.items() if save_part == key}
547        for key, value in self._part_hisysevent_config.items():
548            if save_part == key:
549                self._part_hisysevent_config = {key : value}
550        self._parts_module_list = {key : value for key, value in self._parts_module_list.items() if save_part == key}
551
552def _output_parts_info(parts_config_dict, config_output_path):
553    parts_info_output_path = os.path.join(config_output_path, "parts_info")
554    # parts_info.json
555    if 'parts_info' in parts_config_dict:
556        parts_info = parts_config_dict.get('parts_info')
557        parts_info_file = os.path.join(parts_info_output_path,
558                                       "parts_info.json")
559        write_json_file(parts_info_file, parts_info)
560        _part_subsystem_dict = {}
561        for key, value in parts_info.items():
562            for _info in value:
563                _sub_name = _info.get('subsystem_name')
564                _part_subsystem_dict[key] = _sub_name
565                break
566        _part_subsystem_file = os.path.join(parts_info_output_path,
567                                            "part_subsystem.json")
568        write_json_file(_part_subsystem_file, _part_subsystem_dict)
569
570    # subsystem_parts.json
571    if 'subsystem_parts' in parts_config_dict:
572        subsystem_parts = parts_config_dict.get('subsystem_parts')
573        subsystem_parts_file = os.path.join(parts_info_output_path,
574                                            "subsystem_parts.json")
575        write_json_file(subsystem_parts_file, subsystem_parts)
576        # adapter mini system
577        for _sub_name, _p_list in subsystem_parts.items():
578            _output_info = {}
579            _output_info['parts'] = _p_list
580            _sub_info_output_file = os.path.join(config_output_path,
581                                                 'mini_adapter',
582                                                 '{}.json'.format(_sub_name))
583            write_json_file(_sub_info_output_file, _output_info)
584
585    # parts_variants.json
586    if 'parts_variants' in parts_config_dict:
587        parts_variants = parts_config_dict.get('parts_variants')
588        parts_variants_info_file = os.path.join(parts_info_output_path,
589                                                "parts_variants.json")
590        write_json_file(parts_variants_info_file, parts_variants)
591
592    # inner_kits_info.json
593    if 'parts_inner_kits_info' in parts_config_dict:
594        parts_inner_kits_info = parts_config_dict.get('parts_inner_kits_info')
595        parts_inner_kits_info_file = os.path.join(parts_info_output_path,
596                                                  "inner_kits_info.json")
597        write_json_file(parts_inner_kits_info_file, parts_inner_kits_info)
598
599    # parts_targets.json
600    if 'parts_targets' in parts_config_dict:
601        parts_targets = parts_config_dict.get('parts_targets')
602        parts_targets_info_file = os.path.join(parts_info_output_path,
603                                               "parts_targets.json")
604        write_json_file(parts_targets_info_file, parts_targets)
605
606    # phony_targets.json
607    if 'phony_target' in parts_config_dict:
608        phony_target = parts_config_dict.get('phony_target')
609        phony_target_info_file = os.path.join(parts_info_output_path,
610                                              "phony_target.json")
611        write_json_file(phony_target_info_file, phony_target)
612
613    # paths_path_info.json
614    if 'parts_path_info' in parts_config_dict:
615        parts_path_info = parts_config_dict.get('parts_path_info')
616        parts_path_info_file = os.path.join(parts_info_output_path,
617                                            'parts_path_info.json')
618        write_json_file(parts_path_info_file, parts_path_info)
619        path_to_parts = {}
620        for _key, _val in parts_path_info.items():
621            _p_list = path_to_parts.get(_val, [])
622            _p_list.append(_key)
623            path_to_parts[_val] = _p_list
624        path_to_parts_file = os.path.join(parts_info_output_path,
625                                          'path_to_parts.json')
626        write_json_file(path_to_parts_file, path_to_parts)
627
628    # hisysevent_config
629    if 'hisysevent_config' in parts_config_dict:
630        hisysevent_config = parts_config_dict.get('hisysevent_config')
631        hisysevent_info_file = os.path.join(parts_info_output_path,
632                                            'hisysevent_configs.json')
633        write_json_file(hisysevent_info_file, hisysevent_config)
634
635    # _parts_modules_info
636    if 'parts_modules_info' in parts_config_dict:
637        parts_modules_info = parts_config_dict.get('parts_modules_info')
638        _output_info = {}
639        _all_p_info = []
640        for key, value in parts_modules_info.items():
641            _p_info = {}
642            _p_info['part_name'] = key
643            _module_list = value.get('module_list')
644            _p_info['module_list'] = _module_list
645            _all_p_info.append(_p_info)
646        _output_info['parts'] = _all_p_info
647        parts_modules_info_file = os.path.join(parts_info_output_path,
648                                               'parts_modules_info.json')
649        write_json_file(parts_modules_info_file, _output_info)
650
651
652def get_parts_info(source_root_dir,
653                   config_output_relpath,
654                   subsystem_info,
655                   variant_toolchains,
656                   target_arch,
657                   ignored_subsystems,
658                   exclusion_modules_config_file,
659                   load_test_config,
660                   build_xts=False):
661    """parts info,
662    get info from build config file.
663    """
664    parts_variants = {}
665    parts_inner_kits_info = {}
666    parts_kits_info = {}
667    parts_targets = {}
668    parts_info = {}
669    subsystem_parts = {}
670    _phony_target = {}
671    _parts_path_info = {}
672    _parts_hisysevent_config = {}
673    _parts_modules_info = {}
674    system_syscap = []
675    for subsystem_name, build_config_info in subsystem_info.items():
676        build_loader = LoadBuildConfig(source_root_dir, build_config_info,
677                                       config_output_relpath,
678                                       variant_toolchains, subsystem_name,
679                                       target_arch, ignored_subsystems,
680                                       exclusion_modules_config_file,
681                                       load_test_config)
682        # xts subsystem special handling, device_attest and
683        # device_attest_lite parts need to be compiled into the version image, other parts are not
684        if subsystem_name == 'xts' and build_xts is False:
685            xts_device_attest_name = {}
686            if 'device_attest' in build_loader.parts_modules_info():
687                xts_device_attest_name = 'device_attest'
688            elif 'device_attest_lite' in build_loader.parts_modules_info():
689                xts_device_attest_name = 'device_attest_lite'
690            else:
691                continue
692            build_loader.parts_info_filter(xts_device_attest_name)
693
694        _parts_variants = build_loader.parts_variants()
695        parts_variants.update(_parts_variants)
696        _inner_kits_info = build_loader.parts_inner_kits_info()
697        parts_inner_kits_info.update(_inner_kits_info)
698        parts_kits_info.update(build_loader.parts_kits_info())
699        _parts_targets = build_loader.parts_build_targets()
700        parts_targets.update(_parts_targets)
701        subsystem_parts[subsystem_name] = build_loader.parts_name_list()
702        parts_info.update(build_loader.parts_info())
703        _phony_target.update(build_loader.parts_phony_target())
704        _parts_path_info.update(build_loader.parts_path_info())
705        _parts_hisysevent_config.update(build_loader.parts_hisysevent_config())
706        _parts_modules_info.update(build_loader.parts_modules_info())
707        system_syscap.extend(build_loader.parse_syscap_info())
708    parts_config_dict = {}
709    parts_config_dict['parts_info'] = parts_info
710    parts_config_dict['subsystem_parts'] = subsystem_parts
711    parts_config_dict['parts_variants'] = parts_variants
712    parts_config_dict['parts_inner_kits_info'] = parts_inner_kits_info
713    parts_config_dict['parts_kits_info'] = parts_kits_info
714    parts_config_dict['parts_targets'] = parts_targets
715    parts_config_dict['phony_target'] = _phony_target
716    parts_config_dict['parts_path_info'] = _parts_path_info
717    parts_config_dict['hisysevent_config'] = _parts_hisysevent_config
718    parts_config_dict['parts_modules_info'] = _parts_modules_info
719    _output_parts_info(parts_config_dict,
720                       os.path.join(source_root_dir, config_output_relpath))
721    parts_config_dict['syscap_info'] = system_syscap
722    return parts_config_dict
723