1# C Toolchain in Kleaf 2 3## Toolchain declaration 4 5Source: [BUILD.bazel](BUILD.bazel) 6 7The following toolchains are declared: 8 9* Default toolchains 10* Versioned toolchains 11* User toolchains, provided via command line flags 12 13### Default toolchains 14 15[Source: `BUILD.bazel`](BUILD.bazel) 16 17Default toolchains, named `{target_os}_{target_cpu}_clang_toolchain`, 18are the fallback toolchains when a C toolchain is requested without 19any version information. 20 21These toolchains are marked "target_compatible_with": 22* the corresponding `@platforms//os:{target_os}` 23* the corresponding `@platforms//cpu:{target_cpu}` 24 25These toolchains are marked "exec_compatible_with": 26* `@platforms//os:linux` 27* `@platforms//cpu:x86_64` 28 29These toolchains have `cc_toolchain.compiler` set to `CLANG_VERSION` from 30`@kernel_toolchain_info//:dict.bzl`. 31 32### Versioned toolchains 33 34[Source: `BUILD.bazel`](BUILD.bazel) 35 36Versioned toolchains, named 37`{version}_{target_os}_{target_cpu}_clang_toolchain`, 38are the toolchains bearing extra version information. 39 40These toolchains are marked "target_compatible_with": 41* the corresponding `@platforms//os:{target_os}` 42* the corresponding `@platforms//cpu:{target_cpu}` 43* the corresponding `//prebuilts/clang/host/linux-x86/kleaf:{version}` 44 45These toolchains are marked "exec_compatible_with": 46* `@platforms//os:linux` 47* `@platforms//cpu:x86_64` 48* the corresponding `//prebuilts/clang/host/linux-x86/kleaf:{version}` 49 50These toolchains have `cc_toolchain.compiler` set to the corresponding 51`{version}`. 52 53### User toolchains 54 55[Source: `clang_toolchain_repository.bzl`](clang_toolchain_repository.bzl) 56 57User toolchains, 58`@kleaf_clang_toolchain//:1_user_{target_os}_{target_cpu}_clang_toolchain`, 59are the toolchains provided by the user from the command line. 60 61These toolchains are marked "target_compatible_with": 62* the corresponding `@platforms//os:{target_os}` 63* the corresponding `@platforms//cpu:{target_cpu}` 64 65These toolchains are marked "exec_compatible_with": 66* `@platforms//os:linux` 67* `@platforms//cpu:x86_64` 68 69These toolchains have `cc_toolchain.compiler` set to 70`"kleaf_clang_toolchain_skip_version_check"` (an implementation detail). 71 72## Toolchain registration 73 74[Source: `clang_toolchain_repository.bzl`](clang_toolchain_repository.bzl) 75 76Toolchains are registered in the following order: 77 781. If `--user_clang_toolchain` is set, the user toolchains are registered. 79 Otherwise, fake user toolchains are registered. 802. The versioned toolchains 813. The default toolchains 82 83## Toolchain resolution 84 85The following assumes that the reader is familar with 86[Bazel's toolchain resolution process](https://bazel.build/extending/toolchains#toolchain-resolution). 87 88Each toolchain registered through Bazel can specify a list of compatible 89constraint values with `exec_compatible_with` and `target_compatible_with`. A 90toolchain matches a platform when the toolchain’s constraint values are a 91**SUBSET** of the platform's constraint values. 92 93To determine the toolchain for a 94[build target](https://bazel.build/extending/rules#target_instantiation), 95Bazel does the following. 96 971. The platform of the build target is determined. By default, the platform of 98 of the build target is the 99 [target platform](https://bazel.build/extending/platforms), subject to 100 transitions. If the build target is built in an `exec` configuration (e.g. 101 when building as one of the 102 [`tools` of a `genrule`](https://bazel.build/reference/be/general#genrule.tools), 103 or as 104 [a dependency with `cfg="exec"`](https://bazel.build/extending/rules#configurations), the platform of the build target is the 105 [execution platform](https://bazel.build/extending/platforms), subject to 106 transitions. 1072. Bazel looks for a toolchain such that the toolchain's constraint values 108 are a **SUBSET** of the constraint values of the platform of the build 109 target. 110 111For a build without any flags or transitions, the execution platform is 112`@local_config_platform//:host`. For Kleaf, this usually contains two 113constraint values: (`linux`, `x86_64`). 114 115For a build without any flags or transitions, Bazel uses 116["single-platform builds"](https://bazel.build/extending/platforms) 117by default, so the target platform is the same as the execution platform with 118two constraint values: (`linux`, `x86_64`). 119 120In Kleaf, if a target is built with `--config=android_{cpu}`, or is wrapped in 121an `android_filegroup` with a given `cpu`, the target platform has two 122constraint values (`android`, `{cpu}`). 123 124### Example: cc\_* rules 125 126For a build without any flags or transitions, the platform of the build target 127has two constrants: (`linux`, `x86_64`). The toolchains are looked up in 128the following order: 129 1301. If `--user_clang_toolchain` is set, `1_user_linux_x86_64_clang_toolchain` 131 is returned because its constraint values (`linux`, `x86_64`) are a subset 132 of the platform's constraint values (`linux`, `x86_64`). Otherwise, if 133 `--user_clang_toolchain` is not set, Bazel continues checking the following 134 toolchains. 1352. The versioned toolchains are skipped because their constraint values 136 (`{version}`, `{target_os}`, `{target_cpu}`) are not a subset of 137 the platform's constraint values (`linux`, `x86_64`). 1383. The default toolchain `linux_x86_64_clang_toolchain` is returned because 139 its constraint values (`linux`, `x86_64`) are a subset 140 of the platform's constraint values (`linux`, `x86_64`) 141 142If a `cc_*` target is built with `--config=android_arm64`, the platform of the 143build target has two constrants: (`android`, `arm64`). The toolchains are looked 144up in the following order: 145 1461. If `--user_clang_toolchain` is set, `1_user_android_arm64_clang_toolchain` 147 is returned because its constraint values (`android`, `arm64`) are a subset 148 of the platform's constraint values (`android`, `arm64`). Otherwise, if 149 `--user_clang_toolchain` is not set, Bazel continues checking the following 150 toolchains. 1512. The versioned toolchains are skipped because their constraint values 152 (`{version}`, `{target_os}`, `{target_cpu}`) are not a subset of 153 the platform's constraint values (`android`, `arm64`). 1543. The default toolchain `android_arm64_clang_toolchain` is returned because 155 its constraint values (`android`, `arm64`) are a subset 156 of the platform's constraint values (`android`, `arm64`) 157 158If a `cc_*` target is wrapped in an `android_filegroup` target with 159`cpu="arm64"`, **when the `android_filegroup` target is built**, a transition is 160applied on the `cc_*` target so its platform has constraint values 161(`android`, `arm64`). The toolchain resolution process is the same as with 162`--config=android_arm64.` 163 164### Example: kernel\_* rules without toolchain\_version 165 166If a `kernel_build` does not specify `toolchain_version`: 167 168* Its execution platform has constraint values (`linux`, `x86_64`) 169* Its target platform has constraint values (`android`, `{target_cpu}`) where 170 `{target_cpu}` is specified in `kernel_build.arch`. 171 172When `kernel_toolchains` looks up the toolchains for the execution platform 173and the target platform, respectively, the process is similar to the one 174for [`cc_*` rules](#example-cc_-rules). That is: 175 176* If `--user_clang_toolchain` is set, the user toolchains are returned: 177 * `user_linux_x86_64_clang_toolchain` is resolved for the 178 execution platform 179 * `user_android_{target_cpu}_clang_toolchain` is resolved for the 180 target platform 181* Otherwise, the default toolchains are returned: 182 * `linux_x86_64_clang_toolchain` is resolved for the 183 execution platform 184 * `android_{target_cpu}_clang_toolchain` is resolved for the 185 target platform 186 187### Example: kernel\_* rules with toolchain\_version 188 189This is unusual. You are recommended to not set `kernel_build.toolchain_version` 190to use the default toolchains. 191 192If a `kernel_build` does specify `toolchain_version`: 193 194* Its execution platform has constraint values 195 (`linux`, `x86_64`, `{toolchain_version}`) 196* Its target platform has constraint values 197 (`android`, `{target_cpu}`, `{toolchain_version}`) where 198 `{target_cpu}` is specified in `kernel_build.arch`. 199 200When `kernel_toolchains` looks up the toolchains for the execution platform: 201 202* If `--user_clang_toolchain` is set, the user toolchain 203 `1_user_linux_x86_64_clang_toolchain` is returned because its constraint 204 values (`linux`, `x86_64`) are a subset of the execution platform's 205 constraint values (`linux`, `x86_64`, `{toolchain_version}`). However, 206 `kernel_toolchains` rejects the user toolchain because the version 207 `"unknown"` does not match the declared value, 208 `kernel_build.toolchain_version`, resulting in a build error. You should 209 delete `kernel_build.toolchain_version`, and try again. 210* If `--user_clang_toolchain` is not set, the matching versioned toolchain, 211 `{version}_linux_x86_64_clang_toolchain` is returned because 212 its constraint values (`linux`, `x86_64` `{toolchain_version}`) are a subset 213 of the execution platform's constraint values 214 (`linux`, `x86_64`, `{toolchain_version}`). 215* If no matching versioned toolchain is found, the default toolchain is 216 returned. However, `kernel_toolchains` rejects the default toolchain 217 because the version does not match the declared value, 218 `kernel_build.toolchain_version`, resulting in a build error as expected. 219 220The same goes for the target platform: 221 222* If `--user_clang_toolchain` is set, the user toolchain 223 `1_user_android_{target_cpu}_clang_toolchain` is returned because its 224 constraint values (`android`, `{target_cpu}`) are a subset of the target 225 platform's constraint values 226 (`android`, `{target_cpu}`, `{toolchain_version}`). 227 `kernel_toolchains` accepts the user toolchain with a warning because 228 the version of the user toolchain 229 `"kleaf_clang_toolchain_skip_version_check"` does not match the declared value, `kernel_build.toolchain_version`. 230* If `--user_clang_toolchain` is not set, the matching versioned toolchain, 231 `{version}_android_{target_cpu}_clang_toolchain` is returned because 232 its constraint values (`android`, `{target_cpu}` `{toolchain_version}`) are a subset of the target platform's constraint values 233 (`android`, `{target_cpu}`, `{toolchain_version}`). 234* If no matching versioned toolchain is found, the default toolchain is 235 returned. However, `kernel_toolchains` rejects the default toolchain 236 because the version does not match the declared value, 237 `kernel_build.toolchain_version`, resulting in a build error as expected. 238 239## Caveats 240 241To use the user toolchains, the following is expected from the workspace: 242 243* An environment variable, `KLEAF_USER_CLANG_TOOLCHAIN_PATH`, must 244 be set to the path to the user clang toolchain. This is set by 245 Kleaf's Bazel wrapper, `bazel.py`, when `--user_clang_toolchain` is set. 246