`extra_targets`, user configurable toolchains, and wasm support
(this PR builds on #75; that PR should be reviewed/merged before this one)
This PR is not ready for merging yet but I thought I'd open the PR anyways to get some feedback and see if this is a use case the maintainers are interested in.
This PR adds support for extra_toolchains, an attribute on configure that lets users register additional toolchains for different target triples:
load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "llvm_toolchain")
llvm_toolchain(
name = "llvm_toolchain",
llvm_version = "8.0.0",
extra_targets = [
"wasm32-unknown-wasi",
],
# Extra targets can have their sysroots overriden too:
sysroot = {
"linux": "@some_example_sysroot_repo//:linux_sysroot",
"darwin": "@some_example_sysroot_repo//:macos_sysroot",
"linux_wasm32-unknown-wasi": "@some_example_sysroot_repo//:wasi_sysroot",
"darwin_wasm32-unknown-wasi": "@some_example_sysroot_repo//:wasi_sysroot",
},
)
The toolchains registered with extra_targets have the appropriate constraint values so that Bazel will use them as necessary through toolchain resolution.
In extending the internals of this repo to support extra_targets, cc_toolchain_config and other internal macros were made a fair bit more general. This PR also tweaks these macros to be usable externally, allowing users to make small modifications to the configured toolchains without needing to modify this repo:
# WORKSPACE
# (parts to set up `@llvm_toolchain` have been elided; see above)
llvm_toolchain(
name = "llvm_toolchain",
llvm_version = "8.0.0",
# NOTE: This is required to set up toolchains outside of `@llvm_toolchain`, unfortunately
absolute_paths = True,
)
# This registers the default toolchains.
load("@llvm_toolchain//:toolchains.bzl", "llvm_register_toolchains", "register_toolchain")
llvm_register_toolchains()
# Now let's make our own:
http_archive(
name = "thumbv7-sysroot",
urls = ["example.com"],
)
register_toolchain("//tests:custom_toolchain_example")
# BUILD file:
# Example Custom Toolchain:
load("@llvm_toolchain//:cc_toolchain_config.bzl", "cc_toolchain_config")
# Docs for this function and `overrides` are in `cc_toolchain_config.bzl.tpl`.
cc_toolchain_config(
name = "custom_toolchain_example_config",
host_platform = "linux",
custom_target_triple = "thumbv7em-unknown-none-gnueabihf",
overrides = {
"target_system_name": "thumbv7em-unknown-none-gnueabihf",
"target_cpu": "thumbv7em",
"target_libc": "unknown",
"abi_libc_version": "unknown",
# If you omit this, be sure to depend on
# `@llvm_toolchain:host_sysroot_components`.
# "sysroot_path": "external/thumbv7-sysroot/sysroot",
"extra_compile_flags": [
"-mthumb",
"-mcpu=cortex-m4",
"-mfpu=fpv4-sp-d16",
"-mfloat-abi=hard",
],
"omit_hosted_linker_flags": True,
"omit_cxx_stdlib_flag": False,
"use_llvm_ar_instead_of_libtool_on_macos": True,
}
)
load("@com_grail_bazel_toolchain//toolchain:rules.bzl", "conditional_cc_toolchain")
conditional_cc_toolchain(
name = "custom_toolchain",
toolchain_config = ":custom_toolchain_example_config",
host_is_darwin = False,
sysroot_label = "@llvm_toolchain//:host_sysroot_components", # use this if not overriding
# sysroot_label = "@thumbv7-sysroot//:sysroot", # override
absolute_paths = True, # this is required for toolchains set up outside of `@llvm_toolchain`, unfortunately
llvm_repo_label_prefix = "@llvm_toolchain//",
)
# Constraints come from here: https://github.com/bazelbuild/platforms
toolchain(
name = "custom_toolchain_example",
exec_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
target_compatible_with = [
"@platforms//cpu:armv7", # `v7e-mf` has not yet made it to stable Bazel?
# "@platforms//os:none",
],
toolchain = ":custom_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
The interface is currently extremely rough and is just intended to be a way to prototype support for other targets without needing to modify this repo. If there's interest, there's lots that can be done to turn this into a user-friendly API.
Currently, only the wasm32-unknown-wasi target triple is tested and actually working. However this PR lays the foundation for support for other targets; it should just be a matter of adding sysroot and compiler_rt locations for other targets and fine-tuning the LLVM target triple to Bazel constraint value mappings.
As an aside, even in adding support for just a single additional (not-hosted) target the ways in which using unix_cc_toolchain_config.bzl (#75) limit us becomes apparent (we would like to have the toolchain for wasm targets not support the dynamic linking actions since they just error; instead we're forced to use --features=-supports_dynamic_linker on the command line or transitions/selects or other such workarounds).
So far this has been manageable but this definitely casts some doubt on whether #75 is the way to go.
Another thing to consider is whether upstream Bazel would be willing to make unix_cc_toolchain_config.bzl slightly more general/whether or not our use case aligns with its intended purpose.