make_grpcio_tools.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #!/usr/bin/env python3
  2. # Copyright 2016 gRPC authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from __future__ import print_function
  16. import errno
  17. import filecmp
  18. import glob
  19. import os
  20. import os.path
  21. import shutil
  22. import subprocess
  23. import sys
  24. import traceback
  25. import uuid
  26. DEPS_FILE_CONTENT = """
  27. # Copyright 2017 gRPC authors.
  28. #
  29. # Licensed under the Apache License, Version 2.0 (the "License");
  30. # you may not use this file except in compliance with the License.
  31. # You may obtain a copy of the License at
  32. #
  33. # http://www.apache.org/licenses/LICENSE-2.0
  34. #
  35. # Unless required by applicable law or agreed to in writing, software
  36. # distributed under the License is distributed on an "AS IS" BASIS,
  37. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  38. # See the License for the specific language governing permissions and
  39. # limitations under the License.
  40. # AUTO-GENERATED BY make_grpcio_tools.py!
  41. CC_FILES={cc_files}
  42. PROTO_FILES={proto_files}
  43. CC_INCLUDE={cc_include}
  44. PROTO_INCLUDE={proto_include}
  45. {commit_hash}
  46. """
  47. COMMIT_HASH_PREFIX = 'PROTOBUF_SUBMODULE_VERSION="'
  48. COMMIT_HASH_SUFFIX = '"'
  49. # Bazel query result prefix for expected source files in protobuf.
  50. PROTOBUF_CC_PREFIX = '//:src/'
  51. PROTOBUF_PROTO_PREFIX = '//:src/'
  52. GRPC_ROOT = os.path.abspath(
  53. os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', '..'))
  54. GRPC_PYTHON_ROOT = os.path.join(GRPC_ROOT, 'tools', 'distrib', 'python',
  55. 'grpcio_tools')
  56. GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT = os.path.join('third_party', 'protobuf',
  57. 'src')
  58. GRPC_PROTOBUF = os.path.join(GRPC_ROOT, GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT)
  59. GRPC_PROTOBUF_SUBMODULE_ROOT = os.path.join(GRPC_ROOT, 'third_party',
  60. 'protobuf')
  61. GRPC_PROTOC_PLUGINS = os.path.join(GRPC_ROOT, 'src', 'compiler')
  62. GRPC_PYTHON_PROTOBUF = os.path.join(GRPC_PYTHON_ROOT, 'third_party', 'protobuf',
  63. 'src')
  64. GRPC_PYTHON_PROTOC_PLUGINS = os.path.join(GRPC_PYTHON_ROOT, 'grpc_root', 'src',
  65. 'compiler')
  66. GRPC_PYTHON_PROTOC_LIB_DEPS = os.path.join(GRPC_PYTHON_ROOT,
  67. 'protoc_lib_deps.py')
  68. GRPC_INCLUDE = os.path.join(GRPC_ROOT, 'include')
  69. GRPC_PYTHON_INCLUDE = os.path.join(GRPC_PYTHON_ROOT, 'grpc_root', 'include')
  70. BAZEL_DEPS = os.path.join(GRPC_ROOT, 'tools', 'distrib', 'python',
  71. 'bazel_deps.sh')
  72. BAZEL_DEPS_PROTOC_LIB_QUERY = '//:protoc_lib'
  73. BAZEL_DEPS_COMMON_PROTOS_QUERY = '//:well_known_protos'
  74. def protobuf_submodule_commit_hash():
  75. """Gets the commit hash for the HEAD of the protobuf submodule currently
  76. checked out."""
  77. cwd = os.getcwd()
  78. os.chdir(GRPC_PROTOBUF_SUBMODULE_ROOT)
  79. output = subprocess.check_output(['git', 'rev-parse', 'HEAD'])
  80. os.chdir(cwd)
  81. return output.decode("ascii").splitlines()[0].strip()
  82. def bazel_query(query):
  83. print('Running "bazel query %s"' % query)
  84. output = subprocess.check_output([BAZEL_DEPS, query])
  85. return output.decode("ascii").splitlines()
  86. def get_deps():
  87. """Write the result of the bazel query `query` against protobuf to
  88. `out_file`."""
  89. cc_files_output = bazel_query(BAZEL_DEPS_PROTOC_LIB_QUERY)
  90. cc_files = [
  91. name[len(PROTOBUF_CC_PREFIX):]
  92. for name in cc_files_output
  93. if name.endswith('.cc') and name.startswith(PROTOBUF_CC_PREFIX)
  94. ]
  95. proto_files_output = bazel_query(BAZEL_DEPS_COMMON_PROTOS_QUERY)
  96. proto_files = [
  97. name[len(PROTOBUF_PROTO_PREFIX):]
  98. for name in proto_files_output
  99. if name.endswith('.proto') and name.startswith(PROTOBUF_PROTO_PREFIX)
  100. ]
  101. commit_hash = protobuf_submodule_commit_hash()
  102. deps_file_content = DEPS_FILE_CONTENT.format(
  103. cc_files=cc_files,
  104. proto_files=proto_files,
  105. cc_include=repr(GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT),
  106. proto_include=repr(GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT),
  107. commit_hash=COMMIT_HASH_PREFIX + commit_hash + COMMIT_HASH_SUFFIX)
  108. return deps_file_content
  109. def long_path(path):
  110. if os.name == 'nt':
  111. return '\\\\?\\' + path
  112. else:
  113. return path
  114. def main():
  115. os.chdir(GRPC_ROOT)
  116. for source, target in [(GRPC_PROTOBUF, GRPC_PYTHON_PROTOBUF),
  117. (GRPC_PROTOC_PLUGINS, GRPC_PYTHON_PROTOC_PLUGINS),
  118. (GRPC_INCLUDE, GRPC_PYTHON_INCLUDE)]:
  119. for source_dir, _, files in os.walk(source):
  120. target_dir = os.path.abspath(
  121. os.path.join(target, os.path.relpath(source_dir, source)))
  122. try:
  123. os.makedirs(target_dir)
  124. except OSError as error:
  125. if error.errno != errno.EEXIST:
  126. raise
  127. for relative_file in files:
  128. source_file = os.path.abspath(
  129. os.path.join(source_dir, relative_file))
  130. target_file = os.path.abspath(
  131. os.path.join(target_dir, relative_file))
  132. shutil.copyfile(source_file, target_file)
  133. try:
  134. print('Invoking "bazel query" to gather the protobuf dependencies.')
  135. protoc_lib_deps_content = get_deps()
  136. except Exception as error:
  137. # We allow this script to succeed even if we couldn't get the dependencies,
  138. # as then we can assume that even without a successful bazel run the
  139. # dependencies currently in source control are 'good enough'.
  140. sys.stderr.write("Got non-fatal error:\n")
  141. traceback.print_exc(file=sys.stderr)
  142. return
  143. # If we successfully got the dependencies, truncate and rewrite the deps file.
  144. with open(GRPC_PYTHON_PROTOC_LIB_DEPS, 'w') as deps_file:
  145. deps_file.write(protoc_lib_deps_content)
  146. print('File "%s" updated.' % GRPC_PYTHON_PROTOC_LIB_DEPS)
  147. print('Done.')
  148. if __name__ == '__main__':
  149. main()