• 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
20
21sys.path.append(
22    os.path.dirname(os.path.dirname(os.path.dirname(
23        os.path.abspath(__file__)))))
24from scripts.util.file_utils import read_json_file, write_json_file, write_file  # noqa: E402
25from scripts.util import build_utils  # noqa: E402
26
27sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "rules"))
28from categorized_libraries_utils import load_categorized_libraries
29from categorized_libraries_utils import update_module_info
30from bootpath_collection import BootPathCollection
31
32
33def _get_modules_info(system_install_info: dict, depfiles: list):
34    modules_info_dict = {}
35    for subsystem_info in system_install_info:
36        part_name = subsystem_info.get('part_name')
37        part_info_file = subsystem_info.get('part_info_file')
38
39        # read subsystem module info
40        part_install_info = read_json_file(part_info_file)
41        if part_install_info is None:
42            raise Exception(
43                "read part '{}' installed modules info failed.".format(
44                    part_name))
45        depfiles.append(part_info_file)
46
47        for info in part_install_info:
48            module_def = info.get('module_def')
49            module_info_file = info.get('module_info_file')
50            depfiles.append(module_info_file)
51            if module_def not in modules_info_dict:
52                modules_info_dict[module_def] = module_info_file
53    return modules_info_dict
54
55
56def _get_post_process_modules_info(post_process_modules_info_files: list, depfiles: list):
57    modules_info_list = []
58    for _modules_info_file in post_process_modules_info_files:
59        _modules_info = read_json_file(_modules_info_file)
60        if _modules_info is None:
61            raise Exception("read _modules_info_file '{}' failed.".format(
62                _modules_info_file))
63        modules_info_list.extend(_modules_info)
64        depfiles.append(_modules_info_file)
65    return modules_info_list
66
67
68def copy_modules(system_install_info: dict, install_modules_info_file: str,
69                 modules_info_file: str, module_list_file: str,
70                 post_process_modules_info_files: list, platform_installed_path: str,
71                 host_toolchain, additional_system_files: dict, depfiles: list, categorized_libraries: dict):
72    output_result = []
73    dest_list = []
74    symlink_dest = []
75
76    modules_info_dict = _get_modules_info(system_install_info, depfiles)
77    for value in modules_info_dict.values():
78        module_info = read_json_file(value)
79        if not module_info:
80            raise Exception("read module install info file '{}' error.".format(value))
81        install = module_info.get('install_enable')
82        if not install:
83            continue
84        update_module_info(module_info, categorized_libraries)
85        output_result.append(module_info)
86
87    # get post process modules info
88    post_process_modules = _get_post_process_modules_info(
89        post_process_modules_info_files, depfiles)
90    for _module_info in post_process_modules:
91        install = _module_info.get('install_enable')
92        if not install:
93            continue
94        output_result.append(_module_info)
95
96    for source, system_path in additional_system_files:
97        shutil.copy(source, os.path.join(platform_installed_path, system_path))
98
99    # copy modules
100    for module_info in output_result:
101        if module_info.get('type') == 'none':
102            continue
103        # copy module lib
104        label = module_info.get('label')
105        if label and host_toolchain in label:
106            continue
107        source = module_info.get('source')
108        dests = module_info.get('dest')
109        # check source
110        if not os.path.exists(source):
111            raise Exception("source '{}' doesn't exist.".format(source))
112        depfiles.append(source)
113        for dest in dests:
114            if dest.startswith('/'):
115                dest = dest[1:]
116            dest_list.append(dest)
117            # dest_dir_prefix
118            if os.path.isfile(source):
119                dest_dir = os.path.join(platform_installed_path,
120                                        os.path.dirname(dest))
121            elif os.path.isdir(source):
122                dest_dir = os.path.join(platform_installed_path, dest)
123            if not os.path.exists(dest_dir):
124                os.makedirs(dest_dir, exist_ok=True)
125            if os.path.isdir(source):
126                is_hvigor_hap = False
127                for filename in os.listdir(source):
128                    if filename.endswith('.hap') or filename.endswith('.hsp'):
129                        is_hvigor_hap = True
130                        shutil.copy2(os.path.join(source, filename),
131                                     os.path.join(platform_installed_path, dest, filename))
132                if not is_hvigor_hap:
133                    shutil.copytree(source, os.path.join(platform_installed_path, dest), dirs_exist_ok=True)
134            else:
135                shutil.copy2(source, os.path.join(platform_installed_path, dest))
136
137        # add symlink
138        if 'symlink' in module_info:
139            symlink_dest = module_info.get('symlink')
140            for dest in dests:
141                symlink_src_file = os.path.basename(dest)
142                for name in symlink_dest:
143                    symlink_dest_dir = os.path.dirname(dest)
144                    symlink_dest_file = os.path.join(platform_installed_path,
145                                                     symlink_dest_dir, name)
146                    if not os.path.exists(symlink_dest_file):
147                        os.symlink(symlink_src_file, symlink_dest_file)
148        if 'symlink_ext' in module_info:
149            symlink_ext = module_info.get('symlink_ext')
150            for dest in dests:
151                symlink_src_file = os.path.join(platform_installed_path, dest)
152                for name in symlink_ext:
153                    symlink_dest_file = os.path.join(platform_installed_path, dest.split('/')[0], name)
154                    relpath = os.path.relpath(os.path.dirname(symlink_src_file), os.path.dirname(symlink_dest_file))
155                    if not os.path.exists(os.path.dirname(symlink_dest_file)):
156                        os.makedirs(os.path.dirname(symlink_dest_file), exist_ok=True)
157                    if not os.path.exists(symlink_dest_file):
158                        os.symlink(os.path.join(relpath, os.path.basename(dest)), symlink_dest_file)
159        if 'symlink_path' in module_info:
160            symlink_path = module_info.get('symlink_path')
161            dest_file = os.path.join(platform_installed_path, dests[0])
162            if os.path.exists(dest_file):
163                os.remove(dest_file)
164            os.symlink(symlink_path, dest_file)
165            if not os.path.lexists(dest_file):
166                raise FileNotFoundError(f"target symlink {dest_file} to {symlink_path} create failed")
167        # innerapi_tags create softlink for ndk、platformsdk
168        if "softlink_create_path" in module_info:
169            softlink_create_path = module_info.get("softlink_create_path")
170            for dest in dests:
171                replace_subdir = os.path.dirname(dest).split("/")[-1]
172                file_name = os.path.basename(dest)
173                dest_file = os.path.join(platform_installed_path, dest)
174                if replace_subdir in ["llndk", "chipset-sdk", "chipset-sdk-sp"]:
175                    if softlink_create_path == "ndk":
176                        link_path = dest_file.replace(f"{replace_subdir}/{file_name}", f"ndk/{file_name}")
177                    else:
178                        link_path = dest_file.replace(f"{replace_subdir}/{file_name}", f"platformsdk/{file_name}")
179                    if 'symlink' in module_info:
180                        actual_file_name = module_info.get("symlink")[0]
181                        link_path = link_path.replace(file_name, actual_file_name)
182                    if link_path != dest_file:
183                        relative_path = os.path.relpath(os.path.dirname(dest_file), os.path.dirname(link_path))
184                        os.makedirs(os.path.dirname(link_path), exist_ok=True)
185                        src_file = os.path.join(relative_path, file_name)
186                        os.symlink(src_file, link_path)
187                    else:
188                        raise FileExistsError(f"{link_path} create failed, src_file:{dest_file} and {dest_file} is same")
189
190    # write install module info to file
191    write_json_file(install_modules_info_file, modules_info_dict)
192
193    # write all module info
194    write_json_file(modules_info_file, output_result)
195
196    # output module list to file
197    write_file(module_list_file, '\n'.join(dest_list))
198
199
200def main():
201    parser = argparse.ArgumentParser()
202    parser.add_argument('--system-install-info-file', required=True)
203    parser.add_argument('--install-modules-info-file', required=True)
204    parser.add_argument('--modules-info-file', required=True)
205    parser.add_argument('--modules-list-file', required=True)
206    parser.add_argument('--platform-installed-path', required=True)
207    parser.add_argument('--system-dir', required=True)
208    parser.add_argument('--sa-profile-extract-dir', required=True)
209    parser.add_argument('--merged-sa-profile', required=True)
210    parser.add_argument('--depfile', required=True)
211    parser.add_argument('--system-image-zipfile', required=True)
212    parser.add_argument('--host-toolchain', required=True)
213    parser.add_argument('--categorized-libraries', required=False)
214    parser.add_argument(
215        '--additional-system-files',
216        action='append',
217        help="additional system files is used for files don't have module infos. \
218                use with caution"
219    )
220    parser.add_argument('--post-process-modules-info-files',
221                        nargs='*',
222                        default=[])
223    args = parser.parse_args()
224
225    additional_system_files = []
226    for tuples in args.additional_system_files or []:
227        filepath, system_path = tuples.split(':')
228        additional_system_files.append((filepath, system_path))
229
230    depfiles = []
231    build_utils.extract_all(args.merged_sa_profile,
232                            args.sa_profile_extract_dir,
233                            no_clobber=False)
234    sa_files = build_utils.get_all_files(args.sa_profile_extract_dir)
235
236    system_install_info = read_json_file(args.system_install_info_file)
237    if system_install_info is None:
238        raise Exception("read file '{}' failed.".format(
239            args.system_install_info_file))
240
241    system_install_base_dir = args.system_dir
242    if os.path.exists(system_install_base_dir):
243        shutil.rmtree(system_install_base_dir)
244        print('remove system dir...')
245    os.makedirs(system_install_base_dir, exist_ok=True)
246
247    vendor_install_base_dir = os.path.join(args.platform_installed_path,
248                                           'vendor')
249    if os.path.exists(vendor_install_base_dir):
250        shutil.rmtree(vendor_install_base_dir)
251        print('remove vendor dir...')
252
253    eng_system_install_base_dir = os.path.join(args.platform_installed_path,
254                                           'eng_system')
255    if os.path.exists(eng_system_install_base_dir):
256        shutil.rmtree(eng_system_install_base_dir)
257        print('remove eng_system dir...')
258
259    eng_chipset_install_base_dir = os.path.join(args.platform_installed_path,
260                                           'eng_chipset')
261    if os.path.exists(eng_chipset_install_base_dir):
262        shutil.rmtree(eng_chipset_install_base_dir)
263        print('remove eng_chipset dir...')
264
265    sys_prod_install_base_dir = os.path.join(args.platform_installed_path,
266                                           'sys_prod')
267    if os.path.exists(sys_prod_install_base_dir):
268        shutil.rmtree(sys_prod_install_base_dir)
269        print('remove sys_prod dir...')
270
271    chip_prod_install_base_dir = os.path.join(args.platform_installed_path,
272                                           'chip_prod')
273    if os.path.exists(chip_prod_install_base_dir):
274        shutil.rmtree(chip_prod_install_base_dir)
275        print('remove chip_prod dir...')
276
277    updater_install_base_dir = os.path.join(args.platform_installed_path,
278                                            'updater')
279    if os.path.exists(updater_install_base_dir):
280        shutil.rmtree(updater_install_base_dir)
281        print('remove updater dir...')
282
283    updater_vendor_install_base_dir = os.path.join(args.platform_installed_path,
284                                            'updater_vendor')
285    if os.path.exists(updater_vendor_install_base_dir):
286        shutil.rmtree(updater_vendor_install_base_dir)
287        print('remove updater dir...')
288
289    ramdisk_install_base_dir = os.path.join(args.platform_installed_path,
290                                            'ramdisk')
291    if os.path.exists(ramdisk_install_base_dir):
292        shutil.rmtree(ramdisk_install_base_dir)
293        print('remove ramdisk dir...')
294
295    cloud_rom_install_base_dir = os.path.join(args.platform_installed_path,
296                                            'cloud_rom')
297    if os.path.exists(cloud_rom_install_base_dir):
298        shutil.rmtree(cloud_rom_install_base_dir)
299        print('remove cloud_rom dir...')
300
301    print('copy modules...')
302    categorized_libraries = load_categorized_libraries(args.categorized_libraries)
303    copy_modules(system_install_info, args.install_modules_info_file,
304                 args.modules_info_file, args.modules_list_file,
305                 args.post_process_modules_info_files,
306                 args.platform_installed_path, args.host_toolchain,
307                 additional_system_files, depfiles, categorized_libraries)
308
309    if os.path.exists(args.system_image_zipfile):
310        os.unlink(args.system_image_zipfile)
311    build_utils.zip_dir(args.system_image_zipfile, args.system_dir)
312    depfiles.extend([item for item in depfiles if item not in sa_files])
313    build_utils.write_depfile(args.depfile, args.install_modules_info_file,
314                              depfiles)
315
316    BootPathCollection.run(args.system_dir)
317    return 0
318
319
320if __name__ == '__main__':
321    sys.exit(main())
322