runtimes_build_info.bzl 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. """Provides variables and rules to work with Clang's runtime library sources.
  5. These are organized into groups based on the Clang runtimes providing them and
  6. how they are built:
  7. - CRT: The C language runtimes not provided by the C standard library, currently
  8. just infrastructure for global initialization and teardown.
  9. - Builtins: The compiler builtins library mirroring `libgcc` that provides
  10. function definitions for operations not reliably available in hardware but
  11. needed by Clang.
  12. - Libc++ and libc++abi: The C++ standard library and its ABI components.
  13. - Libunwind: The unwinding library.
  14. Future runtimes we plan to add support for but not yet included:
  15. - Sanitizers
  16. - Profiling runtimes
  17. """
  18. load("@llvm-project//:vars.bzl", "LLVM_VERSION_MAJOR")
  19. load("@llvm-project//compiler-rt:compiler-rt.bzl", "builtins_copts", "crt_copts")
  20. load("@llvm-project//libcxx:libcxx_library.bzl", "libcxx_and_abi_copts")
  21. load("@llvm-project//libunwind:libunwind_library.bzl", "libunwind_copts")
  22. load("//bazel/cc_rules:defs.bzl", "cc_library")
  23. CRT_FILES = {
  24. "crtbegin_src": "@llvm-project//compiler-rt:builtins_crtbegin_src",
  25. "crtend_src": "@llvm-project//compiler-rt:builtins_crtend_src",
  26. }
  27. BUILTINS_SRCS_FILEGROUPS = [
  28. "@llvm-project//compiler-rt:builtins_aarch64_srcs",
  29. "@llvm-project//compiler-rt:builtins_i386_srcs",
  30. "@llvm-project//compiler-rt:builtins_x86_64_srcs",
  31. ]
  32. BUILTINS_TEXTUAL_SRCS_FILEGROUPS = [
  33. "@llvm-project//compiler-rt:builtins_aarch64_textual_srcs",
  34. "@llvm-project//compiler-rt:builtins_i386_textual_srcs",
  35. "@llvm-project//compiler-rt:builtins_x86_64_textual_srcs",
  36. ]
  37. RUNTIMES_HDRS_FILEGROUPS = [
  38. "@llvm-project//libc:libcxx_shared_headers_hdrs",
  39. "@llvm-project//libcxx:libcxx_hdrs",
  40. "@llvm-project//libcxxabi:libcxxabi_hdrs",
  41. "@llvm-project//libunwind:libunwind_hdrs",
  42. ]
  43. RUNTIMES_SRCS_FILEGROUPS = [
  44. "@llvm-project//libcxx:libcxx_linux_srcs",
  45. "@llvm-project//libcxx:libcxx_macos_srcs",
  46. "@llvm-project//libcxx:libcxx_win32_srcs",
  47. "@llvm-project//libcxxabi:libcxxabi_srcs",
  48. "@llvm-project//libunwind:libunwind_srcs",
  49. ]
  50. RUNTIMES_TEXTUAL_SRCS_FILEGROUPS = [
  51. "@llvm-project//libcxxabi:libcxxabi_textual_srcs",
  52. ]
  53. RUNTIMES_PREFIXES = {
  54. "libcxx_hdrs": "runtimes/libcxx/",
  55. "libcxx_linux_srcs": "runtimes/libcxx/",
  56. "libcxx_macos_srcs": "runtimes/libcxx/",
  57. "libcxx_shared_headers_hdrs": "runtimes/libc/internal/",
  58. "libcxx_win32_srcs": "runtimes/libcxx/",
  59. "libcxxabi_hdrs": "runtimes/libcxxabi/",
  60. "libcxxabi_srcs": "runtimes/libcxxabi/",
  61. "libcxxabi_textual_srcs": "runtimes/libcxxabi/",
  62. "libunwind_hdrs": "runtimes/libunwind/",
  63. "libunwind_srcs": "runtimes/libunwind/",
  64. }
  65. def _get_name(target):
  66. return target.split(":")[1]
  67. def _format_one_per_line(list):
  68. return "\n" + "\n".join([
  69. ' "{0}",'.format(item)
  70. for item in list
  71. ]) + "\n"
  72. def _builtins_path(file):
  73. """Returns the install path for a file in CompilerRT's builtins library."""
  74. path = file.path
  75. # Skip to the relative path below the workspace root.
  76. path = path.rpartition(file.owner.workspace_root + "/")[2]
  77. # And now we can predictably remove the `compiler-rt/lib` prefix.
  78. path = path.removeprefix("compiler-rt/lib/")
  79. if not path.startswith("builtins/"):
  80. fail("Not a builtins-relative path for: {0}".format(file.path))
  81. return "runtimes/" + path
  82. def _runtimes_path(file):
  83. """Returns the install path for a file in a normal runtimes library."""
  84. return file.owner.name
  85. def _get_path(file_attr, to_path_fn):
  86. files = file_attr[DefaultInfo].files.to_list()
  87. if len(files) > 1:
  88. fail("Expected a single file and got {0} files.".format(len(files)))
  89. return '"{0}"'.format(to_path_fn(files[0]))
  90. def _get_paths(files_attr, to_path_fn, prefix = ""):
  91. files = []
  92. for src in files_attr:
  93. files.extend(src[DefaultInfo].files.to_list())
  94. files.extend(src[DefaultInfo].default_runfiles.files.to_list())
  95. return _format_one_per_line([
  96. "{0}{1}".format(prefix, to_path_fn(f))
  97. for f in files
  98. ])
  99. def _get_substitutions(ctx):
  100. key_attr = lambda k: getattr(ctx.attr, "_" + k)
  101. return {
  102. "BUILTINS_COPTS": _format_one_per_line(builtins_copts),
  103. "CRT_COPTS": _format_one_per_line(crt_copts),
  104. "LIBCXX_AND_ABI_COPTS": _format_one_per_line(libcxx_and_abi_copts),
  105. "LIBUNWIND_COPTS": _format_one_per_line(libunwind_copts),
  106. "LLVM_VERSION_MAJOR": LLVM_VERSION_MAJOR,
  107. } | {
  108. k.upper(): _get_path(key_attr(k), _builtins_path)
  109. for k in CRT_FILES.keys()
  110. } | {
  111. name.upper(): _get_paths(key_attr(name), _builtins_path)
  112. for name in [_get_name(g) for g in (
  113. BUILTINS_SRCS_FILEGROUPS + BUILTINS_TEXTUAL_SRCS_FILEGROUPS
  114. )]
  115. } | {
  116. # Other runtimes are installed under separate directories named the
  117. # same as their key.
  118. name.upper(): _get_paths(
  119. key_attr(name),
  120. _runtimes_path,
  121. RUNTIMES_PREFIXES[name],
  122. )
  123. for name in [_get_name(g) for g in (
  124. RUNTIMES_HDRS_FILEGROUPS + RUNTIMES_SRCS_FILEGROUPS +
  125. RUNTIMES_TEXTUAL_SRCS_FILEGROUPS
  126. )]
  127. }
  128. _common_runtimes_rule_attrs = {
  129. "_" + k: attr.label(default = v, allow_single_file = True)
  130. for k, v in CRT_FILES.items()
  131. } | {
  132. "_" + _get_name(g): attr.label_list(default = [g], allow_files = True)
  133. for g in (
  134. BUILTINS_SRCS_FILEGROUPS +
  135. BUILTINS_TEXTUAL_SRCS_FILEGROUPS +
  136. RUNTIMES_HDRS_FILEGROUPS +
  137. RUNTIMES_SRCS_FILEGROUPS +
  138. RUNTIMES_TEXTUAL_SRCS_FILEGROUPS
  139. )
  140. }
  141. def _generate_runtimes_build_info_h_rule(ctx):
  142. h_file = ctx.actions.declare_file(ctx.label.name)
  143. ctx.actions.expand_template(
  144. template = ctx.file._template_file,
  145. output = h_file,
  146. substitutions = _get_substitutions(ctx),
  147. )
  148. return [DefaultInfo(files = depset([h_file]))]
  149. generate_runtimes_build_info_h = rule(
  150. implementation = _generate_runtimes_build_info_h_rule,
  151. attrs = _common_runtimes_rule_attrs | {
  152. "_template_file": attr.label(
  153. default = "runtimes_build_info.tpl.h",
  154. allow_single_file = True,
  155. ),
  156. },
  157. )
  158. def generate_runtimes_build_info_cc_library(name, deps = [], **kwargs):
  159. """Generates a `runtimes_build_info.h` header and a `cc_library` rule.
  160. This first generates the header file with variables describing the runtimes
  161. build info from Clang, and then a `cc_library` that exports that header.
  162. The `cc_library` rule name is the provided `name` and should be depended on
  163. by code that includes the generated header. The `kwargs` are expanded into
  164. the `cc_library` in case other attributes need to be configured there.
  165. """
  166. generate_runtimes_build_info_h(name = "runtimes_build_info.h")
  167. cc_library(
  168. name = name,
  169. hdrs = ["runtimes_build_info.h"],
  170. deps = [
  171. # For StringRef.h
  172. "@llvm-project//llvm:Support",
  173. ] + deps,
  174. **kwargs
  175. )
  176. def _generate_runtimes_build_vars_rule(ctx):
  177. file = ctx.actions.declare_file(ctx.label.name)
  178. ctx.actions.expand_template(
  179. template = ctx.file._template_file,
  180. output = file,
  181. substitutions = _get_substitutions(ctx),
  182. )
  183. return [DefaultInfo(files = depset([file]))]
  184. generate_runtimes_build_vars = rule(
  185. implementation = _generate_runtimes_build_vars_rule,
  186. attrs = _common_runtimes_rule_attrs | {
  187. "_template_file": attr.label(
  188. default = "runtimes_build_vars.tpl.bzl",
  189. allow_single_file = True,
  190. ),
  191. },
  192. )