Skip to content

Commit c678623

Browse files
rickeylevaignas
andauthored
refactor: explicitly define host platform ordering (#2890)
It turns out the `unsorted-dict-items` disable in versions.bzl is load-bearing: the precedence of what host-compatible runtime is selected depends on the order of keys. Hence, the keys are carefully defined such that freethreaded and musl come after the regular runtimes. Make this subtle and implicit behavior explicit by having an ordering function that sorts keys in the order we want. Work towards #2081 --------- Co-authored-by: Ignas Anikevicius <[email protected]>
1 parent f36d120 commit c678623

File tree

3 files changed

+62
-17
lines changed

3 files changed

+62
-17
lines changed

python/private/python.bzl

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ load(":full_version.bzl", "full_version")
2121
load(":python_register_toolchains.bzl", "python_register_toolchains")
2222
load(":pythons_hub.bzl", "hub_repo")
2323
load(":repo_utils.bzl", "repo_utils")
24-
load(":toolchains_repo.bzl", "host_toolchain", "multi_toolchain_aliases")
24+
load(":toolchains_repo.bzl", "host_toolchain", "multi_toolchain_aliases", "sorted_host_platforms")
2525
load(":util.bzl", "IS_BAZEL_6_4_OR_HIGHER")
2626
load(":version.bzl", "version")
2727

@@ -298,9 +298,8 @@ def _python_impl(module_ctx):
298298
_internal_bzlmod_toolchain_call = True,
299299
**kwargs
300300
)
301-
host_platforms = []
302-
host_os_names = {}
303-
host_archs = {}
301+
302+
host_platforms = {}
304303
for repo_name, (platform_name, platform_info) in register_result.impl_repos.items():
305304
toolchain_impls.append(struct(
306305
# str: The base name to use for the toolchain() target
@@ -319,17 +318,21 @@ def _python_impl(module_ctx):
319318
set_python_version_constraint = is_last,
320319
))
321320
if _is_compatible_with_host(module_ctx, platform_info):
322-
host_key = str(len(host_platforms))
323-
host_platforms.append(platform_name)
324-
host_os_names[host_key] = platform_info.os_name
325-
host_archs[host_key] = platform_info.arch
321+
host_platforms[platform_name] = platform_info
326322

323+
host_platforms = sorted_host_platforms(host_platforms)
327324
host_toolchain(
328325
name = toolchain_info.name + "_host",
329326
# NOTE: Order matters. The first found to be compatible is (usually) used.
330-
platforms = host_platforms,
331-
os_names = host_os_names,
332-
arch_names = host_archs,
327+
platforms = host_platforms.keys(),
328+
os_names = {
329+
str(i): platform_info.os_name
330+
for i, platform_info in enumerate(host_platforms.values())
331+
},
332+
arch_names = {
333+
str(i): platform_info.arch
334+
for i, platform_info in enumerate(host_platforms.values())
335+
},
333336
python_version = full_python_version,
334337
)
335338

python/private/toolchains_repo.bzl

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ platform-specific repositories.
2525

2626
load(
2727
"//python:versions.bzl",
28+
"FREETHREADED",
29+
"MUSL",
2830
"PLATFORMS",
2931
"WINDOWS_NAME",
3032
)
@@ -433,6 +435,44 @@ multi_toolchain_aliases = repository_rule(
433435
},
434436
)
435437

438+
def sorted_host_platforms(platform_map):
439+
"""Sort the keys in the platform map to give correct precedence.
440+
441+
The order of keys in the platform mapping matters for the host toolchain
442+
selection. When multiple runtimes are compatible with the host, we take the
443+
first that is compatible (usually; there's also the
444+
`RULES_PYTHON_REPO_TOOLCHAIN_*` environment variables). The historical
445+
behavior carefully constructed the ordering of platform keys such that
446+
the ordering was:
447+
* Regular platforms
448+
* The "-freethreaded" suffix
449+
* The "-musl" suffix
450+
451+
Here, we formalize that so it isn't subtly encoded in the ordering of keys
452+
in a dict that autoformatters like to clobber and whose only documentation
453+
is an innocous looking formatter disable directive.
454+
455+
Args:
456+
platform_map: a mapping of platforms and their metadata.
457+
458+
Returns:
459+
dict; the same values, but with the keys inserted in the desired
460+
order so that iteration happens in the desired order.
461+
"""
462+
463+
def platform_keyer(name):
464+
# Ascending sort: lower is higher precedence
465+
return (
466+
1 if MUSL in name else 0,
467+
1 if FREETHREADED in name else 0,
468+
)
469+
470+
sorted_platform_keys = sorted(platform_map.keys(), key = platform_keyer)
471+
return {
472+
key: platform_map[key]
473+
for key in sorted_platform_keys
474+
}
475+
436476
def _get_host_platform(*, rctx, logger, python_version, os_name, cpu_name, platforms):
437477
"""Gets the host platform.
438478
@@ -455,7 +495,7 @@ def _get_host_platform(*, rctx, logger, python_version, os_name, cpu_name, platf
455495
arch = rctx.attr.arch_names[key],
456496
)
457497
else:
458-
platform_map = PLATFORMS
498+
platform_map = sorted_host_platforms(PLATFORMS)
459499

460500
candidates = []
461501
for platform in platforms:

python/versions.bzl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
MACOS_NAME = "osx"
2020
LINUX_NAME = "linux"
2121
WINDOWS_NAME = "windows"
22-
FREETHREADED = "freethreaded"
22+
23+
FREETHREADED = "-freethreaded"
24+
MUSL = "-musl"
2325
INSTALL_ONLY = "install_only"
2426

2527
DEFAULT_RELEASE_BASE_URL = "https://github.com/astral-sh/python-build-standalone/releases/download"
@@ -845,7 +847,7 @@ def _generate_platforms():
845847
for p, v in platforms.items()
846848
for suffix, freethreadedness in {
847849
"": is_freethreaded_no,
848-
"-" + FREETHREADED: is_freethreaded_yes,
850+
FREETHREADED: is_freethreaded_yes,
849851
}.items()
850852
}
851853

@@ -879,11 +881,11 @@ def get_release_info(platform, python_version, base_url = DEFAULT_RELEASE_BASE_U
879881
release_filename = None
880882
rendered_urls = []
881883
for u in url:
882-
p, _, _ = platform.partition("-" + FREETHREADED)
884+
p, _, _ = platform.partition(FREETHREADED)
883885

884-
if FREETHREADED in platform:
886+
if FREETHREADED.lstrip("-") in platform:
885887
build = "{}+{}-full".format(
886-
FREETHREADED,
888+
FREETHREADED.lstrip("-"),
887889
{
888890
"aarch64-apple-darwin": "pgo+lto",
889891
"aarch64-unknown-linux-gnu": "lto",

0 commit comments

Comments
 (0)