clang_bootstrap.bzl 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. # Exceptions. See /LICENSE for license information.
  3. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. """Starlark rules to bootstrap Clang (and LLVM).
  5. These rules are loaded as part of the `WORKSPACE`, and used by
  6. `clang_configuration.bzl`. The llvm-project submodule is used for the build.
  7. """
  8. def _run(
  9. repository_ctx,
  10. cmd,
  11. timeout = 10,
  12. environment = {},
  13. quiet = True):
  14. """Runs the provided `cmd`, checks for failure, and returns the result."""
  15. exec_result = repository_ctx.execute(
  16. cmd,
  17. timeout = timeout,
  18. environment = environment,
  19. quiet = quiet,
  20. )
  21. if exec_result.return_code != 0:
  22. fail("Unable to run command successfully: %s" % str(cmd))
  23. return exec_result
  24. def _detect_system_clang(repository_ctx):
  25. """Detects whether a system-provided clang can be used.
  26. Returns a tuple of (is_clang, environment).
  27. """
  28. # If the user provides an explicit `CC` environment variable, use that as
  29. # the compiler.
  30. cc = repository_ctx.os.environ.get("CC")
  31. cxx = repository_ctx.os.environ.get("CXX")
  32. if cc or cxx:
  33. version_output = _run(repository_ctx, [cc, "--version"]).stdout
  34. return "clang" in version_output, {}
  35. # If we can build our Clang toolchain using a system-installed Clang, try
  36. # to do so.
  37. system_clang = repository_ctx.which("clang")
  38. if system_clang:
  39. return True, {
  40. "CC": str(system_clang),
  41. "CXX": str(system_clang) + "++",
  42. }
  43. return False, {}
  44. def _get_cmake_defines(repository_ctx, is_clang):
  45. """Returns a long list of cmake defines for the bootstrap."""
  46. modules_setting = "OFF"
  47. if is_clang:
  48. modules_setting = "ON"
  49. static_link_cxx = "ON"
  50. unstable_libcxx_abi = "ON"
  51. if repository_ctx.os.name.lower().startswith("mac os"):
  52. # macOS doesn't support the static C++ standard library linking. Turn
  53. # it off here, and disable the unstable libc++ ABI as we will also be
  54. # unable to use it later on.
  55. static_link_cxx = "OFF"
  56. unstable_libcxx_abi = "OFF"
  57. return [
  58. "-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;lld;libcxx;libcxxabi;compiler-rt;libunwind",
  59. "-DCMAKE_BUILD_TYPE=Release",
  60. "-DLLVM_ENABLE_ASSERTIONS=OFF",
  61. "-DLLVM_ENABLE_MODULES=" + modules_setting,
  62. "-DLLVM_STATIC_LINK_CXX_STDLIB=" + static_link_cxx,
  63. "-DLLVM_TARGETS_TO_BUILD=AArch64;X86",
  64. "-DLIBCXX_ABI_UNSTABLE=" + unstable_libcxx_abi,
  65. "-DLIBCXX_ENABLE_ASSERTIONS=OFF",
  66. "-DLIBCXXABI_ENABLE_ASSERTIONS=OFF",
  67. # Disable components of the build that we don't use while building Carbon.
  68. "-DCLANG_ENABLE_ARCMT=OFF",
  69. "-DCLANG_INCLUDE_TESTS=OFF",
  70. "-DCLANG_TOOL_APINOTES_TEST_BUILD=OFF",
  71. "-DCLANG_TOOL_ARCMT_TEST_BUILD=OFF",
  72. "-DCLANG_TOOL_CLANG_CHECK_BUILD=OFF",
  73. "-DCLANG_TOOL_CLANG_DIFF_BUILD=OFF",
  74. "-DCLANG_TOOL_CLANG_EXTDEF_MAPPING_BUILD=OFF",
  75. "-DCLANG_TOOL_CLANG_FUZZER_BUILD=OFF",
  76. "-DCLANG_TOOL_CLANG_IMPORT_TEST_BUILD=OFF",
  77. "-DCLANG_TOOL_CLANG_OFFLOAD_BUNDLER_BUILD=OFF",
  78. "-DCLANG_TOOL_CLANG_OFFLOAD_WRAPPER_BUILD=OFF",
  79. "-DCLANG_TOOL_CLANG_SCAN_DEPS_BUILD=OFF",
  80. "-DCLANG_TOOL_CLANG_SHLIB_BUILD=OFF",
  81. "-DCLANG_TOOL_C_ARCMT_TEST_BUILD=OFF",
  82. "-DCLANG_TOOL_C_INDEX_TEST_BUILD=OFF",
  83. "-DCLANG_TOOL_DIAGTOOL_BUILD=OFF",
  84. "-DCLANG_TOOL_LIBCLANG_BUILD=OFF",
  85. "-DCLANG_TOOL_SCAN_BUILD_BUILD=OFF",
  86. "-DCLANG_TOOL_SCAN_VIEW_BUILD=OFF",
  87. "-DLLVM_BUILD_UTILS=OFF",
  88. "-DLLVM_ENABLE_BINDINGS=OFF",
  89. "-DLLVM_ENABLE_LIBXML2=OFF",
  90. "-DLLVM_ENABLE_OCAMLDOC=OFF",
  91. "-DLLVM_INCLUDE_BENCHMARKS=OFF",
  92. "-DLLVM_INCLUDE_DOCS=OFF",
  93. "-DLLVM_INCLUDE_EXAMPLES=OFF",
  94. "-DLLVM_INCLUDE_GO_TESTS=OFF",
  95. "-DLLVM_INCLUDE_TESTS=OFF",
  96. "-DLLVM_INCLUDE_UTILS=OFF",
  97. "-DLLVM_TOOL_BUGPOINT_BUILD=OFF",
  98. "-DLLVM_TOOL_BUGPOINT_PASSES_BUILD=OFF",
  99. "-DLLVM_TOOL_DSYMUTIL_BUILD=OFF",
  100. "-DLLVM_TOOL_GOLD_BUILD=OFF",
  101. "-DLLVM_TOOL_LLC_BUILD=OFF",
  102. "-DLLVM_TOOL_LLI_BUILD=OFF",
  103. "-DLLVM_TOOL_LLVM_AS_BUILD=OFF",
  104. "-DLLVM_TOOL_LLVM_BCANALYZER_BUILD=OFF",
  105. "-DLLVM_TOOL_LLVM_CAT_BUILD=OFF",
  106. "-DLLVM_TOOL_LLVM_CFI_VERIFY_BUILD=OFF",
  107. "-DLLVM_TOOL_LLVM_CONFIG_BUILD=OFF",
  108. "-DLLVM_TOOL_LLVM_CVTRES_BUILD=OFF",
  109. "-DLLVM_TOOL_LLVM_CXXDUMP_BUILD=OFF",
  110. "-DLLVM_TOOL_LLVM_CXXFILT_BUILD=OFF",
  111. "-DLLVM_TOOL_LLVM_CXXMAP_BUILD=OFF",
  112. "-DLLVM_TOOL_LLVM_C_TEST_BUILD=OFF",
  113. "-DLLVM_TOOL_LLVM_DIFF_BUILD=OFF",
  114. "-DLLVM_TOOL_LLVM_DWARFDUMP_BUILD=OFF",
  115. "-DLLVM_TOOL_LLVM_ELFABI_BUILD=OFF",
  116. "-DLLVM_TOOL_LLVM_EXEGESIS_BUILD=OFF",
  117. "-DLLVM_TOOL_LLVM_EXTRACT_BUILD=OFF",
  118. "-DLLVM_TOOL_LLVM_GO_BUILD=OFF",
  119. "-DLLVM_TOOL_LLVM_GSYMUTIL_BUILD=OFF",
  120. "-DLLVM_TOOL_LLVM_IFS_BUILD=OFF",
  121. "-DLLVM_TOOL_LLVM_ISEL_FUZZER_BUILD=OFF",
  122. "-DLLVM_TOOL_LLVM_ITANIUM_DEMANGLE_FUZZER_BUILD=OFF",
  123. "-DLLVM_TOOL_LLVM_JITLINK_BUILD=OFF",
  124. "-DLLVM_TOOL_LLVM_JITLISTENER_BUILD=OFF",
  125. "-DLLVM_TOOL_LLVM_LIBTOOL_DARWIN_BUILD=OFF",
  126. "-DLLVM_TOOL_LLVM_LINK_BUILD=OFF",
  127. "-DLLVM_TOOL_LLVM_LIPO_BUILD=OFF",
  128. "-DLLVM_TOOL_LLVM_LTO2_BUILD=OFF",
  129. "-DLLVM_TOOL_LLVM_LTO_BUILD=OFF",
  130. "-DLLVM_TOOL_LLVM_MCA_BUILD=OFF",
  131. "-DLLVM_TOOL_LLVM_MC_BUILD=OFF",
  132. "-DLLVM_TOOL_LLVM_ML_BUILD=OFF",
  133. "-DLLVM_TOOL_LLVM_MICROSOFT_DEMANGLE_FUZZER_BUILD=OFF",
  134. "-DLLVM_TOOL_LLVM_MT_BUILD=OFF",
  135. "-DLLVM_TOOL_LLVM_OPT_FUZZER_BUILD=OFF",
  136. "-DLLVM_TOOL_LLVM_PDBUTIL_BUILD=OFF",
  137. "-DLLVM_TOOL_LLVM_PROFDATA_BUILD=OFF",
  138. "-DLLVM_TOOL_LLVM_PROFGEN_BUILD=OFF",
  139. "-DLLVM_TOOL_LLVM_RC_BUILD=OFF",
  140. "-DLLVM_TOOL_LLVM_READOBJ_BUILD=OFF",
  141. "-DLLVM_TOOL_LLVM_REDUCE_BUILD=OFF",
  142. "-DLLVM_TOOL_LLVM_RTDYLD_BUILD=OFF",
  143. "-DLLVM_TOOL_LLVM_SHLIB_BUILD=OFF",
  144. "-DLLVM_TOOL_LLVM_SIZE_BUILD=OFF",
  145. "-DLLVM_TOOL_LLVM_SPECIAL_CASE_LIST_FUZZER_BUILD=OFF",
  146. "-DLLVM_TOOL_LLVM_SPLIT_BUILD=OFF",
  147. "-DLLVM_TOOL_LLVM_STRESS_BUILD=OFF",
  148. "-DLLVM_TOOL_LLVM_STRINGS_BUILD=OFF",
  149. "-DLLVM_TOOL_LLVM_XRAY_BUILD=OFF",
  150. "-DLLVM_TOOL_LLVM_YAML_NUMERIC_PARSER_FUZZER_BUILD=OFF",
  151. "-DLLVM_TOOL_LLVM_YAML_PARSER_FUZZER_BUILD=OFF",
  152. "-DLLVM_TOOL_LTO_BUILD=OFF",
  153. "-DLLVM_TOOL_OBJ2YAML_BUILD=OFF",
  154. "-DLLVM_TOOL_OPT_BUILD=OFF",
  155. "-DLLVM_TOOL_OPT_VIEWER_BUILD=OFF",
  156. "-DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF",
  157. "-DLLVM_TOOL_SPLIT_FILE_BUILD=OFF",
  158. "-DLLVM_TOOL_VERIFY_USELISTORDER_BUILD=OFF",
  159. "-DLLVM_TOOL_YAML2OBJ_BUILD=OFF",
  160. ]
  161. def _bootstrap_clang_toolchain_impl(repository_ctx):
  162. """Returns the path a bootstrapped Clang executable.
  163. This bootstraps Clang and the rest of the LLVM toolchain from the LLVM
  164. submodule.
  165. """
  166. repository_ctx.report_progress("Configuring Clang toolchain bootstrap...")
  167. is_clang, environment = _detect_system_clang(repository_ctx)
  168. cmake = repository_ctx.which("cmake")
  169. if not cmake:
  170. fail("`cmake` not found: is it installed?")
  171. ninja = repository_ctx.which("ninja")
  172. if not ninja:
  173. fail("`ninja` not found: is it installed?")
  174. workspace_dir = repository_ctx.path(repository_ctx.attr._workspace).dirname
  175. llvm_dir = repository_ctx.path("%s/third_party/llvm-project/llvm" %
  176. workspace_dir)
  177. repository_ctx.report_progress(
  178. "Running CMake for the Clang toolchain build...",
  179. )
  180. cmake_args = [cmake, "-G", "Ninja", str(llvm_dir)]
  181. cmake_args += _get_cmake_defines(repository_ctx, is_clang)
  182. _run(
  183. repository_ctx,
  184. cmake_args,
  185. timeout = 600,
  186. environment = environment,
  187. # This is very slow, so print output as a form of progress.
  188. quiet = False,
  189. )
  190. # Run ninja for the final build.
  191. repository_ctx.report_progress("Building the Clang toolchain...")
  192. _run(
  193. repository_ctx,
  194. [ninja],
  195. timeout = 10800,
  196. # This is very slow, so print output as a form of progress.
  197. quiet = False,
  198. )
  199. # Create an empty BUILD file to mark the package. The files are used without
  200. # Bazel labels directly pointing at them.
  201. repository_ctx.file("BUILD", content = "")
  202. bootstrap_clang_toolchain = repository_rule(
  203. implementation = _bootstrap_clang_toolchain_impl,
  204. configure = True,
  205. attrs = {
  206. # We use a label pointing at the workspace file to compute the
  207. # workspace directory.
  208. "_workspace": attr.label(
  209. default = Label("//:WORKSPACE"),
  210. allow_single_file = True,
  211. ),
  212. },
  213. environ = ["CC", "CXX"],
  214. )