diff options
author | 2017-12-13 14:44:29 -0800 | |
---|---|---|
committer | 2017-12-13 14:44:29 -0800 | |
commit | 54d699ddda18e8aca7a556ad3c38d1684efc88ec (patch) | |
tree | b0ecaaf07074bdcde6c3315f647cc04417da7b90 /tools/run_tests/sanity/check_sources_and_headers.py | |
parent | 62d86e9987121c8bd79d4594fb0db019c4faafad (diff) | |
parent | 91a851c6e1f6bc7c1dbf84ea12558d535c911252 (diff) |
Merge branch 'master' of github.com:grpc/grpc into backoff_cpp
Diffstat (limited to 'tools/run_tests/sanity/check_sources_and_headers.py')
-rwxr-xr-x | tools/run_tests/sanity/check_sources_and_headers.py | 136 |
1 files changed, 87 insertions, 49 deletions
diff --git a/tools/run_tests/sanity/check_sources_and_headers.py b/tools/run_tests/sanity/check_sources_and_headers.py index cae175cfc3..6a704eb2e0 100755 --- a/tools/run_tests/sanity/check_sources_and_headers.py +++ b/tools/run_tests/sanity/check_sources_and_headers.py @@ -21,71 +21,109 @@ import re import sys root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..')) -with open(os.path.join(root, 'tools', 'run_tests', 'generated', 'sources_and_headers.json')) as f: - js = json.loads(f.read()) +with open( + os.path.join(root, 'tools', 'run_tests', 'generated', + 'sources_and_headers.json')) as f: + js = json.loads(f.read()) re_inc1 = re.compile(r'^#\s*include\s*"([^"]*)"') assert re_inc1.match('#include "foo"').group(1) == 'foo' re_inc2 = re.compile(r'^#\s*include\s*<((grpc|grpc\+\+)/[^"]*)>') assert re_inc2.match('#include <grpc++/foo>').group(1) == 'grpc++/foo' + def get_target(name): - for target in js: - if target['name'] == name: - return target - assert False, 'no target %s' % name + for target in js: + if target['name'] == name: + return target + assert False, 'no target %s' % name + + +def get_headers_transitive(): + """Computes set of headers transitively provided by each target""" + target_headers_transitive = {} + for target in js: + target_name = target['name'] + assert not target_headers_transitive.has_key(target_name) + target_headers_transitive[target_name] = set(target['headers']) + + # Make sure each target's transitive headers contain those + # of their dependencies. If not, add them and continue doing + # so until we get a full pass over all targets without any updates. + closure_changed = True + while closure_changed: + closure_changed = False + for target in js: + target_name = target['name'] + for dep in target['deps']: + headers = target_headers_transitive[target_name] + old_count = len(headers) + headers.update(target_headers_transitive[dep]) + if old_count != len(headers): + closure_changed = True + return target_headers_transitive + + +# precompute transitive closure of headers provided by each target +target_headers_transitive = get_headers_transitive() + def target_has_header(target, name): - if name.startswith('absl/'): return True - # print target['name'], name - if name in target['headers']: - return True - for dep in target['deps']: - if target_has_header(get_target(dep), name): - return True - if name in ['src/core/lib/profiling/stap_probes.h', - 'src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h']: - return True - return False + if name.startswith('absl/'): return True + # print target['name'], name + if name in target['headers']: + return True + for dep in target['deps']: + if target_has_header(get_target(dep), name): + return True + if name in [ + 'src/core/lib/profiling/stap_probes.h', + 'src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h' + ]: + return True + return False + def produces_object(name): - return os.path.splitext(name)[1] in ['.c', '.cc'] + return os.path.splitext(name)[1] in ['.c', '.cc'] + c_ish = {} obj_producer_to_source = {'c': c_ish, 'c++': c_ish, 'csharp': {}} errors = 0 for target in js: - if not target['third_party']: - for fn in target['src']: - with open(os.path.join(root, fn)) as f: - src = f.read().splitlines() - for line in src: - m = re_inc1.match(line) - if m: - if not target_has_header(target, m.group(1)): - print ( - 'target %s (%s) does not name header %s as a dependency' % ( - target['name'], fn, m.group(1))) - errors += 1 - m = re_inc2.match(line) - if m: - if not target_has_header(target, 'include/' + m.group(1)): - print ( - 'target %s (%s) does not name header %s as a dependency' % ( - target['name'], fn, m.group(1))) - errors += 1 - if target['type'] in ['lib', 'filegroup']: - for fn in target['src']: - language = target['language'] - if produces_object(fn): - obj_base = os.path.splitext(os.path.basename(fn))[0] - if obj_base in obj_producer_to_source[language]: - if obj_producer_to_source[language][obj_base] != fn: - print ( - 'target %s (%s) produces an aliased object file with %s' % ( - target['name'], fn, obj_producer_to_source[language][obj_base])) - else: - obj_producer_to_source[language][obj_base] = fn + if not target['third_party']: + for fn in target['src']: + with open(os.path.join(root, fn)) as f: + src = f.read().splitlines() + for line in src: + m = re_inc1.match(line) + if m: + if not target_has_header(target, m.group(1)): + print( + 'target %s (%s) does not name header %s as a dependency' + % (target['name'], fn, m.group(1))) + errors += 1 + m = re_inc2.match(line) + if m: + if not target_has_header(target, 'include/' + m.group(1)): + print( + 'target %s (%s) does not name header %s as a dependency' + % (target['name'], fn, m.group(1))) + errors += 1 + if target['type'] in ['lib', 'filegroup']: + for fn in target['src']: + language = target['language'] + if produces_object(fn): + obj_base = os.path.splitext(os.path.basename(fn))[0] + if obj_base in obj_producer_to_source[language]: + if obj_producer_to_source[language][obj_base] != fn: + print( + 'target %s (%s) produces an aliased object file with %s' + % (target['name'], fn, + obj_producer_to_source[language][obj_base])) + else: + obj_producer_to_source[language][obj_base] = fn assert errors == 0 |