tree: 3a9b94c0bfece59972de0a717c19b30cb0fc2607 [path history] [tgz]
  1. android.bzl
  2. architecture_constants.bzl
  3. BUILD.bazel
  4. clang_config.bzl
  5. clang_toolchain.bzl
  6. clang_toolchain_repository.bzl
  7. common.bzl
  8. empty_toolchain.bzl
  9. linux.bzl
  10. OWNERS
  11. README.md
  12. versions.bzl
kleaf/README.md

C Toolchain in Kleaf

Toolchain declaration

Source: BUILD.bazel

The following toolchains are declared:

  • Default toolchains
  • Versioned toolchains
  • User toolchains, provided via command line flags

Default toolchains

Source: BUILD.bazel

Default toolchains, named {target_os}_{target_cpu}_clang_toolchain, are the fallback toolchains when a C toolchain is requested without any version information.

These toolchains are marked “target_compatible_with”:

  • the corresponding @platforms//os:{target_os}
  • the corresponding @platforms//cpu:{target_cpu}

These toolchains are marked “exec_compatible_with”:

  • @platforms//os:linux
  • @platforms//cpu:x86_64

These toolchains have cc_toolchain.compiler set to CLANG_VERSION from @kernel_toolchain_info//:dict.bzl.

Versioned toolchains

Source: BUILD.bazel

Versioned toolchains, named {version}_{target_os}_{target_cpu}_clang_toolchain, are the toolchains bearing extra version information.

These toolchains are marked “target_compatible_with”:

  • the corresponding @platforms//os:{target_os}
  • the corresponding @platforms//cpu:{target_cpu}
  • the corresponding //prebuilts/clang/host/linux-x86/kleaf:{version}

These toolchains are marked “exec_compatible_with”:

  • @platforms//os:linux
  • @platforms//cpu:x86_64
  • the corresponding //prebuilts/clang/host/linux-x86/kleaf:{version}

These toolchains have cc_toolchain.compiler set to the corresponding {version}.

User toolchains

Source: clang_toolchain_repository.bzl

User toolchains, @kleaf_clang_toolchain//:1_user_{target_os}_{target_cpu}_clang_toolchain, are the toolchains provided by the user from the command line.

These toolchains are marked “target_compatible_with”:

  • the corresponding @platforms//os:{target_os}
  • the corresponding @platforms//cpu:{target_cpu}

These toolchains are marked “exec_compatible_with”:

  • @platforms//os:linux
  • @platforms//cpu:x86_64

These toolchains have cc_toolchain.compiler set to "kleaf_clang_toolchain_skip_version_check" (an implementation detail).

Toolchain registration

Source: clang_toolchain_repository.bzl

Toolchains are registered in the following order:

  1. If --user_clang_toolchain is set, the user toolchains are registered. Otherwise, fake user toolchains are registered.
  2. The versioned toolchains
  3. The default toolchains

Toolchain resolution

The following assumes that the reader is familar with Bazel's toolchain resolution process.

Each toolchain registered through Bazel can specify a list of compatible constraint values with exec_compatible_with and target_compatible_with. A toolchain matches a platform when the toolchain’s constraint values are a SUBSET of the platform's constraint values.

