check_bazel_workspace.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 # Copyright 2016 gRPC authors.
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16 
17 import ast
18 import os
19 import re
20 import subprocess
21 import sys
22 
23 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
24 
25 git_hash_pattern = re.compile('[0-9a-f]{40}')
26 
27 # Parse git hashes from submodules
28 git_submodules = subprocess.check_output(
29  'git submodule', shell=True).decode().strip().split('\n')
30 git_submodule_hashes = {
31  re.search(git_hash_pattern, s).group() for s in git_submodules
32 }
33 
34 _BAZEL_SKYLIB_DEP_NAME = 'bazel_skylib'
35 _BAZEL_TOOLCHAINS_DEP_NAME = 'bazel_toolchains'
36 _BAZEL_COMPDB_DEP_NAME = 'bazel_compdb'
37 _TWISTED_TWISTED_DEP_NAME = 'com_github_twisted_twisted'
38 _YAML_PYYAML_DEP_NAME = 'com_github_yaml_pyyaml'
39 _TWISTED_INCREMENTAL_DEP_NAME = 'com_github_twisted_incremental'
40 _ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME = 'com_github_zopefoundation_zope_interface'
41 _TWISTED_CONSTANTLY_DEP_NAME = 'com_github_twisted_constantly'
42 
43 _GRPC_DEP_NAMES = [
44  'upb', 'boringssl', 'zlib', 'com_google_protobuf', 'com_google_googletest',
45  'rules_cc', 'com_github_google_benchmark', 'com_github_cares_cares',
46  'com_google_absl', 'io_opencensus_cpp', 'envoy_api', _BAZEL_SKYLIB_DEP_NAME,
47  _BAZEL_TOOLCHAINS_DEP_NAME, _BAZEL_COMPDB_DEP_NAME,
48  _TWISTED_TWISTED_DEP_NAME, _YAML_PYYAML_DEP_NAME,
49  _TWISTED_INCREMENTAL_DEP_NAME, _ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME,
50  _TWISTED_CONSTANTLY_DEP_NAME, 'io_bazel_rules_go',
51  'build_bazel_rules_apple', 'build_bazel_apple_support',
52  'com_github_libuv_libuv', 'com_googlesource_code_re2', 'bazel_gazelle',
53  'opencensus_proto', 'com_envoyproxy_protoc_gen_validate',
54  'com_google_googleapis', 'com_google_libprotobuf_mutator',
55  'com_github_cncf_udpa'
56 ]
57 
58 _GRPC_BAZEL_ONLY_DEPS = [
59  'upb', # third_party/upb is checked in locally
60  'rules_cc',
61  'com_google_absl',
62  'io_opencensus_cpp',
63  _BAZEL_SKYLIB_DEP_NAME,
64  _BAZEL_TOOLCHAINS_DEP_NAME,
65  _BAZEL_COMPDB_DEP_NAME,
66  _TWISTED_TWISTED_DEP_NAME,
67  _YAML_PYYAML_DEP_NAME,
68  _TWISTED_INCREMENTAL_DEP_NAME,
69  _ZOPEFOUNDATION_ZOPE_INTERFACE_DEP_NAME,
70  _TWISTED_CONSTANTLY_DEP_NAME,
71  'io_bazel_rules_go',
72  'build_bazel_rules_apple',
73  'build_bazel_apple_support',
74  'com_googlesource_code_re2',
75  'bazel_gazelle',
76  'opencensus_proto',
77  'com_envoyproxy_protoc_gen_validate',
78  'com_google_googleapis',
79  'com_google_libprotobuf_mutator'
80 ]
81 
82 
83 class BazelEvalState(object):
84 
85  def __init__(self, names_and_urls, overridden_name=None):
86  self.names_and_urls = names_and_urls
87  self.overridden_name = overridden_name
88 
89  def http_archive(self, **args):
90  self.archive(**args)
91 
92  def new_http_archive(self, **args):
93  self.archive(**args)
94 
95  def bind(self, **args):
96  pass
97 
98  def existing_rules(self):
99  if self.overridden_name:
100  return [self.overridden_name]
101  return []
102 
103  def archive(self, **args):
104  assert self.names_and_urls.get(args['name']) is None
105  if args['name'] in _GRPC_BAZEL_ONLY_DEPS:
106  self.names_and_urls[args['name']] = 'dont care'
107  return
108  url = args.get('url', None)
109  if not url:
110  # we will only be looking for git commit hashes, so concatenating
111  # the urls is fine.
112  url = ' '.join(args['urls'])
113  self.names_and_urls[args['name']] = url
114 
115  def git_repository(self, **args):
116  assert self.names_and_urls.get(args['name']) is None
117  if args['name'] in _GRPC_BAZEL_ONLY_DEPS:
118  self.names_and_urls[args['name']] = 'dont care'
119  return
120  self.names_and_urls[args['name']] = args['remote']
121 
122  def grpc_python_deps(self):
123  pass
124 
125 
126 # Parse git hashes from bazel/grpc_deps.bzl {new_}http_archive rules
127 with open(os.path.join('bazel', 'grpc_deps.bzl'), 'r') as f:
128  names_and_urls = {}
129  eval_state = BazelEvalState(names_and_urls)
130  bazel_file = f.read()
131 
132 # grpc_deps.bzl only defines 'grpc_deps' and 'grpc_test_only_deps', add these
133 # lines to call them.
134 bazel_file += '\ngrpc_deps()\n'
135 bazel_file += '\ngrpc_test_only_deps()\n'
136 build_rules = {
137  'native': eval_state,
138  'http_archive': lambda **args: eval_state.http_archive(**args),
139  'load': lambda a, b: None,
140  'git_repository': lambda **args: eval_state.git_repository(**args),
141  'grpc_python_deps': lambda: None,
142 }
143 exec((bazel_file), build_rules)
144 for name in _GRPC_DEP_NAMES:
145  assert name in list(names_and_urls.keys())
146 assert len(_GRPC_DEP_NAMES) == len(list(names_and_urls.keys()))
147 
148 # There are some "bazel-only" deps that are exceptions to this sanity check,
149 # we don't require that there is a corresponding git module for these.
150 names_without_bazel_only_deps = list(names_and_urls.keys())
151 for dep_name in _GRPC_BAZEL_ONLY_DEPS:
152  names_without_bazel_only_deps.remove(dep_name)
153 archive_urls = [names_and_urls[name] for name in names_without_bazel_only_deps]
154 workspace_git_hashes = {
155  re.search(git_hash_pattern, url).group() for url in archive_urls
156 }
157 if len(workspace_git_hashes) == 0:
158  print("(Likely) parse error, did not find any bazel git dependencies.")
159  sys.exit(1)
160 
161 # Validate the equivalence of the git submodules and Bazel git dependencies. The
162 # condition we impose is that there is a git submodule for every dependency in
163 # the workspace, but not necessarily conversely. E.g. Bloaty is a dependency
164 # not used by any of the targets built by Bazel.
165 if len(workspace_git_hashes - git_submodule_hashes) > 0:
166  print(
167  "Found discrepancies between git submodules and Bazel WORKSPACE dependencies"
168  )
169  print(("workspace_git_hashes: %s" % workspace_git_hashes))
170  print(("git_submodule_hashes: %s" % git_submodule_hashes))
171  print(("workspace_git_hashes - git_submodule_hashes: %s" %
172  (workspace_git_hashes - git_submodule_hashes)))
173  sys.exit(1)
174 
175 # Also check that we can override each dependency
176 for name in _GRPC_DEP_NAMES:
177  names_and_urls_with_overridden_name = {}
178  state = BazelEvalState(names_and_urls_with_overridden_name,
179  overridden_name=name)
180  rules = {
181  'native': state,
182  'http_archive': lambda **args: state.http_archive(**args),
183  'load': lambda a, b: None,
184  'git_repository': lambda **args: state.git_repository(**args),
185  'grpc_python_deps': lambda *args, **kwargs: None,
186  }
187  exec((bazel_file), rules)
188  assert name not in list(names_and_urls_with_overridden_name.keys())
189 
190 sys.exit(0)
check_bazel_workspace.BazelEvalState.existing_rules
def existing_rules(self)
Definition: check_bazel_workspace.py:98
check_bazel_workspace.BazelEvalState.grpc_python_deps
def grpc_python_deps(self)
Definition: check_bazel_workspace.py:122
get
absl::string_view get(const Cont &c)
Definition: abseil-cpp/absl/strings/str_replace_test.cc:185
check_bazel_workspace.BazelEvalState.overridden_name
overridden_name
Definition: check_bazel_workspace.py:87
check_bazel_workspace.BazelEvalState.bind
def bind(self, **args)
Definition: check_bazel_workspace.py:95
check_bazel_workspace.BazelEvalState.names_and_urls
names_and_urls
Definition: check_bazel_workspace.py:86
check_bazel_workspace.BazelEvalState.archive
def archive(self, **args)
Definition: check_bazel_workspace.py:103
upload.group
group
Definition: bloaty/third_party/googletest/googlemock/scripts/upload.py:397
check_bazel_workspace.BazelEvalState.git_repository
def git_repository(self, **args)
Definition: check_bazel_workspace.py:115
check_bazel_workspace.BazelEvalState.__init__
def __init__(self, names_and_urls, overridden_name=None)
Definition: check_bazel_workspace.py:85
grpc._common.decode
def decode(b)
Definition: grpc/_common.py:75
check_bazel_workspace.BazelEvalState.http_archive
def http_archive(self, **args)
Definition: check_bazel_workspace.py:89
check_bazel_workspace.BazelEvalState.new_http_archive
def new_http_archive(self, **args)
Definition: check_bazel_workspace.py:92
open
#define open
Definition: test-fs.c:46
check_bazel_workspace.BazelEvalState
Definition: check_bazel_workspace.py:83
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
split
static void split(const char *s, char ***ss, size_t *ns)
Definition: debug/trace.cc:111


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:44