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 argparse 17import sys 18import os 19import pathlib 20import re 21from convert_permissions import convert_permissions 22 23sys.path.append( 24 os.path.dirname( 25 os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 26from scripts.util.file_utils import write_file, read_json_file, \ 27 write_json_file # noqa: E402 28from scripts.util import build_utils # noqa: E402 29 30# Import jinja2 from third_party/jinja2 31sys.path.insert(1, os.path.join(os.path.abspath( 32 os.path.join(os.path.dirname(__file__), 33 '..', '..', '..')), 'third_party')) 34from jinja2 import Template # noqa: E402 # pylint: disable=F0401 35 36KEYS = ['target_os', 'install_dir', 'module_label', 'build_only'] 37 38 39class SdkTargets: 40 41 def __init__(self, os_type): 42 self.os_type = os_type 43 self.targets = [] 44 45 def add_target(self, target): 46 if target not in self.targets: 47 self.targets.append(target) 48 49 def get_targets(self): 50 return self.targets 51 52 53def check_keys(keys): 54 for key in keys: 55 if key not in KEYS: 56 raise Exception( 57 'Error: failed to parse ohos sdk description file, missing {}.' 58 .format(key)) 59 60 61def get_sdk_type(path_name: str): 62 p = pathlib.Path(path_name) 63 if path_name.startswith('/'): 64 top_dir = p.parts[1] 65 else: 66 top_dir = p.parts[0] 67 return top_dir 68 69 70def add_target(item: dict, target: str, sdk_systems: list): 71 for _os in sdk_systems: 72 if _os == 'linux' or _os == 'Linux': 73 item.get('targets').get('linux').add_target('"%s",' % target) 74 elif _os == 'windows' or _os == 'Windows': 75 item.get('targets').get('windows').add_target('"%s",' % target) 76 elif _os == 'darwin' or _os == 'Darwin': 77 item.get('targets').get('darwin').add_target('"%s",' % target) 78 elif _os == 'ohos' or _os == 'Ohos': 79 item.get('targets').get('ohos').add_target('"%s",' % target) 80 81 82def write_sdk_build_gni(sdk_targets: list, build_only_targets: list, gni: str): 83 template = Template( 84 """#Generated code, DONOT modify it. 85 ohos_sdk_modules = { 86 {% for item in sdk_targets %} 87 88 {% set sdk_type = item.get('type') %} 89 {% set targets = item.get('targets') %} 90 {% set systems = targets.keys() %} 91 {% set _sdk_type = sdk_type.replace('-', '_') %} 92 93 {{ _sdk_type }} = { 94 {% for os in systems %} 95 {{ os }} = [ 96 {% for t in targets.get(os).get_targets() %} 97 {{ t }} 98 {% endfor %} 99 ] 100 {% endfor %} 101 } 102 {% endfor %} 103 104 extras = [ 105 {% for t in build_only_targets%} 106 "{{ t }}", 107 {% endfor %} 108 ] 109 } 110 """, # noqa E501 111 trim_blocks=True, 112 lstrip_blocks=True) 113 114 contents = template.render( 115 sdk_targets=sdk_targets, build_only_targets=build_only_targets) 116 write_file(gni, contents) 117 118 119def get_build_gn(label: str): 120 match = re.search(r"(.*?):(.*?)", label) 121 if match: 122 gn = '{}/BUILD.gn'.format(match.group(1)) 123 if gn.startswith("//"): 124 return gn[len("//"):] 125 else: 126 return gn 127 else: 128 raise Exception("failed to get BUILD.gn of {}".format(label)) 129 130 131def variant_to_product(variant: dict, options: dict): 132 relations = read_json_file(options.variant_to_product) 133 if variant in relations.keys(): 134 return relations.get(variant) 135 else: 136 raise Exception('Error: failed to read {} in {}'.format( 137 variant, options.variant_to_product)) 138 139 140def expand_platform_targets(options, label: str, install_dir: str): 141 base = options.base_platform 142 platforms = options.platforms 143 variant = list(set(platforms) - set([base])) 144 145 if label.find('${base}') != -1: 146 return [label.replace('${base}', base)], [install_dir] 147 elif label.find('${platforms}') != -1: 148 return [label.replace('${platforms}', p) for p in platforms], [ 149 install_dir.replace('${platforms}', 150 variant_to_product(c, options)) 151 for c in platforms 152 ] 153 elif label.find('${variant}') != -1: 154 return [label.replace('${variant}', c) for c in variant], [ 155 install_dir.replace('${variant}', variant_to_product(c, options)) 156 for c in variant 157 ] 158 else: 159 return [label], [install_dir] 160 161 162def add_sdk_targets(sdk_type, sdk_targets): 163 sdk_targets.append({ 164 'type': sdk_type, 165 'targets': { 166 'linux': SdkTargets('linux'), 167 'windows': SdkTargets('windows'), 168 'darwin': SdkTargets('darwin'), 169 'ohos': SdkTargets('ohos') 170 } 171 }) 172 173 174def parse_description_file(options): 175 data = read_json_file(options.sdk_description_file) 176 if data is None: 177 raise Exception("read file '{}' failed.".format( 178 options.sdk_description_file)) 179 180 module_install_infos = [] 181 sdk_types = [] 182 sdk_targets = [] 183 build_only_targets = [] 184 185 for d in data: 186 check_keys(d.keys()) 187 188 label = d.get('module_label') 189 install_dir = d.get('install_dir') 190 build_only = d.get('build_only') 191 192 # skip labels that we cannot find. 193 rebased_build_gn = build_utils.rebase_path( 194 get_build_gn(label), current_base=options.source_root_dir) 195 if not os.path.exists(rebased_build_gn): 196 continue 197 198 if build_only: 199 build_only_targets.append(label) 200 continue 201 202 module_labels, install_dirs = expand_platform_targets( 203 options, label, install_dir) 204 target_os = d.get('target_os') 205 206 sdk_type = get_sdk_type(install_dir) 207 208 if sdk_type not in sdk_types: 209 add_sdk_targets(sdk_type, sdk_targets) 210 sdk_types.append(sdk_type) 211 212 for item in sdk_targets: 213 if item['type'] == sdk_type: 214 for m in module_labels: 215 add_target(item, m, target_os) 216 217 for label, install_dir in zip(module_labels, install_dirs): 218 install_info = { 219 'label': label, 220 'install_dir': install_dir 221 } 222 module_install_infos.append(install_info) 223 224 return { 225 "sdk_targets": sdk_targets, 226 "install_infos": module_install_infos, 227 "sdk_types": sdk_types, 228 "build_only_targets": build_only_targets 229 } 230 231 232def main(): 233 parser = argparse.ArgumentParser() 234 parser.add_argument('--sdk-description-file', required=True) 235 parser.add_argument('--sdk-install-info-file', required=True) 236 parser.add_argument('--sdk-modules-gni', required=True) 237 parser.add_argument('--sdk-types-file', required=True) 238 parser.add_argument('--base-platform', required=True) 239 parser.add_argument('--platforms', action='append', required=True) 240 parser.add_argument('--source-root-dir', required=True) 241 parser.add_argument('--variant-to-product', required=True) 242 parser.add_argument('--node-js', required=True) 243 244 options = parser.parse_args() 245 246 convert_permissions(options.source_root_dir, options.node_js) 247 248 data = parse_description_file(options) 249 250 write_sdk_build_gni( 251 data.get('sdk_targets'), data.get('build_only_targets'), 252 options.sdk_modules_gni) 253 write_json_file(options.sdk_install_info_file, data.get('install_infos')) 254 with open(options.sdk_types_file, 'w') as f: 255 f.write('\n'.join(data.get('sdk_types'))) 256 257 258if __name__ == '__main__': 259 sys.exit(main()) 260