To determine the toolchain for a build target, Bazel does the following.

  1. The platform of the build target is determined. By default, the platform of of the build target is the target platform, subject to transitions. If the build target is built in an exec configuration (e.g. when building as one of the tools of a genrule, or as a dependency with cfg="exec", the platform of the build target is the execution platform, subject to transitions.
  2. Bazel looks for a toolchain such that the toolchain's constraint values are a SUBSET of the constraint values of the platform of the build target.

For a build without any flags or transitions, the execution platform is @local_config_platform//:host. For Kleaf, this usually contains two constraint values: (linux, x86_64).

For a build without any flags or transitions, Bazel uses “single-platform builds” by default, so the target platform is the same as the execution platform with two constraint values: (linux, x86_64).

In Kleaf, if a target is built with --config=android_{cpu}, or is wrapped in an android_filegroup with a given cpu, the target platform has two constraint values (android, {cpu}).

Example: cc_* rules

For a build without any flags or transitions, the platform of the build target has two constrants: (linux, x86_64). The toolchains are looked up in the following order:

  1. If --user_clang_toolchain is set, 1_user_linux_x86_64_clang_toolchain is returned because its constraint values (linux, x86_64) are a subset of the platform's constraint values (linux, x86_64). Otherwise, if --user_clang_toolchain is not set, Bazel continues checking the following toolchains.
  2. The versioned toolchains are skipped because their constraint values ({version}, {target_os}, {target_cpu}) are not a subset of the platform's constraint values (linux, x86_64).
  3. The default toolchain linux_x86_64_clang_toolchain is returned because its constraint values (linux, x86_64) are a subset of the platform's constraint values (linux, x86_64)

If a cc_* target is built with --config=android_arm64, the platform of the build target has two constrants: (android, arm64). The toolchains are looked up in the following order:

  1. If --user_clang_toolchain is set, 1_user_android_arm64_clang_toolchain is returned because its constraint values (android, arm64) are a subset of the platform's constraint values (android, arm64). Otherwise, if --user_clang_toolchain is not set, Bazel continues checking the following toolchains.
  2. The versioned toolchains are skipped because their constraint values ({version}, {target_os}, {target_cpu}) are not a subset of the platform's constraint values (android, arm64).
  3. The default toolchain android_arm64_clang_toolchain is returned because its constraint values (android, arm64) are a subset of the platform's constraint values (android, arm64)

If a cc_* target is wrapped in an android_filegroup target with cpu="arm64", when the android_filegroup target is built, a transition is applied on the cc_* target so its platform has constraint values (android, arm64). The toolchain resolution process is the same as with --config=android_arm64.

Example: kernel_* rules without toolchain_version

If a kernel_build does not specify toolchain_version:

  • Its execution platform has constraint values (linux, x86_64)
  • Its target platform has constraint values (android, {target_cpu}) where {target_cpu} is specified in kernel_build.arch.

When kernel_toolchains looks up the toolchains for the execution platform and the target platform, respectively, the process is similar to the one for cc_* rules. That is:

  • If --user_clang_toolchain is set, the user toolchains are returned:
    • user_linux_x86_64_clang_toolchain is resolved for the execution platform
    • user_android_{target_cpu}_clang_toolchain is resolved for the target platform
  • Otherwise, the default toolchains are returned:
    • linux_x86_64_clang_toolchain is resolved for the execution platform
    • android_{target_cpu}_clang_toolchain is resolved for the target platform

Example: kernel_* rules with toolchain_version

This is unusual. You are recommended to not set kernel_build.toolchain_version to use the default toolchains.

If a kernel_build does specify toolchain_version:

  • Its execution platform has constraint values (linux, x86_64, {toolchain_version})
  • Its target platform has constraint values (android, {target_cpu}, {toolchain_version}) where {target_cpu} is specified in kernel_build.arch.

When kernel_toolchains looks up the toolchains for the execution platform:

  • If --user_clang_toolchain is set, the user toolchain 1_user_linux_x86_64_clang_toolchain is returned because its constraint values (linux, x86_64) are a subset of the execution platform's constraint values (linux, x86_64, {toolchain_version}). However, kernel_toolchains rejects the user toolchain because the version "unknown" does not match the declared value, kernel_build.toolchain_version, resulting in a build error. You should delete kernel_build.toolchain_version, and try again.
  • If --user_clang_toolchain is not set, the matching versioned toolchain, {version}_linux_x86_64_clang_toolchain is returned because its constraint values (linux, x86_64 {toolchain_version}) are a subset of the execution platform's constraint values (linux, x86_64, {toolchain_version}).
  • If no matching versioned toolchain is found, the default toolchain is returned. However, kernel_toolchains rejects the default toolchain because the version does not match the declared value, kernel_build.toolchain_version, resulting in a build error as expected.

The same goes for the target platform:

  • If --user_clang_toolchain is set, the user toolchain 1_user_android_{target_cpu}_clang_toolchain is returned because its constraint values (android, {target_cpu}) are a subset of the target platform's constraint values (android, {target_cpu}, {toolchain_version}). kernel_toolchains accepts the user toolchain with a warning because the version of the user toolchain "kleaf_clang_toolchain_skip_version_check" does not match the declared value, kernel_build.toolchain_version.
  • If --user_clang_toolchain is not set, the matching versioned toolchain, {version}_android_{target_cpu}_clang_toolchain is returned because its constraint values (android, {target_cpu} {toolchain_version}) are a subset of the target platform's constraint values (android, {target_cpu}, {toolchain_version}).
  • If no matching versioned toolchain is found, the default toolchain is returned. However, kernel_toolchains rejects the default toolchain because the version does not match the declared value, kernel_build.toolchain_version, resulting in a build error as expected.

Caveats

To use the user toolchains, the following is expected from the workspace:

  • An environment variable, KLEAF_USER_CLANG_TOOLCHAIN_PATH, must be set to the path to the user clang toolchain. This is set by Kleaf's Bazel wrapper, bazel.py, when --user_clang_toolchain is set.