@@ -25,6 +25,8 @@ platform-specific repositories.
2525
2626load (
2727 "//python:versions.bzl" ,
28+ "FREETHREADED" ,
29+ "MUSL" ,
2830 "PLATFORMS" ,
2931 "WINDOWS_NAME" ,
3032)
@@ -386,18 +388,18 @@ toolchain_aliases repo because referencing the `python` interpreter target from
386388this repo causes an eager fetch of the toolchain for the host platform.
387389 """ ,
388390 attrs = {
389- "platforms" : attr .string_list (mandatory = True ),
390- "python_version" : attr .string (mandatory = True ),
391- "os_names" : attr .string_dict (
391+ "archs" : attr .string_dict (
392392 doc = """
393393If set, overrides the platform metadata. Keyed by index in `platforms`
394394""" ,
395395 ),
396- "archs " : attr .string_dict (
396+ "os_names " : attr .string_dict (
397397 doc = """
398398If set, overrides the platform metadata. Keyed by index in `platforms`
399399""" ,
400400 ),
401+ "platforms" : attr .string_list (mandatory = True ),
402+ "python_version" : attr .string (mandatory = True ),
401403 "_rule_name" : attr .string (default = "host_toolchain" ),
402404 "_rules_python_workspace" : attr .label (default = Label ("//:WORKSPACE" )),
403405 },
@@ -436,6 +438,46 @@ multi_toolchain_aliases = repository_rule(
436438def sanitize_platform_name (platform ):
437439 return platform .replace ("-" , "_" )
438440
441+ def sorted_host_platforms (platform_map ):
442+ """Sort the keys in the platform map to give correct precedence.
443+
444+ The order of keys in the platform mapping matters for the host toolchain
445+ selection. When multiple runtimes are compatible with the host, we take the
446+ first that is compatible (usually; there's also the
447+ `RULES_PYTHON_REPO_TOOLCHAIN_*` environment variables). The historical
448+ behavior carefully constructed the ordering of platform keys such that
449+ the ordering was:
450+ * Regular platforms
451+ * The "-freethreaded" suffix
452+ * The "-musl" suffix
453+
454+ Here, we formalize that so it isn't subtly encoded in the ordering of keys
455+ in a dict that autoformatters like to clobber and whose only documentation
456+ is an innocous looking formatter disable directive.
457+
458+ Args:
459+ platform_map: a mapping of platforms and their metadata.
460+
461+ Returns:
462+ dict; the same values, but with the keys inserted in the desired
463+ order so that iteration happens in the desired order.
464+ """
465+
466+ def platform_keyer (name ):
467+ # Ascending sort: lower is higher precedence
468+ pref = 0
469+ if name .endswith ("-" + FREETHREADED ):
470+ pref = 1
471+ elif name .endswith ("-" + MUSL ):
472+ pref = 2
473+ return (pref , name )
474+
475+ sorted_platform_keys = sorted (platform_map .keys (), key = platform_keyer )
476+ return {
477+ key : platform_map [key ]
478+ for key in sorted_platform_keys
479+ }
480+
439481def _get_host_platform (* , rctx , logger , python_version , os_name , cpu_name , platforms ):
440482 """Gets the host platform.
441483
@@ -458,7 +500,7 @@ def _get_host_platform(*, rctx, logger, python_version, os_name, cpu_name, platf
458500 arch = rctx .attr .archs [key ],
459501 )
460502 else :
461- platform_map = PLATFORMS
503+ platform_map = sorted_host_platforms ( PLATFORMS )
462504
463505 candidates = []
464506 for platform in platforms :
0 commit comments