llvm_tools.bzl 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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 automate working with LLVM's CLI tools."""
  5. load("//bazel/cc_rules:defs.bzl", "cc_library")
  6. # The main LLVM command line tools, including their "primary" name, binary name,
  7. # and the library dependency required to use them.
  8. LLVM_MAIN_TOOLS = {
  9. "ar": struct(bin_name = "llvm-ar", lib = "@llvm-project//llvm:llvm-ar-lib"),
  10. "cgdata": struct(bin_name = "llvm-cgdata", lib = "@llvm-project//llvm:llvm-cgdata-lib"),
  11. "cxxfilt": struct(bin_name = "llvm-cxxfilt", lib = "@llvm-project//llvm:llvm-cxxfilt-lib"),
  12. "debuginfod-find": struct(bin_name = "llvm-debuginfod-find", lib = "@llvm-project//llvm:llvm-debuginfod-find-lib"),
  13. "dsymutil": struct(bin_name = "dsymutil", lib = "@llvm-project//llvm:dsymutil-lib"),
  14. "dwp": struct(bin_name = "llvm-dwp", lib = "@llvm-project//llvm:llvm-dwp-lib"),
  15. "gsymutil": struct(bin_name = "llvm-gsymutil", lib = "@llvm-project//llvm:llvm-gsymutil-lib"),
  16. "ifs": struct(bin_name = "llvm-ifs", lib = "@llvm-project//llvm:llvm-ifs-lib"),
  17. "libtool-darwin": struct(bin_name = "llvm-libtool-darwin", lib = "@llvm-project//llvm:llvm-libtool-darwin-lib"),
  18. "lipo": struct(bin_name = "llvm-lipo", lib = "@llvm-project//llvm:llvm-lipo-lib"),
  19. "ml": struct(bin_name = "llvm-ml", lib = "@llvm-project//llvm:llvm-ml-lib"),
  20. "mt": struct(bin_name = "llvm-mt", lib = "@llvm-project//llvm:llvm-mt-lib"),
  21. "nm": struct(bin_name = "llvm-nm", lib = "@llvm-project//llvm:llvm-nm-lib"),
  22. "objcopy": struct(bin_name = "llvm-objcopy", lib = "@llvm-project//llvm:llvm-objcopy-lib"),
  23. "objdump": struct(bin_name = "llvm-objdump", lib = "@llvm-project//llvm:llvm-objdump-lib"),
  24. "rc": struct(bin_name = "llvm-rc", lib = "@llvm-project//llvm:llvm-rc-lib"),
  25. "readobj": struct(bin_name = "llvm-readobj", lib = "@llvm-project//llvm:llvm-readobj-lib"),
  26. "sancov": struct(bin_name = "sancov", lib = "@llvm-project//llvm:sancov-lib"),
  27. "size": struct(bin_name = "llvm-size", lib = "@llvm-project//llvm:llvm-size-lib"),
  28. "symbolizer": struct(bin_name = "llvm-symbolizer", lib = "@llvm-project//llvm:llvm-symbolizer-lib"),
  29. }
  30. # A collection of additional alias names that should be available for the main
  31. # tools. The key is the main tool with the support for these names, followed by
  32. # a list of the aliased names.
  33. #
  34. # Note that we don't track separate binary names for the alias names as those
  35. # are always formed by prepending `llvm-` for the aliases.
  36. LLVM_TOOL_ALIASES = {
  37. "ar": ["ranlib", "lib", "dlltool"],
  38. "objcopy": ["bitcode-strip", "install-name-tool", "strip"],
  39. "objdump": ["otool"],
  40. "rc": ["windres"],
  41. "readobj": ["readelf"],
  42. "symbolizer": ["addr2line"],
  43. }
  44. _DEF_FILE_TEMPLATE = """
  45. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  46. // Exceptions. See /LICENSE for license information.
  47. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  48. //
  49. // This is a generated X-macro header for defining LLVM tools. It does not use
  50. // `#include` guards, and instead is designed to be `#include`ed after the
  51. // x-macro is defined in order for its inclusion to expand to the desired
  52. // output. Macro definitions are cleaned up at the end of this file.
  53. //
  54. // Each X-macro takes four arguments:
  55. // - `Id` is the identifier-shaped PascalCased tool name.
  56. // - `Name` is a string literal of the tool name.
  57. // - `BinName` is a string literal of the binary name of the tool when installed
  58. // as a stand-alone command line tool.
  59. // - `MainFn` is the function symbol name used to run the tool as-if its `main`.
  60. //
  61. // There are three X-macros available:
  62. // - `CARBON_LLVM_TOOL` is available for every tool.
  63. // - `CARBON_LLVM_MAIN_TOOL` is available for each tool with a distinct
  64. // `MainFn` symbol name.
  65. // - `CARBON_LLVM_ALIAS_TOOL` is available for each tool that is an alias of
  66. // some other tool. It's `MainFn` will be the alias-target symbol name.
  67. //
  68. // See toolchain/driver/llvm_tools.bzl for more details.
  69. #ifndef CARBON_LLVM_TOOL
  70. #define CARBON_LLVM_TOOL(Id, Name, BinName, MainFn)
  71. #endif
  72. #ifndef CARBON_LLVM_MAIN_TOOL
  73. #define CARBON_LLVM_MAIN_TOOL(Id, Name, BinName, MainFn) \\
  74. CARBON_LLVM_TOOL(Id, Name, BinName, MainFn)
  75. #endif
  76. #ifndef CARBON_LLVM_ALIAS_TOOL
  77. #define CARBON_LLVM_ALIAS_TOOL(Id, Name, BinName, MainFn) \\
  78. CARBON_LLVM_TOOL(Id, Name, BinName, MainFn)
  79. #endif
  80. {}
  81. #undef CARBON_LLVM_TOOL
  82. #undef CARBON_LLVM_MAIN_TOOL
  83. #undef CARBON_LLVM_ALIAS_TOOL
  84. """
  85. _DEF_MACRO_TEMPLATE = """
  86. CARBON_LLVM_{kind}TOOL({id}, "{name}", "{bin_name}", {main_fn})
  87. """.strip()
  88. def _build_def_macro(kind, name, bin_name, main_info):
  89. id = "".join([w.title() for w in name.split("-")])
  90. main_fn = main_info.bin_name.replace("-", "_") + "_main"
  91. return _DEF_MACRO_TEMPLATE.format(
  92. kind = kind,
  93. id = id,
  94. name = name,
  95. bin_name = bin_name,
  96. main_fn = main_fn,
  97. )
  98. def _generate_llvm_tools_def_rule(ctx):
  99. def_lines = []
  100. for name, tool_info in LLVM_MAIN_TOOLS.items():
  101. def_lines.append(_build_def_macro("MAIN_", name, tool_info.bin_name, tool_info))
  102. for target, aliases in LLVM_TOOL_ALIASES.items():
  103. tool_info = LLVM_MAIN_TOOLS[target]
  104. for alias in aliases:
  105. bin_name = "llvm-" + alias
  106. def_lines.append(_build_def_macro("ALIAS_", alias, bin_name, tool_info))
  107. def_file = ctx.actions.declare_file(ctx.label.name)
  108. ctx.actions.write(def_file, _DEF_FILE_TEMPLATE.format("\n".join(def_lines)))
  109. return [DefaultInfo(files = depset([def_file]))]
  110. generate_llvm_tools_def_rule = rule(
  111. implementation = _generate_llvm_tools_def_rule,
  112. attrs = {},
  113. )
  114. def generate_llvm_tools_def(name, out, **kwargs):
  115. """Generates the LLVM tools `.def` file.
  116. This first generates the `.def` file into the `out` filename, and then
  117. synthesizes a `cc_library` rule exporting that file in its `textual_hdrs`.
  118. The `cc_library` rule name is the provided `name` and should be depended on
  119. by code that includes the generated file. The `kwargs` are expanded into the
  120. `cc_library` in case other attributes need to be configured there.
  121. The two-step process is necessary to avoid trying to compile or otherwise
  122. process the generated file as something other than a textual header.
  123. """
  124. generate_llvm_tools_def_rule(name = out)
  125. cc_library(
  126. name = name,
  127. textual_hdrs = [out],
  128. **kwargs
  129. )