• 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 sys
17import argparse
18import os
19import shutil
20import json
21from interface_mgr import InterfaceMgr
22
23sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
24from scripts.util.file_utils import read_json_file, write_file, write_json_file  # noqa: E402 E501
25from scripts.util import build_utils  # noqa: E402
26
27SHARED_LIBRARY_BUILD_TEMPLATE = '''
28config("%s_config") {
29  include_dirs = [ "%s/include", ]
30}
31ohos_prebuilt_shared_library("%s") {
32  source = "%s"
33  public_configs = [ ":%s_config" ]
34  subsystem_name = "%s"
35  part_name = "%s"
36  install_enable = false
37}
38
39'''
40JAR_BUILD_TEMPLATE = '''
41java_prebuilt("%s") {
42  jar_path = "%s"
43'''
44MAPLE_BUILD_TEMPLATE = '''
45ohos_maple_java_prebuilt("%s") {
46  mplt = %s
47  jar_path = "%s"
48'''
49
50
51# check sdk header file signature,
52# skip check if file dir not exist
53def check_header_files(checkfile_dir: str, subsystem_sdk_dir: str, subsystem_name: str,
54                       module_name: str, interface_mgr):
55    if checkfile_dir is None or not os.path.exists(checkfile_dir):
56        return
57    interface_mgr.check(checkfile_dir, subsystem_sdk_dir, subsystem_name,
58                        module_name)
59
60
61def get_build_config_from_label(label: str, current_toolchain_dir: str) -> str:
62    build_config = label.replace('//', 'gen/').replace(':', '/')
63    bc_file = '{}/{}.build_config'.format(current_toolchain_dir, build_config)
64    return bc_file
65
66
67def add_dynamic_deps(output: str, build_config: str) -> str:
68    external_deps = build_utils.expand_file_args(
69        ['@FileArg({}:deps_info:external_deps)'.format(build_config)])
70    if external_deps[0] != '[  ]':
71        output += "external_deps = " + external_deps[0]
72    output += "}"
73    return output
74
75
76# Copy the SDK module to the sdk output directory,
77# and generate the prebuilt template to BUILD.gn file.
78def gen_build_file(input_file: str, sdk_out_dir: str, generate_sig: bool,
79                   signature_file_check_dir: str):
80    data = read_json_file(input_file)
81    if data is None:
82        raise Exception(
83            "sdk interface description info error, file [{}] does not exist.".
84            format(input_file))
85
86    build_file_content = 'import("//build/ohos.gni")\n'
87    sdk_info = {}
88    # interface check
89    interface_mgr = InterfaceMgr()
90    for module_desc in data:
91        subsystem_name = module_desc.get('subsystem_name')
92        part_name = module_desc.get('part_name')
93        origin_name = module_desc.get('origin_name')
94        module_type = module_desc.get('type')
95        module_name = module_desc.get('name')
96        module_info_file = module_desc.get('source_info')
97        _current_toolchain_dir = module_desc.get('current_toolchain_dir')
98
99        # read module_info.json file, get module source path
100        source_data = read_json_file(module_info_file)
101        if not source_data:
102            print("read module [{}] info file failed, filename [{}].".format(
103                module_name, module_info_file))
104            continue
105
106        # copy lib file
107        source = source_data.get('source')
108        if module_type == 'jar':
109            source = source_data.get('alternative_source')
110
111        # check sdk type consistency
112        suffix = module_type
113        if module_type == "none":
114            continue
115        # Don't check suffix for maple sdk.
116        if module_type == "maple":
117            pass
118        elif not source.endswith(suffix):
119            raise Exception(
120                "sdk module [{}] type configuration is inconsistent.".format(
121                    module_name))
122
123        module_sdk_out_dir = os.path.join(sdk_out_dir, module_name)
124        if not os.path.exists(module_sdk_out_dir):
125            os.makedirs(module_sdk_out_dir, exist_ok=True)
126        if module_type == "maple":
127            pass
128        else:
129            shutil.copy(source, module_sdk_out_dir)
130
131        # copy headers file
132        header_base = module_desc.get('header_base')
133        if not header_base:
134            raise Exception("{}: header_base config error.".format(
135                module_desc.get('label')))
136
137        header_files = module_desc.get('header_files')
138        # copy to sdk/{subsystem_name}/{module_name}/include/
139        for header_file in header_files:
140            rel_h_file = os.path.join(header_base, header_file)
141
142            header_file_dest = os.path.join(module_sdk_out_dir, 'include',
143                                            header_file)
144            header_file_dest_dir = os.path.dirname(header_file_dest)
145            if not os.path.exists(header_file_dest_dir):
146                os.makedirs(header_file_dest_dir, exist_ok=True)
147
148            shutil.copy(rel_h_file, header_file_dest)
149
150        # generate or check header files
151        if module_type == 'so' and generate_sig is False:
152            check_header_files(signature_file_check_dir, sdk_out_dir,
153                               origin_name, module_name, interface_mgr)
154
155        # gen build file
156        lib_file = os.path.join(module_name, os.path.basename(source))
157        if module_type == 'so':
158            build_file_content += SHARED_LIBRARY_BUILD_TEMPLATE % (
159                module_name, module_name, module_name, lib_file, module_name,
160                subsystem_name, part_name)
161        elif module_type == 'jar':
162            bc = get_build_config_from_label(source_data.get("label"),
163                                             _current_toolchain_dir)
164            build_file_content += JAR_BUILD_TEMPLATE % (module_name, lib_file)
165            build_file_content = add_dynamic_deps(build_file_content, bc)
166        elif module_type == 'maple':
167            bc = get_build_config_from_label(source_data.get("label"),
168                                             _current_toolchain_dir)
169            bc_mplts = build_utils.expand_file_args(
170                ['@FileArg({}:outputs:output_mplt)'.format(bc)])
171            bc_mplts = build_utils.parse_and_flatten_gn_lists(bc_mplts)
172            sdk_mplts = []
173            base_dir = os.path.basename(module_sdk_out_dir)
174            for mplt in bc_mplts:
175                shutil.copy(mplt, module_sdk_out_dir)
176                sdk_mplts.append(os.path.join(base_dir,
177                                              os.path.basename(mplt)))
178
179            bc_jar_path = build_utils.expand_file_args(
180                ["@FileArg({}:deps_info:unprocessed_jar_path)".format(bc)])
181            bc_jar_path = build_utils.parse_and_flatten_gn_lists(bc_jar_path)
182            sdk_jar_path = []
183            for jar in bc_jar_path:
184                shutil.copy(jar, module_sdk_out_dir)
185                sdk_jar_path.append(
186                    os.path.join(base_dir, os.path.basename(jar)))
187            build_file_content += MAPLE_BUILD_TEMPLATE % (
188                module_name, json.dumps(sdk_mplts, sort_keys=True,
189                                        indent=2), sdk_jar_path[0])
190            build_file_content = add_dynamic_deps(build_file_content, bc)
191        elif module_type == 'rlib':
192            pass
193        else:
194            raise Exception(
195                'The type of sdk module configuration is not supported.')
196
197        module_info = {
198            'source': lib_file,
199            'label': module_desc.get('label'),
200            'type': module_type
201        }
202        sdk_info[module_name] = module_info
203    return build_file_content, sdk_info
204
205
206def generate_sdk(input_file: str, sdk_out_dir: str, output_build_file: str, sdk_info_file: str,
207                 generate_sig: str, signature_file_check_dir: str,
208                 signature_file_gen_dir: str):
209    build_file_content, sdk_info = gen_build_file(input_file, sdk_out_dir,
210                                                  generate_sig,
211                                                  signature_file_check_dir)
212    # write file, build gn file
213    write_file(output_build_file, build_file_content)
214    # sdk info return
215    write_json_file(sdk_info_file, sdk_info)
216
217    # gen signature file
218    if generate_sig is True:
219        interface_mgr = InterfaceMgr()
220        interface_mgr.gen_sig_file_by_subsystem(sdk_out_dir,
221                                                signature_file_gen_dir)
222
223
224def main():
225    parser = argparse.ArgumentParser()
226    parser.add_argument('--input-file', help='', required=True)
227    parser.add_argument('--sdk-out-dir', help='', required=True)
228    parser.add_argument('--output-build-file', help='', required=True)
229    parser.add_argument('--sdk-info-file', help='', required=True)
230    parser.add_argument('--generate-sig',
231                        dest='generate_sig',
232                        action='store_true')
233    parser.set_defaults(generate_sig=False)
234    parser.add_argument('--signature-file-check-dir', help='', required=False)
235    parser.add_argument('--signature-file-gen-dir', help='', required=False)
236    args = parser.parse_args()
237
238    generate_sdk(args.input_file, args.sdk_out_dir, args.output_build_file,
239                 args.sdk_info_file, args.generate_sig,
240                 args.signature_file_check_dir, args.signature_file_gen_dir)
241    return 0
242
243
244if __name__ == '__main__':
245    sys.exit(main())
246