skia2/tools/rewrite_includes.py
John Stiles f35853a4a2 Clarify output from rewrite_includes assertion.
Previously, the conflicting header names were printed between several
lines of "boilerplate" text, and without any explanatory text. This
made them difficult to notice. The assertion now has an explanatory
message and prints the conflicting filenames directly at the point of
the assertion.

Before:
---
Running presubmit upload checks ...
tests/sksl/dslfp GrSwizzle.h /Users/johnstiles/skia/src/gpu/GrSwizzle.h
Traceback (most recent call last):
  File "tools/rewrite_includes.py", line 60, in <module>
    assert file_name not in headers
AssertionError

** Presubmit ERRORS ** (etc)
username$ _

After:
---
Running presubmit upload checks ...
Traceback (most recent call last):
  File "tools/rewrite_includes.py", line 61, in <module>
    assert file_name not in headers, message
AssertionError: Header filename is used more than once!
- tests/sksl/dslfp/GrSwizzle.h
- /Users/johnstiles/skia/src/gpu/GrSwizzle.h

** Presubmit ERRORS ** (etc)
username$ _

Change-Id: I2b6848ef82c4b1c6d4b5577a76969785e5e122bb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/397149
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
2021-04-15 19:44:32 +00:00

122 lines
3.6 KiB
Python
Executable File

#!/usr/bin/python2
#
# Copyright 2019 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import print_function
import StringIO
import argparse
import os
import sys
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--dry-run', action='store_true',
help='Just check there is nothing to rewrite.')
parser.add_argument('sources', nargs='*',
help='Source files to rewrite, or all if empty.')
args = parser.parse_args()
roots = [
'bench',
'dm',
'docs',
'example',
'experimental',
'fuzz',
'gm',
'include',
'modules',
'platform_tools/android/apps',
'samplecode',
'src',
'tests',
'third_party/etc1',
'third_party/gif',
'tools'
]
# Don't count our local Vulkan headers as Skia headers;
# we don't want #include <vulkan/vulkan_foo.h> rewritten to point to them.
# Nor do we care about things in node_modules, used by *Kits.
ignorelist = ['include/third_party/vulkan', 'node_modules']
assert '/' in [os.sep, os.altsep]
def fix_path(p):
return p.replace(os.sep, os.altsep) if os.altsep else p
# Map short name -> absolute path for all Skia headers.
headers = {}
for root in roots:
for path, _, files in os.walk(root):
if not any(snippet in fix_path(path) for snippet in ignorelist):
for file_name in files:
if file_name.endswith('.h'):
if file_name in headers:
message = ('Header filename is used more than once!\n- ' + path + '/' + file_name +
'\n- ' + headers[file_name])
assert file_name not in headers, message
headers[file_name] = os.path.abspath(os.path.join(path, file_name))
def to_rewrite():
if args.sources:
for path in args.sources:
yield path
else:
for root in roots:
for path, _, files in os.walk(root):
for file_name in files:
yield os.path.join(path, file_name)
# Rewrite any #includes relative to Skia's top-level directory.
need_rewriting = []
for file_path in to_rewrite():
if ('/generated/' in file_path or
'tests/sksl/' in file_path or
'third_party/skcms' in file_path):
continue
if (file_path.endswith('.h') or
file_path.endswith('.c') or
file_path.endswith('.m') or
file_path.endswith('.mm') or
file_path.endswith('.inc') or
file_path.endswith('.fp') or
file_path.endswith('.cc') or
file_path.endswith('.cpp')):
# Read the whole file into memory.
lines = open(file_path).readlines()
# Write it back out again line by line with substitutions for #includes.
output = StringIO.StringIO() if args.dry_run else open(file_path, 'wb')
includes = []
for line in lines:
parts = line.replace('<', '"').replace('>', '"').split('"')
if (len(parts) == 3
and '#' in parts[0]
and 'include' in parts[0]
and os.path.basename(parts[1]) in headers):
header = fix_path(os.path.relpath(headers[os.path.basename(parts[1])], '.'))
includes.append(parts[0] + '"%s"' % header + parts[2])
else:
for inc in sorted(includes):
output.write(inc.strip('\n') + '\n')
includes = []
output.write(line.strip('\n') + '\n')
if args.dry_run and output.getvalue() != open(file_path).read():
need_rewriting.append(file_path)
rc = 1
output.close()
if need_rewriting:
print('Some files need rewritten #includes:')
for path in need_rewriting:
print('\t' + path)
print('To do this automatically, run')
print('python tools/rewrite_includes.py ' + ' '.join(need_rewriting))
sys.exit(1)