llvm_tools.bzl 6.5 KB

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