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