8f4063c6ea
Based on Primiano's prototype: https://chromium-review.googlesource.com/c/v8/v8/+/1290549 This is still behind a build flag. I'll add functionality incrementally rather than land everything in one giant CL. This CL sets up the basic classes that will be used for the Perfetto implementation, e.g. the producer, consumer, controller and task runner. This implementation produces a binary proto file in the current directory named v8_trace.proto. It doesn't yet produce JSON output, that is coming in a following CL. Currently the old tracing and perfetto tracing are both run alongside each other if the build flag is enabled. Cq-Include-Trybots: luci.v8.try:v8_linux64_perfetto_dbg_ng Bug: v8:8339 Change-Id: I0eb9ecefa191ceead60aadd5b591d75c99395a6e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1408995 Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Commit-Queue: Peter Marshall <petermarshall@chromium.org> Cr-Commit-Position: refs/heads/master@{#61209}
149 lines
4.9 KiB
Python
Executable File
149 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# vim:fenc=utf-8:shiftwidth=2
|
|
|
|
# Copyright 2018 the V8 project authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Check that each header can be included in isolation.
|
|
|
|
For each header we generate one .cc file which only includes this one header.
|
|
All these .cc files are then added to a sources.gni file which is included in
|
|
BUILD.gn. Just compile to check whether there are any violations to the rule
|
|
that each header must be includable in isolation.
|
|
"""
|
|
|
|
# for py2/py3 compatibility
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import os
|
|
import os.path
|
|
import re
|
|
import sys
|
|
|
|
# TODO(clemensh): Extend to tests.
|
|
DEFAULT_INPUT = ['base', 'src']
|
|
DEFAULT_GN_FILE = 'BUILD.gn'
|
|
MY_DIR = os.path.dirname(os.path.realpath(__file__))
|
|
V8_DIR = os.path.dirname(MY_DIR)
|
|
OUT_DIR = os.path.join(V8_DIR, 'check-header-includes')
|
|
AUTO_EXCLUDE = [
|
|
# flag-definitions.h needs a mode set for being included.
|
|
'src/flag-definitions.h',
|
|
]
|
|
AUTO_EXCLUDE_PATTERNS = [
|
|
'src/base/atomicops_internals_.*',
|
|
# TODO(petermarshall): Enable once Perfetto is built by default.
|
|
'src/libplatform/tracing/perfetto*',
|
|
] + [
|
|
# platform-specific headers
|
|
'\\b{}\\b'.format(p) for p in
|
|
('win', 'win32', 'ia32', 'x64', 'arm', 'arm64', 'mips', 'mips64', 's390',
|
|
'ppc')]
|
|
|
|
args = None
|
|
def parse_args():
|
|
global args
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-i', '--input', type=str, action='append',
|
|
help='Headers or directories to check (directories '
|
|
'are scanned for headers recursively); default: ' +
|
|
','.join(DEFAULT_INPUT))
|
|
parser.add_argument('-x', '--exclude', type=str, action='append',
|
|
help='Add an exclude pattern (regex)')
|
|
parser.add_argument('-v', '--verbose', action='store_true',
|
|
help='Be verbose')
|
|
args = parser.parse_args()
|
|
args.exclude = (args.exclude or []) + AUTO_EXCLUDE_PATTERNS
|
|
args.exclude += ['^' + re.escape(x) + '$' for x in AUTO_EXCLUDE]
|
|
if not args.input:
|
|
args.input=DEFAULT_INPUT
|
|
|
|
|
|
def printv(line):
|
|
if args.verbose:
|
|
print(line)
|
|
|
|
|
|
def find_all_headers():
|
|
printv('Searching for headers...')
|
|
header_files = []
|
|
exclude_patterns = [re.compile(x) for x in args.exclude]
|
|
def add_recursively(filename):
|
|
full_name = os.path.join(V8_DIR, filename)
|
|
if not os.path.exists(full_name):
|
|
sys.exit('File does not exist: {}'.format(full_name))
|
|
if os.path.isdir(full_name):
|
|
for subfile in os.listdir(full_name):
|
|
full_name = os.path.join(filename, subfile)
|
|
printv('Scanning {}'.format(full_name))
|
|
add_recursively(full_name)
|
|
elif filename.endswith('.h'):
|
|
printv('--> Found header file {}'.format(filename))
|
|
for p in exclude_patterns:
|
|
if p.search(filename):
|
|
printv('--> EXCLUDED (matches {})'.format(p.pattern))
|
|
return
|
|
header_files.append(filename)
|
|
|
|
for filename in args.input:
|
|
add_recursively(filename)
|
|
|
|
return header_files
|
|
|
|
|
|
def get_cc_file_name(header):
|
|
split = os.path.split(header)
|
|
header_dir = os.path.relpath(split[0], V8_DIR)
|
|
# Prefix with the directory name, to avoid collisions in the object files.
|
|
prefix = header_dir.replace(os.path.sep, '-')
|
|
cc_file_name = 'test-include-' + prefix + '-' + split[1][:-1] + 'cc'
|
|
return os.path.join(OUT_DIR, cc_file_name)
|
|
|
|
|
|
def create_including_cc_files(header_files):
|
|
comment = 'check including this header in isolation'
|
|
for header in header_files:
|
|
cc_file_name = get_cc_file_name(header)
|
|
rel_cc_file_name = os.path.relpath(cc_file_name, V8_DIR)
|
|
content = '#include "{}" // {}\n'.format(header, comment)
|
|
if os.path.exists(cc_file_name):
|
|
with open(cc_file_name) as cc_file:
|
|
if cc_file.read() == content:
|
|
printv('File {} is up to date'.format(rel_cc_file_name))
|
|
continue
|
|
printv('Creating file {}'.format(rel_cc_file_name))
|
|
with open(cc_file_name, 'w') as cc_file:
|
|
cc_file.write(content)
|
|
|
|
|
|
def generate_gni(header_files):
|
|
gni_file = os.path.join(OUT_DIR, 'sources.gni')
|
|
printv('Generating file "{}"'.format(os.path.relpath(gni_file, V8_DIR)))
|
|
with open(gni_file, 'w') as gn:
|
|
gn.write("""\
|
|
# Copyright 2018 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
# This list is filled automatically by tools/check_header_includes.py.
|
|
check_header_includes_sources = [
|
|
""");
|
|
for header in header_files:
|
|
cc_file_name = get_cc_file_name(header)
|
|
gn.write(' "{}",\n'.format(os.path.relpath(cc_file_name, V8_DIR)))
|
|
gn.write(']\n')
|
|
|
|
|
|
def main():
|
|
parse_args()
|
|
header_files = find_all_headers()
|
|
if not os.path.exists(OUT_DIR):
|
|
os.mkdir(OUT_DIR)
|
|
create_including_cc_files(header_files)
|
|
generate_gni(header_files)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|