184 lines · plain
1# This file is licensed under the Apache License v2.0 with LLVM Exceptions.2# See https://llvm.org/LICENSE.txt for license information.3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception4 5"""Configuration for the llvm-driver tool."""6 7load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")8load("@bazel_skylib//rules:expand_template.bzl", "expand_template")9load("@rules_cc//cc:defs.bzl", "CcInfo", "cc_binary")10 11# Mapping from every tool to the cc_library that implements the tool's entrypoint.12_TOOLS = {13 "clang-scan-deps": "//clang:clang-scan-deps-lib",14 "clang": "//clang:clang-driver",15 "dsymutil": "//llvm:dsymutil-lib",16 "lld": "//lld:lld-lib",17 "llvm-ar": "//llvm:llvm-ar-lib",18 "llvm-cgdata": "//llvm:llvm-cgdata-lib",19 "llvm-cxxfilt": "//llvm:llvm-cxxfilt-lib",20 "llvm-debuginfod-find": "//llvm:llvm-debuginfod-find-lib",21 "llvm-dwp": "//llvm:llvm-dwp-lib",22 "llvm-gsymutil": "//llvm:llvm-gsymutil-lib",23 "llvm-ifs": "//llvm:llvm-ifs-lib",24 "llvm-libtool-darwin": "//llvm:llvm-libtool-darwin-lib",25 "llvm-lipo": "//llvm:llvm-lipo-lib",26 "llvm-ml": "//llvm:llvm-ml-lib",27 "llvm-mt": "//llvm:llvm-mt-lib",28 "llvm-nm": "//llvm:llvm-nm-lib",29 "llvm-objcopy": "//llvm:llvm-objcopy-lib",30 "llvm-objdump": "//llvm:llvm-objdump-lib",31 "llvm-rc": "//llvm:llvm-rc-lib",32 "llvm-readobj": "//llvm:llvm-readobj-lib",33 "llvm-size": "//llvm:llvm-size-lib",34 "llvm-symbolizer": "//llvm:llvm-symbolizer-lib",35 "sancov": "//llvm:sancov-lib",36}37 38# Tools automatically get their own name as an alias, but there may be additional39# aliases for a given tool.40_EXTRA_ALIASES = {41 "clang": ["clang++", "clang-cl", "clang-cpp"],42 "lld": ["ld", "lld-link", "ld.lld", "ld64.lld", "wasm-ld"],43 "llvm-ar": ["ranlib", "lib", "dlltool"],44 "llvm-cxxfilt": ["c++filt"],45 "llvm-objcopy": ["bitcode-strip", "install-name-tool", "strip"],46 "llvm-objdump": ["otool"],47 "llvm-rc": ["windres"],48 "llvm-readobj": ["readelf"],49 "llvm-symbolizer": ["addr2line"],50}51 52def _validated_string_list_flag_impl(ctx):53 invalid_values = [v for v in ctx.build_setting_value if v not in ctx.attr.values]54 if invalid_values:55 fail("Tool(s) [{}] are not in the known list of tools: {}".format(56 ", ".join(invalid_values),57 ", ".join(ctx.attr.values),58 ))59 return BuildSettingInfo(value = ctx.build_setting_value)60 61# Like string_list_flag, but with the validation that string_flag provides.62_validated_string_list_flag = rule(63 implementation = _validated_string_list_flag_impl,64 build_setting = config.string_list(flag = True),65 attrs = {66 "values": attr.string_list(67 doc = "The list of allowed values for this setting. An error is raised if any other value is given.",68 ),69 },70 doc = "A string list-typed build setting that can be set on the command line",71)72 73def generate_driver_selects(name):74 """Generates flags and config settings to configure the tool list.75 76 By default, all supported tools are included in the "llvm" driver binary.77 To build only a subset, specify just the subset you want as the flag.78 For example, to produce a binary with just llvm-nm and llvm-size, run:79 80 $ bazel build \81 --@llvm-project//llvm:driver-tools=llvm-nm,llvm-size \82 @llvm-project//llvm:llvm83 84 Note: this assumes the flag name is "driver-tools" by being invoked as:85 generate_driver_selects(name = "driver-tools")86 87 Args:88 name: the name of the flag that configures which tools are included.89 """90 91 _validated_string_list_flag(92 name = name,93 build_setting_default = _TOOLS.keys(),94 values = _TOOLS.keys(),95 )96 for tool in _TOOLS.keys():97 native.config_setting(98 name = "{}-include-{}".format(name, tool),99 flag_values = {name: tool},100 )101 102def select_driver_tools(flag):103 """Produce a list of tool deps based on generate_driver_selects().104 105 Args:106 flag: name that was used for generate_driver_selects().107 Returns:108 List of tool deps based on generate_driver_selects().109 """110 tools = []111 for tool, target in _TOOLS.items():112 tools += select({113 "{}-include-{}".format(flag, tool): [target],114 "//conditions:default": [],115 })116 return tools117 118def _generate_driver_tools_def_impl(ctx):119 # Depending on how the LLVM build files are included,120 # it may or may not have the @llvm-project repo prefix.121 # Compare just on the name. We could also include the package,122 # but the name itself is unique in practice.123 label_to_name = {Label(v).name: k for k, v in _TOOLS.items()}124 125 # Reverse sort by the *main* tool name, but keep aliases together.126 # This is consistent with how tools/llvm-driver/CMakeLists.txt does it,127 # and this makes sure that more specific tools are checked first.128 # For example, "clang-scan-deps" should not match "clang".129 tools = [label_to_name[tool.label.name] for tool in ctx.attr.driver_tools]130 tool_alias_pairs = []131 for tool_name in reversed(tools):132 tool_alias_pairs.append((tool_name, tool_name))133 for extra_alias in _EXTRA_ALIASES.get(tool_name, []):134 tool_alias_pairs.append((tool_name, extra_alias))135 136 lines = [137 'LLVM_DRIVER_TOOL("{alias}", {tool})'.format(138 tool = tool_name.replace("-", "_"),139 alias = alias.removeprefix("llvm-"),140 )141 for (tool_name, alias) in tool_alias_pairs142 ]143 lines.append("#undef LLVM_DRIVER_TOOL")144 145 ctx.actions.write(146 output = ctx.outputs.out,147 content = "\n".join(lines),148 )149 150generate_driver_tools_def = rule(151 implementation = _generate_driver_tools_def_impl,152 doc = """Generate a list of LLVM_DRIVER_TOOL macros.153See tools/llvm-driver/CMakeLists.txt for the reference implementation.""",154 attrs = {155 "driver_tools": attr.label_list(156 doc = "List of tools to include in the generated header. Use select_driver_tools() to provide this.",157 providers = [CcInfo],158 ),159 "out": attr.output(160 doc = "Name of the generated .def output file.",161 mandatory = True,162 ),163 },164)165 166def llvm_driver_cc_binary(167 name,168 deps = None,169 **kwargs):170 """cc_binary wrapper for binaries using the llvm-driver template."""171 expand_template(172 name = "_gen_" + name,173 out = name + "-driver.cpp",174 substitutions = {"@TOOL_NAME@": name.replace("-", "_")},175 template = "//llvm:cmake/modules/llvm-driver-template.cpp.in",176 )177 deps = deps or []178 cc_binary(179 name = name,180 srcs = [name + "-driver.cpp"],181 deps = deps + ["//llvm:Support"],182 **kwargs183 )184