Skip to content

Commit 23721c9

Browse files
authored
Add extra_llvm_distributions attribute (#495)
This simplifies adding new versions without upgrading the toolchain. Tested: * Removed 20.1.4 and added those instead to the config of a repo using the toolchain. * Added the config for 20.1.4 back to see whether the config can be present in the toolchain and in the user repo.
1 parent ecb27d2 commit 23721c9

File tree

3 files changed

+77
-31
lines changed

3 files changed

+77
-31
lines changed

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,25 @@ We currently offer limited customizability through attributes of the
5050
[llvm_toolchain\_\* rules](toolchain/rules.bzl). You can send us a PR to add
5151
more configuration attributes.
5252

53-
The following shows how to add a specific version for a specific target before
54-
the version was added to [llvm_distributions.bzl](toolchain/internal/llvm_distributions.bzl):
53+
The `MODULE.bazel` example below demonstrates how to add new LLVM distributions before the toolchain has
54+
been updated. They can easily be computed using the provided checksum tool (see `llvm_checksums.sh -h`).
55+
56+
```starlark
57+
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm", dev_dependency = True)
58+
llvm.toolchain(
59+
name = "llvm_toolchain",
60+
llvm_version = "20.1.4",
61+
extra_llvm_distributions = {
62+
"LLVM-20.1.4-Linux-ARM64.tar.xz": "4de80a332eecb06bf55097fd3280e1c69ed80f222e5bdd556221a6ceee02721a",
63+
"LLVM-20.1.4-Linux-X64.tar.xz": "113b54c397adb2039fa45e38dc8107b9ec5a0baead3a3bac8ccfbb65b2340caa",
64+
"LLVM-20.1.4-macOS-ARM64.tar.xz": "debb43b7b364c5cf864260d84ba1b201d49b6460fe84b76eaa65688dfadf19d2",
65+
"clang+llvm-20.1.4-x86_64-pc-windows-msvc.tar.xz": "2b12ac1a0689e29a38a7c98c409cbfa83f390aea30c60b7a06e4ed73f82d2457",
66+
},
67+
)
68+
```
69+
70+
The following `WORKSPACE` snippet shows how to add a specific version for a specific target before
71+
the version was added to [llvm_distributions.bzl](toolchain/internal/llvm_distributions.bzl).
5572

5673
```starlark
5774
llvm_toolchain(

toolchain/internal/llvm_distributions.bzl

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -709,14 +709,16 @@ def download_llvm(rctx):
709709
updated_attrs["sha256"].update([(key, res.sha256)])
710710
return updated_attrs
711711

712-
def _urls(rctx):
713-
(key, urls) = exec_os_arch_dict_value(rctx, "urls", debug = False)
714-
if not urls:
715-
print("LLVM archive URLs missing and no default fallback provided; will try 'distribution' attribute") # buildifier: disable=print
716-
712+
def _key_attrs(rctx):
713+
key, urls = exec_os_arch_dict_value(rctx, "urls", debug = False)
717714
sha256 = rctx.attr.sha256.get(key, default = "")
718715
strip_prefix = rctx.attr.strip_prefix.get(key, default = "")
716+
return urls, sha256, strip_prefix, key
719717

718+
def _urls(rctx):
719+
urls, sha256, strip_prefix, key = _key_attrs(rctx)
720+
if not urls:
721+
print("LLVM archive URLs missing and no default fallback provided; will try 'distribution' attribute") # buildifier: disable=print
720722
return urls, sha256, strip_prefix, key
721723

722724
def _get_llvm_version(rctx):
@@ -736,6 +738,11 @@ def _get_llvm_version(rctx):
736738
)
737739
return llvm_version
738740

741+
def _get_all_llvm_distributions(rctx):
742+
if rctx.attr.extra_llvm_distributions:
743+
return _llvm_distributions | rctx.attr.extra_llvm_distributions
744+
return _llvm_distributions
745+
739746
_UBUNTU_NAMES = [
740747
"arch",
741748
"linuxmint",
@@ -827,16 +834,16 @@ def _dist_to_os_names(dist, default_os_names = []):
827834
] + _UBUNTU_VERSIONS
828835
return default_os_names
829836

830-
def _find_llvm_basenames_by_stem(prefixes, *, is_prefix = False, return_first_match = False):
837+
def _find_llvm_basenames_by_stem(prefixes, *, all_llvm_distributions, is_prefix = False, return_first_match = False):
831838
basenames = []
832839
for prefix in prefixes:
833840
for suffix in [".tar.gz", ".tar.xz"]:
834841
basename = prefix + suffix
835-
if basename in _llvm_distributions:
842+
if basename in all_llvm_distributions:
836843
return [basename]
837844
if not is_prefix:
838845
continue
839-
for llvm_dist in _llvm_distributions:
846+
for llvm_dist in all_llvm_distributions:
840847
if not llvm_dist.startswith(prefix):
841848
continue
842849
for suffix in [".tar.gz", ".tar.xz"]:
@@ -846,8 +853,8 @@ def _find_llvm_basenames_by_stem(prefixes, *, is_prefix = False, return_first_ma
846853
basenames.append(llvm_dist)
847854
return basenames
848855

849-
def _find_llvm_basename_list(llvm_version, host_info):
850-
"""Lookup (llvm_version, arch, os) in the list of basenames in `_llvm_distributions.`"""
856+
def _find_llvm_basename_list(llvm_version, all_llvm_distributions, host_info):
857+
"""Lookup (llvm_version, host_info) in the list of basenames in `all_llvm_distributions.`"""
851858
arch = host_info.arch
852859
os = host_info.os
853860
dist = host_info.dist
@@ -866,7 +873,7 @@ def _find_llvm_basename_list(llvm_version, host_info):
866873
"windows": "Windows",
867874
}.get(os, os),
868875
),
869-
])
876+
], all_llvm_distributions = all_llvm_distributions)
870877
if basenames:
871878
return basenames
872879

@@ -881,15 +888,15 @@ def _find_llvm_basename_list(llvm_version, host_info):
881888
os = select_os,
882889
)
883890
for select_os in ["apple-darwin", "apple-macos", "darwin-apple"]
884-
], is_prefix = True)
891+
], all_llvm_distributions = all_llvm_distributions, is_prefix = True)
885892
elif os == "windows":
886893
return _find_llvm_basenames_by_stem([
887894
"clang+llvm-{llvm_version}-{arch}-{os}".format(
888895
llvm_version = llvm_version,
889896
arch = arch,
890897
os = "pc-windows-msvc",
891898
),
892-
])
899+
], all_llvm_distributions = all_llvm_distributions)
893900
elif dist.name == "raspbian":
894901
return _find_llvm_basenames_by_stem([
895902
"clang+llvm-{llvm_version}-{arch}-{os}".format(
@@ -898,7 +905,7 @@ def _find_llvm_basename_list(llvm_version, host_info):
898905
os = select_os,
899906
)
900907
for select_os in _dist_to_os_names(dist)
901-
])
908+
], all_llvm_distributions = all_llvm_distributions)
902909
elif os == "linux":
903910
if arch in ["aarch64", "armv7a", "mips", "mipsel", "sparc64", "sparcv9"]:
904911
arch_alias_list = {
@@ -914,7 +921,7 @@ def _find_llvm_basename_list(llvm_version, host_info):
914921
)
915922
for arch_alias in arch_alias_list
916923
for os_name in ["linux-gnu", "unknown-linux-gnu"] + _dist_to_os_names(dist)
917-
])
924+
], all_llvm_distributions = all_llvm_distributions)
918925

919926
arch_alias_list = {
920927
"x86_32": ["x86_32", "i386"],
@@ -932,7 +939,7 @@ def _find_llvm_basename_list(llvm_version, host_info):
932939
dist_name = dist_name,
933940
dist_version = dist.version,
934941
),
935-
])
942+
], all_llvm_distributions = all_llvm_distributions)
936943
if basenames:
937944
return basenames
938945
if dist.name not in ["freebsd"]:
@@ -941,11 +948,11 @@ def _find_llvm_basename_list(llvm_version, host_info):
941948
arch = arch_alias,
942949
dist_name = dist_name,
943950
))
944-
return _find_llvm_basenames_by_stem(prefixes, is_prefix = True, return_first_match = True)
951+
return _find_llvm_basenames_by_stem(prefixes, all_llvm_distributions = all_llvm_distributions, is_prefix = True, return_first_match = True)
945952
return []
946953

947-
def _find_llvm_basename_or_error(llvm_version, host_info):
948-
basenames = _find_llvm_basename_list(llvm_version, host_info)
954+
def _find_llvm_basename_or_error(llvm_version, all_llvm_distributions, host_info):
955+
basenames = _find_llvm_basename_list(llvm_version, all_llvm_distributions, host_info)
949956
if len(basenames) > 1:
950957
return None, "ERROR: Multiple configurations found for version {llvm_version} on {os}/{dist_name}/{dist_version} with arch {arch}: [{basenames}].".format(
951958
llvm_version = llvm_version,
@@ -966,21 +973,36 @@ def _find_llvm_basename_or_error(llvm_version, host_info):
966973

967974
# Use the following for debugging:
968975
# print("Found LLVM: " + basenames[0]) # buildifier: disable=print
976+
if basenames[0] not in all_llvm_distributions:
977+
return None, "ERROR: Unknown LLVM release: %s\nPlease ensure file name is correct." % basenames[0]
978+
969979
return basenames[0], None
970980

971981
def _distribution_urls(rctx):
972982
"""Return LLVM `urls`, `shha256` and `strip_prefix` for the given context."""
973983
llvm_version = _get_llvm_version(rctx)
984+
all_llvm_distributions = _get_all_llvm_distributions(rctx)
985+
_, sha256, strip_prefix, _ = _key_attrs(rctx)
974986

975987
if rctx.attr.distribution == "auto":
976-
basename, error = _find_llvm_basename_or_error(llvm_version, host_info(rctx))
988+
basename, error = _find_llvm_basename_or_error(llvm_version, all_llvm_distributions, host_info(rctx))
977989
if error:
978990
fail(error)
991+
if sha256 and sha256 != all_llvm_distributions[basename]:
992+
fail("ERROR: Attribute sha256 provided a different SHA than the stored one.")
993+
sha256 = all_llvm_distributions[basename]
979994
else:
980995
basename = rctx.attr.distribution
996+
if sha256:
997+
if basename in all_llvm_distributions and sha256 != all_llvm_distributions[basename]:
998+
fail("ERROR: Attribute sha256 provided a different SHA than the stored one.")
999+
elif basename in all_llvm_distributions:
1000+
sha256 = all_llvm_distributions[basename]
1001+
else:
1002+
fail("ERROR: Unknown LLVM release: %s\nPlease ensure file name is correct." % basename)
9811003

982-
if basename not in _llvm_distributions:
983-
fail("ERROR: Unknown LLVM release: %s\nPlease ensure file name is correct." % basename)
1004+
if basename.startswith("http"):
1005+
return [basename], sha256, strip_prefix
9841006

9851007
urls = []
9861008
url_suffix = "{0}/{1}".format(llvm_version, basename).replace("+", "%2B")
@@ -992,8 +1014,6 @@ def _distribution_urls(rctx):
9921014
url_base = _llvm_distributions_base_url.get(llvm_version, _llvm_distributions_base_url_default)
9931015
urls.append(url_base + url_suffix)
9941016

995-
sha256 = _llvm_distributions[basename]
996-
9971017
strip_prefix = ""
9981018
for suffix in [".exe", ".tar.gz", ".tar.xz", ".tar.zst"]:
9991019
if basename.endswith(suffix):
@@ -1023,6 +1043,7 @@ def _write_distributions_impl(ctx):
10231043
verify that predicted distributions have been configured. Otherwise the
10241044
algorithm could not know the hash value.
10251045
"""
1046+
all_llvm_distributions = _llvm_distributions
10261047
arch_list = [
10271048
"aarch64",
10281049
"armv7a",
@@ -1087,7 +1108,7 @@ def _write_distributions_impl(ctx):
10871108
MIN_VERSION = _parse_version("6.0.0")
10881109
MAX_VERSION = _parse_version("20.1.3")
10891110
version_list = []
1090-
for name in _llvm_distributions.keys():
1111+
for name in all_llvm_distributions.keys():
10911112
for prefix in ["LLVM-", "clang+llvm-"]:
10921113
if name.startswith(prefix):
10931114
version = _parse_version(name.split("-", 2)[1])
@@ -1110,7 +1131,7 @@ def _write_distributions_impl(ctx):
11101131
# So at the end all version that were not found remain, hence the name.
11111132
not_found = {
11121133
k: v
1113-
for k, v in _llvm_distributions.items()
1134+
for k, v in all_llvm_distributions.items()
11141135
if _parse_version(k.split("-")[1]) >= MIN_VERSION
11151136
}
11161137

@@ -1132,10 +1153,11 @@ def _write_distributions_impl(ctx):
11321153
os = os,
11331154
dist = dist,
11341155
)
1135-
basenames = _find_llvm_basename_list(_version_string(version), host_info)
1156+
basenames = _find_llvm_basename_list(_version_string(version), all_llvm_distributions, host_info)
11361157
if version <= MAX_VERSION:
11371158
predicted, error = _find_llvm_basename_or_error(
11381159
_version_string(version),
1160+
all_llvm_distributions,
11391161
host_info,
11401162
)
11411163
if error:
@@ -1145,7 +1167,7 @@ def _write_distributions_impl(ctx):
11451167
else:
11461168
if predicted.endswith(".exe"):
11471169
error = "ERROR: Windows .exe is not supported: " + predicted
1148-
elif predicted not in _llvm_distributions:
1170+
elif predicted not in all_llvm_distributions:
11491171
error = "ERROR: Unavailable prediction: " + predicted
11501172
elif len(basenames) == 0:
11511173
error = "ERROR: No version selected"
@@ -1178,7 +1200,7 @@ def _write_distributions_impl(ctx):
11781200
dupes.extend([" : " + basename for basename in basenames])
11791201
continue
11801202
basename = basenames[0]
1181-
if basename in _llvm_distributions:
1203+
if basename in all_llvm_distributions:
11821204
if basename in not_found:
11831205
not_found.pop(basename)
11841206
else:

toolchain/internal/repo.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ llvm_repo_attrs.update({
5252
"`auto` value for the `distribution` attribute, and as a default value " +
5353
"for the `llvm_versions` attribute."),
5454
),
55+
"extra_llvm_distributions": attr.string_dict(
56+
mandatory = False,
57+
doc = ("A dictionary that maps distributions to their SHA256 values. " +
58+
"It allows for simple additon of llvm distributiosn using the " +
59+
"'utils/lvm_checksums.sh' tool. This also allows to use the " +
60+
"distributions lists of future toolchain versions."),
61+
),
5562
"urls": attr.string_list_dict(
5663
mandatory = False,
5764
doc = ("URLs to LLVM pre-built binary distribution archives, keyed by host OS " +

0 commit comments

Comments
 (0)