199 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"""Helper macros to configure the LLVM overlay project."""6 7# Directory of overlay files relative to WORKSPACE8DEFAULT_OVERLAY_PATH = "llvm-project-overlay"9 10DEFAULT_TARGETS = [11 "AArch64",12 "AMDGPU",13 "ARM",14 "AVR",15 "BPF",16 "Hexagon",17 "Lanai",18 "LoongArch",19 "Mips",20 "MSP430",21 "NVPTX",22 "PowerPC",23 "RISCV",24 "Sparc",25 "SPIRV",26 "SystemZ",27 "VE",28 "WebAssembly",29 "X86",30 "XCore",31]32 33def _overlay_directories(repository_ctx):34 src_path = repository_ctx.path(Label("@llvm-raw//:WORKSPACE")).dirname35 bazel_path = src_path.get_child("utils").get_child("bazel")36 overlay_path = bazel_path.get_child("llvm-project-overlay")37 script_path = bazel_path.get_child("overlay_directories.py")38 39 python_bin = repository_ctx.which("python3")40 if not python_bin:41 # Windows typically just defines "python" as python3. The script itself42 # contains a check to ensure python3.43 python_bin = repository_ctx.which("python")44 45 if not python_bin:46 fail("Failed to find python3 binary")47 48 cmd = [49 python_bin,50 script_path,51 "--src",52 src_path,53 "--overlay",54 overlay_path,55 "--target",56 ".",57 ]58 exec_result = repository_ctx.execute(cmd, timeout = 20)59 60 if exec_result.return_code != 0:61 fail(("Failed to execute overlay script: '{cmd}'\n" +62 "Exited with code {return_code}\n" +63 "stdout:\n{stdout}\n" +64 "stderr:\n{stderr}\n").format(65 cmd = " ".join([str(arg) for arg in cmd]),66 return_code = exec_result.return_code,67 stdout = exec_result.stdout,68 stderr = exec_result.stderr,69 ))70 71def _extract_cmake_settings(repository_ctx, llvm_cmake):72 # The list to be written to vars.bzl73 # `CMAKE_CXX_STANDARD` may be used from WORKSPACE for the toolchain.74 c = {75 "CMAKE_CXX_STANDARD": None,76 "LLVM_VERSION_MAJOR": None,77 "LLVM_VERSION_MINOR": None,78 "LLVM_VERSION_PATCH": None,79 "LLVM_VERSION_SUFFIX": None,80 }81 82 # It would be easier to use external commands like sed(1) and python.83 # For portability, the parser should run on Starlark.84 llvm_cmake_path = repository_ctx.path(Label("//:" + llvm_cmake))85 for line in repository_ctx.read(llvm_cmake_path).splitlines():86 # Extract "set ( FOO bar ... "87 setfoo = line.partition("(")88 if setfoo[1] != "(":89 continue90 if setfoo[0].strip().lower() != "set":91 continue92 93 # `kv` is assumed as \s*KEY\s+VAL\s*\).*94 # Typical case is like95 # LLVM_REQUIRED_CXX_STANDARD 17)96 # Possible case -- It should be ignored.97 # CMAKE_CXX_STANDARD ${...} CACHE STRING "...")98 kv = setfoo[2].strip()99 i = kv.find(" ")100 if i < 0:101 continue102 k = kv[:i]103 104 # Prefer LLVM_REQUIRED_CXX_STANDARD instead of CMAKE_CXX_STANDARD105 if k == "LLVM_REQUIRED_CXX_STANDARD":106 k = "CMAKE_CXX_STANDARD"107 c[k] = None108 if k not in c:109 continue110 111 # Skip if `CMAKE_CXX_STANDARD` is set with112 # `LLVM_REQUIRED_CXX_STANDARD`.113 # Then `v` will not be desired form, like "${...} CACHE"114 if c[k] != None:115 continue116 117 # Pick up 1st word as the value.118 # Note: It assumes unquoted word.119 v = kv[i:].strip().partition(")")[0].partition(" ")[0]120 c[k] = v121 122 # Synthesize `LLVM_VERSION` for convenience.123 c["LLVM_VERSION"] = "{}.{}.{}".format(124 c["LLVM_VERSION_MAJOR"],125 c["LLVM_VERSION_MINOR"],126 c["LLVM_VERSION_PATCH"],127 )128 129 c["PACKAGE_VERSION"] = "{}.{}.{}{}".format(130 c["LLVM_VERSION_MAJOR"],131 c["LLVM_VERSION_MINOR"],132 c["LLVM_VERSION_PATCH"],133 c["LLVM_VERSION_SUFFIX"],134 )135 136 return c137 138def _write_dict_to_file(repository_ctx, filepath, header, vars):139 # (fci + individual vars) + (fcd + dict items) + (fct)140 fci = header141 fcd = "\nllvm_vars={\n"142 fct = "}\n"143 144 for k, v in vars.items():145 fci += '{} = "{}"\n'.format(k, v)146 fcd += ' "{}": "{}",\n'.format(k, v)147 148 repository_ctx.file(filepath, content = fci + fcd + fct)149 150def _llvm_configure_impl(repository_ctx):151 _overlay_directories(repository_ctx)152 153 llvm_cmake = "llvm/CMakeLists.txt"154 vars = _extract_cmake_settings(155 repository_ctx,156 llvm_cmake,157 )158 159 # Grab version info and merge it with the other vars160 version = _extract_cmake_settings(161 repository_ctx,162 "cmake/Modules/LLVMVersion.cmake",163 )164 version = {k: v for k, v in version.items() if v != None}165 vars.update(version)166 167 _write_dict_to_file(168 repository_ctx,169 filepath = "vars.bzl",170 header = "# Generated from {}\n\n".format(llvm_cmake),171 vars = vars,172 )173 174 # Create a starlark file with the requested LLVM targets.175 llvm_targets = repository_ctx.attr.targets176 repository_ctx.file(177 "llvm/targets.bzl",178 content = "llvm_targets = " + str(llvm_targets),179 executable = False,180 )181 182 # Create a starlark file with the requested BOLT targets.183 bolt_targets = ["AArch64", "X86", "RISCV"] # Supported targets.184 bolt_targets = [t for t in llvm_targets if t in bolt_targets]185 repository_ctx.file(186 "bolt/targets.bzl",187 content = "bolt_targets = " + str(bolt_targets),188 executable = False,189 )190 191llvm_configure = repository_rule(192 implementation = _llvm_configure_impl,193 local = True,194 configure = True,195 attrs = {196 "targets": attr.string_list(default = DEFAULT_TARGETS),197 },198)199