blob: 69f1e82e04ddaecae2006313319d581ce0de47f8 [file] [log] [blame]
#!/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())