import argparse
import sys
import os
import shutil
import zipfile
sys.path.append(
os.path.dirname(os.path.dirname(os.path.dirname(
os.path.abspath(__file__)))))
from scripts.util import build_utils
from scripts.util.file_utils import read_json_file
def get_source_from_module_info_file(module_info_file: str):
data = read_json_file(module_info_file)
if data is None:
raise Exception("read file '{}' failed.".format(module_info_file))
source = data.get('source')
notice = data.get('notice')
return source, notice
def remove_symlinks_in_dir(dest_dir: str):
"""Remove all symbolic links under dest_dir (files and symlinked dirs).
This keeps real files and directories intact but removes symlinks so that
subsequent copytree operations with dirs_exist_ok=True won't fail due to
existing symlink entries.
"""
if not os.path.exists(dest_dir):
return
for root, dirs, files in os.walk(dest_dir, topdown=True, followlinks=False):
for d in list(dirs):
path = os.path.join(root, d)
try:
if os.path.islink(path):
os.unlink(path)
dirs.remove(d)
except OSError:
pass
for f in files:
path = os.path.join(root, f)
try:
if os.path.islink(path):
os.unlink(path)
except OSError:
pass
def clear_copy_symlinks_dest_dir(copy_infos: dict):
for cp_info in copy_infos:
copy_with_symlinks = cp_info.get("copy_with_symlinks")
if copy_with_symlinks:
dest = cp_info.get('dest')
build_utils.make_directory(dest)
remove_symlinks_in_dir(dest)
def do_copy_and_stamp(copy_infos: dict, options, depfile_deps: list):
notice_tuples = []
clear_copy_symlinks_dest_dir(copy_infos)
for cp_info in copy_infos:
source = cp_info.get('source')
dest = cp_info.get('dest')
notice = cp_info.get('notice')
install_dir = cp_info.get('install_dir')
copy_with_symlinks = cp_info.get("copy_with_symlinks")
if os.path.isdir(source):
if os.listdir(source):
files = build_utils.get_all_files(source)
if files:
shutil.copytree(source, dest, symlinks=copy_with_symlinks, dirs_exist_ok=True)
depfile_deps.update(build_utils.get_all_files(source))
else:
depfile_deps.add(source)
else:
if not os.path.exists(source) and source.endswith('.so'):
z_so_source = source[:-3] + '.z.so'
if os.path.exists(z_so_source):
source = z_so_source
stale_so_dest = dest
dest = dest[:-3] + '.z.so'
if os.path.exists(stale_so_dest):
os.remove(stale_so_dest)
dest_dir = os.path.dirname(dest)
os.makedirs(dest_dir, exist_ok=True)
shutil.copy2(source, dest)
depfile_deps.add(source)
if notice and os.path.exists(notice):
depfile_deps.add(notice)
if notice.endswith('.zip'):
suffix = ".zip"
else:
suffix = ".txt"
if os.path.isdir(source):
notice_dest = os.path.join('{}{}'.format(install_dir, suffix))
else:
notice_dest = os.path.join(
install_dir, '{}{}'.format(os.path.basename(source),
suffix))
notice_tuples.append((notice_dest, notice))
if (options.enable_archive_sdk):
build_utils.zip_dir(options.sdk_output_archive,
options.archive_dir,
compress_fn=lambda _: zipfile.ZIP_DEFLATED,
zip_prefix_path=options.zip_prefix_path)
with zipfile.ZipFile(options.notice_output_archive, 'w') as outfile:
for zip_path, fs_path in notice_tuples:
build_utils.add_to_zip_hermetic(outfile, zip_path, src_path=fs_path)
build_utils.write_depfile(options.depfile,
options.sdk_output_archive,
depfile_deps,
add_pydeps=False)
def main():
parser = argparse.ArgumentParser()
build_utils.add_depfile_option(parser)
parser.add_argument('--sdk-modules-desc-file', required=True)
parser.add_argument('--sdk-archive-paths-file', required=True)
parser.add_argument('--dest-dir', required=True)
parser.add_argument('--archive-dir', required=True)
parser.add_argument('--zip-prefix-path', default=None)
parser.add_argument('--notice-output-archive', required=True)
parser.add_argument('--sdk-output-archive', required=True)
parser.add_argument('--enable-archive-sdk', help='archive sdk')
options = parser.parse_args()
sdk_modules_desc_file = options.sdk_modules_desc_file
sdk_out_dir = options.dest_dir
sdk_archive_paths_file = options.sdk_archive_paths_file
sdk_modules = read_json_file(sdk_modules_desc_file)
if sdk_modules is None:
sdk_modules = []
archive_paths = read_json_file(sdk_archive_paths_file)
if archive_paths is None:
archive_paths = []
depfile_deps = set(
[options.sdk_modules_desc_file, options.sdk_archive_paths_file])
copy_infos = []
for module in sdk_modules:
sdk_label = module.get('label')
module_info_file = module.get('module_info_file')
source, notice = get_source_from_module_info_file(module_info_file)
depfile_deps.add(module_info_file)
for item in archive_paths:
if sdk_label == item.get('label'):
dest = os.path.join(sdk_out_dir, item.get('install_dir'),
os.path.basename(source))
copy_infos.append({'source': source,
'notice': notice,
'dest': dest,
'install_dir': item.get('install_dir'),
'copy_with_symlinks': item.get('copy_with_symlinks')})
do_copy_and_stamp(copy_infos, options, depfile_deps)
if __name__ == '__main__':
sys.exit(main())