import argparse
import sys
import os
import pathlib
import re
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from scripts.util.file_utils import write_file, read_json_file, \
write_json_file
from scripts.util import build_utils
_SOURCE_ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..'))
sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
from jinja2 import Template
KEYS = ['target_os', 'install_dir', 'module_label', 'build_only']
class SdkTargets:
def __init__(self, os_type):
self.os_type = os_type
self.targets = []
def add_target(self, target):
if target not in self.targets:
self.targets.append(target)
def get_targets(self):
return self.targets
def check_keys(keys):
for key in keys:
if key not in KEYS:
raise Exception(
'Error: failed to parse arkui cross sdk description file, missing {}.'
.format(key))
def get_sdk_type(path_name):
p = pathlib.Path(path_name)
if path_name.startswith('/'):
top_dir = p.parts[1]
else:
top_dir = p.parts[0]
return top_dir
def add_target(item, target, sdk_systems):
for _os in sdk_systems:
if _os == 'linux' or _os == 'Linux':
item.get('targets').get('linux').add_target('"%s",' % target)
elif _os == 'windows' or _os == 'Windows':
item.get('targets').get('windows').add_target('"%s",' % target)
elif _os == 'darwin' or _os == 'Darwin':
item.get('targets').get('darwin').add_target('"%s",' % target)
def write_sdk_build_gni(sdk_targets, build_only_targets, gni):
template = Template(
"""#Generated code, DONOT modify it.
arkui_cross_sdk_modules = {
{% for item in sdk_targets %}
{% set sdk_type = item.get('type') %}
{% set targets = item.get('targets') %}
{% set systems = targets.keys() %}
{% set _sdk_type = sdk_type.replace('-', '_') %}
{{ _sdk_type }} = {
{% for os in systems %}
{{ os }} = [
{% for t in targets.get(os).get_targets() %}
{{ t }}
{% endfor %}
]
{% endfor %}
}
{% endfor %}
extras = [
{% for t in build_only_targets%}
"{{ t }}",
{% endfor %}
]
}
""",
trim_blocks=True,
lstrip_blocks=True)
contents = template.render(
sdk_targets=sdk_targets, build_only_targets=build_only_targets)
write_file(gni, contents)
def get_build_gn(label):
match = re.search(r"(.*?):(.*?)", label)
if match:
gn = '{}/BUILD.gn'.format(match.group(1))
if gn.startswith("//"):
return gn[len("//"):]
else:
return gn
else:
raise Exception("failed to get BUILD.gn of {}".format(label))
def variant_to_product(variant, options):
relations = read_json_file(options.variant_to_product)
if variant in relations.keys():
return relations.get(variant)
else:
raise Exception('Error: failed to read {} in {}'.format(
variant, options.variant_to_product))
def expand_platform_targets(options, label, install_dir):
base = options.base_platform
platforms = options.platforms
variant = list(set(platforms) - set([base]))
if label.find('${base}') != -1:
return [label.replace('${base}', base)], [install_dir]
elif label.find('${platforms}') != -1:
return [label.replace('${platforms}', p) for p in platforms], [
install_dir.replace('${platforms}',
variant_to_product(c, options))
for c in platforms
]
elif label.find('${variant}') != -1:
return [label.replace('${variant}', c) for c in variant], [
install_dir.replace('${variant}', variant_to_product(c, options))
for c in variant
]
else:
return [label], [install_dir]
def filter(arch_list, runtime_mode, gen_full_sdk, target_cpu, build_target_arch=None):
res = []
if build_target_arch:
for arch in arch_list:
if build_target_arch in arch and runtime_mode in arch:
res.append(arch)
return res
if gen_full_sdk:
for arch in arch_list:
res.append(arch.replace('-debug', ''))
else:
res.extend(['arm64-simulator', 'x86_64-simulator', 'x86_64'])
for arch in arch_list:
if runtime_mode in arch:
res.append(arch.replace('-debug', ''))
return res
def parse_description_file(options):
data = read_json_file(options.sdk_description_file)
if data is None:
raise Exception("read file '{}' failed.".format(
options.sdk_description_file))
module_install_infos = []
sdk_types = []
sdk_targets = []
build_only_targets = []
sdk_items = []
arch_dict = data.get('arch_dict')
multi_arch_items = data.get(options.platform)
target_os_list = []
if hasattr(options, 'build_target_os') and options.build_target_os:
target_os_list = [options.build_target_os.lower()]
for item in multi_arch_items:
install_dir = item.get('install_dir')
module_label = item.get('module_label')
target_os = item.get('target_os')
for os_name in target_os:
if target_os_list and os_name.lower() not in target_os_list:
continue
arch_list = arch_dict.get(os_name)
arch_list = filter(arch_list, options.runtime_mode, options.gen_full_sdk,
options.target_cpu,
options.build_target_arch if hasattr(options, 'build_target_arch') else None)
for arch in arch_list:
tmp_item = dict()
platform_arch = '{}-{}'.format(options.platform, arch)
toolchain = data.get('toolchains').get(os_name).get(platform_arch)
if not toolchain:
continue
platform_type = ''
if 'release' in platform_arch or 'simulator' in platform_arch:
platform_type = '{}-{}'.format(options.platform, 'release')
elif 'profile' in platform_arch:
platform_type = '{}-{}'.format(options.platform, 'profile')
new_install_dir_pre = install_dir.replace('arch_type', platform_arch)
new_install_dir = new_install_dir_pre.replace('platform_type', platform_type)
tmp_item['install_dir'] = new_install_dir
tmp_item['module_label'] = '{}({})'.format(module_label, toolchain)
tmp_item['target_os'] = [os_name]
sdk_items.append(tmp_item)
for d in sdk_items:
check_keys(d.keys())
label = d.get('module_label')
install_dir = d.get('install_dir')
build_only = d.get('build_only')
rebased_build_gn = build_utils.rebase_path(
get_build_gn(label), current_base=options.source_root_dir)
if not os.path.exists(rebased_build_gn):
continue
if build_only:
build_only_targets.append(label)
continue
module_labels, install_dirs = expand_platform_targets(
options, label, install_dir)
target_os = d.get('target_os')
sdk_type = get_sdk_type(install_dir)
if sdk_type not in sdk_types:
sdk_targets.append({
'type': sdk_type,
'targets': {
'linux': SdkTargets('linux'),
'windows': SdkTargets('windows'),
'darwin': SdkTargets('darwin')
}
})
sdk_types.append(sdk_type)
for item in sdk_targets:
if item['type'] == sdk_type:
for m in module_labels:
if options.build_target_include:
if options.build_target_include in m:
add_target(item, m, target_os)
else:
add_target(item, m, target_os)
for i in range(len(module_labels)):
install_info = {
'label': module_labels[i],
'install_dir': install_dirs[i]
}
module_install_infos.append(install_info)
return {
"sdk_targets": sdk_targets,
"install_infos": module_install_infos,
"sdk_types": sdk_types,
"build_only_targets": build_only_targets
}
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--sdk-description-file', required=True)
parser.add_argument('--sdk-install-info-file', required=True)
parser.add_argument('--sdk-modules-gni', required=True)
parser.add_argument('--sdk-types-file', required=True)
parser.add_argument('--base-platform', required=True)
parser.add_argument('--platforms', action='append', required=True)
parser.add_argument('--source-root-dir', required=True)
parser.add_argument('--variant-to-product', required=True)
parser.add_argument('--node-js', required=True)
parser.add_argument('--platform', required=True)
parser.add_argument('--build-type')
parser.add_argument('--runtime-mode')
parser.add_argument('--gen-full-sdk', action='store_true')
parser.add_argument('--target-cpu')
parser.add_argument('--build-target-os', required=False, help='Specify target OS, e.g. linux, windows, darwin')
parser.add_argument('--build-target-arch', required=False, help='Specify target CPU, e.g. arm, arm64, x86_64')
parser.add_argument('--build-target-include', required=False, help='Specify target include, e.g. libarkui_android')
options = parser.parse_args()
data = parse_description_file(options)
write_sdk_build_gni(
data.get('sdk_targets'), data.get('build_only_targets'),
options.sdk_modules_gni)
write_json_file(options.sdk_install_info_file, data.get('install_infos'))
with open(options.sdk_types_file, 'w') as f:
f.write('\n'.join(data.get('sdk_types')))
if __name__ == '__main__':
sys.exit(main())