• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 os
17import sys
18import argparse
19from concurrent.futures import ThreadPoolExecutor
20from containers.status import throw_exception
21from exceptions.ohos_exception import OHOSException
22from scripts.util.file_utils import read_json_file, write_json_file  # noqa: E402 E501
23from util.log_util import LogUtil
24from scripts.util.detect_cpu_count import get_cpu_count
25
26_default_subsystem = {"build": "build"}
27
28
29@throw_exception
30def _read_config(subsystem_config_file, example_subsystem_file):
31    if not os.path.exists(subsystem_config_file):
32        raise OHOSException(
33            "config file '{}' doesn't exist.".format(subsystem_config_file), "2013")
34    subsystem_config = read_json_file(subsystem_config_file)
35    if subsystem_config is None:
36        raise OHOSException("read file '{}' failed.".format(
37            subsystem_config_file), "2013")
38
39    # example subsystem
40    if example_subsystem_file:
41        example_subsystem_config = read_json_file(example_subsystem_file)
42        if example_subsystem_config is not None:
43            subsystem_config.update(example_subsystem_config)
44
45    subsystem_info = {}
46    for key, val in subsystem_config.items():
47        if 'path' not in val:
48            raise OHOSException(
49                "subsystem '{}' not config path.".format(key), "2013")
50        subsystem_info[key] = val.get('path')
51    return subsystem_info
52
53
54def _scan_build_file(subsystem_path):
55    _files = []
56    _bundle_files = []
57    for root, dirs, files in os.walk(subsystem_path):
58        for name in files:
59            if name == 'ohos.build':
60                _files.append(os.path.join(root, name))
61            elif name == 'bundle.json':
62                _bundle_files.append(os.path.join(root, name))
63    if _bundle_files:
64        _files.extend(_bundle_files)
65    return _files
66
67
68def _check_path_prefix(paths):
69    allow_path_prefix = ['vendor', 'device']
70    result = list(
71        filter(lambda x: x is False,
72               map(lambda p: p.split('/')[0] in allow_path_prefix, paths)))
73    return len(result) <= 1
74
75
76def scan_task(args):
77    key, paths = args
78    _all_build_config_files = []
79    for _subsystem_path in paths:
80        _all_build_config_files.extend(_scan_build_file(_subsystem_path))
81    return key, _all_build_config_files
82
83
84@throw_exception
85def scan(subsystem_config_file, example_subsystem_file, source_root_dir):
86    subsystem_infos = _read_config(subsystem_config_file,
87                                   example_subsystem_file)
88    # add common subsystem info
89    subsystem_infos.update(_default_subsystem)
90
91    no_src_subsystem = {}
92    _build_configs = {}
93    scan_tasks = []
94
95    for key, val in subsystem_infos.items():
96        _all_build_config_files = []
97        if not isinstance(val, list):
98            val = [val]
99        else:
100            if not _check_path_prefix(val):
101                raise OHOSException(
102                    "subsystem '{}' path configuration is incorrect.".format(
103                        key), "2013")
104        subsystem_paths = [os.path.join(source_root_dir, _path) for _path in val]
105        scan_tasks.append((key, subsystem_paths))
106    try:
107        cpu_cap = get_cpu_count()
108    except OSError:
109        cpu_cap = 8
110    thread_num = cpu_cap * 2
111    LogUtil.hb_info(f'The thread num for subsytem config scan is {thread_num}')
112    with ThreadPoolExecutor(max_workers=thread_num) as executor:
113        results = list(executor.map(scan_task, scan_tasks))
114    for key, build_files in results:
115        if build_files:
116            _build_configs[key] = {
117                "path": list(subsystem_infos[key] if isinstance(subsystem_infos[key], list) else [subsystem_infos[key]]),
118                "build_files": build_files
119            }
120        else:
121            no_src_subsystem[key] = list(subsystem_infos[key] if isinstance(subsystem_infos[key], list) else [subsystem_infos[key]])
122
123    scan_result = {
124        'source_path': source_root_dir,
125        'subsystem': _build_configs,
126        'no_src_subsystem': no_src_subsystem
127    }
128
129    LogUtil.hb_info('subsytem config scan completed')
130    return scan_result
131
132
133def main():
134    parser = argparse.ArgumentParser()
135    parser.add_argument('--subsystem-config-file', required=True)
136    parser.add_argument('--subsystem-config-overlay-file', required=True)
137    parser.add_argument('--example-subsystem-file', required=False)
138    parser.add_argument('--source-root-dir', required=True)
139    parser.add_argument('--output-dir', required=True)
140    args = parser.parse_args()
141
142    build_configs = scan(args.subsystem_config_file,
143                         args.example_subsystem_file, args.source_root_dir)
144
145    build_configs_file = os.path.join(args.output_dir,
146                                      "subsystem_build_config.json")
147    write_json_file(build_configs_file, build_configs)
148    return 0
149
150
151if __name__ == '__main__':
152    sys.exit(main())
153