xref: /aosp_15_r20/external/perfetto/tools/check_include_violations (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Worker# This tool checks for layering violations in the include/ directory.
17*6dbdd20aSAndroid Build Coastguard Worker# It checks that:
18*6dbdd20aSAndroid Build Coastguard Worker# - public includes don't end up depending on non-public /ext/ includes.
19*6dbdd20aSAndroid Build Coastguard Worker# - public includes don't end up depending on private src/ headers.
20*6dbdd20aSAndroid Build Coastguard Worker# - We use consistently <angle brackets> for other libraries.
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Workerfrom __future__ import absolute_import
23*6dbdd20aSAndroid Build Coastguard Workerfrom __future__ import division
24*6dbdd20aSAndroid Build Coastguard Workerfrom __future__ import print_function
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Workerimport os
27*6dbdd20aSAndroid Build Coastguard Workerimport re
28*6dbdd20aSAndroid Build Coastguard Workerimport subprocess
29*6dbdd20aSAndroid Build Coastguard Workerimport sys
30*6dbdd20aSAndroid Build Coastguard Worker
31*6dbdd20aSAndroid Build Coastguard WorkerROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker
34*6dbdd20aSAndroid Build Coastguard Workerdef main():
35*6dbdd20aSAndroid Build Coastguard Worker  errors = 0
36*6dbdd20aSAndroid Build Coastguard Worker  include_root = os.path.join(ROOT_DIR, 'include')
37*6dbdd20aSAndroid Build Coastguard Worker  for root, _, files in os.walk(include_root):
38*6dbdd20aSAndroid Build Coastguard Worker    for fname in files:
39*6dbdd20aSAndroid Build Coastguard Worker      fpath = os.path.join(root, fname).replace('\\', '/')  # For Windows.
40*6dbdd20aSAndroid Build Coastguard Worker      rel_path = os.path.relpath(fpath, ROOT_DIR).replace('\\', '/')
41*6dbdd20aSAndroid Build Coastguard Worker      if not os.path.isfile(fpath):
42*6dbdd20aSAndroid Build Coastguard Worker        continue
43*6dbdd20aSAndroid Build Coastguard Worker      if fpath.endswith('.cc'):
44*6dbdd20aSAndroid Build Coastguard Worker        sys.stderr.write('.cc files not allowed in includes/ : ' + rel_path +
45*6dbdd20aSAndroid Build Coastguard Worker                         '\n')
46*6dbdd20aSAndroid Build Coastguard Worker        errors += 1
47*6dbdd20aSAndroid Build Coastguard Worker        continue
48*6dbdd20aSAndroid Build Coastguard Worker      if fpath.endswith('.h'):
49*6dbdd20aSAndroid Build Coastguard Worker        with open(fpath) as f:
50*6dbdd20aSAndroid Build Coastguard Worker          lines = f.readlines()
51*6dbdd20aSAndroid Build Coastguard Worker        for line in lines:
52*6dbdd20aSAndroid Build Coastguard Worker          if '// no-include-violation-check' in line:
53*6dbdd20aSAndroid Build Coastguard Worker            continue
54*6dbdd20aSAndroid Build Coastguard Worker          m = re.findall(r'^#include "(.*\.h)"', line)
55*6dbdd20aSAndroid Build Coastguard Worker          if not m:
56*6dbdd20aSAndroid Build Coastguard Worker            continue
57*6dbdd20aSAndroid Build Coastguard Worker          incl = m[0]
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Worker          # Allow only #include "perfetto/..." or "protos/..." but not "src/".
60*6dbdd20aSAndroid Build Coastguard Worker          if not (incl.startswith('perfetto/') or incl.startswith('protos/')):
61*6dbdd20aSAndroid Build Coastguard Worker            sys.stderr.write(
62*6dbdd20aSAndroid Build Coastguard Worker                ('Public header %s is trying to include %s which is outside ' +
63*6dbdd20aSAndroid Build Coastguard Worker                 'of include/. If you are trying to include a library use ' +
64*6dbdd20aSAndroid Build Coastguard Worker                 ' <angle brackets> instead\n') % (rel_path, incl))
65*6dbdd20aSAndroid Build Coastguard Worker            errors += 1
66*6dbdd20aSAndroid Build Coastguard Worker            continue
67*6dbdd20aSAndroid Build Coastguard Worker
68*6dbdd20aSAndroid Build Coastguard Worker          # Ignore lines marked with nogncheck.
69*6dbdd20aSAndroid Build Coastguard Worker          if '// nogncheck' in line:
70*6dbdd20aSAndroid Build Coastguard Worker            continue
71*6dbdd20aSAndroid Build Coastguard Worker
72*6dbdd20aSAndroid Build Coastguard Worker          # Public (non-/ext/) headers cannot include /ext/ headers.
73*6dbdd20aSAndroid Build Coastguard Worker          if (not rel_path.startswith('include/perfetto/ext/') and
74*6dbdd20aSAndroid Build Coastguard Worker              incl.startswith('perfetto/ext/')):
75*6dbdd20aSAndroid Build Coastguard Worker            sys.stderr.write(('Public header %s cannot include the non-public' +
76*6dbdd20aSAndroid Build Coastguard Worker                              '/ext/ header %s.\n') % (rel_path, incl))
77*6dbdd20aSAndroid Build Coastguard Worker            errors += 1
78*6dbdd20aSAndroid Build Coastguard Worker            continue
79*6dbdd20aSAndroid Build Coastguard Worker
80*6dbdd20aSAndroid Build Coastguard Worker  return 0 if errors == 0 else 1
81*6dbdd20aSAndroid Build Coastguard Worker
82*6dbdd20aSAndroid Build Coastguard Worker
83*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__':
84*6dbdd20aSAndroid Build Coastguard Worker  sys.exit(main())
85