README.md
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