• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3import argparse
4import collections
5import os
6import shutil
7import time
8
9from utils import (
10    AOSP_DIR, COMPRESSED_SOURCE_ABI_DUMP_EXT, SOURCE_ABI_DUMP_EXT,
11    SOURCE_ABI_DUMP_EXT_END, SO_EXT, Target, copy_reference_dump,
12    find_lib_lsdumps, get_build_vars_for_product, make_libraries, make_tree,
13    read_lsdump_paths)
14
15
16PRODUCTS_DEFAULT = ['aosp_arm', 'aosp_arm64', 'aosp_x86', 'aosp_x86_64']
17
18PREBUILTS_ABI_DUMPS_DEFAULT = os.path.join(AOSP_DIR, 'prebuilts', 'abi-dumps')
19
20SOONG_DIR = os.path.join(AOSP_DIR, 'out', 'soong', '.intermediates')
21
22
23def choose_vndk_version(version, platform_vndk_version, board_vndk_version):
24    if version is None:
25        # This logic must be in sync with the logic for reference ABI dumps
26        # directory in `build/soong/cc/library.go`.
27        version = platform_vndk_version
28        if board_vndk_version not in ('current', ''):
29            version = board_vndk_version
30    return version
31
32
33def make_libs_for_product(libs, product, variant, vndk_version, targets):
34    print('making libs for', product + '-' + variant)
35    if libs:
36        make_libraries(product, variant, vndk_version, targets, libs)
37    else:
38        make_tree(product, variant)
39
40
41def get_ref_dump_dir_stem(ref_dump_dir, category, chosen_vndk_version,
42                          binder_bitness, arch):
43    return os.path.join(ref_dump_dir, category, chosen_vndk_version,
44                        binder_bitness, arch)
45
46
47def find_and_remove_path(root_path, file_name=None):
48    if file_name is not None:
49        root_path = os.path.join(root_path, 'source-based', file_name)
50
51    if os.path.exists(root_path):
52        print('removing', root_path)
53        if os.path.isfile(root_path):
54            os.remove(root_path)
55        else:
56            shutil.rmtree(root_path)
57
58
59def remove_references_for_all_arches(ref_dump_dir, chosen_vndk_version,
60                                     binder_bitness, targets, libs):
61    for target in targets:
62        for category in ('ndk', 'platform', 'vndk'):
63            dir_to_remove = get_ref_dump_dir_stem(
64                ref_dump_dir, category, chosen_vndk_version, binder_bitness,
65                target.get_arch_str())
66            if libs:
67                for lib in libs:
68                    find_and_remove_path(dir_to_remove,
69                                         lib + SOURCE_ABI_DUMP_EXT)
70                    find_and_remove_path(dir_to_remove,
71                                         lib + COMPRESSED_SOURCE_ABI_DUMP_EXT)
72            else:
73                find_and_remove_path(dir_to_remove)
74
75
76def tag_to_dir_name(tag):
77    if tag == 'NDK':
78        return 'ndk'
79    if tag == 'PLATFORM':
80        return 'platform'
81    if tag.startswith('VNDK') or tag == 'LLNDK':
82        return 'vndk'
83    raise ValueError(tag + 'is not a known tag.')
84
85
86def find_and_copy_lib_lsdumps(ref_dump_dir, chosen_vndk_version,
87                              binder_bitness, target, libs, lsdump_paths,
88                              compress):
89    arch_lsdump_paths = find_lib_lsdumps(lsdump_paths, libs, target)
90
91    num_created = 0
92    for tag, path in arch_lsdump_paths:
93        ref_dump_dir_stem = get_ref_dump_dir_stem(
94            ref_dump_dir, tag_to_dir_name(tag), chosen_vndk_version,
95            binder_bitness, target.get_arch_str())
96        copy_reference_dump(
97            path, os.path.join(ref_dump_dir_stem, 'source-based'), compress)
98        num_created += 1
99    return num_created
100
101
102def create_source_abi_reference_dumps(args, chosen_vndk_version,
103                                      binder_bitness, lsdump_paths, targets):
104    num_libs_copied = 0
105    for target in targets:
106        assert target.primary_arch != ''
107        print(f'Creating dumps for arch: {target.arch}, '
108              f'primary arch: {target.primary_arch}')
109
110        num_libs_copied += find_and_copy_lib_lsdumps(
111            args.ref_dump_dir, chosen_vndk_version, binder_bitness, target,
112            args.libs, lsdump_paths, args.compress)
113    return num_libs_copied
114
115
116def create_source_abi_reference_dumps_for_all_products(args):
117    """Create reference ABI dumps for all specified products."""
118
119    num_processed = 0
120
121    for product in args.products:
122        build_vars = get_build_vars_for_product(
123            ['PLATFORM_VNDK_VERSION', 'BOARD_VNDK_VERSION', 'BINDER32BIT'],
124            product, args.build_variant)
125
126        platform_vndk_version = build_vars[0]
127        board_vndk_version = build_vars[1]
128        if build_vars[2] == 'true':
129            binder_bitness = '32'
130        else:
131            binder_bitness = '64'
132
133        chosen_vndk_version = choose_vndk_version(
134            args.version, platform_vndk_version, board_vndk_version)
135
136        targets = [t for t in (Target(True, product), Target(False, product))
137                   if t.arch]
138        # Remove reference ABI dumps specified in `args.libs` (or remove all of
139        # them if none of them are specified) so that we may build these
140        # libraries successfully.
141        remove_references_for_all_arches(
142            args.ref_dump_dir, chosen_vndk_version, binder_bitness, targets,
143            args.libs)
144
145        if not args.no_make_lib:
146            # Build all the specified libs, or build `findlsdumps` if no libs
147            # are specified.
148            make_libs_for_product(args.libs, product, args.build_variant,
149                                  platform_vndk_version, targets)
150
151        lsdump_paths = read_lsdump_paths(product, args.build_variant,
152                                         platform_vndk_version, targets,
153                                         build=False)
154
155        num_processed += create_source_abi_reference_dumps(
156            args, chosen_vndk_version, binder_bitness, lsdump_paths, targets)
157
158    return num_processed
159
160
161def _parse_args():
162    """Parse the command line arguments."""
163
164    parser = argparse.ArgumentParser()
165    parser.add_argument('--version', help='VNDK version')
166    parser.add_argument('--no-make-lib', action='store_true',
167                        help='no m -j lib.vendor while creating reference')
168    parser.add_argument('--llndk', action='store_true',
169                        help='the flag is deprecated and has no effect')
170    parser.add_argument('-libs', action='append',
171                        help='libs to create references for')
172    parser.add_argument('-products', action='append',
173                        help='products to create references for')
174    parser.add_argument('--build-variant', default='userdebug',
175                        help='build variant to create references for')
176    parser.add_argument('--compress', action='store_true',
177                        help='compress reference dump with gzip')
178    parser.add_argument('-ref-dump-dir',
179                        help='directory to copy reference abi dumps into',
180                        default=PREBUILTS_ABI_DUMPS_DEFAULT)
181
182    args = parser.parse_args()
183
184    if args.libs:
185        if any(lib_name.endswith(SOURCE_ABI_DUMP_EXT_END) or
186               lib_name.endswith(SO_EXT) for lib_name in args.libs):
187            parser.error('-libs should be followed by a base name without '
188                         'file extension.')
189
190    if args.products is None:
191        # If `args.products` is unspecified, generate reference ABI dumps for
192        # all products.
193        args.products = PRODUCTS_DEFAULT
194
195    return args
196
197
198def main():
199    args = _parse_args()
200
201    start = time.time()
202    num_processed = create_source_abi_reference_dumps_for_all_products(args)
203    end = time.time()
204
205    print()
206    print('msg: Processed', num_processed, 'libraries in ', (end - start) / 60,
207          ' minutes')
208
209
210if __name__ == '__main__':
211    main()
212