• 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, subsystem_sdk_dir, subsystem_name,
54                       module_name, 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, current_toolchain_dir):
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, build_config):
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, sdk_out_dir, generate_sig,
79                   signature_file_check_dir):
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    build_file_content += 'import("//build/config/ohos/rules.gni")\n'
88    sdk_info = {}
89    # interface check
90    interface_mgr = InterfaceMgr()
91    for module_desc in data:
92        subsystem_name = module_desc.get('subsystem_name')
93        part_name = module_desc.get('part_name')
94        origin_name = module_desc.get('origin_name')
95        module_type = module_desc.get('type')
96        module_name = module_desc.get('name')
97        module_info_file = module_desc.get('source_info')
98        _current_toolchain_dir = module_desc.get('current_toolchain_dir')
99
100        # read module_info.json file, get module source path
101        source_data = read_json_file(module_info_file)
102        if not source_data:
103            print("read module [{}] info file failed, filename [{}].".format(
104                module_name, module_info_file))
105            continue
106
107        # copy lib file
108        source = source_data.get('source')
109        if module_type == 'jar':
110            source = source_data.get('alternative_source')
111
112        # check sdk type consistency
113        suffix = module_type
114        if module_type == "none":
115            continue
116        # Don't check suffix for maple sdk.
117        if module_type == "maple":
118            pass
119        elif not source.endswith(suffix):
120            raise Exception(
121                "sdk module [{}] type configuration is inconsistent.".format(
122                    module_name))
123
124        module_sdk_out_dir = os.path.join(sdk_out_dir, module_name)
125        if not os.path.exists(module_sdk_out_dir):
126            os.makedirs(module_sdk_out_dir, exist_ok=True)
127        if module_type == "maple":
128            pass
129        else:
130            shutil.copy(source, module_sdk_out_dir)
131
132        # copy headers file
133        header_base = module_desc.get('header_base')
134        if not header_base:
135            raise Exception("{}: header_base config error.".format(
136                module_desc.get('label')))
137
138        header_files = module_desc.get('header_files')
139        # copy to sdk/{subsystem_name}/{module_name}/include/
140        for header_file in header_files:
141            rel_h_file = os.path.join(header_base, header_file)
142
143            header_file_dest = os.path.join(module_sdk_out_dir, 'include',
144                                            header_file)
145            header_file_dest_dir = os.path.dirname(header_file_dest)
146            if not os.path.exists(header_file_dest_dir):
147                os.makedirs(header_file_dest_dir, exist_ok=True)
148
149            shutil.copy(rel_h_file, header_file_dest)
150
151        # generate or check header files
152        if module_type == 'so' and generate_sig is False:
153            check_header_files(signature_file_check_dir, sdk_out_dir,
154                               origin_name, module_name, interface_mgr)
155
156        # gen build file
157        lib_file = os.path.join(module_name, os.path.basename(source))
158        if module_type == 'so':
159            build_file_content += SHARED_LIBRARY_BUILD_TEMPLATE % (
160                module_name, module_name, module_name, lib_file, module_name,
161                subsystem_name, part_name)
162        elif module_type == 'jar':
163            bc = get_build_config_from_label(source_data.get("label"),
164                                             _current_toolchain_dir)
165            build_file_content += JAR_BUILD_TEMPLATE % (module_name, lib_file)
166            build_file_content = add_dynamic_deps(build_file_content, bc)
167        elif module_type == 'maple':
168            bc = get_build_config_from_label(source_data.get("label"),
169                                             _current_toolchain_dir)
170            bc_mplts = build_utils.expand_file_args(
171                ['@FileArg({}:outputs:output_mplt)'.format(bc)])
172            bc_mplts = build_utils.parse_and_flatten_gn_lists(bc_mplts)
173            sdk_mplts = []
174            base_dir = os.path.basename(module_sdk_out_dir)
175            for mplt in bc_mplts:
176                shutil.copy(mplt, module_sdk_out_dir)
177                sdk_mplts.append(os.path.join(base_dir,
178                                              os.path.basename(mplt)))
179
180            bc_jar_path = build_utils.expand_file_args(
181                ["@FileArg({}:deps_info:unprocessed_jar_path)".format(bc)])
182            bc_jar_path = build_utils.parse_and_flatten_gn_lists(bc_jar_path)
183            sdk_jar_path = []
184            for jar in bc_jar_path:
185                shutil.copy(jar, module_sdk_out_dir)
186                sdk_jar_path.append(
187                    os.path.join(base_dir, os.path.basename(jar)))
188            build_file_content += MAPLE_BUILD_TEMPLATE % (
189                module_name, json.dumps(sdk_mplts, sort_keys=True,
190                                        indent=2), sdk_jar_path[0])
191            build_file_content = add_dynamic_deps(build_file_content, bc)
192        else:
193            raise Exception(
194                'The type of sdk module configuration is not supported.')
195
196        module_info = {
197            'source': lib_file,
198            'label': module_desc.get('label'),
199            'type': module_type
200        }
201        sdk_info[module_name] = module_info
202    return build_file_content, sdk_info
203
204
205def generate_sdk(input_file, sdk_out_dir, output_build_file, sdk_info_file,
206                 generate_sig, signature_file_check_dir,
207                 signature_file_gen_dir):
208    build_file_content, sdk_info = gen_build_file(input_file, sdk_out_dir,
209                                                  generate_sig,
210                                                  signature_file_check_dir)
211    # write file, build gn file
212    write_file(output_build_file, build_file_content)
213    # sdk info return
214    write_json_file(sdk_info_file, sdk_info)
215
216    # gen signature file
217    if generate_sig is True:
218        interface_mgr = InterfaceMgr()
219        interface_mgr.gen_sig_file_by_subsystem(sdk_out_dir,
220                                                signature_file_gen_dir)
221
222
223def main():
224    parser = argparse.ArgumentParser()
225    parser.add_argument('--input-file', help='', required=True)
226    parser.add_argument('--sdk-out-dir', help='', required=True)
227    parser.add_argument('--output-build-file', help='', required=True)
228    parser.add_argument('--sdk-info-file', help='', required=True)
229    parser.add_argument('--generate-sig',
230                        dest='generate_sig',
231                        action='store_true')
232    parser.set_defaults(generate_sig=False)
233    parser.add_argument('--signature-file-check-dir', help='', required=False)
234    parser.add_argument('--signature-file-gen-dir', help='', required=False)
235    args = parser.parse_args()
236
237    generate_sdk(args.input_file, args.sdk_out_dir, args.output_build_file,
238                 args.sdk_info_file, args.generate_sig,
239                 args.signature_file_check_dir, args.signature_file_gen_dir)
240    return 0
241
242
243if __name__ == '__main__':
244    sys.exit(main())
245