| #!/usr/bin/env python2.7 |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import argparse |
| import os |
| import subprocess |
| import sys |
| |
| |
| SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| FUCHSIA_ROOT = os.path.dirname( # $root |
| os.path.dirname( # scripts |
| SCRIPT_DIR)) # unification |
| |
| |
| class Finder(object): |
| |
| def __init__(self, gn_binary, zircon_dir, build_dir): |
| self._zircon_dir = zircon_dir |
| self._command = [gn_binary, '--root=' + zircon_dir, 'refs', build_dir, |
| '--all-toolchains'] |
| |
| def find_references(self, type, name): |
| category_label = '//system/' + type |
| base_label = '//system/' + type + '/' + name |
| |
| command = self._command + [base_label + ':*'] |
| try: |
| output = subprocess.check_output(command) |
| except subprocess.CalledProcessError: |
| return None |
| |
| references = set() |
| for line in output.splitlines(): |
| line = line.strip() |
| if line.startswith(base_label): |
| continue |
| # Remove target name and toolchain. |
| line = line[0:line.find(':')] |
| if line == category_label: |
| continue |
| # Insert 'zircon' directory at the start. |
| line = '//zircon' + line[1:] |
| references.add(line) |
| |
| return references |
| |
| |
| def find_libraries(self, type): |
| base = os.path.join(self._zircon_dir, 'system', type) |
| def has_build_file(dir): |
| return os.path.isfile(os.path.join(base, dir, 'BUILD.gn')) |
| for _, dirs, _ in os.walk(base): |
| return filter(has_build_file, dirs) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser('Determines whether libraries can be ' |
| 'moved out of the ZN build') |
| parser.add_argument('--build-dir', |
| help='Path to the GN build dir', |
| required=True) |
| type = parser.add_mutually_exclusive_group(required=True) |
| type.add_argument('--banjo', |
| help='Inspect Banjo libraries', |
| action='store_true') |
| type.add_argument('--fidl', |
| help='Inspect FIDL libraries', |
| action='store_true') |
| type.add_argument('--ulib', |
| help='Inspect C/C++ libraries', |
| action='store_true') |
| parser.add_argument('name', |
| help='Name of the library to inspect; if empty, scan ' |
| 'all libraries of the given type', |
| nargs='?') |
| args = parser.parse_args() |
| |
| source_dir = FUCHSIA_ROOT |
| zircon_dir = os.path.join(source_dir, 'zircon') |
| build_dir = os.path.abspath(args.build_dir) |
| |
| if sys.platform.startswith('linux'): |
| platform = 'linux-x64' |
| elif sys.platform.startswith('darwin'): |
| platform = 'mac-x64' |
| else: |
| print('Unsupported platform: %s' % sys.platform) |
| return 1 |
| gn_binary = os.path.join(source_dir, 'prebuilt', 'third_party', 'gn', |
| platform, 'gn') |
| |
| finder = Finder(gn_binary, zircon_dir, build_dir) |
| |
| if args.fidl: |
| type = 'fidl' |
| elif args.banjo: |
| type = 'banjo' |
| elif args.ulib: |
| type = 'ulib' |
| |
| # Case 1: a library name is given. |
| if args.name: |
| name = args.name |
| if args.fidl: |
| # FIDL library names use the dot separator, but folders use an |
| # hyphen: be nice to users and support both forms. |
| name = name.replace('.', '-') |
| |
| references = finder.find_references(type, name) |
| |
| if references is None: |
| print('Could not find "%s", please check spelling!' % args.name) |
| return 1 |
| elif references: |
| print('Nope, there are still references in the ZN build:') |
| for ref in sorted(references): |
| print(' ' + ref) |
| else: |
| print('Yes you can!') |
| |
| return 0 |
| |
| # Case 2: no library name given. |
| print('Warning: this operation can take a while!') |
| names = finder.find_libraries(type) |
| movable = set() |
| for name in names: |
| references = finder.find_references(type, name) |
| if not references: |
| movable.add(name) |
| if movable: |
| print('These libraries are free to go:') |
| for name in sorted(movable): |
| print(' ' + name) |
| else: |
| print('No library may be moved') |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |