Add support for bzlmod (#198)

This is a fairly straightforward change that adds support for using `bazel-toolchain` with `bzlmod`.

The `llvm.toolchain` extension is only a wrapper around the existing `llvm_toolchain` repository rule and supports the same attributes.

For trying it out, add the following to your `MODULE.bazel`:

```
bazel_dep(name = "com_grail_bazel_toolchain", version = "0.8")
git_override(module_name = "com_grail_bazel_toolchain", remote = "https://github.com/grailbio/bazel-toolchain", commit = "cf915e5c7cfcd19a3e71de54e385e01240b865dc")

llvm = use_extension("@com_grail_bazel_toolchain//toolchain:extensions.bzl", "llvm")
llvm.toolchain(
    llvm_version = "15.0.0"
)

use_repo(llvm, "llvm_toolchain")

register_toolchains("@llvm_toolchain//:all")
```

---------

Co-authored-by: James Sharpe <james.sharpe@zenotech.com>
Co-authored-by: Fabian Meumertzheim <fabian@meumertzhe.im>
Co-authored-by: Gabriel Féron <g@leirbagl.net>
This commit is contained in:
Gabriel Féron 2023-09-12 18:46:02 +02:00 committed by GitHub
parent 9d8cc8a498
commit 5c6f8066fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 592 additions and 310 deletions

View File

@ -13,17 +13,30 @@ jobs:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest]
script: [run_tests.sh, run_external_tests.sh]
bazel_version: [latest, 6.0.0]
exclude:
- script: run_external_tests.sh
bazel_version: 6.0.0
bazel_version: [latest, 6.3.0]
bzlmod: [true, false]
steps:
- uses: actions/checkout@v3
- name: test
env:
USE_BAZEL_VERSION: ${{ matrix.bazel_version }}
run: tests/scripts/${{ matrix.script }}
USE_BZLMOD: ${{ matrix.bzlmod }}
run: tests/scripts/run_tests.sh
external_test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest]
bazel_version: [latest, 6.3.0]
bzlmod: [true, false]
steps:
- uses: actions/checkout@v2
- name: external_test
env:
USE_BAZEL_VERSION: ${{ matrix.bazel_version }}
USE_BZLMOD: ${{ matrix.bzlmod }}
run: tests/scripts/run_external_tests.sh
container_test:
runs-on: ubuntu-latest
strategy:

9
MODULE.bazel Normal file
View File

@ -0,0 +1,9 @@
module(
name = "llvm_toolchain",
version = "0.0.0",
compatibility_level = 0,
)
bazel_dep(name = "bazel_skylib", version = "1.4.2")
bazel_dep(name = "rules_cc", version = "0.0.8")
bazel_dep(name = "platforms", version = "0.0.6")

View File

