generate_cmake 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #!/usr/bin/env python3
  2. import sys
  3. import os
  4. import shutil
  5. import subprocess
  6. import multiprocessing
  7. import json
  8. import stat
  9. import filecmp
  10. import urllib.request
  11. from argparse import ArgumentParser
  12. def mkdir(path):
  13. try:
  14. os.mkdir(path)
  15. except FileExistsError as e:
  16. pass
  17. def remove_file(path):
  18. try:
  19. os.remove(path)
  20. except FileNotFoundError as e:
  21. pass
  22. def compare_files(lhs_file_path, rhs_file_path):
  23. try:
  24. return filecmp.cmp(lhs_file_path, rhs_file_path)
  25. except FileNotFoundError as e:
  26. return False
  27. def rmtree(path):
  28. try:
  29. shutil.rmtree(path)
  30. except FileNotFoundError as e:
  31. pass
  32. def make_file_executable(file_path):
  33. st = os.stat(file_path)
  34. os.chmod(file_path, st.st_mode + stat.S_IEXEC)
  35. def get_binary_id(resource_file_path):
  36. with open(resource_file_path) as file:
  37. ymake_file_json = json.load(file)
  38. linux_uri = str(ymake_file_json["by_platform"]["linux"]["uri"])
  39. return linux_uri.split(":")[1]
  40. def download_binary(root_path, binary_name, binary_path):
  41. root_binary_resource_file_path = (
  42. f"{root_path}/build/external_resources/{binary_name}/resources.json"
  43. )
  44. tmp_binary_resource_file_path = binary_path + "_resources.json"
  45. if compare_files(root_binary_resource_file_path, tmp_binary_resource_file_path):
  46. print(f"Use {binary_name} binary from cache {binary_path}")
  47. else:
  48. binary_id = get_binary_id(root_binary_resource_file_path)
  49. devtools_registry_s3_url = "https://devtools-registry.s3.yandex.net"
  50. devtools_registry_s3_binary_url = f"{devtools_registry_s3_url}/{binary_id}"
  51. print(
  52. f"Download {binary_name} binary from {devtools_registry_s3_binary_url} into {binary_path}"
  53. )
  54. remove_file(binary_path)
  55. urllib.request.urlretrieve(devtools_registry_s3_binary_url, binary_path)
  56. make_file_executable(binary_path)
  57. shutil.copy(root_binary_resource_file_path, tmp_binary_resource_file_path)
  58. def generate_graph_for_platform(generate_graph_for_platform):
  59. platform = generate_graph_for_platform[0]
  60. generate_graph_command = generate_graph_for_platform[1]
  61. output = subprocess.check_output(
  62. generate_graph_command, stderr=subprocess.STDOUT, shell=True
  63. ).decode("utf-8")
  64. allowed_error_patterns = [
  65. "to directory without ya.make: [[imp]]$S/build/platform/",
  66. "to directory without ya.make: [[imp]]$S/build/external_resources/",
  67. "could not resolve include file: [[imp]]openssl",
  68. "could not resolve include file: [[imp]]zlib",
  69. "could not resolve include file: [[imp]]ares.h",
  70. "in $B/contrib/libs/openssl/",
  71. "in $B/contrib/libs/zlib",
  72. "in $B/contrib/libs/c-ares",
  73. "in $B/contrib/libs/libc_compat/ubuntu_14/liblibs-libc_compat-ubuntu_14.a",
  74. "in $B/contrib/libs/linux-headers/libcontrib-libs-linux-headers.a",
  75. "in $B/contrib/libs/farmhash/",
  76. "in $B/contrib/libs/curl/",
  77. "in $B/contrib/libs/libxml/",
  78. "in $B/contrib/libs/apache/arrow/",
  79. "in $B/contrib/libs/grpc/",
  80. "in $S/contrib/tools/protoc/plugins/cpp_styleguide/ya.make",
  81. "in $S/contrib/tools/protoc/plugins/grpc_cpp",
  82. "in $B/contrib/restricted/boost/",
  83. "in $B/library/cpp/charset/",
  84. "in $B/library/cpp/uri/",
  85. "in $B/library/cpp/unicode/punycode/",
  86. "in $B/library/cpp/config/",
  87. "in $S/tools/rescompiler/bin/",
  88. # Fix
  89. "in $B/library/cpp/actors/dnsresolver/ut/library-cpp-actors-dnsresolver-ut",
  90. "in $B/ydb/library/pdisk_io/libydb-library-pdisk_io",
  91. ]
  92. if platform == "windows-x86_64":
  93. # Fix
  94. allowed_error_patterns.append("in $B/ydb/core/tx/tiering/core-tx-tiering")
  95. allowed_error_patterns.append(
  96. "in $B/ydb/library/yql/providers/s3/serializations/providers-s3-serializations"
  97. )
  98. result_errors = []
  99. for line in output.split("\n"):
  100. if not line.startswith("Error"):
  101. continue
  102. error_is_allowed = False
  103. for allowed_error_pattern in allowed_error_patterns:
  104. if allowed_error_pattern in line:
  105. error_is_allowed = True
  106. break
  107. if error_is_allowed:
  108. continue
  109. result_errors.append(line)
  110. return result_errors
  111. if __name__ == "__main__":
  112. parser = ArgumentParser(description="Generate CMake files from Ya make files")
  113. parser.add_argument("--ymake_bin", help="Path to ymake binary")
  114. parser.add_argument("--yexport_bin", help="Path to yexport binary")
  115. parser.add_argument("--tmp", help="Path to tmp dir")
  116. parser.add_argument(
  117. "--debug", action="store_true", default=False, help="Run script in debug mode"
  118. )
  119. try:
  120. args = parser.parse_args()
  121. except Exception as e:
  122. print(e, file=sys.stderr)
  123. sys.exit(1)
  124. tmp_folder_path = args.tmp
  125. if tmp_folder_path is None:
  126. tmp_folder_path = "/tmp/ydb-generate-cmake"
  127. ymake_binary_path = args.ymake_bin
  128. yexport_binary_path = args.yexport_bin
  129. debug = args.debug
  130. ydb_tmp_folder_path = tmp_folder_path + "/ydb"
  131. ydb_metadata_folder_path = tmp_folder_path + "/metadata"
  132. ydb_bin_folder_path = tmp_folder_path + "/bin"
  133. plugins_folder_path = ydb_tmp_folder_path + "/build/plugins"
  134. mkdir(tmp_folder_path)
  135. mkdir(ydb_metadata_folder_path)
  136. mkdir(ydb_bin_folder_path)
  137. root_folder = os.getcwd()
  138. if ymake_binary_path is None:
  139. ymake_binary_path = ydb_bin_folder_path + "/ymake"
  140. download_binary(root_folder, "ymake", ymake_binary_path)
  141. if yexport_binary_path is None:
  142. yexport_binary_path = ydb_bin_folder_path + "/yexport"
  143. download_binary(root_folder, "yexport", yexport_binary_path)
  144. rmtree(ydb_tmp_folder_path)
  145. shutil.copytree(root_folder, ydb_tmp_folder_path)
  146. platforms = [
  147. ("linux-x86_64", "default-linux-x86_64"),
  148. ("linux-aarch64", "default-linux-aarch64"),
  149. ("darwin-x86_64", "default-darwin-x86_64"),
  150. ("windows-x86_64", "default-win-x86_64"),
  151. ]
  152. generate_graph_for_platform_commands = []
  153. for platform, target_platform in platforms:
  154. print(f"Platform {platform} target platform {target_platform}")
  155. dump_export_path = f"{ydb_metadata_folder_path}/{platform}.conf"
  156. graph_export_path = f"{ydb_metadata_folder_path}/sem.{platform}.json"
  157. generate_dump_command = f"{root_folder}/scripts/generate_dump.sh {platform} {target_platform} > {dump_export_path}"
  158. print(f"Generate dump command {generate_dump_command}")
  159. subprocess.check_output(generate_dump_command, shell=True)
  160. # In original script there are targets kikimr/docs/ru/docs_oss ydb ydb/tests/oss/launch library/cpp/actors tools/rescompiler/bin
  161. generate_graph_command = f'{ymake_binary_path} --build-root "{ydb_tmp_folder_path}" --config "{dump_export_path}"\
  162. --plugins-root "{plugins_folder_path}" --xs --xx --sem-graph --keep-going\
  163. ydb ydb/tests/oss/launch library/cpp/actors tools/rescompiler/bin > {graph_export_path}'
  164. print(f"Generate graph command {generate_graph_command}")
  165. generate_graph_for_platform_commands.append((platform, generate_graph_command))
  166. errors_for_platform = []
  167. with multiprocessing.Pool(len(generate_graph_for_platform_commands)) as pool:
  168. errors_for_platform = pool.map(
  169. generate_graph_for_platform, generate_graph_for_platform_commands
  170. )
  171. for index, (platform, target_platform) in enumerate(platforms):
  172. errors_for_platform_size = len(errors_for_platform[index])
  173. if errors_for_platform_size == 0:
  174. continue
  175. print(
  176. f"Found {errors_for_platform_size} errors for platform {platform}",
  177. file=sys.stderr,
  178. )
  179. for error in errors_for_platform[index]:
  180. print(error, file=sys.stderr)
  181. sys.exit(1)
  182. yexport_command = f"{yexport_binary_path} --export-root \"{ydb_tmp_folder_path}\" --target YDB \
  183. --semantic-graph \"{ydb_metadata_folder_path + '/sem.linux-x86_64.json'}\" --platforms linux-x86_64 \
  184. --semantic-graph \"{ydb_metadata_folder_path + '/sem.linux-aarch64.json'}\" --platforms linux-aarch64 \
  185. --semantic-graph \"{ydb_metadata_folder_path + '/sem.darwin-x86_64.json'}\" --platforms darwin-x86_64 \
  186. --semantic-graph \"{ydb_metadata_folder_path + '/sem.windows-x86_64.json'}\" --platforms windows-x86_64"
  187. print(f"yexport command {yexport_command}")
  188. yexport_output = subprocess.check_output(
  189. yexport_command, stderr=subprocess.STDOUT, shell=True
  190. ).decode("utf-8")
  191. if debug:
  192. print("yexport output")
  193. print(yexport_output)
  194. rsync_command = f'rsync --recursive --delete --perms\
  195. --exclude .git --exclude contrib --exclude library/cpp/actors\
  196. "{ydb_tmp_folder_path}/" "{root_folder}/"'
  197. print(f"rsync command {rsync_command}")
  198. subprocess.check_output(rsync_command, shell=True)
  199. sys.exit(0)