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_SOURCE_ROOT = os.path.abspath( 31 os.path.join(os.path.dirname(__file__), '..', '..', '..')) 32# Import jinja2 from third_party/jinja2 33sys.path.insert(1, os.path.join(_SOURCE_ROOT, '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): 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, target, sdk_systems): 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 79 80def write_sdk_build_gni(sdk_targets, build_only_targets, gni): 81 template = Template( 82 """#Generated code, DONOT modify it. 83 ohos_sdk_modules = { 84 {% for item in sdk_targets %} 85 86 {% set sdk_type = item.get('type') %} 87 {% set targets = item.get('targets') %} 88 {% set systems = targets.keys() %} 89 {% set _sdk_type = sdk_type.replace('-', '_') %} 90 91 {{ _sdk_type }} = { 92 {% for os in systems %} 93 {{ os }} = [ 94 {% for t in targets.get(os).get_targets() %} 95 {{ t }} 96 {% endfor %} 97 ] 98 {% endfor %} 99 } 100 {% endfor %} 101 102 extras = [ 103 {% for t in build_only_targets%} 104 "{{ t }}", 105 {% endfor %} 106 ] 107 } 108 """, # noqa E501 109 trim_blocks=True, 110 lstrip_blocks=True) 111 112 contents = template.render( 113 sdk_targets=sdk_targets, build_only_targets=build_only_targets) 114 write_file(gni, contents) 115 116 117def get_build_gn(label): 118 match = re.search(r"(.*?):(.*?)", label) 119 if match: 120 gn = '{}/BUILD.gn'.format(match.group(1)) 121 if gn.startswith("//"): 122 return gn[len("//"):] 123 else: 124 return gn 125 else: 126 raise Exception("failed to get BUILD.gn of {}".format(label)) 127 128 129def variant_to_product(variant, options): 130 relations = read_json_file(options.variant_to_product) 131 if variant in relations.keys(): 132 return relations.get(variant) 133 else: 134 raise Exception('Error: failed to read {} in {}'.format( 135 variant, options.variant_to_product)) 136 137 138def expand_platform_targets(options, label, install_dir): 139 base = options.base_platform 140 platforms = options.platforms 141 variant = list(set(platforms) - set([base])) 142 143 if label.find('${base}') != -1: 144 return [label.replace('${base}', base)], [install_dir] 145 elif label.find('${platforms}') != -1: 146 return [label.replace('${platforms}', p) for p in platforms], [ 147 install_dir.replace('${platforms}', 148 variant_to_product(c, options)) 149 for c in platforms 150 ] 151 elif label.find('${variant}') != -1: 152 return [label.replace('${variant}', c) for c in variant], [ 153 install_dir.replace('${variant}', variant_to_product(c, options)) 154 for c in variant 155 ] 156 else: 157 return [label], [install_dir] 158 159 160def parse_description_file(options): 161 data = read_json_file(options.sdk_description_file) 162 if data is None: 163 raise Exception("read file '{}' failed.".format( 164 options.sdk_description_file)) 165 166 module_install_infos = [] 167 sdk_types = [] 168 sdk_targets = [] 169 build_only_targets = [] 170 171 for d in data: 172 check_keys(d.keys()) 173 174 label = d.get('module_label') 175 install_dir = d.get('install_dir') 176 build_only = d.get('build_only') 177 178 # skip labels that we cannot find. 179 rebased_build_gn = build_utils.rebase_path( 180 get_build_gn(label), current_base=options.source_root_dir) 181 if not os.path.exists(rebased_build_gn): 182 continue 183 184 if build_only: 185 build_only_targets.append(label) 186 continue 187 188 module_labels, install_dirs = expand_platform_targets( 189 options, label, install_dir) 190 target_os = d.get('target_os') 191 192 sdk_type = get_sdk_type(install_dir) 193 if sdk_type not in sdk_types: 194 sdk_targets.append({ 195 'type': sdk_type, 196 'targets': { 197 'linux': SdkTargets('linux'), 198 'windows': SdkTargets('windows'), 199 'darwin': SdkTargets('darwin') 200 } 201 }) 202 sdk_types.append(sdk_type) 203 for item in sdk_targets: 204 if item['type'] == sdk_type: 205 for m in module_labels: 206 add_target(item, m, target_os) 207 208 for i in range(len(module_labels)): 209 install_info = { 210 'label': module_labels[i], 211 'install_dir': install_dirs[i] 212 } 213 module_install_infos.append(install_info) 214 215 return { 216 "sdk_targets": sdk_targets, 217 "install_infos": module_install_infos, 218 "sdk_types": sdk_types, 219 "build_only_targets": build_only_targets 220 } 221 222 223def main(): 224 parser = argparse.ArgumentParser() 225 parser.add_argument('--sdk-description-file', required=True) 226 parser.add_argument('--sdk-install-info-file', required=True) 227 parser.add_argument('--sdk-modules-gni', required=True) 228 parser.add_argument('--sdk-types-file', required=True) 229 parser.add_argument('--base-platform', required=True) 230 parser.add_argument('--platforms', action='append', required=True) 231 parser.add_argument('--source-root-dir', required=True) 232 parser.add_argument('--variant-to-product', required=True) 233 parser.add_argument('--node-js', required=True) 234 235 options = parser.parse_args() 236 237 convert_permissions(options.source_root_dir, options.node_js) 238 239 data = parse_description_file(options) 240 241 write_sdk_build_gni( 242 data.get('sdk_targets'), data.get('build_only_targets'), 243 options.sdk_modules_gni) 244 write_json_file(options.sdk_install_info_file, data.get('install_infos')) 245 with open(options.sdk_types_file, 'w') as f: 246 f.write('\n'.join(data.get('sdk_types'))) 247 248 249if __name__ == '__main__': 250 sys.exit(main()) 251