1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Defines a cc toolchain for kernel build, based on clang.""" 16 17load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "CPP_TOOLCHAIN_TYPE") 18load( 19 "@kernel_toolchain_info//:dict.bzl", 20 "VARS", 21) 22load(":clang_config.bzl", "clang_config") 23 24def _clang_toolchain_internal( 25 name, 26 clang_version, 27 arch, 28 clang_pkg, 29 linker_files = None, 30 sysroot_label = None, 31 sysroot_dir = None, 32 bin_files = None, 33 bin_dirs = None, 34 lib_files = None, 35 lib_dirs = None, 36 target = None, 37 extra_compatible_with = None, 38 extra_features = None, 39 dynamic_runtime_lib = None, 40 static_runtime_lib = None, 41 static_link_cpp_runtimes = None): 42 """Defines a cc toolchain for kernel build, based on clang. 43 44 Args: 45 name: name of the toolchain 46 clang_version: value of `CLANG_VERSION`, e.g. `r475365b`. 47 arch: an ArchInfo object to look up extra kwargs. 48 clang_pkg: Label to any target in the clang toolchain package. 49 50 This is used as an anchor to locate other targets in the package. 51 Name of the label is ignored. 52 linker_files: Additional dependencies to the linker 53 sysroot_label: Label to a list of files from sysroot 54 sysroot_dir: Label containing a single directory to sysroot. 55 bin_files: Files for `-B` 56 bin_dirs: Directory to be set in `-B` 57 lib_files: Files for `-L` 58 lib_dirs: Directory to be set in `-L` 59 target: The `--target` option provided to clang. This is usually `NDK_TRIPLE`. 60 extra_compatible_with: Extra `exec_compatible_with` / `target_compatible_with`. 61 extra_features: Extra features enabled on this toolchain 62 dynamic_runtime_lib: pass to cc_toolchain 63 static_runtime_lib: pass to cc_toolchain 64 static_link_cpp_runtimes: If true, enable "static_link_cpp_runtimes" feature but 65 disable "static-libgcc". 66 """ 67 68 sysroot_labels = [] 69 if sysroot_label != None: 70 sysroot_labels.append(sysroot_label) 71 72 if linker_files == None: 73 linker_files = [] 74 75 if bin_files == None: 76 bin_files = [] 77 78 if lib_files == None: 79 lib_files = [] 80 81 if extra_compatible_with == None: 82 extra_compatible_with = [] 83 84 clang_pkg = native.package_relative_label(clang_pkg) 85 clang_includes = clang_pkg.relative(":includes") 86 87 # Technically we can split the binaries into those for compiler, linker 88 # etc., but since these binaries are usually updated together, it is okay 89 # to use a superset here. 90 clang_all_binaries = clang_pkg.relative(":binaries") 91 92 # Individual binaries 93 # From _setup_env.sh 94 # HOSTCC=clang 95 # HOSTCXX=clang++ 96 # CC=clang 97 # LD=ld.lld 98 # AR=llvm-ar 99 # NM=llvm-nm 100 # OBJCOPY=llvm-objcopy 101 # OBJDUMP=llvm-objdump 102 # OBJSIZE=llvm-size 103 # READELF=llvm-readelf 104 # STRIP=llvm-strip 105 # 106 # Note: ld.lld does not recognize --target etc. from android.bzl, 107 # so just use clang directly 108 clang = clang_pkg.relative(":bin/clang") 109 clang_plus_plus = clang_pkg.relative(":bin/clang++") 110 111 # TODO: Support building C++ device binaries. 112 # This requires adding "-static-libstdc++" to avoid dynamic linkage. 113 ld = clang_plus_plus if arch.target_os == "linux" else clang 114 strip = clang_pkg.relative(":bin/llvm-strip") 115 ar = clang_pkg.relative(":bin/llvm-ar") 116 objcopy = clang_pkg.relative(":bin/llvm-objcopy") 117 # cc_* rules doesn't seem to need nm, obj-dump, size, and readelf 118 119 native.filegroup( 120 name = name + "_compiler_files", 121 srcs = [ 122 clang_all_binaries, 123 clang_includes, 124 ] + sysroot_labels + bin_files, 125 ) 126 127 native.filegroup( 128 name = name + "_linker_files", 129 srcs = [clang_all_binaries] + sysroot_labels + linker_files + bin_files + lib_files, 130 ) 131 132 native.filegroup( 133 name = name + "_all_files", 134 srcs = [ 135 clang_all_binaries, 136 name + "_compiler_files", 137 name + "_linker_files", 138 ], 139 ) 140 141 clang_config( 142 name = name + "_clang_config", 143 clang_version = clang_version, 144 sysroot_dir = sysroot_dir, 145 bin_dirs = bin_dirs, 146 lib_dirs = lib_dirs, 147 target_cpu = arch.target_cpu, 148 target_os = arch.target_os, 149 target = target, 150 toolchain_identifier = name + "_clang_id", 151 clang = clang, 152 ld = ld, 153 clang_plus_plus = clang_plus_plus, 154 strip = strip, 155 ar = ar, 156 objcopy = objcopy, 157 extra_features = extra_features, 158 static_link_cpp_runtimes = static_link_cpp_runtimes, 159 ) 160 161 native.cc_toolchain( 162 name = name + "_cc_toolchain", 163 all_files = name + "_all_files", 164 ar_files = clang_all_binaries, 165 compiler_files = name + "_compiler_files", 166 dwp_files = clang_all_binaries, 167 linker_files = name + "_linker_files", 168 objcopy_files = clang_all_binaries, 169 strip_files = clang_all_binaries, 170 dynamic_runtime_lib = dynamic_runtime_lib, 171 static_runtime_lib = static_runtime_lib, 172 supports_param_files = False, 173 toolchain_config = name + "_clang_config", 174 toolchain_identifier = name + "_clang_id", 175 ) 176 177 target_compatible_with = [ 178 "@platforms//os:{}".format(arch.target_os), 179 "@platforms//cpu:{}".format(arch.target_cpu), 180 ] + extra_compatible_with 181 if arch.target_libc != None: 182 target_compatible_with.append(Label("//build/kernel/kleaf/platforms/libc:{}".format(arch.target_libc))) 183 184 native.toolchain( 185 name = name, 186 exec_compatible_with = [ 187 "@platforms//os:linux", 188 "@platforms//cpu:x86_64", 189 ] + extra_compatible_with, 190 target_compatible_with = target_compatible_with, 191 toolchain = name + "_cc_toolchain", 192 toolchain_type = CPP_TOOLCHAIN_TYPE, 193 visibility = ["@kleaf_clang_toolchain//:__subpackages__"], 194 ) 195 196def clang_toolchain( 197 name, 198 clang_version, 199 clang_pkg, 200 arch, 201 extra_compatible_with = None): 202 """Declare a clang toolchain for the given OS-architecture. 203 204 The toolchain should be under `prebuilts/clang/host/linux-x86`. 205 206 Args: 207 name: name of the toolchain 208 clang_version: nonconfigurable. version of the toolchain 209 clang_pkg: Label to any target in the clang toolchain package. 210 211 This is used as an anchor to locate other targets in the package. 212 Name of the label is ignored. 213 arch: key to look up extra kwargs. 214 extra_compatible_with: nonconfigurable. extra `exec_compatible_with` and `target_compatible_with` 215 """ 216 217 extra_kwargs = _get_extra_kwargs(arch) 218 219 _clang_toolchain_internal( 220 name = name, 221 clang_version = clang_version, 222 arch = arch, 223 clang_pkg = clang_pkg, 224 extra_compatible_with = extra_compatible_with, 225 **extra_kwargs 226 ) 227 228_GCC_PKG = Label("//prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8") 229 230def _get_extra_kwargs(arch): 231 if arch.target_os == "linux" and arch.target_libc == "musl": 232 return dict( 233 target = "x86_64-unknown-linux-musl", 234 sysroot_label = Label("//prebuilts/kernel-build-tools:musl_sysroot_files"), 235 sysroot_dir = Label("//prebuilts/kernel-build-tools:musl_sysroot_dir"), 236 linker_files = [ 237 Label("//prebuilts/kernel-build-tools:libs"), 238 ], 239 extra_features = [ 240 "kleaf-lld-compiler-rt", 241 "kleaf-host-musl", 242 ], 243 static_runtime_lib = Label(":empty_filegroup"), 244 dynamic_runtime_lib = Label("//prebuilts/kernel-build-tools:libc_musl_file"), 245 static_link_cpp_runtimes = True, 246 ) 247 248 if arch.target_os == "linux": 249 return dict( 250 linker_files = [ 251 Label("//prebuilts/kernel-build-tools:linux-x86-libs"), 252 ], 253 target = "x86_64-unknown-linux-gnu", 254 sysroot_label = Label("//build/kernel:sysroot"), 255 sysroot_dir = Label("//build/kernel:sysroot_dir"), 256 bin_files = [_GCC_PKG.relative(":bin_files")], 257 bin_dirs = [_GCC_PKG.relative(":bin_dirs")], 258 lib_files = [_GCC_PKG.relative(":lib_files")], 259 lib_dirs = [_GCC_PKG.relative(":lib_dirs")], 260 extra_features = [ 261 "kleaf-lld", 262 ], 263 ) 264 265 if arch.target_os != "android": 266 fail("Unsupported {}".format(arch)) 267 268 if arch.target_cpu == "arm64": 269 return dict( 270 target = VARS.get("AARCH64_NDK_TRIPLE"), 271 sysroot_label = "@prebuilt_ndk//:sysroot_{}_files".format(VARS.get("AARCH64_NDK_TRIPLE")) if "AARCH64_NDK_TRIPLE" in VARS else None, 272 sysroot_dir = "@prebuilt_ndk//:sysroot_dir" if "AARCH64_NDK_TRIPLE" in VARS else None, 273 ) 274 275 if arch.target_cpu == "arm": 276 return dict( 277 target = VARS.get("ARM_NDK_TRIPLE"), 278 sysroot_label = "@prebuilt_ndk//:sysroot_{}_files".format(VARS.get("ARM_NDK_TRIPLE")) if "ARM_NDK_TRIPLE" in VARS else None, 279 sysroot_dir = "@prebuilt_ndk//:sysroot_dir" if "ARM_NDK_TRIPLE" in VARS else None, 280 ) 281 282 if arch.target_cpu == "x86_64": 283 return dict( 284 target = VARS.get("X86_64_NDK_TRIPLE"), 285 sysroot_label = "@prebuilt_ndk//:sysroot_{}_files".format(VARS.get("X86_64_NDK_TRIPLE")) if "X86_64_NDK_TRIPLE" in VARS else None, 286 sysroot_dir = "@prebuilt_ndk//:sysroot_dir" if "X86_64_NDK_TRIPLE" in VARS else None, 287 ) 288 289 if arch.target_cpu == "i386": 290 return dict( 291 # i386 uses the same NDK_TRIPLE as x86_64 292 target = VARS.get("X86_64_NDK_TRIPLE"), 293 sysroot_label = "@prebuilt_ndk//:sysroot_{}_files".format(VARS.get("X86_64_NDK_TRIPLE")) if "X86_64_NDK_TRIPLE" in VARS else None, 294 sysroot_dir = "@prebuilt_ndk//:sysroot_dir" if "X86_64_NDK_TRIPLE" in VARS else None, 295 ) 296 297 if arch.target_cpu == "riscv64": 298 return dict( 299 # TODO(b/271919464): We need NDK_TRIPLE for riscv 300 ) 301 302 fail("Unsupported {}".format(arch)) 303