| #!/usr/bin/env python2.7 |
| # Copyright 2020 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 json |
| import os |
| import re |
| import sys |
| |
| from common import FUCHSIA_ROOT |
| |
| |
| class Sdk(object): |
| |
| SOURCE = 'source' |
| STATIC = 'static' |
| SHARED = 'shared' |
| NOPE = '' |
| |
| |
| class Library(object): |
| |
| FINGERPRINT_PARAMS = ['kernel', 'static', 'shared', 'host'] |
| PARAMS = FINGERPRINT_PARAMS + [ 'sdk_publishable' ] |
| |
| def __init__(self, name, file): |
| self.name = name |
| self.file = os.path.relpath(file, os.path.join(FUCHSIA_ROOT, 'zircon')) |
| self.sdk = Sdk.NOPE |
| for param in Library.PARAMS: |
| setattr(self, param, False) |
| |
| def set(self, param): |
| setattr(self, param, True) |
| |
| def set_sdk(self, value): |
| self.sdk = value |
| |
| def to_json(self): |
| result = { |
| 'name': self.name, |
| 'file': self.file, |
| } |
| for param in Library.PARAMS + ['sdk']: |
| result[param] = getattr(self, param, False) |
| return result |
| |
| def fingerprint(self): |
| params = [p for p in Library.FINGERPRINT_PARAMS if getattr(self, p, False)] |
| return '|'.join(params) if params else 'none' |
| |
| def __repr__(self): |
| return json.dumps(self.to_json(), indent=2, sort_keys=True, |
| separators=(',', ': ')) |
| |
| |
| def get_library_stats(build_path): |
| result = [] |
| with open(build_path, 'r') as build_file: |
| lines = build_file.readlines() |
| current_library = None |
| bracket_count = 0 |
| for line in lines: |
| match = re.match('^\s*zx_library\("([^"]+)"\)\s*{$', line) |
| if match: |
| current_library = Library(match.group(1), build_path) |
| bracket_count = 1 |
| continue |
| if not current_library: |
| continue |
| for param in Library.PARAMS: |
| if param + ' = true' in line: |
| current_library.set(param) |
| match = re.match('^\s*sdk = "([^"]+)"\s*$', line) |
| if match: |
| current_library.set_sdk(match.group(1)) |
| bracket_count += line.count('{') |
| bracket_count -= line.count('}') |
| if bracket_count <= 0: |
| result.append(current_library) |
| current_library = None |
| bracket_count = 0 |
| return result |
| |
| |
| class CustomJSONEncoder(json.JSONEncoder): |
| |
| def default(self, object): |
| if isinstance(object, Library): |
| return object.to_json() |
| return json.JSONEncoder.default(self, object) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description='Analyzes Zircon libraries') |
| parser.add_argument('--output', |
| help='file to write library information to', |
| required=False) |
| args = parser.parse_args() |
| |
| libraries = [] |
| for base, _, files in os.walk(os.path.join(FUCHSIA_ROOT, 'zircon')): |
| for file in files: |
| if file != 'BUILD.gn': |
| continue |
| build_path = os.path.join(base, file) |
| libraries.extend(get_library_stats(build_path)) |
| |
| if args.output: |
| with open(args.output, 'w') as output_file: |
| json.dump(libraries, output_file, cls=CustomJSONEncoder, indent=2, |
| sort_keys=True, separators=(',', ': ')) |
| |
| stats = {} |
| for lib in libraries: |
| fingerprint = lib.fingerprint() |
| stats[fingerprint] = stats.setdefault(fingerprint, 0) + 1 |
| for stat in sorted(stats.items(), key=lambda item: item[1]): |
| print('{:>18}{:>5}'.format(*stat)) |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |