3 # Copyright 2016 gRPC authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 from __future__ import print_function
25 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
27 git_hash_pattern = re.compile('[0-9a-f]{40}')
29 # Parse git hashes from submodules
30 git_submodules = subprocess.check_output('git submodule',
31 shell=True).strip().split('\n')
32 git_submodule_hashes = {
33 re.search(git_hash_pattern, s).group() for s in git_submodules
36 _BAZEL_SKYLIB_DEP_NAME = 'bazel_skylib'
37 _BAZEL_TOOLCHAINS_DEP_NAME = 'bazel_toolchains'
38 _BAZEL_COMPDB_DEP_NAME = 'bazel_compdb'
39 _TWISTED_TWISTED_DEP_NAME = 'com_github_twisted_twisted'
40 _YAML_PYYAML_DEP_NAME = 'com_github_yaml_pyyaml'
41 _TWISTED_INCREMENTAL_DEP_NAME = 'com_github_twisted_incremental'
42 _ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME = 'com_github_zopefoundation_zope_interface'
43 _TWISTED_CONSTANTLY_DEP_NAME = 'com_github_twisted_constantly'
49 'com_google_protobuf',
50 'com_google_googletest',
52 'com_github_google_benchmark',
53 'com_github_cares_cares',
57 _BAZEL_SKYLIB_DEP_NAME,
58 _BAZEL_TOOLCHAINS_DEP_NAME,
59 _BAZEL_COMPDB_DEP_NAME,
60 _TWISTED_TWISTED_DEP_NAME,
61 _YAML_PYYAML_DEP_NAME,
62 _TWISTED_INCREMENTAL_DEP_NAME,
63 _ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME,
64 _TWISTED_CONSTANTLY_DEP_NAME,
66 'build_bazel_rules_apple',
67 'build_bazel_apple_support',
69 'com_github_google_re2',
72 _GRPC_BAZEL_ONLY_DEPS = [
73 'upb', # third_party/upb is checked in locally
77 _BAZEL_SKYLIB_DEP_NAME,
78 _BAZEL_TOOLCHAINS_DEP_NAME,
79 _BAZEL_COMPDB_DEP_NAME,
80 _TWISTED_TWISTED_DEP_NAME,
81 _YAML_PYYAML_DEP_NAME,
82 _TWISTED_INCREMENTAL_DEP_NAME,
83 _ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME,
84 _TWISTED_CONSTANTLY_DEP_NAME,
86 'build_bazel_rules_apple',
87 'build_bazel_apple_support',
91 class BazelEvalState(object):
93 def __init__(self, names_and_urls, overridden_name=None):
94 self.names_and_urls = names_and_urls
95 self.overridden_name = overridden_name
97 def http_archive(self, **args):
100 def new_http_archive(self, **args):
103 def bind(self, **args):
106 def existing_rules(self):
107 if self.overridden_name:
108 return [self.overridden_name]
111 def archive(self, **args):
112 assert self.names_and_urls.get(args['name']) is None
113 if args['name'] in _GRPC_BAZEL_ONLY_DEPS:
114 self.names_and_urls[args['name']] = 'dont care'
116 url = args.get('url', None)
118 # we will only be looking for git commit hashes, so concatenating
120 url = ' '.join(args['urls'])
121 self.names_and_urls[args['name']] = url
123 def git_repository(self, **args):
124 assert self.names_and_urls.get(args['name']) is None
125 if args['name'] in _GRPC_BAZEL_ONLY_DEPS:
126 self.names_and_urls[args['name']] = 'dont care'
128 self.names_and_urls[args['name']] = args['remote']
130 def grpc_python_deps(self):
134 # Parse git hashes from bazel/grpc_deps.bzl {new_}http_archive rules
135 with open(os.path.join('bazel', 'grpc_deps.bzl'), 'r') as f:
137 eval_state = BazelEvalState(names_and_urls)
138 bazel_file = f.read()
140 # grpc_deps.bzl only defines 'grpc_deps' and 'grpc_test_only_deps', add these
141 # lines to call them.
142 bazel_file += '\ngrpc_deps()\n'
143 bazel_file += '\ngrpc_test_only_deps()\n'
145 'native': eval_state,
146 'http_archive': lambda **args: eval_state.http_archive(**args),
147 'load': lambda a, b: None,
148 'git_repository': lambda **args: eval_state.git_repository(**args),
149 'grpc_python_deps': lambda: None,
151 exec(bazel_file) in build_rules
152 for name in _GRPC_DEP_NAMES:
153 assert name in names_and_urls.keys()
154 if len(_GRPC_DEP_NAMES) != len(names_and_urls.keys()):
155 assert False, "Diff: " + (str(set(_GRPC_DEP_NAMES) - set(names_and_urls)) +
157 str(set(names_and_urls) - set(_GRPC_DEP_NAMES)))
159 # There are some "bazel-only" deps that are exceptions to this sanity check,
160 # we don't require that there is a corresponding git module for these.
161 names_without_bazel_only_deps = names_and_urls.keys()
162 for dep_name in _GRPC_BAZEL_ONLY_DEPS:
163 names_without_bazel_only_deps.remove(dep_name)
164 archive_urls = [names_and_urls[name] for name in names_without_bazel_only_deps]
165 workspace_git_hashes = {
166 re.search(git_hash_pattern, url).group() for url in archive_urls
168 if len(workspace_git_hashes) == 0:
169 print("(Likely) parse error, did not find any bazel git dependencies.")
172 # Validate the equivalence of the git submodules and Bazel git dependencies. The
173 # condition we impose is that there is a git submodule for every dependency in
174 # the workspace, but not necessarily conversely. E.g. Bloaty is a dependency
175 # not used by any of the targets built by Bazel.
176 if len(workspace_git_hashes - git_submodule_hashes) > 0:
178 "Found discrepancies between git submodules and Bazel WORKSPACE dependencies"
180 print("workspace_git_hashes: %s" % workspace_git_hashes)
181 print("git_submodule_hashes: %s" % git_submodule_hashes)
182 print("workspace_git_hashes - git_submodule_hashes: %s" %
183 (workspace_git_hashes - git_submodule_hashes))
186 # Also check that we can override each dependency
187 for name in _GRPC_DEP_NAMES:
188 names_and_urls_with_overridden_name = {}
189 state = BazelEvalState(names_and_urls_with_overridden_name,
190 overridden_name=name)
193 'http_archive': lambda **args: state.http_archive(**args),
194 'load': lambda a, b: None,
195 'git_repository': lambda **args: state.git_repository(**args),
196 'grpc_python_deps': lambda *args, **kwargs: None,
198 exec(bazel_file) in rules
199 assert name not in names_and_urls_with_overridden_name.keys()