@ -22,7 +22,24 @@ implementation, please let me know and I can redirect people there.
Minimum bazel version: **6.0.0**
To use this toolchain, include this section in your WORKSPACE:
If you're using `bzlmod`, add the following to `MODULE.bazel`:
```starlark
bazel_dep(name = "llvm_toolchain", version = "0.8.2")
llvm = use_extension("@llvm_toolchain//toolchain/extensions:llvm.bzl", "llvm")
llvm.toolchain(
llvm_version = "15.0.6",
)
use_repo(llvm, "llvm_toolchain")
# use_repo(llvm, "llvm_toolchain_llvm") # if you depend on specific tools in scripts
register_toolchains("@llvm_toolchain//:all")
```
To use this toolchain, include this section in your `WORKSPACE`:
```starlark
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

View File

@ -119,6 +119,10 @@ cc_test(
sh_test(
name = "file_dependency_test",
srcs = ["file_dependency_test.sh"],
args = [
"$(execpath @llvm_toolchain_llvm//:bin/clang-format)",
"$(rootpaths @llvm_toolchain_llvm//:lib)",
],
data = [
"@llvm_toolchain_llvm//:bin/clang-format",
"@llvm_toolchain_llvm//:lib",

139
tests/MODULE.bazel Normal file
View File

@ -0,0 +1,139 @@
module(name = "com_grail_bazel_toolchain_tests")
bazel_dep(name = "llvm_toolchain", version = "0.8.2", repo_name = "com_grail_bazel_toolchain")
local_path_override(module_name = "llvm_toolchain", path = "..")
bazel_dep(name = "bazel_skylib", version = "1.4.2")
bazel_dep(name = "platforms", version = "0.0.6")
bazel_dep(name = "rules_cc", version = "0.0.8")
bazel_dep(name = "rules_go", version = "0.40.1", repo_name = "io_bazel_rules_go")
bazel_dep(name = "rules_foreign_cc", version = "0.9.0")
bazel_dep(name = "rules_rust", version = "0.27.0")
# We have to patch abseil-cpp to add a dep on googletest
bazel_dep(name = "abseil-cpp", repo_name = "com_google_absl")
archive_override(module_name = "abseil-cpp", urls = ["https://github.com/abseil/abseil-cpp/archive/refs/tags/20230125.3.tar.gz"], patches = ["//patches:abseil-cpp.patch"], strip_prefix = "abseil-cpp-20230125.3")
# Temporary overrides until newer versions of these rulesets are released in the central registry
git_override(module_name = "rules_foreign_cc", remote = "https://github.com/bazelbuild/rules_foreign_cc.git", commit = "6ecc134b114f6e086537f5f0148d166467042226")
git_override(module_name = "rules_rust", remote = "https://github.com/bazelbuild/rules_rust.git", commit = "4dbb81a008f4031c9ad65138fa2a49f32352f80f")
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
rust.toolchain(edition = "2021")
use_repo(
rust,
"rust_toolchains",
)
register_toolchains("@rust_toolchains//:all")
llvm = use_extension("@com_grail_bazel_toolchain//toolchain/extensions:llvm.bzl", "llvm")
# When updating this version, also update the versions associated with
# llvm_toolchain below, sys_paths_test in the workflows file, and xcompile_test
# through the `llvm_toolchain_with_sysroot` toolchain.
LLVM_VERSION = "15.0.6"
llvm.toolchain(
name = "llvm_toolchain",
llvm_versions = {
"": "15.0.6",
"darwin-aarch64": "15.0.7",
"darwin-x86_64": "15.0.7",
},
)
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")
register_toolchains("@llvm_toolchain//:all")
# Example toolchain with user provided URLs.
# TODO(siddharthab): Add test.
llvm.toolchain(
name = "llvm_toolchain_with_urls",
llvm_versions = {
"": "15.0.6",
"darwin-aarch64": "15.0.7",
"darwin-x86_64": "15.0.7",
},
sha256 = {
"": "38bc7f5563642e73e69ac5626724e206d6d539fbef653541b34cae0ba9c3f036",
"darwin-aarch64": "867c6afd41158c132ef05a8f1ddaecf476a26b91c85def8e124414f9a9ba188d",
"darwin-x86_64": "d16b6d536364c5bec6583d12dd7e6cf841b9f508c4430d9ee886726bd9983f1c",
},
strip_prefix = {
"": "clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04",
"darwin-aarch64": "clang+llvm-15.0.7-arm64-apple-darwin22.0",
"darwin-x86_64": "clang+llvm-15.0.7-x86_64-apple-darwin21.0",
},
urls = {
"": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz"],
"darwin-aarch64": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.7/clang+llvm-15.0.7-arm64-apple-darwin22.0.tar.xz"],
"darwin-x86_64": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.7/clang+llvm-15.0.7-x86_64-apple-darwin21.0.tar.xz"],
},
)
use_repo(llvm, "llvm_toolchain_with_urls")
# # This is the latest version of LLVM that seems to work with rules_go; later
# # versions cause the tests to crash.
llvm.toolchain(
name = "llvm_toolchain_14_0_0",
llvm_version = "14.0.0",
)
use_repo(llvm, "llvm_toolchain_14_0_0")
# # This is the last known LLVM version with zlib support in ld.lld. Without zlib
# # support, if the installed gcc toolchain has compressed sections in its object
# # files, then ld.lld won't be able to process them. Example is archlinux docker
# # image base-devel as of the time of this writing (23 May 2022).
llvm.toolchain(
name = "llvm_toolchain_13_0_0",
llvm_version = "13.0.0",
)
use_repo(llvm, "llvm_toolchain_13_0_0")
# ## Toolchain example with absolute paths; tested in GitHub CI.
llvm.toolchain(
name = "llvm_toolchain_with_absolute_paths",
absolute_paths = True,
llvm_version = LLVM_VERSION,
# We can share the downloaded LLVM distribution with the first configuration.
toolchain_roots = {
"": "@llvm_toolchain_llvm//",
},
)
use_repo(llvm, "llvm_toolchain_with_absolute_paths")
# ## Toolchain example with system LLVM; tested in GitHub CI.
llvm.toolchain(
name = "llvm_toolchain_with_system_llvm",
llvm_version = LLVM_VERSION,
# For this toolchain to work, the LLVM distribution archive would need to be unpacked here.
# A path in /tmp to be part of system tmp cleanup schedule.
toolchain_roots = {"": "/tmp/llvm-15"},
)
use_repo(llvm, "llvm_toolchain_with_system_llvm")
# ## Toolchain example with a sysroot.
llvm.toolchain(
name = "llvm_toolchain_with_sysroot",
llvm_versions = {
"": "15.0.6",
"darwin-x86_64": "15.0.7",
"darwin-aarch64": "15.0.7",
},
sysroot = {
"linux-x86_64": "@org_chromium_sysroot_linux_x64//:sysroot",
},
# We can share the downloaded LLVM distribution with the first configuration.
toolchain_roots = {
"": "@llvm_toolchain_llvm//",
},
)
use_repo(llvm, "llvm_toolchain_with_sysroot")

53
tests/WORKSPACE.bzlmod Normal file
View File

@ -0,0 +1,53 @@
workspace(name = "com_grail_bazel_toolchain_tests")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# This sysroot is used by github.com/vsco/bazel-toolchains.
http_archive(
name = "org_chromium_sysroot_linux_x64",
build_file_content = """
filegroup(
name = "sysroot",
srcs = glob(["*/**"]),
visibility = ["//visibility:public"],
)
""",
sha256 = "84656a6df544ecef62169cfe3ab6e41bb4346a62d3ba2a045dc5a0a2ecea94a3",
urls = ["https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/2202c161310ffde63729f29d27fe7bb24a0bc540/debian_stretch_amd64_sysroot.tar.xz"],
)
# Well known repos; present here only for testing.
http_archive(
name = "com_github_google_benchmark",
sha256 = "6430e4092653380d9dc4ccb45a1e2dc9259d581f4866dc0759713126056bc1d7",
strip_prefix = "benchmark-1.7.1",
urls = ["https://github.com/google/benchmark/archive/v1.7.1.tar.gz"],
)
http_archive(
name = "openssl",
build_file = "//openssl:openssl.bazel",
sha256 = "f6fb3079ad15076154eda9413fed42877d668e7069d9b87396d0804fdb3f4c90",
strip_prefix = "openssl-1.1.1c",
urls = ["https://www.openssl.org/source/openssl-1.1.1c.tar.gz"],
)
_ALL_CONTENT = """\
filegroup(
name = "all_srcs",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
"""
http_archive(
name = "pcre",
build_file_content = _ALL_CONTENT,
sha256 = "0b8e7465dc5e98c757cc3650a20a7843ee4c3edf50aaf60bb33fd879690d2c73",
strip_prefix = "pcre-8.43",
urls = [
"https://mirror.bazel.build/ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz",
"https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz",
],
)

View File

@ -18,10 +18,13 @@ fail() {
exit 1
}
[[ -a "external/llvm_toolchain_llvm/bin/clang-format" ]] || fail "bin/clang-format not found"
clang_format_path=$1
libcpp_path=$2
[[ -a "external/llvm_toolchain_llvm/lib/libc++.a" ]] \
|| compgen -G 'external/llvm_toolchain_llvm/lib/*/libc++.a' >/dev/null \
[[ -a "${clang_format_path}" ]] || fail "bin/clang-format not found"
[[ -a "${libcpp_path}" ]] \
|| compgen -G "${libcpp_path}" >/dev/null \
|| fail "libc++.a not found"
echo "SUCCESS!"

View File

@ -1,4 +1,4 @@
exports_files(
srcs = glob(["**/*.h"]),
visibility = ["@openssl//:__pkg__"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,12 @@
--- MODULE.bazel
+++ MODULE.bazel
@@ -0,0 +1,9 @@
+module(
+ name = "abseil-cpp",
+ version = "20230125.1",
+ compatibility_level = 1,
+)
+bazel_dep(name = "rules_cc", version = "0.0.8")
+bazel_dep(name = "platforms", version = "0.0.6")
+bazel_dep(name = "bazel_skylib", version = "1.4.2")
+bazel_dep(name = "googletest", version = "1.12.1", repo_name = "com_google_googletest")

View File

@ -1,34 +0,0 @@
diff --git a/test/unit/linkstamps/linkstamps_test.bzl b/test/unit/linkstamps/linkstamps_test.bzl
index d7423f3..47120c1 100644
--- a/test/unit/linkstamps/linkstamps_test.bzl
+++ b/test/unit/linkstamps/linkstamps_test.bzl
@@ -23 +23,2 @@ def _supports_linkstamps_test(ctx):
- expected_linkstamp_path = tut_out.dirname + "/_objs/" + tut_out.basename + "/test/unit/linkstamps/linkstamp.o"
+ workspace_prefix = "" if ctx.workspace_name == "rules_rust" else "/external/rules_rust"
+ expected_linkstamp_path = tut_out.dirname + "/_objs/" + tut_out.basename + workspace_prefix + "/test/unit/linkstamps/linkstamp.o"
diff --git a/test/unit/native_deps/native_deps_test.bzl b/test/unit/native_deps/native_deps_test.bzl
index 5a91881..6665489 100644
--- a/test/unit/native_deps/native_deps_test.bzl
+++ b/test/unit/native_deps/native_deps_test.bzl
@@ -80,0 +81 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
+ workspace_prefix = "" if ctx.workspace_name == "rules_rust" else "external/rules_rust/"
@@ -84 +85 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
- "link-arg=-Wl,-force_load,bazel-out/darwin-{}/bin/test/unit/native_deps/libalwayslink.lo".format(compilation_mode),
+ "link-arg=-Wl,-force_load,bazel-out/darwin-{}/bin/{}test/unit/native_deps/libalwayslink.lo".format(compilation_mode, workspace_prefix),
@@ -89 +90 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
- "link-arg=/WHOLEARCHIVE:bazel-out/x64_windows-{}/bin/test/unit/native_deps/alwayslink.lo.lib".format(compilation_mode),
+ "link-arg=/WHOLEARCHIVE:bazel-out/x64_windows-{}/bin/{}test/unit/native_deps/alwayslink.lo.lib".format(compilation_mode, workspace_prefix),
@@ -95 +96 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
- "link-arg=bazel-out/k8-{}/bin/test/unit/native_deps/libalwayslink.lo".format(compilation_mode),
+ "link-arg=bazel-out/k8-{}/bin/{}test/unit/native_deps/libalwayslink.lo".format(compilation_mode, workspace_prefix),
@@ -114,0 +116 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx):
+ workspace_prefix = "" if ctx.workspace_name == "rules_rust" else "external/rules_rust/"
@@ -119 +121 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx):
- "link-arg=-Wl,-force_load,bazel-out/darwin-{}/bin/test/unit/native_deps/libalwayslink{}.lo".format(compilation_mode, pic_suffix),
+ "link-arg=-Wl,-force_load,bazel-out/darwin-{}/bin/{}test/unit/native_deps/libalwayslink{}.lo".format(compilation_mode, workspace_prefix, pic_suffix),
@@ -124 +126 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx):
- "link-arg=/WHOLEARCHIVE:bazel-out/x64_windows-{}/bin/test/unit/native_deps/alwayslink.lo.lib".format(compilation_mode),
+ "link-arg=/WHOLEARCHIVE:bazel-out/x64_windows-{}/bin/{}test/unit/native_deps/alwayslink.lo.lib".format(compilation_mode, workspace_prefix),
@@ -130 +132 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx):
- "link-arg=bazel-out/k8-{}/bin/test/unit/native_deps/libalwayslink{}.lo".format(compilation_mode, pic_suffix),
+ "link-arg=bazel-out/k8-{}/bin/{}test/unit/native_deps/libalwayslink{}.lo".format(compilation_mode, workspace_prefix, pic_suffix),

View File

@ -23,10 +23,16 @@ cd "${scripts_dir}"
# Generate some files needed for the tests.
"${bazel}" fetch @io_bazel_rules_go//tests/core/cgo:all
"$("${bazel}" info output_base)/external/io_bazel_rules_go/tests/core/cgo/generate_imported_dylib.sh"
if [[ "$USE_BZLMOD" == "true" ]]; then
"$("${bazel}" info output_base)/external/rules_go~0.40.1/tests/core/cgo/generate_imported_dylib.sh"
else
"$("${bazel}" info output_base)/external/io_bazel_rules_go/tests/core/cgo/generate_imported_dylib.sh"
fi
set -x
test_args=(
"${common_test_args[@]}"
"--enable_bzlmod=${USE_BZLMOD:-false}"
# Fix LLVM version to be 14.0.0 because that's the last known version with
# which the tests in rules_go pass.
"--extra_toolchains=@llvm_toolchain_14_0_0//:all"
@ -39,12 +45,19 @@ test_args=(
# link it statically on linux.
# - external_includes_test from rules_go because it is a nested bazel test and so takes a long time
# to run, and it is not particularly useful to us.
# - time_zone_format_test from abseil-cpp because it assumes TZ is set to America/Los_Angeles, but
# we run the tests in UTC.
# The rules_rust tests should be:
# @rules_rust//test/unit/{native_deps,linkstamps,interleaved_cc_info}:all
# but under bzlmod the linkstamp tests fail due to the fact we are currently
# overriding rules_rust locally as its not yet released in the BCR
"${bazel}" --bazelrc=/dev/null test "${test_args[@]}" -- \
//foreign:pcre \
@openssl//:libssl \
@rules_rust//test/unit/{native_deps,linkstamps,interleaved_cc_info}:all \
@rules_rust//test/unit/interleaved_cc_info:all \
@io_bazel_rules_go//tests/core/cgo:all \
-@io_bazel_rules_go//tests/core/cgo:cc_libs_test \
-@io_bazel_rules_go//tests/core/cgo:external_includes_test \
$("${bazel}" query 'attr(timeout, short, tests(@com_google_absl//absl/...))') \
-@com_google_absl//absl/time/internal/cctz:time_zone_format_test

View File

@ -36,10 +36,12 @@ cd "${scripts_dir}"
set -x
test_args=(
--extra_toolchains="${toolchain_name}"
--copt=-v
--linkopt=-Wl,-t
"--enable_bzlmod=${USE_BZLMOD:-false}"
"--extra_toolchains=${toolchain_name}"
"--copt=-v"
"--linkopt=-Wl,-t"
)
"${bazel}" ${TEST_MIGRATION:+"--strict"} --bazelrc=/dev/null test \
"${common_test_args[@]}" "${test_args[@]}" //:all

View File

View File

@ -0,0 +1,41 @@
"""LLVM extension for use with bzlmod"""
load("@llvm_toolchain//toolchain:rules.bzl", "llvm_toolchain")
load(
"@llvm_toolchain//toolchain/internal:repo.bzl",
_llvm_config_attrs = "llvm_config_attrs",
_llvm_repo_attrs = "llvm_repo_attrs",
)
def _llvm_impl_(module_ctx):
for mod in module_ctx.modules:
if not mod.is_root:
fail("Only the root module can use the 'llvm' extension")
for toolchain_attr in mod.tags.toolchain:
llvm_toolchain(
name = toolchain_attr.name,
llvm_version = toolchain_attr.llvm_version,
llvm_versions = toolchain_attr.llvm_versions,
stdlib = toolchain_attr.stdlib,
sha256 = toolchain_attr.sha256,
strip_prefix = toolchain_attr.strip_prefix,
urls = toolchain_attr.urls,
)
_attrs = {
"name": attr.string(doc = """\
Base name for generated repositories, allowing more than one mylang toolchain to be registered.
Overriding the default is only permitted in the root module.
""", default = "llvm_toolchain"),
}
_attrs.update(_llvm_config_attrs)
_attrs.update(_llvm_repo_attrs)
llvm = module_extension(
implementation = _llvm_impl_,
tag_classes = {
"toolchain": tag_class(
attrs = _attrs,
),
},
)

View File

@ -38,6 +38,16 @@ load(
_aliased_tools = "aliased_tools",
)
# When bzlmod is enabled, canonical repos names have @@ in them, while under
# workspace builds, there is never a @@ in labels.
BZLMOD_ENABLED = "@@" in str(Label("//:unused"))
def _include_dirs_str(rctx, key):
dirs = rctx.attr.cxx_builtin_include_directories.get(key)
if not dirs:
return ""
return ("\n" + 12 * " ").join(["\"%s\"," % d for d in dirs])
def llvm_config_impl(rctx):
_check_os_arch_keys(rctx.attr.sysroot)
_check_os_arch_keys(rctx.attr.cxx_builtin_include_directories)
@ -52,14 +62,16 @@ def llvm_register_toolchains():
return
arch = _arch(rctx)
(key, toolchain_root) = _host_os_arch_dict_value(rctx, "toolchain_roots")
if not toolchain_root:
fail("LLVM toolchain root missing for ({}, {})", os, arch)
(key, llvm_version) = _host_os_arch_dict_value(rctx, "llvm_versions")
if not llvm_version:
fail("LLVM version string missing for ({}, {})", os, arch)
if not rctx.attr.toolchain_roots:
toolchain_root = "@@%s_llvm//" % rctx.attr.name if BZLMOD_ENABLED else "@%s_llvm//" % rctx.attr.name
else:
(_key, toolchain_root) = _host_os_arch_dict_value(rctx, "toolchain_roots")
config_repo_path = "external/%s/" % rctx.name
if not toolchain_root:
fail("LLVM toolchain root missing for ({}, {})".format(os, arch))
(_key, llvm_version) = _host_os_arch_dict_value(rctx, "llvm_versions")
if not llvm_version:
fail("LLVM version string missing for ({}, {})".format(os, arch))
use_absolute_paths_llvm = rctx.attr.absolute_paths
use_absolute_paths_sysroot = use_absolute_paths_llvm
@ -249,7 +261,7 @@ def _cc_toolchains_str(
return cc_toolchains_str, toolchain_labels_str
# Gets a value from the dict for the target pair, falling back to an empty
# key, if present. Bazel 4.* doesn't support nested skylark functions, so
# key, if present. Bazel 4.* doesn't support nested starlark functions, so
# we cannot simplify _dict_value() by defining it as a nested function.
def _dict_value(d, target_pair, default = None):
return d.get(target_pair, d.get("", default))

View File

@ -357,7 +357,7 @@ def download_llvm(rctx):
return updated_attrs
def _urls(rctx):
(key, urls) = _host_os_arch_dict_value(rctx, "urls", debug = True)
(key, urls) = _host_os_arch_dict_value(rctx, "urls", debug = False)
if not urls:
print("LLVM archive URLs missing and no default fallback provided; will try 'distribution' attribute")

View File

@ -11,16 +11,261 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load(
"//toolchain/internal:common.bzl",
_os = "os",
_supported_os_arch_keys = "supported_os_arch_keys",
)
load(
"//toolchain/internal:llvm_distributions.bzl",
_download_llvm = "download_llvm",
)
_target_pairs = ", ".join(_supported_os_arch_keys())
# Atributes common to both `llvm` and `toolchain` repository rules.
common_attrs = {
"llvm_versions": attr.string_dict(
mandatory = False,
doc = ("LLVM version strings, keyed by host OS release name and architecture, " +
"e.g. darwin-x86_64, darwin-aarch64, ubuntu-20.04-x86_64, etc., or a " +
"less specific OS and arch pair ({}). ".format(_target_pairs) +
"An empty key is used to specify a fallback default for all hosts. " +
"If no `toolchain_roots` is given, then the toolchain will be looked up " +
"in the list of known llvm_distributions using the provided version. " +
"If unset, a default value is set from the `llvm_version` attribute."),
),
}
llvm_repo_attrs = dict(common_attrs)
llvm_repo_attrs.update({
"llvm_version": attr.string(
doc = ("One of the supported versions of LLVM, e.g. 12.0.0; used with the " +
"`auto` value for the `distribution` attribute, and as a default value " +
"for the `llvm_versions` attribute."),
),
"urls": attr.string_list_dict(
mandatory = False,
doc = ("URLs to LLVM pre-built binary distribution archives, keyed by host OS " +
"release name and architecture, e.g. darwin-x86_64, darwin-aarch64, " +
"ubuntu-20.04-x86_64, etc., or a less specific OS and arch pair " +
"({}). ".format(_target_pairs) +
"May also need the `strip_prefix` attribute. " +
"Consider also setting the `sha256` attribute. An empty key is " +
"used to specify a fallback default for all hosts. This attribute " +
"overrides `distribution`, `llvm_version`, `llvm_mirror` and " +
"`alternative_llvm_sources` attributes if the host OS key is present."),
),
"sha256": attr.string_dict(
mandatory = False,
doc = "The expected SHA-256 of the file downloaded as per the `urls` attribute.",
),
"strip_prefix": attr.string_dict(
mandatory = False,
doc = "The prefix to strip from the extracted file from the `urls` attribute.",
),
"distribution": attr.string(
default = "auto",
doc = ("LLVM pre-built binary distribution filename, must be one " +
"listed on http://releases.llvm.org/download.html for the version " +
"specified in the `llvm_version` attribute. A special value of " +
"'auto' tries to detect the version based on host OS."),
),
"llvm_mirror": attr.string(
doc = "Base URL for an LLVM release mirror." +
"\n\n" +
"This mirror must follow the same structure as the official LLVM release " +
"sources (`releases.llvm.org` for versions <= 9, `llvm/llvm-project` GitHub " +
"releases for newer versions)." +
"\n\n" +
"If provided, this mirror will be given precedence over the official LLVM release " +
"sources (see: " +
"https://github.com/grailbio/bazel-toolchain/toolchain/internal/llvm_distributions.bzl).",
),
"alternative_llvm_sources": attr.string_list(
doc = "Patterns for alternative LLVM release sources. Unlike URLs specified for `llvm_mirror` " +
"these do not have to follow the same structure as the official LLVM release sources." +
"\n\n" +
"Patterns may include `{llvm_version}` (which will be substituted for the full LLVM " +
"version, i.e. 13.0.0) and `{basename}` (which will be replaced with the filename " +
"used by the official LLVM release sources for a particular distribution; i.e. " +
"`llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz`)." +
"\n\n" +
"As with `llvm_mirror`, these sources will take precedence over the official LLVM " +
"release sources.",
),
"netrc": attr.string(
mandatory = False,
doc = "Path to the netrc file for authenticated LLVM URL downloads.",
),
"auth_patterns": attr.string_dict(
mandatory = False,
doc = "An optional dict mapping host names to custom authorization patterns.",
),
})
_compiler_configuration_attrs = {
"sysroot": attr.string_dict(
mandatory = False,
doc = ("System path or fileset, for each target OS and arch pair you want to support " +
"({}), ".format(_target_pairs) +
"used to indicate the set of files that form the sysroot for the compiler. " +
"If the value begins with exactly one forward slash '/', then the value is " +
"assumed to be a system path. Else, the value will be assumed to be a label " +
"containing the files and the sysroot path will be taken as the path to the " +
"package of this label."),
),
"cxx_builtin_include_directories": attr.string_list_dict(
mandatory = False,
doc = ("Additional builtin include directories to be added to the default system " +
"directories, for each target OS and arch pair you want to support " +
"({}); ".format(_target_pairs) +
"see documentation for bazel's create_cc_toolchain_config_info."),
),
"stdlib": attr.string_dict(
mandatory = False,
doc = ("stdlib implementation, for each target OS and arch pair you want to support " +
"({}), ".format(_target_pairs) +
"linked to the compiled binaries. An empty key can be used to specify a " +
"value for all target pairs. Possible values are `builtin-libc++` (default) " +
"which uses the libc++ shipped with clang, `libc++` which uses libc++ available on " +
"the host or sysroot, `stdc++` which uses libstdc++ available on the host or " +
"sysroot, and `none` which uses `-nostdlib` with the compiler."),
),
"cxx_standard": attr.string_dict(
mandatory = False,
doc = ("C++ standard, for each target OS and arch pair you want to support " +
"({}), ".format(_target_pairs) +
"passed as `-std` flag to the compiler. An empty key can be used to specify a " +
"value for all target pairs. Default value is c++17."),
),
# For default values of all the below flags overrides, consult
# cc_toolchain_config.bzl in this directory.
"compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"cxx_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for cxx_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"link_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for link_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"link_libs": attr.string_list_dict(
mandatory = False,
doc = ("Override for link_libs, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"opt_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for opt_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"opt_link_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for opt_link_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"dbg_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for dbg_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"coverage_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for coverage_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"coverage_link_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for coverage_link_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"unfiltered_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for unfiltered_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"target_settings": attr.string_list_dict(
mandatory = False,
doc = ("Override the toolchain's `target_settings` attribute."),
),
}
llvm_config_attrs = dict(common_attrs)
llvm_config_attrs.update(_compiler_configuration_attrs)
llvm_config_attrs.update({
"toolchain_roots": attr.string_dict(
mandatory = False,
# TODO: Ideally, we should be taking a filegroup label here instead of a package path, but
# we ultimately need to subset the files to be more selective in what we include in the
# sandbox for which operations, and it is not straightforward to subset a filegroup.
doc = ("System or package path, keyed by host OS release name and architecture, e.g. " +
"darwin-x86_64, darwin-aarch64, ubuntu-20.04-x86_64, etc., or a less specific " +
"OS and arch pair ({}), to be used as the LLVM toolchain ".format(_target_pairs) +
"distributions. An empty key can be used to specify a fallback default for " +
"all hosts, e.g. with the llvm_toolchain_repo rule. " +
"If the value begins with exactly one forward slash '/', then the value is " +
"assumed to be a system path and the toolchain is configured to use absolute " +
"paths. Else, the value will be assumed to be a bazel package containing the " +
"filegroup targets as in BUILD.llvm_repo."),
),
"absolute_paths": attr.bool(
default = False,
doc = "Use absolute paths in the toolchain. Avoids sandbox overhead.",
),
"_cc_toolchain_config_bzl": attr.label(
default = "//toolchain:cc_toolchain_config.bzl",
),
"_toolchains_bzl_tpl": attr.label(
default = "//toolchain:toolchains.bzl.tpl",
),
"_build_toolchain_tpl": attr.label(
default = "//toolchain:BUILD.toolchain.tpl",
),
"_darwin_cc_wrapper_sh_tpl": attr.label(
default = "//toolchain:osx_cc_wrapper.sh.tpl",
),
"_cc_wrapper_sh_tpl": attr.label(
default = "//toolchain:cc_wrapper.sh.tpl",
),
})
def llvm_repo_impl(rctx):
os = _os(rctx)
if os == "windows":

View File

@ -12,264 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load(
"//toolchain/internal:common.bzl",
_supported_os_arch_keys = "supported_os_arch_keys",
)
load(
"//toolchain/internal:configure.bzl",
_llvm_config_impl = "llvm_config_impl",
)
load(
"//toolchain/internal:repo.bzl",
_common_attrs = "common_attrs",
_llvm_config_attrs = "llvm_config_attrs",
_llvm_repo_attrs = "llvm_repo_attrs",
_llvm_repo_impl = "llvm_repo_impl",
)
_target_pairs = ", ".join(_supported_os_arch_keys())
# Atributes common to both `llvm` and `toolchain` repository rules.
_common_attrs = {
"llvm_versions": attr.string_dict(
mandatory = False,
doc = ("LLVM version strings, keyed by host OS release name and architecture, " +
"e.g. darwin-x86_64, darwin-aarch64, ubuntu-20.04-x86_64, etc., or a " +
"less specific OS and arch pair ({}). ".format(_target_pairs) +
"An empty key is used to specify a fallback default for all hosts. " +
"If no `toolchain_roots` is given, then the toolchain will be looked up " +
"in the list of known llvm_distributions using the provided version. " +
"If unset, a default value is set from the `llvm_version` attribute."),
),
}
_llvm_repo_attrs = dict(_common_attrs)
_llvm_repo_attrs.update({
"llvm_version": attr.string(
doc = ("One of the supported versions of LLVM, e.g. 12.0.0; used with the " +
"`auto` value for the `distribution` attribute, and as a default value " +
"for the `llvm_versions` attribute."),
),
"urls": attr.string_list_dict(
mandatory = False,
doc = ("URLs to LLVM pre-built binary distribution archives, keyed by host OS " +
"release name and architecture, e.g. darwin-x86_64, darwin-aarch64, " +
"ubuntu-20.04-x86_64, etc., or a less specific OS and arch pair " +
"({}). ".format(_target_pairs) +
"May also need the `strip_prefix` attribute. " +
"Consider also setting the `sha256` attribute. An empty key is " +
"used to specify a fallback default for all hosts. This attribute " +
"overrides `distribution`, `llvm_version`, `llvm_mirror` and " +
"`alternative_llvm_sources` attributes if the host OS key is present."),
),
"sha256": attr.string_dict(
mandatory = False,
doc = "The expected SHA-256 of the file downloaded as per the `urls` attribute.",
),
"strip_prefix": attr.string_dict(
mandatory = False,
doc = "The prefix to strip from the extracted file from the `urls` attribute.",
),
"distribution": attr.string(
default = "auto",
doc = ("LLVM pre-built binary distribution filename, must be one " +
"listed on http://releases.llvm.org/download.html for the version " +
"specified in the `llvm_version` attribute. A special value of " +
"'auto' tries to detect the version based on host OS."),
),
"llvm_mirror": attr.string(
doc = "Base URL for an LLVM release mirror." +
"\n\n" +
"This mirror must follow the same structure as the official LLVM release " +
"sources (`releases.llvm.org` for versions <= 9, `llvm/llvm-project` GitHub " +
"releases for newer versions)." +
"\n\n" +
"If provided, this mirror will be given precedence over the official LLVM release " +
"sources (see: " +
"https://github.com/grailbio/bazel-toolchain/toolchain/internal/llvm_distributions.bzl).",
),
"alternative_llvm_sources": attr.string_list(
doc = "Patterns for alternative LLVM release sources. Unlike URLs specified for `llvm_mirror` " +
"these do not have to follow the same structure as the official LLVM release sources." +
"\n\n" +
"Patterns may include `{llvm_version}` (which will be substituted for the full LLVM " +
"version, i.e. 13.0.0) and `{basename}` (which will be replaced with the filename " +
"used by the official LLVM release sources for a particular distribution; i.e. " +
"`llvm-13.0.0-x86_64-linux-gnu-ubuntu-20.04.tar.xz`)." +
"\n\n" +
"As with `llvm_mirror`, these sources will take precedence over the official LLVM " +
"release sources.",
),
"netrc": attr.string(
mandatory = False,
doc = "Path to the netrc file for authenticated LLVM URL downloads.",
),
"auth_patterns": attr.string_dict(
mandatory = False,
doc = "An optional dict mapping host names to custom authorization patterns.",
),
})
_compiler_configuration_attrs = {
"sysroot": attr.string_dict(
mandatory = False,
doc = ("System path or fileset, for each target OS and arch pair you want to support " +
"({}), ".format(_target_pairs) +
"used to indicate the set of files that form the sysroot for the compiler. " +
"If the value begins with exactly one forward slash '/', then the value is " +
"assumed to be a system path. Else, the value will be assumed to be a label " +
"containing the files and the sysroot path will be taken as the path to the " +
"package of this label."),
),
"cxx_builtin_include_directories": attr.string_list_dict(
mandatory = False,
doc = ("Additional builtin include directories to be added to the default system " +
"directories, for each target OS and arch pair you want to support " +
"({}); ".format(_target_pairs) +
"see documentation for bazel's create_cc_toolchain_config_info."),
),
"stdlib": attr.string_dict(
mandatory = False,
doc = ("stdlib implementation, for each target OS and arch pair you want to support " +
"({}), ".format(_target_pairs) +
"linked to the compiled binaries. An empty key can be used to specify a " +
"value for all target pairs. Possible values are `builtin-libc++` (default) " +
"which uses the libc++ shipped with clang, `libc++` which uses libc++ available on " +
"the host or sysroot, `stdc++` which uses libstdc++ available on the host or " +
"sysroot, and `none` which uses `-nostdlib` with the compiler."),
),
"cxx_standard": attr.string_dict(
mandatory = False,
doc = ("C++ standard, for each target OS and arch pair you want to support " +
"({}), ".format(_target_pairs) +
"passed as `-std` flag to the compiler. An empty key can be used to specify a " +
"value for all target pairs. Default value is c++17."),
),
# For default values of all the below flags overrides, consult
# cc_toolchain_config.bzl in this directory.
"compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"cxx_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for cxx_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"link_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for link_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"link_libs": attr.string_list_dict(
mandatory = False,
doc = ("Override for link_libs, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"opt_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for opt_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"opt_link_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for opt_link_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"dbg_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for dbg_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"coverage_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for coverage_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"coverage_link_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for coverage_link_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"unfiltered_compile_flags": attr.string_list_dict(
mandatory = False,
doc = ("Override for unfiltered_compile_flags, replacing the default values. " +
"`{toolchain_path_prefix}` in the flags will be substituted by the path " +
"to the root LLVM distribution directory. Provide one list for each " +
"target OS and arch pair you want to override " +
"({}); empty key overrides all.".format(_target_pairs)),
),
"target_settings": attr.string_list_dict(
mandatory = False,
doc = ("Override the toolchain's `target_settings` attribute."),
),
}
_llvm_config_attrs = dict(_common_attrs)
_llvm_config_attrs.update(_compiler_configuration_attrs)
_llvm_config_attrs.update({
"toolchain_roots": attr.string_dict(
mandatory = True,
# TODO: Ideally, we should be taking a filegroup label here instead of a package path, but
# we ultimately need to subset the files to be more selective in what we include in the
# sandbox for which operations, and it is not straightforward to subset a filegroup.
doc = ("System or package path, keyed by host OS release name and architecture, e.g. " +
"darwin-x86_64, darwin-aarch64, ubuntu-20.04-x86_64, etc., or a less specific " +
"OS and arch pair ({}), to be used as the LLVM toolchain ".format(_target_pairs) +
"distributions. An empty key can be used to specify a fallback default for " +
"all hosts, e.g. with the llvm_toolchain_repo rule. " +
"If the value begins with exactly one forward slash '/', then the value is " +
"assumed to be a system path and the toolchain is configured to use absolute " +
"paths. Else, the value will be assumed to be a bazel package containing the " +
"filegroup targets as in BUILD.llvm_repo."),
),
"absolute_paths": attr.bool(
default = False,
doc = "Use absolute paths in the toolchain. Avoids sandbox overhead.",
),
"_cc_toolchain_config_bzl": attr.label(
default = "//toolchain:cc_toolchain_config.bzl",
),
"_toolchains_bzl_tpl": attr.label(
default = "//toolchain:toolchains.bzl.tpl",
),
"_build_toolchain_tpl": attr.label(
default = "//toolchain:BUILD.toolchain.tpl",
),
"_darwin_cc_wrapper_sh_tpl": attr.label(
default = "//toolchain:osx_cc_wrapper.sh.tpl",
),
"_cc_wrapper_sh_tpl": attr.label(
default = "//toolchain:cc_wrapper.sh.tpl",
),
})
llvm = repository_rule(
attrs = _llvm_repo_attrs,
local = False,
@ -294,7 +48,6 @@ def llvm_toolchain(name, **kwargs):
if (k not in _llvm_config_attrs.keys()) or (k in _common_attrs.keys())
}
llvm(name = name + "_llvm", **llvm_args)
kwargs.update(toolchain_roots = {"": "@%s_llvm//" % name})
if not kwargs.get("llvm_versions"):
kwargs.update(llvm_versions = {"": kwargs.get("llvm_version")})