1*c8dee2aaSAndroid Build Coastguard Worker#!/usr/bin/python 2*c8dee2aaSAndroid Build Coastguard Worker# 3*c8dee2aaSAndroid Build Coastguard Worker# Copyright 2019 Google Inc. 4*c8dee2aaSAndroid Build Coastguard Worker# 5*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 6*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file. 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker 9*c8dee2aaSAndroid Build Coastguard Workerimport argparse 10*c8dee2aaSAndroid Build Coastguard Workerimport os 11*c8dee2aaSAndroid Build Coastguard Workerimport sys 12*c8dee2aaSAndroid Build Coastguard Worker 13*c8dee2aaSAndroid Build Coastguard Workerfrom io import StringIO 14*c8dee2aaSAndroid Build Coastguard Worker 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Workerparser = argparse.ArgumentParser() 17*c8dee2aaSAndroid Build Coastguard Workerparser.add_argument('-n', '--dry-run', action='store_true', 18*c8dee2aaSAndroid Build Coastguard Worker help='Just check there is nothing to rewrite.') 19*c8dee2aaSAndroid Build Coastguard Workerparser.add_argument('sources', nargs='*', 20*c8dee2aaSAndroid Build Coastguard Worker help='Source files to rewrite, or all if empty.') 21*c8dee2aaSAndroid Build Coastguard Workerargs = parser.parse_args() 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Workerroots = [ 24*c8dee2aaSAndroid Build Coastguard Worker 'bench', 25*c8dee2aaSAndroid Build Coastguard Worker 'dm', 26*c8dee2aaSAndroid Build Coastguard Worker 'docs', 27*c8dee2aaSAndroid Build Coastguard Worker 'experimental', 28*c8dee2aaSAndroid Build Coastguard Worker 'fuzz', 29*c8dee2aaSAndroid Build Coastguard Worker 'gm', 30*c8dee2aaSAndroid Build Coastguard Worker 'include', 31*c8dee2aaSAndroid Build Coastguard Worker 'modules', 32*c8dee2aaSAndroid Build Coastguard Worker 'platform_tools/android/apps', 33*c8dee2aaSAndroid Build Coastguard Worker 'samplecode', 34*c8dee2aaSAndroid Build Coastguard Worker 'src', 35*c8dee2aaSAndroid Build Coastguard Worker 'tests', 36*c8dee2aaSAndroid Build Coastguard Worker 'third_party/etc1', 37*c8dee2aaSAndroid Build Coastguard Worker 'third_party/gif', 38*c8dee2aaSAndroid Build Coastguard Worker 'tools' 39*c8dee2aaSAndroid Build Coastguard Worker] 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Workerignorelist = [ 42*c8dee2aaSAndroid Build Coastguard Worker # Don't count our local Vulkan headers as Skia headers; 43*c8dee2aaSAndroid Build Coastguard Worker # we don't want #include <vulkan/vulkan_foo.h> rewritten to point to them. 44*c8dee2aaSAndroid Build Coastguard Worker 'include/third_party/vulkan', 45*c8dee2aaSAndroid Build Coastguard Worker # Some node_modules/ files (used by CanvasKit et al) have c++ code which we should ignore. 46*c8dee2aaSAndroid Build Coastguard Worker 'node_modules', 47*c8dee2aaSAndroid Build Coastguard Worker 'include/third_party/skcms', 48*c8dee2aaSAndroid Build Coastguard Worker 'src/gpu/vk/vulkanmemoryallocator', 49*c8dee2aaSAndroid Build Coastguard Worker # Used by Jetski and Graphite 50*c8dee2aaSAndroid Build Coastguard Worker 'Surface.h', 51*c8dee2aaSAndroid Build Coastguard Worker # Used by Ganesh and Graphite 52*c8dee2aaSAndroid Build Coastguard Worker 'Device.h', 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker # Transitional 55*c8dee2aaSAndroid Build Coastguard Worker 'tools/window', 56*c8dee2aaSAndroid Build Coastguard Worker] 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Workerassert '/' in [os.sep, os.altsep] 59*c8dee2aaSAndroid Build Coastguard Workerdef fix_path(p): 60*c8dee2aaSAndroid Build Coastguard Worker return p.replace(os.sep, os.altsep) if os.altsep else p 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker# Map short name -> absolute path for all Skia headers. 63*c8dee2aaSAndroid Build Coastguard Workerheaders = {} 64*c8dee2aaSAndroid Build Coastguard Workerfor root in roots: 65*c8dee2aaSAndroid Build Coastguard Worker for path, _, files in os.walk(root): 66*c8dee2aaSAndroid Build Coastguard Worker if not any(snippet in fix_path(path) for snippet in ignorelist): 67*c8dee2aaSAndroid Build Coastguard Worker for file_name in files: 68*c8dee2aaSAndroid Build Coastguard Worker if file_name.endswith('.h') and not file_name in ignorelist: 69*c8dee2aaSAndroid Build Coastguard Worker if file_name in headers: 70*c8dee2aaSAndroid Build Coastguard Worker message = ('Header filename is used more than once!\n- ' + path + '/' + file_name + 71*c8dee2aaSAndroid Build Coastguard Worker '\n- ' + headers[file_name]) 72*c8dee2aaSAndroid Build Coastguard Worker assert file_name not in headers, message 73*c8dee2aaSAndroid Build Coastguard Worker headers[file_name] = os.path.abspath(os.path.join(path, file_name)) 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard Workerdef to_rewrite(): 76*c8dee2aaSAndroid Build Coastguard Worker if args.sources: 77*c8dee2aaSAndroid Build Coastguard Worker for path in args.sources: 78*c8dee2aaSAndroid Build Coastguard Worker yield path 79*c8dee2aaSAndroid Build Coastguard Worker else: 80*c8dee2aaSAndroid Build Coastguard Worker for root in roots: 81*c8dee2aaSAndroid Build Coastguard Worker for path, _, files in os.walk(root): 82*c8dee2aaSAndroid Build Coastguard Worker for file_name in files: 83*c8dee2aaSAndroid Build Coastguard Worker yield os.path.join(path, file_name) 84*c8dee2aaSAndroid Build Coastguard Worker 85*c8dee2aaSAndroid Build Coastguard Worker# Rewrite any #includes relative to Skia's top-level directory. 86*c8dee2aaSAndroid Build Coastguard Workerneed_rewriting = [] 87*c8dee2aaSAndroid Build Coastguard Workerfor file_path in to_rewrite(): 88*c8dee2aaSAndroid Build Coastguard Worker if ('/generated/' in file_path or 89*c8dee2aaSAndroid Build Coastguard Worker 'tests/sksl/' in file_path or 90*c8dee2aaSAndroid Build Coastguard Worker 'third_party/skcms' in file_path or 91*c8dee2aaSAndroid Build Coastguard Worker 'modules/skcms' in file_path or 92*c8dee2aaSAndroid Build Coastguard Worker # transitional 93*c8dee2aaSAndroid Build Coastguard Worker 'jetski' in file_path or 94*c8dee2aaSAndroid Build Coastguard Worker 'tools/window' in file_path or 95*c8dee2aaSAndroid Build Coastguard Worker file_path.startswith('bazel/rbe') or 96*c8dee2aaSAndroid Build Coastguard Worker 'example/external_client/' in file_path or 97*c8dee2aaSAndroid Build Coastguard Worker # We intentionally list SkUserConfig.h not from the root in this file. 98*c8dee2aaSAndroid Build Coastguard Worker file_path == 'include/private/base/SkLoadUserConfig.h'): 99*c8dee2aaSAndroid Build Coastguard Worker continue 100*c8dee2aaSAndroid Build Coastguard Worker if (file_path.endswith('.h') or 101*c8dee2aaSAndroid Build Coastguard Worker file_path.endswith('.c') or 102*c8dee2aaSAndroid Build Coastguard Worker file_path.endswith('.m') or 103*c8dee2aaSAndroid Build Coastguard Worker file_path.endswith('.mm') or 104*c8dee2aaSAndroid Build Coastguard Worker file_path.endswith('.inc') or 105*c8dee2aaSAndroid Build Coastguard Worker file_path.endswith('.cc') or 106*c8dee2aaSAndroid Build Coastguard Worker file_path.endswith('.cpp')): 107*c8dee2aaSAndroid Build Coastguard Worker # Read the whole file into memory. 108*c8dee2aaSAndroid Build Coastguard Worker lines = open(file_path).readlines() 109*c8dee2aaSAndroid Build Coastguard Worker 110*c8dee2aaSAndroid Build Coastguard Worker # Write it back out again line by line with substitutions for #includes. 111*c8dee2aaSAndroid Build Coastguard Worker output = StringIO() if args.dry_run else open(file_path, 'w') 112*c8dee2aaSAndroid Build Coastguard Worker 113*c8dee2aaSAndroid Build Coastguard Worker includes = [] 114*c8dee2aaSAndroid Build Coastguard Worker for line in lines: 115*c8dee2aaSAndroid Build Coastguard Worker parts = line.replace('<', '"').replace('>', '"').split('"') 116*c8dee2aaSAndroid Build Coastguard Worker if (len(parts) == 3 117*c8dee2aaSAndroid Build Coastguard Worker and '#' in parts[0] 118*c8dee2aaSAndroid Build Coastguard Worker and 'include' in parts[0] 119*c8dee2aaSAndroid Build Coastguard Worker and os.path.basename(parts[1]) in headers): 120*c8dee2aaSAndroid Build Coastguard Worker header = fix_path(os.path.relpath(headers[os.path.basename(parts[1])], '.')) 121*c8dee2aaSAndroid Build Coastguard Worker includes.append(parts[0] + '"%s"' % header + parts[2]) 122*c8dee2aaSAndroid Build Coastguard Worker else: 123*c8dee2aaSAndroid Build Coastguard Worker # deduplicate includes in this block. If a file needs to be included 124*c8dee2aaSAndroid Build Coastguard Worker # multiple times, the separate includes should go in different blocks. 125*c8dee2aaSAndroid Build Coastguard Worker includes = sorted(list(set(includes))) 126*c8dee2aaSAndroid Build Coastguard Worker for inc in includes: 127*c8dee2aaSAndroid Build Coastguard Worker output.write(inc.strip('\n') + '\n') 128*c8dee2aaSAndroid Build Coastguard Worker includes = [] 129*c8dee2aaSAndroid Build Coastguard Worker output.write(line.strip('\n') + '\n') 130*c8dee2aaSAndroid Build Coastguard Worker # Fix any straggling includes, e.g. in a file that only includes something else. 131*c8dee2aaSAndroid Build Coastguard Worker for inc in sorted(includes): 132*c8dee2aaSAndroid Build Coastguard Worker output.write(inc.strip('\n') + '\n') 133*c8dee2aaSAndroid Build Coastguard Worker if args.dry_run and output.getvalue() != open(file_path).read(): 134*c8dee2aaSAndroid Build Coastguard Worker need_rewriting.append(file_path) 135*c8dee2aaSAndroid Build Coastguard Worker rc = 1 136*c8dee2aaSAndroid Build Coastguard Worker output.close() 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Workerif need_rewriting: 139*c8dee2aaSAndroid Build Coastguard Worker print('Some files need rewritten #includes:') 140*c8dee2aaSAndroid Build Coastguard Worker for path in need_rewriting: 141*c8dee2aaSAndroid Build Coastguard Worker print('\t' + path) 142*c8dee2aaSAndroid Build Coastguard Worker print('To do this automatically, run') 143*c8dee2aaSAndroid Build Coastguard Worker print('python3 tools/rewrite_includes.py ' + ' '.join(need_rewriting)) 144*c8dee2aaSAndroid Build Coastguard Worker sys.exit(1) 145