carbon_bootstrapping.bzl 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 for bootstrapping the Carbon toolchain."""
  5. load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
  6. load("//toolchain/runtimes:carbon_runtimes.bzl", "carbon_runtimes_build")
  7. load(
  8. ":carbon_cc_toolchain_config.bzl",
  9. "carbon_cc_toolchain",
  10. )
  11. def _bootstrap_transition_impl(_, attr):
  12. return {
  13. "//:bootstrap_stage": attr.stage,
  14. # Note that we need to either set or clear the runtimes build flag each
  15. # time we transition to a different bootstarp stage or we can
  16. # incorrectly inherit an unexpected state.
  17. "//:runtimes_build": attr.enable_runtimes_build,
  18. }
  19. _bootstrap_transition = transition(
  20. inputs = [],
  21. outputs = [
  22. "//:bootstrap_stage",
  23. "//:runtimes_build",
  24. ],
  25. implementation = _bootstrap_transition_impl,
  26. )
  27. def _filegroup_with_stage_impl(ctx):
  28. return [DefaultInfo(files = depset(ctx.files.srcs))]
  29. filegroup_with_stage = rule(
  30. implementation = _filegroup_with_stage_impl,
  31. attrs = {
  32. "enable_runtimes_build": attr.bool(default = False),
  33. "srcs": attr.label_list(mandatory = True, cfg = _bootstrap_transition),
  34. "stage": attr.int(mandatory = True),
  35. "_allowlist_function_transition": attr.label(
  36. default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
  37. ),
  38. },
  39. doc = "A filegroup whose sources are built using a specific toolchain stage.",
  40. )
  41. def _exec_filegroup_impl(ctx):
  42. return [DefaultInfo(files = depset(ctx.files.srcs))]
  43. _exec_filegroup = rule(
  44. implementation = _exec_filegroup_impl,
  45. attrs = {
  46. "srcs": attr.label_list(cfg = "exec"),
  47. },
  48. )
  49. def filegroup_with_stage_and_exec(name, srcs, stage, tags = []):
  50. """Wraps `filegroup_with_stage` with a conditional `exec` config transition.
  51. When `//:bootstrap_exec_config` is disabled, this works exactly like
  52. `filegroup_with_stage`. But when it is _enabled_, it also adds an `exec`
  53. config transition.
  54. """
  55. impl_tags = tags if "manual" in tags else tags + ["manual"]
  56. filegroup_with_stage(
  57. name = name + "_stage_only",
  58. srcs = srcs,
  59. stage = stage,
  60. tags = impl_tags,
  61. )
  62. _exec_filegroup(
  63. name = name + "_with_exec",
  64. srcs = [":" + name + "_stage_only"],
  65. tags = impl_tags,
  66. )
  67. native.alias(
  68. name = name,
  69. actual = select({
  70. "//:bootstrap_with_exec_config": ":" + name + "_with_exec",
  71. "//conditions:default": ":" + name + "_stage_only",
  72. }),
  73. tags = tags,
  74. )
  75. def _gen_cc_toolchain_paths_impl(ctx):
  76. cc_toolchain = find_cpp_toolchain(ctx)
  77. expanded_vars = [
  78. ctx.expand_make_variables("vars", v, {})
  79. for v in ctx.attr.vars
  80. ]
  81. out = ctx.actions.declare_file(ctx.attr.name + ".txt")
  82. ctx.actions.write(out, "\n".join(expanded_vars) + "\n")
  83. # Include all toolchain files in runfiles.
  84. runfiles = ctx.runfiles(files = [out]).merge(
  85. ctx.runfiles(transitive_files = cc_toolchain.all_files),
  86. )
  87. return [DefaultInfo(files = depset([out]), runfiles = runfiles)]
  88. gen_cc_toolchain_paths_with_stage = rule(
  89. implementation = _gen_cc_toolchain_paths_impl,
  90. attrs = {
  91. "enable_runtimes_build": attr.bool(default = False),
  92. "stage": attr.int(mandatory = True),
  93. "vars": attr.string_list(
  94. default = ["$(CC)", "$(AR)", "$(NM)", "$(OBJCOPY)", "$(STRIP)"],
  95. ),
  96. "_allowlist_function_transition": attr.label(
  97. default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
  98. ),
  99. "_cc_toolchain": attr.label(
  100. default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
  101. ),
  102. },
  103. toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
  104. cfg = _bootstrap_transition,
  105. )
  106. def carbon_bootstrapped_cc_toolchain(
  107. name,
  108. all_hdrs,
  109. base_files,
  110. clang_hdrs,
  111. platforms,
  112. runtimes_cfg,
  113. build_stage = 1,
  114. base_stage = 0,
  115. tags = []):
  116. """Create a bootstrapped Carbon `cc_toolchain` for the current target.
  117. This builds on `carbon_cc_toolchain`, but enables bootstrapping the produced
  118. toolchain from a base stage's toolchain.
  119. Args:
  120. name:
  121. The name of the toolchain suite to produce, used as the base of the
  122. names of each component of the toolchain suite.
  123. all_hdrs: A list of header files to include in the toolchain.
  124. base_files: A list of files to include in the toolchain.
  125. build_stage: The stage to use for the build files.
  126. base_stage: The stage to use for the base files.
  127. clang_hdrs: A list of header files to include in the toolchain.
  128. platforms: An array of (os, cpu) pairs to support in the toolchain.
  129. runtimes_cfg: The runtimes configuration to use in the toolchain.
  130. tags: Tags to apply to the toolchain.
  131. """
  132. impl_tags = tags if "manual" in tags else tags + ["manual"]
  133. filegroup_with_stage_and_exec(
  134. name = "{}_clang_hdrs".format(name),
  135. srcs = clang_hdrs,
  136. stage = base_stage,
  137. tags = impl_tags,
  138. )
  139. filegroup_with_stage_and_exec(
  140. name = "{}_base_files".format(name),
  141. srcs = base_files,
  142. stage = base_stage,
  143. tags = impl_tags,
  144. )
  145. filegroup_with_stage_and_exec(
  146. name = "{}_runtimes_compile_files".format(name),
  147. srcs = [
  148. ":{}_base_files".format(name),
  149. ":{}_clang_hdrs".format(name),
  150. ],
  151. stage = base_stage,
  152. tags = impl_tags,
  153. )
  154. filegroup_with_stage_and_exec(
  155. name = "{}_compile_files".format(name),
  156. srcs = [":{}_base_files".format(name)] + all_hdrs,
  157. stage = base_stage,
  158. tags = impl_tags,
  159. )
  160. # The runtimes build for this stage of the bootstrap is only compatible with
  161. # both the build stage and the runtimes build. We'll induce those below, and
  162. # constrain them here to avoid any other usage.
  163. carbon_runtimes_build(
  164. name = "{}_runtimes_build".format(name),
  165. config = runtimes_cfg,
  166. clang_hdrs = ["{}_clang_hdrs".format(name)],
  167. tags = impl_tags,
  168. )
  169. # Wrap the runtimes build in a filegroup that both sets the stage to the
  170. # build stage as well as enabling runtimes building. Note that this is _not_
  171. # the base stage -- runtimes should be built by the same stage, simply using
  172. # the runtimes build setting.
  173. filegroup_with_stage(
  174. name = "{}_runtimes".format(name),
  175. srcs = [":{}_runtimes_build".format(name)],
  176. stage = build_stage,
  177. enable_runtimes_build = True,
  178. tags = impl_tags,
  179. )
  180. carbon_cc_toolchain(
  181. name = name,
  182. platforms = platforms,
  183. base_files_target = ":{}_base_files".format(name),
  184. runtimes_compile_files_target = ":{}_runtimes_compile_files".format(name),
  185. compile_files_target = ":{}_compile_files".format(name),
  186. runtimes_target = ":{}_runtimes".format(name),
  187. extra_toolchain_settings = [":is_bootstrap_stage_{}".format(build_stage)],
  188. tags = tags,
  189. )