lachlansneff / bazel-toolchain

LLVM toolchain for bazel

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LLVM toolchain for Bazel Tests Migration


The project is in a relatively stable state and in use for all code development at GRAIL and other organizations. Having said that, I am unable to give time to it at any regular cadence.

I rely on the community for maintenance and new feature implementations. If you are interested in being part of this project, please let me know and I can give you write access, so you can merge your changes directly.

If you feel like you have a better maintained fork or an alternative/derived implementation, please let me know and I can redirect people there.

– @siddharthab


Quickstart

Minimum bazel version: 4.0.0

To use this toolchain, include this section in your WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

BAZEL_TOOLCHAIN_TAG = "0.6.3"
BAZEL_TOOLCHAIN_SHA = "da607faed78c4cb5a5637ef74a36fdd2286f85ca5192222c4664efec2d529bb8"

http_archive(
    name = "com_grail_bazel_toolchain",
    sha256 = BAZEL_TOOLCHAIN_SHA,
    strip_prefix = "bazel-toolchain-{tag}".format(tag = BAZEL_TOOLCHAIN_TAG),
    canonical_id = BAZEL_TOOLCHAIN_TAG,
    url = "https://github.com/grailbio/bazel-toolchain/archive/{tag}.tar.gz".format(tag = BAZEL_TOOLCHAIN_TAG),
)

load("@com_grail_bazel_toolchain//toolchain:deps.bzl", "bazel_toolchain_dependencies")

bazel_toolchain_dependencies()

load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")

llvm_toolchain(
    name = "llvm_toolchain",
    llvm_version = "13.0.0",
)

load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains")

llvm_register_toolchains()

And add the following section to your .bazelrc file (not needed after this issue is closed):

build --incompatible_enable_cc_toolchain_resolution

Basic Usage

The toolchain can automatically detect your OS and arch type, and use the right pre-built binary distribution from llvm.org. The detection is currently based on host OS and is not perfect, so some distributions, docker based sandboxed builds, and remote execution builds will need toolchains configured manually through the distribution attribute. We expect the detection logic to grow through community contributions. We welcome PRs! 😄

See in-code documentation in rules.bzl for available attributes to llvm_toolchain.

Advanced Usage

Customizations

We currently offer limited customizability through attributes of the llvm_toolchain_* rules. You can send us a PR to add more configuration attributes.

A majority of the complexity of this project is to make it generic for multiple use cases. For one-off experiments with new architectures, cross-compilations, new compiler features, etc., my advice would be to look at the toolchain configurations generated by this repo, and copy-paste/edit to make your own in any package in your own workspace.

bazel query --output=build @llvm_toolchain//:all | grep -v -e '^#' -e '^  generator'

Besides defining your toolchain in your package BUILD file, and until this issue is resolved, you would also need a way for bazel to access the tools in LLVM distribution as relative paths from your package without using .. up-references. For this, you can create a symlink that uses up-references to point to the LLVM distribution directory, and also create a wrapper script for clang such that the actual clang invocation is not through the symlinked path. See the files in the @llvm_toolchain//: package as a reference.

# See generated files for reference.
ls -lR "$(bazel info output_base)/external/llvm_toolchain"

# Create symlink to LLVM distribution.
cd _your_package_directory_
ln -s ../....../external/llvm_toolchain_llvm llvm

# Create CC wrapper script.
mkdir bin
cp "$(bazel info output_base)/external/llvm_toolchain/bin/cc_wrapper.sh" bin/cc_wrapper.sh
vim bin/cc_wrapper.sh # Review to ensure relative paths, etc. are good.

See bazel tutorial for how CC toolchains work in general.

Selecting Toolchains

If toolchains are registered (see Quickstart section above), you do not need to do anything special for bazel to find the toolchain. You may want to check once with the --toolchain_resolution_debug flag to see which toolchains were selected by bazel for your target platform.

For specifying unregistered toolchains on the command line, please use the --extra_toolchains flag. For example, --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux.

We no longer support the --crosstool_top=@llvm_toolchain//:toolchain flag, and instead rely on the --incompatible_enable_cc_toolchain_resolution flag.

Bring Your Own LLVM

The LLVM toolchain archive is downloaded and extracted as a separate repository with the suffix _llvm. Alternatively, you can also specify your own repositories for each host os-arch pair through the toolchain_roots attribute. Each of these repositories is typically configured through local_repository or http_archive (with build_file attribute as @com_grail_bazel_toolchain//toolchain:BUILD.llvm_repo).

Sysroots

A sysroot can be specified through the sysroot attribute. This can be either a path on the user's system, or a bazel filegroup like label. One way to create a sysroot is to use docker export to get a single archive of the entire filesystem for the image you want. Another way is to use the build scripts provided by the Chromium project.

Cross-compilation

The toolchain supports cross-compilation if you bring your own sysroot. When cross-compiling, we link against the libstdc++ from the sysroot (single-platform build behavior is to link against libc++ bundled with LLVM). The following pairs have been tested to work for some hello-world binaries:

  • {linux, x86_64} -> {linux, aarch64}
  • {linux, aarch64} -> {linux, x86_64}
  • {darwin, x86_64} -> {linux, x86_64}
  • {darwin, x86_64} -> {linux, aarch64}

A recommended approach would be to define two toolchains, one without sysroot for single-platform builds, and one with sysroot for cross-compilation builds. Then, when cross-compiling, explicitly specify the toolchain with the sysroot and the target platform. For example, see the WORKSPACE file and the test script for cross-compilation.

bazel build \
  --platforms=@com_grail_bazel_toolchain//platforms:linux-x86_64 \
  --extra_toolchains=@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux \
  //...

Sandbox

Sandboxing the toolchain introduces a significant overhead (100ms per action, as of mid 2018). To overcome this, one can use --experimental_sandbox_base=/dev/shm. However, not all environments might have enough shared memory available to load all the files in memory. If this is a concern, you may set the attribute for using absolute paths, which will substitute templated paths to the toolchain as absolute paths. When running bazel actions, these paths will be available from inside the sandbox as part of the / read-only mount. Note that this will make your builds non-hermetic.

Compatibility

The toolchain is tested to work with rules_go, rules_rust, and rules_foreign_cc.

Accessing tools

The LLVM distribution also provides several tools like clang-format. You can depend on these tools directly in the bin directory of the distribution. When using the auto-configured download (not using toolchain_roots), the distribution is available in the repo with the suffix _llvm appended to the name you used for the llvm_toolchain rule. For example, @llvm_toolchain_llvm//:bin/clang-format is a valid and visible target in the quickstart example above.

Prior Art

Other examples of toolchain configuration:

https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain

https://github.com/vsco/bazel-toolchains

About

LLVM toolchain for bazel

License:Apache License 2.0


Languages

Language:Starlark 63.9%Language:Shell 21.5%Language:Python 6.0%Language:C 5.1%Language:C++ 2.0%Language:Smarty 1.4%