| #!/usr/bin/env python3 |
| # Copyright 2021 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. |
| """Checks that all source files are present in exactly 1 gn target""" |
| |
| import sys |
| import os |
| # Ensure that this file can import from cobalt root even if run as a script. |
| sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| |
| import subprocess |
| import json |
| from tools import get_files |
| |
| # Find the root directory of the cobalt core repository (One directory up from the tools/ directory) |
| cobalt_root = os.path.abspath( |
| os.path.join(os.path.join(os.path.dirname(__file__), '..'))) |
| |
| ALLOW_ABSENCE = [ |
| # TODO(fxbug.dev/93229): Remove these once StatusOr move is done. |
| 'src/lib/statusor/statusor.h', # Symlink to file in src/public/lib/statusor/ |
| 'src/lib/statusor/status_macros.h', # Symlink to file in src/public/lib/statusor/ |
| 'src/lib/statusor/statusor_internals.h', # Symlink to file in src/public/lib/statusor/ |
| ] |
| |
| def main(): |
| out_path = os.path.join(cobalt_root, 'out') |
| p = subprocess.Popen( |
| ['gn', 'desc', out_path, '//*', 'sources', '--format=json'], |
| stdout=subprocess.PIPE) |
| out, err = p.communicate() |
| |
| if p.returncode != 0: |
| print('Received non-zero return code (%s)' % p.returncode) |
| print(out.decode()) |
| return 1 |
| |
| data = json.loads(out) |
| |
| present_files = [ |
| os.path.relpath(f, cobalt_root) for f in get_files.files_to_lint( |
| ('.h', '.cc'), only_directories=['src', 'keys'], all_files=True) |
| ] |
| |
| seen_sources = set() |
| errors = 0 |
| for target, attributes in data.items(): |
| if 'sources' not in attributes.keys(): |
| continue |
| for source in attributes['sources']: |
| if source.startswith('//out') or source.startswith( |
| '//build') or source.startswith('//third_party'): |
| # Auto-generated or added by //build rules. Duplicates are allowed. |
| continue |
| if source in seen_sources: |
| print( |
| f'Duplicate source detected {source} present in multiple GN targets {target}' |
| ) |
| errors += 1 |
| seen_sources.add(source) |
| |
| for needed_file in present_files: |
| if f'//{needed_file}' not in seen_sources and needed_file not in ALLOW_ABSENCE: |
| print( |
| f"Saw source file {needed_file} that wasn't present in any gn targets" |
| ) |
| errors += 1 |
| |
| return errors |
| |
| |
| if __name__ == '__main__': |
| exit(main()) |