Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
compiler_layering_check.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2#
3# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
4# for details. All rights reserved. Use of this source code is governed by a
5# BSD-style license that can be found in the LICENSE file.
6
7# Simple tool for verifying that sources from one layer do not reference
8# sources from another layer.
9#
10# Currently it only checks that core runtime headers RUNTIME_LAYER_HEADERS
11# are not included into any sources listed in SHOULD_NOT_DEPEND_ON_RUNTIME.
12
13import os
14import re
15import sys
16
17INCLUDE_DIRECTIVE_RE = re.compile(r'^#include "(.*)"')
18
19RUNTIME_LAYER_HEADERS = [
20 'runtime/vm/isolate.h',
21 'runtime/vm/object.h',
22 'runtime/vm/raw_object.h',
23 'runtime/vm/thread.h',
24]
25
26SHOULD_NOT_DEPEND_ON_RUNTIME = [
27 'runtime/vm/allocation.h',
28 'runtime/vm/growable_array.h',
29]
30
31
32class LayeringChecker(object):
33
34 def __init__(self, root):
35 self.root = root
36 self.worklist = set()
37 # Mapping from header to a set of files it is included into.
38 self.included_into = dict()
39 # Set of files that were parsed to avoid double parsing.
40 self.loaded = set()
41 # Mapping from headers to their layer.
42 self.file_layers = {file: 'runtime' for file in RUNTIME_LAYER_HEADERS}
43
44 def Check(self):
45 self.AddAllSourcesToWorklist(os.path.join(self.root, 'runtime/vm'))
47 errors = self.PropagateLayers()
48 errors += self.CheckNotInRuntime(SHOULD_NOT_DEPEND_ON_RUNTIME)
49 return errors
50
51 def CheckNotInRuntime(self, files):
52 """Check that given files do not depend on runtime layer."""
53 errors = []
54 for file in files:
55 if not os.path.exists(os.path.join(self.root, file)):
56 errors.append('File %s does not exist.' % (file))
57 if self.file_layers.get(file) is not None:
58 errors.append(
59 'LAYERING ERROR: %s includes object.h or raw_object.h' %
60 (file))
61 return errors
62
64 while self.worklist:
65 file = self.worklist.pop()
66 deps = self.ExtractIncludes(file)
67 self.loaded.add(file)
68 for d in deps:
69 if d not in self.included_into:
70 self.included_into[d] = set()
71 self.included_into[d].add(file)
72 if d not in self.loaded:
73 self.worklist.add(d)
74
75 def PropagateLayers(self):
76 """Propagate layering information through include graph.
77
78 If A is in layer L and A is included into B then B is in layer L.
79 """
80 errors = []
81 self.worklist = set(self.file_layers.keys())
82 while self.worklist:
83 file = self.worklist.pop()
84 if file not in self.included_into:
85 continue
86 file_layer = self.file_layers[file]
87 for tgt in self.included_into[file]:
88 if tgt in self.file_layers:
89 if self.file_layers[tgt] != file_layer:
90 errors.add(
91 'Layer mismatch: %s (%s) is included into %s (%s)' %
92 (file, file_layer, tgt, self.file_layers[tgt]))
93 self.file_layers[tgt] = file_layer
94 self.worklist.add(tgt)
95 return errors
96
98 """Add all *.cc and *.h files from dir recursively into worklist."""
99 for file in os.listdir(dir):
100 path = os.path.join(dir, file)
101 if os.path.isdir(path):
102 self.AddAllSourcesToWorklist(path)
103 elif path.endswith('.cc') or path.endswith('.h'):
104 self.worklist.add(os.path.relpath(path, self.root))
105
106 def ExtractIncludes(self, file):
107 """Extract the list of includes from the given file."""
108 deps = set()
109 with open(os.path.join(self.root, file), encoding='utf-8') as file:
110 for line in file:
111 if line.startswith('namespace dart {'):
112 break
113
114 m = INCLUDE_DIRECTIVE_RE.match(line)
115 if m is not None:
116 header = os.path.join('runtime', m.group(1))
117 if os.path.isfile(os.path.join(self.root, header)):
118 deps.add(header)
119 return deps
120
121
122def DoCheck(sdk_root):
123 """Run layering check at the given root folder."""
124 return LayeringChecker(sdk_root).Check()
125
126
127if __name__ == '__main__':
128 errors = DoCheck('.')
129 print('\n'.join(errors))
130 if errors:
131 sys.exit(-1)
static std::function< void(void)> pop(std::deque< std::function< void(void)> > *list)
void print(void *str)
Definition bridge.cpp:126