1#!/usr/bin/env python3 2# 3# Copyright (C) 2017 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import argparse 19from collections import defaultdict 20import glob 21import json 22import logging 23import os 24import sys 25 26import collect_licenses 27import utils 28 29 30class GenBuildFile(object): 31 """Generates Android.bp for VNDK snapshot. 32 33 VNDK snapshot directory structure under prebuilts/vndk/v{version}: 34 Android.bp 35 {SNAPSHOT_ARCH}/ 36 Android.bp 37 arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/ 38 shared/ 39 vndk-core/ 40 (VNDK-core libraries, e.g. libbinder.so) 41 vndk-sp/ 42 (VNDK-SP libraries, e.g. libc++.so) 43 arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/ 44 shared/ 45 vndk-core/ 46 (VNDK-core libraries, e.g. libbinder.so) 47 vndk-sp/ 48 (VNDK-SP libraries, e.g. libc++.so) 49 binder32/ 50 (This directory is newly introduced in v28 (Android P) to hold 51 prebuilts built for 32-bit binder interface.) 52 Android.bp 53 arch-{TARGET_ARCH}-{TARGE_ARCH_VARIANT}/ 54 ... 55 configs/ 56 (various *.txt configuration files, e.g. ld.config.*.txt) 57 ... (other {SNAPSHOT_ARCH}/ directories) 58 common/ 59 Android.bp 60 NOTICE_FILES/ 61 (license files, e.g. libfoo.so.txt) 62 """ 63 INDENT = ' ' 64 ETC_MODULES = [ 65 'llndk.libraries.txt', 66 'vndksp.libraries.txt', 67 'vndkcore.libraries.txt', 68 'vndkprivate.libraries.txt', 69 'vndkproduct.libraries.txt', 70 ] 71 72 def __init__(self, install_dir, vndk_version): 73 """GenBuildFile constructor. 74 75 Args: 76 install_dir: string, absolute path to the prebuilts/vndk/v{version} 77 directory where the build files will be generated. 78 vndk_version: int, VNDK snapshot version (e.g. 30) 79 """ 80 self._install_dir = install_dir 81 self._vndk_version = vndk_version 82 self._etc_paths = self._get_etc_paths() 83 self._snapshot_archs = utils.get_snapshot_archs(install_dir) 84 self._root_bpfile = os.path.join(install_dir, utils.ROOT_BP_PATH) 85 self._common_bpfile = os.path.join(install_dir, utils.COMMON_BP_PATH) 86 self._llndk = self._parse_lib_list( 87 os.path.basename(self._etc_paths['llndk.libraries.txt'])) 88 self._vndk_core = self._parse_lib_list( 89 os.path.basename(self._etc_paths['vndkcore.libraries.txt'])) 90 self._vndk_sp = self._parse_lib_list( 91 os.path.basename(self._etc_paths['vndksp.libraries.txt'])) 92 self._vndk_private = self._parse_lib_list( 93 os.path.basename(self._etc_paths['vndkprivate.libraries.txt'])) 94 self._vndk_product = self._parse_lib_list( 95 os.path.basename(self._etc_paths['vndkproduct.libraries.txt'])) 96 self._modules_with_notice = self._get_modules_with_notice() 97 self._license_in_json = not self._modules_with_notice 98 self._license_kinds_map = defaultdict(set) 99 self._license_texts_map = defaultdict(set) 100 self.modules_with_restricted_lic = set() 101 102 def _get_etc_paths(self): 103 """Returns a map of relative file paths for each ETC module.""" 104 105 etc_paths = dict() 106 for etc_module in self.ETC_MODULES: 107 etc_pattern = '{}*'.format(os.path.splitext(etc_module)[0]) 108 globbed = glob.glob( 109 os.path.join(self._install_dir, utils.CONFIG_DIR_PATH_PATTERN, 110 etc_pattern)) 111 if len(globbed) > 0: 112 rel_etc_path = globbed[0].replace(self._install_dir, '')[1:] 113 etc_paths[etc_module] = rel_etc_path 114 return etc_paths 115 116 def _parse_lib_list(self, txt_filename): 117 """Returns a map of VNDK library lists per VNDK snapshot arch. 118 119 Args: 120 txt_filename: string, name of snapshot config file 121 122 Returns: 123 dict, e.g. {'arm64': ['libfoo.so', 'libbar.so', ...], ...} 124 """ 125 lib_map = dict() 126 for txt_path in utils.find(self._install_dir, [txt_filename]): 127 arch = utils.snapshot_arch_from_path(txt_path) 128 abs_path_of_txt = os.path.join(self._install_dir, txt_path) 129 with open(abs_path_of_txt, 'r') as f: 130 lib_map[arch] = f.read().strip().split('\n') 131 if lib_map[arch] == ['']: 132 lib_map[arch].clear() 133 return lib_map 134 135 def _get_modules_with_notice(self): 136 """Returns a list of modules that have associated notice files. """ 137 notice_paths = glob.glob( 138 os.path.join(self._install_dir, utils.NOTICE_FILES_DIR_PATH, 139 '*.txt')) 140 return sorted(os.path.splitext(os.path.basename(p))[0] for p in notice_paths) 141 142 def generate_root_android_bp(self): 143 """Autogenerates Android.bp.""" 144 145 logging.info('Generating Android.bp for snapshot v{}'.format( 146 self._vndk_version)) 147 prebuilt_buildrules = [] 148 for prebuilt in self.ETC_MODULES: 149 prebuilt_buildrules.append(self._gen_etc_prebuilt(prebuilt)) 150 151 with open(self._root_bpfile, 'w') as bpfile: 152 bpfile.write(self._gen_autogen_msg('/')) 153 bpfile.write('\n') 154 bpfile.write(self._gen_license_package()) 155 bpfile.write('\n') 156 bpfile.write(self._gen_license()) 157 bpfile.write('\n') 158 bpfile.write('\n'.join(prebuilt_buildrules)) 159 bpfile.write('\n') 160 161 logging.info('Successfully generated {}'.format(self._root_bpfile)) 162 163 def generate_common_android_bp(self): 164 """Autogenerates common/Android.bp.""" 165 166 logging.info('Generating common/Android.bp for snapshot v{}'.format( 167 self._vndk_version)) 168 with open(self._common_bpfile, 'w') as bpfile: 169 bpfile.write(self._gen_autogen_msg('/')) 170 bpfile.write('\n') 171 bpfile.write(self._gen_license_package()) 172 if self._license_in_json: 173 for name in self._license_kinds_map: 174 bpfile.write('\n') 175 bpfile.write(self._gen_notice_license(name)) 176 else: 177 for module in self._modules_with_notice: 178 bpfile.write('\n') 179 bpfile.write(self._gen_notice_license(module)) 180 181 def generate_android_bp(self): 182 """Autogenerates Android.bp.""" 183 184 def gen_for_variant(arch, is_binder32=False): 185 """Generates Android.bp file for specified VNDK snapshot variant. 186 187 A VNDK snapshot variant is defined by the TARGET_ARCH and binder 188 bitness. Example snapshot variants: 189 vndk_v{ver}_arm: {arch: arm, binder: 64-bit} 190 vndk_v{ver}_arm_binder32: {arch: arm, binder: 32-bit} 191 192 Args: 193 arch: string, VNDK snapshot arch (e.g. 'arm64') 194 is_binder32: bool, True if binder interface is 32-bit 195 """ 196 binder32_suffix = '_{}'.format( 197 utils.BINDER32) if is_binder32 else '' 198 logging.info('Generating Android.bp for vndk_v{}_{}{}'.format( 199 self._vndk_version, arch, binder32_suffix)) 200 201 src_root = os.path.join(self._install_dir, arch) 202 module_names_txt = os.path.join( 203 src_root, "configs", "module_names.txt") 204 module_names = dict() 205 try: 206 with open(module_names_txt, 'r') as f: 207 # Remove empty lines from module_names_txt 208 module_list = filter(None, f.read().split('\n')) 209 for module in module_list: 210 lib, name = module.split(' ') 211 module_names[lib] = name 212 except IOError: 213 # If module_names.txt doesn't exist, ignore it and parse 214 # module names out from .so filenames. (old snapshot) 215 pass 216 217 variant_subpath = arch 218 if is_binder32: 219 variant_subpath = os.path.join(arch, utils.BINDER32) 220 variant_path = os.path.join(self._install_dir, variant_subpath) 221 bpfile_path = os.path.join(variant_path, 'Android.bp') 222 223 vndk_core_buildrules = self._gen_vndk_shared_prebuilts( 224 self._vndk_core[arch], 225 arch, 226 is_llndk=False, 227 is_vndk_sp=False, 228 is_binder32=is_binder32, 229 module_names=module_names) 230 vndk_sp_buildrules = self._gen_vndk_shared_prebuilts( 231 self._vndk_sp[arch], 232 arch, 233 is_llndk=False, 234 is_vndk_sp=True, 235 is_binder32=is_binder32, 236 module_names=module_names) 237 include_llndk = self._vndk_version > 30 238 if include_llndk: 239 llndk_buildrules = self._gen_vndk_shared_prebuilts( 240 self._llndk[arch], 241 arch, 242 is_llndk=True, 243 is_vndk_sp=False, 244 is_binder32=is_binder32, 245 module_names=module_names) 246 247 with open(bpfile_path, 'w') as bpfile: 248 bpfile.write(self._gen_autogen_msg('/')) 249 bpfile.write('\n') 250 bpfile.write(self._gen_license_package()) 251 bpfile.write('\n') 252 bpfile.write('\n'.join(vndk_core_buildrules)) 253 bpfile.write('\n') 254 bpfile.write('\n'.join(vndk_sp_buildrules)) 255 if include_llndk: 256 bpfile.write('\n') 257 bpfile.write('\n'.join(llndk_buildrules)) 258 259 variant_include_path = os.path.join(variant_path, 'include') 260 include_path = os.path.join(self._install_dir, arch, 'include') 261 if os.path.isdir(include_path) and variant_include_path != include_path: 262 os.symlink(os.path.relpath(include_path, variant_path), 263 variant_include_path) 264 265 logging.info('Successfully generated {}'.format(bpfile_path)) 266 267 for arch in self._snapshot_archs: 268 if os.path.isdir( 269 os.path.join(self._install_dir, arch, utils.BINDER32)): 270 gen_for_variant(arch, is_binder32=True) 271 gen_for_variant(arch) 272 273 def _gen_autogen_msg(self, comment_char): 274 return ('{0}{0} THIS FILE IS AUTOGENERATED BY ' 275 'development/vndk/snapshot/gen_buildfiles.py\n' 276 '{0}{0} DO NOT EDIT\n'.format(comment_char)) 277 278 def _gen_license_package(self): 279 """ Generates license package for VNDK snapshot libs """ 280 return ('package {{\n' 281 '{ind}default_applicable_licenses: ["prebuilts_vndk_v{version}_license"],\n' 282 '}}\n'.format( 283 ind=self.INDENT, 284 version=self._vndk_version)) 285 286 def _get_license_kinds(self, module=''): 287 """ Returns a set of license kinds 288 289 Args: 290 module: module name to find the license kind. 291 If empty, check all license files. 292 """ 293 if self._license_in_json: 294 license_kinds = set() 295 if module == '': 296 # collect all license kinds 297 for kinds in self._license_kinds_map.values(): 298 license_kinds.update(kinds) 299 return license_kinds 300 else: 301 return self._license_kinds_map[module] 302 303 license_collector = collect_licenses.LicenseCollector(self._install_dir) 304 license_collector.run(module) 305 return license_collector.license_kinds 306 307 def _get_license_texts(self, module): 308 if self._license_in_json: 309 return {'{notice_dir}/{license_text}'.format( 310 notice_dir=utils.NOTICE_FILES_DIR_NAME, 311 license_text=license_text) 312 for license_text in self._license_texts_map[module]} 313 else: 314 return {'{notice_dir}/{module}.txt'.format( 315 notice_dir=utils.NOTICE_FILES_DIR_NAME, 316 module=module)} 317 318 def _gen_license(self): 319 """ Generates license module. 320 321 It uses license files for all VNDK snapshot libraries in common/NOTICE_FILES directory. 322 """ 323 license_kinds = self._get_license_kinds() 324 license_kinds_string = '' 325 for license_kind in sorted(license_kinds): 326 license_kinds_string += '{ind}{ind}"{license_kind}",\n'.format( 327 ind=self.INDENT, license_kind=license_kind) 328 return ('license {{\n' 329 '{ind}name: "prebuilts_vndk_v{version}_license",\n' 330 '{ind}visibility: [":__subpackages__"],\n' 331 '{ind}license_kinds: [\n' 332 '{license_kinds}' 333 '{ind}],\n' 334 '{ind}license_text: ["{notice_files}"],\n' 335 '}}\n'.format( 336 ind=self.INDENT, 337 version=self._vndk_version, 338 license_kinds=license_kinds_string, 339 notice_files=os.path.join(utils.NOTICE_FILES_DIR_PATH, '**', '*'))) 340 341 def _get_versioned_name(self, 342 prebuilt, 343 arch, 344 is_etc=False, 345 is_binder32=False, 346 module_names=None): 347 """Returns the VNDK version-specific module name for a given prebuilt. 348 349 The VNDK version-specific module name is defined as follows: 350 For a VNDK shared lib: 'libfoo.so' 351 if binder is 32-bit: 352 'libfoo.vndk.{version}.{arch}.binder32.vendor' 353 else: 354 'libfoo.vndk.{version}.{arch}.vendor' 355 For an ETC module: 'foo.txt' -> 'foo.{version}.txt' 356 357 Args: 358 prebuilt: string, name of the prebuilt object 359 arch: string, VNDK snapshot arch (e.g. 'arm64') 360 is_etc: bool, True if the LOCAL_MODULE_CLASS of prebuilt is 'ETC' 361 is_binder32: bool, True if binder interface is 32-bit 362 module_names: dict, module names for given prebuilts 363 """ 364 if is_etc: 365 name, ext = os.path.splitext(prebuilt) 366 versioned_name = '{}.{}{}'.format(name, self._vndk_version, ext) 367 else: 368 module_names = module_names or dict() 369 if prebuilt in module_names: 370 name = module_names[prebuilt] 371 else: 372 name = os.path.splitext(prebuilt)[0] 373 binder_suffix = '.{}'.format(utils.BINDER32) if is_binder32 else '' 374 versioned_name = '{}.vndk.{}.{}{}.vendor'.format( 375 name, self._vndk_version, arch, binder_suffix) 376 377 return versioned_name 378 379 def _gen_etc_prebuilt(self, prebuilt): 380 """Generates build rule for an ETC prebuilt. 381 382 Args: 383 prebuilt: string, name of ETC prebuilt object 384 """ 385 etc_path = self._etc_paths[prebuilt] 386 etc_sub_path = etc_path[etc_path.index('/') + 1:] 387 388 prebuilt_etc = ('prebuilt_etc {{\n' 389 '{ind}name: "{versioned_name}",\n' 390 '{ind}target: {{\n'.format( 391 ind=self.INDENT, 392 versioned_name=self._get_versioned_name( 393 prebuilt, None, is_etc=True))) 394 for arch in self._snapshot_archs: 395 prebuilt_etc += ('{ind}{ind}android_{arch}: {{\n' 396 '{ind}{ind}{ind}src: "{arch}/{etc_sub_path}",\n' 397 '{ind}{ind}}},\n'.format( 398 ind=self.INDENT, 399 arch=arch, 400 etc_sub_path=etc_sub_path)) 401 prebuilt_etc += ('{ind}}},\n' 402 '}}\n'.format(ind=self.INDENT)) 403 return prebuilt_etc 404 405 def _gen_prebuilt_library_shared(self, prebuilt_lib_info): 406 """Generates cc_prebuilt_library_shared modules for the old vendor 407 compatibility. 408 409 Some vendor modules still require old version of libraries that is not 410 available from the current source tree. To provide the old copy of the 411 libraries, use the vndk snapshot. 412 413 Args: 414 prebuilt_lib_info: pair of (string, list of strings), name of the 415 prebuilt library and the list of shared libs for it. 416 """ 417 lib_name = prebuilt_lib_info[0] 418 shared_libs = prebuilt_lib_info[1] 419 420 shared_libs_prop = '' 421 if shared_libs: 422 shared_libs_prop = ('{ind}shared_libs: [\n'.format(ind=self.INDENT)) 423 for lib in shared_libs: 424 shared_libs_prop += ('{ind}{ind}"{lib}",\n'.format( 425 ind=self.INDENT, lib=lib)) 426 shared_libs_prop += ('{ind}],\n'.format(ind=self.INDENT)) 427 428 cc_prebuilt_libraries = ('cc_prebuilt_library_shared {{\n' 429 '{ind}name: "{name}-vendorcompat",\n' 430 '{ind}stem: "{name}",\n' 431 '{ind}vendor: true,\n' 432 '{ind}// These are already stripped, and ' 433 'restripping them just issues diagnostics.\n' 434 '{ind}strip: {{\n' 435 '{ind}{ind}none: true,\n' 436 '{ind}}},\n' 437 '{shared_libs}' 438 '{ind}target: {{\n'.format( 439 ind=self.INDENT, 440 name=lib_name, 441 shared_libs=shared_libs_prop)) 442 src_paths = utils.find(self._install_dir, [lib_name+'.so']) 443 for src in src_paths: 444 dirs = src.split(os.path.sep) 445 if len(dirs) < 3 or not dirs[1].startswith('arch-{}-'.format(dirs[0])): 446 continue 447 cc_prebuilt_libraries += ('{ind}{ind}android_{arch}: {{\n' 448 '{ind}{ind}{ind}srcs: ["{src}"],\n' 449 '{ind}{ind}}},\n'.format( 450 ind=self.INDENT, arch=dirs[0], src=src)) 451 cc_prebuilt_libraries += ('{ind}}},\n' 452 '}}\n'.format(ind=self.INDENT)) 453 return cc_prebuilt_libraries 454 455 def _gen_notice_license(self, module): 456 """Generates a notice license build rule for a given module. 457 When genererating each notice license, collect 458 modules_with_restricted_lic, the list of modules that are under the GPL. 459 460 Args: 461 module: string, module name 462 """ 463 def has_restricted_license(license_kinds): 464 for lic in license_kinds: 465 if 'GPL' in lic: 466 return True 467 return False 468 469 license_kinds = self._get_license_kinds(module) 470 if has_restricted_license(license_kinds): 471 self.modules_with_restricted_lic.add(module) 472 license_kinds_string = '' 473 for license_kind in sorted(license_kinds): 474 license_kinds_string += '{ind}{ind}"{license_kind}",\n'.format( 475 ind=self.INDENT, license_kind=license_kind) 476 license_texts = self._get_license_texts(module) 477 license_texts_string = '' 478 for license_text in sorted(license_texts): 479 license_texts_string += '{ind}{ind}"{license_text}",\n'.format( 480 ind=self.INDENT, license_text=license_text) 481 return ('license {{\n' 482 '{ind}name: "{license_name}",\n' 483 '{ind}license_kinds: [\n' 484 '{license_kinds}' 485 '{ind}],\n' 486 '{ind}license_text: [\n' 487 '{license_texts}' 488 '{ind}],\n' 489 '}}\n'.format( 490 ind=self.INDENT, 491 license_name=self._get_notice_license_name(module), 492 license_kinds=license_kinds_string, 493 license_texts=license_texts_string)) 494 495 def _get_notice_license_name(self, module): 496 """ Gets a notice license module name for a given module. 497 498 Args: 499 notice: string, module name. 500 """ 501 return 'vndk-v{ver}-{module}-license'.format( 502 ver=self._vndk_version, module=module) 503 504 def _gen_vndk_shared_prebuilts(self, 505 prebuilts, 506 arch, 507 is_llndk, 508 is_vndk_sp, 509 is_binder32, 510 module_names): 511 """Returns list of build rules for given prebuilts. 512 513 Args: 514 prebuilts: list of VNDK shared prebuilts 515 arch: string, VNDK snapshot arch (e.g. 'arm64') 516 is_llndk: bool, True if the prebuilts are LLNDK stubs 517 is_vndk_sp: bool, True if prebuilts are VNDK_SP libs 518 is_binder32: bool, True if binder interface is 32-bit 519 module_names: dict, module names for given prebuilts 520 """ 521 522 module_prebuilts = dict() 523 for prebuilt in prebuilts: 524 if prebuilt in module_names: 525 name = module_names[prebuilt] 526 else: 527 name = os.path.splitext(prebuilt)[0] 528 529 if name not in module_prebuilts: 530 module_prebuilts[name] = list() 531 module_prebuilts[name].append(prebuilt) 532 533 build_rules = [] 534 for name in module_prebuilts: 535 bp_module = self._gen_vndk_shared_prebuilt( 536 name, 537 arch, 538 srcs=module_prebuilts[name], 539 is_llndk=is_llndk, 540 is_vndk_sp=is_vndk_sp, 541 is_binder32=is_binder32) 542 if bp_module: 543 build_rules.append(bp_module) 544 return build_rules 545 546 def _gen_vndk_shared_prebuilt(self, 547 name, 548 arch, 549 srcs, 550 is_llndk, 551 is_vndk_sp, 552 is_binder32): 553 """Returns build rule for given prebuilt module, or an empty 554 string if the module is invalid (e.g. srcs doesn't exist). 555 556 Args: 557 name: string, name of prebuilt module 558 arch: string, VNDK snapshot arch (e.g. 'arm64') 559 srcs: list, prebuilt source file names of this module 560 is_llndk: bool, True if prebuilt is a LLNDK stub 561 is_vndk_sp: bool, True if prebuilt is a VNDK_SP lib 562 is_binder32: bool, True if binder interface is 32-bit 563 """ 564 565 def is_prebuilts_in_list(prebuilts, vndk_list): 566 for prebuilt in prebuilts: 567 if prebuilt in vndk_list: 568 return True 569 return False 570 571 def get_license_prop(name): 572 """Returns the license prop build rule. 573 574 Args: 575 name: string, name of the module 576 """ 577 if name in self._license_kinds_map: 578 return '{ind}licenses: ["{license}"],\n'.format( 579 ind=self.INDENT, 580 license=self._get_notice_license_name(name)) 581 return '' 582 583 def get_notice_file(prebuilts): 584 """Returns build rule for notice file (attribute 'licenses'). 585 586 Args: 587 prebuilts: list, names of prebuilt objects 588 """ 589 notice = '' 590 for prebuilt in prebuilts: 591 if prebuilt in self._modules_with_notice: 592 notice = '{ind}licenses: ["{notice_license}"],\n'.format( 593 ind=self.INDENT, 594 notice_license=self._get_notice_license_name(prebuilt)) 595 break 596 return notice 597 598 def get_arch_props(name, arch, srcs_props): 599 """Returns build rule for arch specific srcs. 600 601 e.g., 602 arch: { 603 arm: { 604 export_include_dirs: ["..."], 605 export_system_include_dirs: ["..."], 606 export_flags: ["..."], 607 relative_install_path: "...", 608 srcs: ["..."] 609 }, 610 arm64: { 611 export_include_dirs: ["..."], 612 export_system_include_dirs: ["..."], 613 export_flags: ["..."], 614 relative_install_path: "...", 615 srcs: ["..."] 616 }, 617 } 618 619 Args: 620 name: string, name of prebuilt module 621 arch: string, VNDK snapshot arch (e.g. 'arm64') 622 srcs_props: dict, prebuilt source paths and corresponding flags 623 """ 624 arch_props = '{ind}arch: {{\n'.format(ind=self.INDENT) 625 626 def list_to_prop_value(l, name): 627 if len(l) == 0: 628 return '' 629 dirs=',\n{ind}{ind}{ind}{ind}'.format( 630 ind=self.INDENT).join(['"%s"' % d for d in l]) 631 return ('{ind}{ind}{ind}{name}: [\n' 632 '{ind}{ind}{ind}{ind}{dirs},\n' 633 '{ind}{ind}{ind}],\n'.format( 634 ind=self.INDENT, 635 dirs=dirs, 636 name=name)) 637 638 def rename_generated_dirs(dirs): 639 # Rename out/soong/.intermediates to generated-headers for better readability. 640 return [d.replace(utils.SOONG_INTERMEDIATES_DIR, utils.GENERATED_HEADERS_DIR, 1) for d in dirs] 641 642 for src in sorted(srcs_props.keys()): 643 include_dirs = '' 644 system_include_dirs = '' 645 flags = '' 646 relative_install_path = '' 647 props = srcs_props[src] 648 if 'ExportedDirs' in props: 649 dirs = rename_generated_dirs(props['ExportedDirs']) 650 l = ['include/%s' % d for d in dirs] 651 include_dirs = list_to_prop_value(l, 'export_include_dirs') 652 if 'ExportedSystemDirs' in props: 653 dirs = rename_generated_dirs(props['ExportedSystemDirs']) 654 l = ['include/%s' % d for d in dirs] 655 system_include_dirs = list_to_prop_value(l, 'export_system_include_dirs') 656 if 'ExportedFlags' in props: 657 flags = list_to_prop_value(props['ExportedFlags'], 'export_flags') 658 if 'RelativeInstallPath' in props: 659 relative_install_path = ('{ind}{ind}{ind}' 660 'relative_install_path: "{path}",\n').format( 661 ind=self.INDENT, 662 path=props['RelativeInstallPath']) 663 if 'LicenseKinds' in props: 664 self._license_kinds_map[name].update(props['LicenseKinds']) 665 if 'LicenseTexts' in props: 666 self._license_texts_map[name].update(props['LicenseTexts']) 667 668 arch_props += ('{ind}{ind}{arch}: {{\n' 669 '{include_dirs}' 670 '{system_include_dirs}' 671 '{flags}' 672 '{relative_install_path}' 673 '{ind}{ind}{ind}srcs: ["{src}"],\n' 674 '{ind}{ind}}},\n').format( 675 ind=self.INDENT, 676 arch=utils.prebuilt_arch_from_path( 677 os.path.join(arch, src)), 678 include_dirs=include_dirs, 679 system_include_dirs=system_include_dirs, 680 flags=flags, 681 relative_install_path=relative_install_path, 682 src=src) 683 arch_props += '{ind}}},\n'.format(ind=self.INDENT) 684 return arch_props 685 686 src_root = os.path.join(self._install_dir, arch) 687 if is_binder32: 688 src_root = os.path.join(src_root, utils.BINDER32) 689 690 src_paths = utils.find(src_root, srcs) 691 # filter out paths under 'binder32' subdirectory 692 src_paths = list(filter(lambda src: not src.startswith(utils.BINDER32), 693 src_paths)) 694 # This module is invalid if no srcs are found. 695 if not src_paths: 696 logging.info('No srcs found for {}; skipping'.format(name)) 697 return "" 698 699 product_available = '' 700 # if vndkproduct.libraries.txt is empty, make the VNDKs available to product by default. 701 if is_llndk or not self._vndk_product[arch] or is_prebuilts_in_list(srcs, self._vndk_product[arch]): 702 product_available = '{ind}product_available: true,\n'.format( 703 ind=self.INDENT) 704 705 vndk_props = '' 706 if not is_llndk: 707 vndk_sp = '' 708 if is_vndk_sp: 709 vndk_sp = '{ind}{ind}support_system_process: true,\n'.format( 710 ind=self.INDENT) 711 712 vndk_private = '' 713 if is_prebuilts_in_list(srcs, self._vndk_private[arch]): 714 vndk_private = '{ind}{ind}private: true,\n'.format( 715 ind=self.INDENT) 716 717 vndk_props = ('{ind}vndk: {{\n' 718 '{ind}{ind}enabled: true,\n' 719 '{vndk_sp}' 720 '{vndk_private}' 721 '{ind}}},\n'.format( 722 ind=self.INDENT, 723 product_available=product_available, 724 vndk_sp=vndk_sp, 725 vndk_private=vndk_private)) 726 727 srcs_props = dict() 728 for src in src_paths: 729 props = dict() 730 prop_path = os.path.join(src_root, src+'.json') 731 try: 732 with open(prop_path, 'r') as f: 733 props = json.loads(f.read()) 734 os.unlink(prop_path) 735 except: 736 # TODO(b/70312118): Parse from soong build system 737 if name == 'android.hidl.memory@1.0-impl': 738 props['RelativeInstallPath'] = 'hw' 739 srcs_props[src] = props 740 arch_props = get_arch_props(name, arch, srcs_props) 741 742 if self._license_in_json: 743 license = get_license_prop(name) 744 else: 745 license = get_notice_file(srcs) 746 747 binder32bit = '' 748 if is_binder32: 749 binder32bit = '{ind}binder32bit: true,\n'.format(ind=self.INDENT) 750 751 min_sdk_version = '' 752 for src, props in srcs_props.items(): 753 if 'MinSdkVersion' in props: 754 min_sdk_version = '{ind}min_sdk_version: "{ver}",\n'.format( 755 ind=self.INDENT, 756 ver=props['MinSdkVersion']) 757 break 758 759 return ('vndk_prebuilt_shared {{\n' 760 '{ind}name: "{name}",\n' 761 '{ind}version: "{ver}",\n' 762 '{ind}target_arch: "{target_arch}",\n' 763 '{binder32bit}' 764 '{ind}vendor_available: true,\n' 765 '{product_available}' 766 '{vndk_props}' 767 '{min_sdk_version}' 768 '{license}' 769 '{arch_props}' 770 '}}\n'.format( 771 ind=self.INDENT, 772 name=name, 773 ver=self._vndk_version, 774 target_arch=arch, 775 binder32bit=binder32bit, 776 product_available=product_available, 777 vndk_props=vndk_props, 778 min_sdk_version=min_sdk_version, 779 license=license, 780 arch_props=arch_props)) 781 782 783def get_args(): 784 parser = argparse.ArgumentParser() 785 parser.add_argument( 786 'vndk_version', 787 type=utils.vndk_version_int, 788 help='VNDK snapshot version to install, e.g. "{}".'.format( 789 utils.MINIMUM_VNDK_VERSION)) 790 parser.add_argument( 791 '-v', 792 '--verbose', 793 action='count', 794 default=0, 795 help='Increase output verbosity, e.g. "-v", "-vv".') 796 return parser.parse_args() 797 798 799def main(): 800 """For local testing purposes. 801 802 Note: VNDK snapshot must be already installed under 803 prebuilts/vndk/v{version}. 804 """ 805 ANDROID_BUILD_TOP = utils.get_android_build_top() 806 PREBUILTS_VNDK_DIR = utils.join_realpath(ANDROID_BUILD_TOP, 807 'prebuilts/vndk') 808 809 args = get_args() 810 vndk_version = args.vndk_version 811 install_dir = os.path.join(PREBUILTS_VNDK_DIR, 'v{}'.format(vndk_version)) 812 if not os.path.isdir(install_dir): 813 raise ValueError( 814 'Please provide valid VNDK version. {} does not exist.' 815 .format(install_dir)) 816 utils.set_logging_config(args.verbose) 817 818 buildfile_generator = GenBuildFile(install_dir, vndk_version) 819 # To parse json information, read and generate arch android.bp using 820 # generate_android_bp() first. 821 buildfile_generator.generate_android_bp() 822 buildfile_generator.generate_root_android_bp() 823 buildfile_generator.generate_common_android_bp() 824 825 logging.info('Done.') 826 827 828if __name__ == '__main__': 829 main() 830