|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
15 | 15 | load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_netrc", "use_netrc")
|
| 16 | +load("@helly25_bzl//bzl/versions:versions.bzl", "versions") |
16 | 17 | load(
|
17 | 18 | "//toolchain/internal:common.bzl",
|
18 | 19 | "attr_dict",
|
@@ -978,14 +979,59 @@ def _find_llvm_basename_or_error(llvm_version, all_llvm_distributions, host_info
|
978 | 979 |
|
979 | 980 | return basenames[0], None
|
980 | 981 |
|
| 982 | +def _parse_version_requirements(version_requirements): |
| 983 | + if version_requirements in ["latest", "first"]: |
| 984 | + return [] |
| 985 | + for prefix in ["latest:", "first:"]: |
| 986 | + if version_requirements.startswith(prefix): |
| 987 | + return versions.parse_requirements(version_requirements.removeprefix(prefix)) |
| 988 | + fail("ERROR: Invalid version requirements: '{version_requirements}'.".format( |
| 989 | + version_requirements = version_requirements, |
| 990 | + )) |
| 991 | + |
| 992 | +def _get_llvm_versions(*, version_requirements, all_llvm_distributions): |
| 993 | + llvm_versions = {} |
| 994 | + for distribution in all_llvm_distributions.keys(): |
| 995 | + version = distribution.split("-")[1] |
| 996 | + llvm_versions[version] = None |
| 997 | + if version_requirements.startswith("latest:"): |
| 998 | + return reversed(llvm_versions.keys()) |
| 999 | + else: |
| 1000 | + return llvm_versions.keys() |
| 1001 | + |
| 1002 | +def _required_llvm_release_name(*, version_requirements, all_llvm_distributions, host_info): |
| 1003 | + llvm_versions = _get_llvm_versions(version_requirements = version_requirements, all_llvm_distributions = all_llvm_distributions) |
| 1004 | + requires = _parse_version_requirements(version_requirements) |
| 1005 | + for llvm_version in llvm_versions: |
| 1006 | + if not versions.check_all_requirements(llvm_version, requires): |
| 1007 | + continue |
| 1008 | + basenames = _find_llvm_basename_list(llvm_version, all_llvm_distributions, host_info) |
| 1009 | + if len(basenames) == 1: |
| 1010 | + return llvm_version, basenames[0], None |
| 1011 | + return None, None, "ERROR: No matching distribution found." |
| 1012 | + |
| 1013 | +def _contains_any(str, chars): |
| 1014 | + for c in chars: |
| 1015 | + if c in str: |
| 1016 | + return True |
| 1017 | + return False |
| 1018 | + |
981 | 1019 | def _distribution_urls(rctx):
|
982 | 1020 | """Return LLVM `urls`, `shha256` and `strip_prefix` for the given context."""
|
983 | 1021 | llvm_version = _get_llvm_version(rctx)
|
984 | 1022 | all_llvm_distributions = _get_all_llvm_distributions(rctx)
|
985 | 1023 | _, sha256, strip_prefix, _ = _key_attrs(rctx)
|
986 | 1024 |
|
987 | 1025 | if rctx.attr.distribution == "auto":
|
988 |
| - basename, error = _find_llvm_basename_or_error(llvm_version, all_llvm_distributions, host_info(rctx)) |
| 1026 | + rctx_host_info = host_info(rctx) |
| 1027 | + if _contains_any(llvm_version, ",:<>!="): |
| 1028 | + llvm_version, basename, error = _required_llvm_release_name( |
| 1029 | + version_requirements = _parse_version_requirements(llvm_version), |
| 1030 | + all_llvm_distributions = all_llvm_distributions, |
| 1031 | + host_info = rctx_host_info, |
| 1032 | + ) |
| 1033 | + else: |
| 1034 | + basename, error = _find_llvm_basename_or_error(llvm_version, all_llvm_distributions, rctx_host_info) |
989 | 1035 | if error:
|
990 | 1036 | fail(error)
|
991 | 1037 | if sha256 and sha256 != all_llvm_distributions[basename]:
|
@@ -1032,7 +1078,7 @@ def _parse_version(v):
|
1032 | 1078 | def _version_string(version):
|
1033 | 1079 | return ".".join([str(v) for v in version])
|
1034 | 1080 |
|
1035 |
| -def _distributions_test_writer_impl(ctx): |
| 1081 | +def _write_distributions_impl(ctx): |
1036 | 1082 | """Analyze the configured versions and write to a file for test consumption.
|
1037 | 1083 |
|
1038 | 1084 | The test generated file '<rule_name>.out' contains the following lines:
|
@@ -1221,3 +1267,80 @@ write_distributions = rule(
|
1221 | 1267 | "select": attr.output(mandatory = True),
|
1222 | 1268 | },
|
1223 | 1269 | )
|
| 1270 | + |
| 1271 | +def _requirements_test_writer_impl(ctx): |
| 1272 | + """Analyze the configured versions and write to a file for test consumption. |
| 1273 | + The test generated file '<rule_name>.out' contains the following lines: |
| 1274 | + [<arch>,<os>,<requirement>]: <llvm_distribution_basename> |
| 1275 | + """ |
| 1276 | + all_llvm_distributions = _llvm_distributions |
| 1277 | + requirement_list = [ |
| 1278 | + "latest:<=20.1.0", |
| 1279 | + "latest:<=20.1.0,>17.0.4,!=19.1.7", |
| 1280 | + "latest:<20.1.0,>17.0.4,!=19.1.7", |
| 1281 | + "latest:<20.1.0,>17.0.4", |
| 1282 | + "latest:>=15.0.6,<16", |
| 1283 | + "first:>=15.0.6,<16", |
| 1284 | + ] |
| 1285 | + arch_list = [ |
| 1286 | + "aarch64", |
| 1287 | + "armv7a", |
| 1288 | + "x86_64", |
| 1289 | + ] |
| 1290 | + os_list = [ |
| 1291 | + "darwin", |
| 1292 | + "linux", |
| 1293 | + "windows", |
| 1294 | + ] |
| 1295 | + ANY_VERSION = "0" # Version does not matter, but must be a valid integer |
| 1296 | + dist_dict_list = { |
| 1297 | + "linux": [ |
| 1298 | + # keep sorted |
| 1299 | + struct(name = "ubuntu", version = ANY_VERSION), |
| 1300 | + struct(name = "raspbian", version = ANY_VERSION), |
| 1301 | + struct(name = "rhel", version = ANY_VERSION), |
| 1302 | + ], |
| 1303 | + } |
| 1304 | + result = [] |
| 1305 | + for arch in arch_list: |
| 1306 | + for os in os_list: |
| 1307 | + dist_list = dist_dict_list.get(os, [struct(name = os, version = "")]) |
| 1308 | + for dist in dist_list: |
| 1309 | + for requirement in requirement_list: |
| 1310 | + host_info = struct( |
| 1311 | + arch = arch, |
| 1312 | + os = os, |
| 1313 | + dist = dist, |
| 1314 | + ) |
| 1315 | + llvm_version, basename, error = _required_llvm_release_name( |
| 1316 | + version_requirements = requirement, |
| 1317 | + all_llvm_distributions = all_llvm_distributions, |
| 1318 | + host_info = host_info, |
| 1319 | + ) |
| 1320 | + if llvm_version and basename: |
| 1321 | + result.append("[{arch},{os}{dist_name}{dist_version},'{requirement}']: {llvm_version} = {basename}".format( |
| 1322 | + arch = arch, |
| 1323 | + os = os, |
| 1324 | + dist_name = "," + dist.name if os == "linux" else "", |
| 1325 | + dist_version = "," + dist.version if os == "linux" else "", |
| 1326 | + requirement = requirement, |
| 1327 | + llvm_version = llvm_version, |
| 1328 | + basename = basename, |
| 1329 | + )) |
| 1330 | + else: |
| 1331 | + result.append("[{arch},{os},\"{requirement}\"]: {error}".format( |
| 1332 | + arch = arch, |
| 1333 | + os = os, |
| 1334 | + requirement = requirement, |
| 1335 | + llvm_version = llvm_version, |
| 1336 | + basename = basename, |
| 1337 | + error = error or "ERROR: N/A", |
| 1338 | + )) |
| 1339 | + ctx.actions.write(ctx.outputs.result, "\n".join(result) + "\n") |
| 1340 | + |
| 1341 | +requirements_test_writer = rule( |
| 1342 | + implementation = _requirements_test_writer_impl, |
| 1343 | + attrs = { |
| 1344 | + "result": attr.output(mandatory = True), |
| 1345 | + }, |
| 1346 | +) |
0 commit comments