@@ -72,15 +72,25 @@ def _platforms(*, python_version, minor_mapping, config):
7272 version = python_version ,
7373 minor_mapping = minor_mapping ,
7474 )
75- abi = "cp3{}" .format (python_version [2 :])
7675
7776 for platform , values in config .platforms .items ():
77+ implementation = values .env ["implementation_name" ][:2 ].lower ()
78+ abi = "{}3{}" .format (implementation , python_version [2 :])
7879 key = "{}_{}" .format (abi , platform )
79- platforms [key ] = env (struct (
80+
81+ env_ = env (struct (
8082 abi = abi ,
8183 os = values .os_name ,
8284 arch = values .arch_name ,
8385 )) | values .env
86+ platforms [key ] = struct (
87+ env = env_ ,
88+ want_abis = [
89+ v .format (* python_version .split ("." ))
90+ for v in values .want_abis
91+ ],
92+ platform_tags = values .platform_tags ,
93+ )
8494 return platforms
8595
8696def _create_whl_repos (
@@ -152,6 +162,8 @@ def _create_whl_repos(
152162 ))
153163 python_interpreter_target = available_interpreters [python_name ]
154164
165+ # TODO @aignas 2025-06-29: we should not need the version in the pip_name if
166+ # we are using pipstar and we are downloading the wheel using the downloader
155167 pip_name = "{}_{}" .format (
156168 hub_name ,
157169 version_label (pip_attr .python_version ),
@@ -184,11 +196,15 @@ def _create_whl_repos(
184196 elif config .enable_pipstar :
185197 evaluate_markers = lambda _ , requirements : evaluate_markers_star (
186198 requirements = requirements ,
187- platforms = _platforms (
188- python_version = pip_attr .python_version ,
189- minor_mapping = minor_mapping ,
190- config = config ,
191- ),
199+ platforms = {
200+ k : p .env
201+ # TODO @aignas 2025-07-05: update evaluate_markers_star
202+ for k , p in _platforms (
203+ python_version = pip_attr .python_version ,
204+ minor_mapping = minor_mapping ,
205+ config = config ,
206+ ).items ()
207+ },
192208 )
193209 else :
194210 # NOTE @aignas 2024-08-02: , we will execute any interpreter that we find either
@@ -230,6 +246,11 @@ def _create_whl_repos(
230246 ),
231247 logger = logger ,
232248 ),
249+ platforms = _platforms (
250+ python_version = pip_attr .python_version ,
251+ minor_mapping = minor_mapping ,
252+ config = config ,
253+ ),
233254 extra_pip_args = pip_attr .extra_pip_args ,
234255 get_index_urls = get_index_urls ,
235256 evaluate_markers = evaluate_markers ,
@@ -359,24 +380,16 @@ def _whl_repo(*, src, whl_library_args, is_multiple_versions, download_only, net
359380 for p in src .target_platforms
360381 ]
361382
362- # Pure python wheels or sdists may need to have a platform here
363- target_platforms = None
364- if is_whl and not src .filename .endswith ("-any.whl" ):
365- pass
366- elif is_multiple_versions :
367- target_platforms = src .target_platforms
368-
369383 return struct (
370384 repo_name = whl_repo_name (src .filename , src .sha256 ),
371385 args = args ,
372386 config_setting = whl_config_setting (
373387 version = python_version ,
374- filename = src .filename ,
375- target_platforms = target_platforms ,
388+ target_platforms = src .target_platforms ,
376389 ),
377390 )
378391
379- def _configure (config , * , platform , os_name , arch_name , config_settings , env = {}, override = False ):
392+ def _configure (config , * , platform , os_name , arch_name , config_settings , env = {}, want_abis , platform_tags , override = False ):
380393 """Set the value in the config if the value is provided"""
381394 config .setdefault ("platforms" , {})
382395 if platform :
@@ -393,12 +406,25 @@ def _configure(config, *, platform, os_name, arch_name, config_settings, env = {
393406 if not arch_name :
394407 fail ("'arch_name' is required" )
395408
409+ if platform_tags and "any" not in platform_tags :
410+ # the lowest priority one needs to be the first one
411+ platform_tags = ["any" ] + platform_tags
412+
396413 config ["platforms" ][platform ] = struct (
397414 name = platform .replace ("-" , "_" ).lower (),
398415 os_name = os_name ,
399416 arch_name = arch_name ,
400417 config_settings = config_settings ,
401- env = env ,
418+ want_abis = want_abis or [
419+ "cp{0}{1}" ,
420+ "abi3" ,
421+ "none" ,
422+ ],
423+ platform_tags = platform_tags ,
424+ env = {
425+ # default to this
426+ "implementation_name" : "cpython" ,
427+ } | env ,
402428 )
403429 else :
404430 config ["platforms" ].pop (platform )
@@ -424,28 +450,42 @@ def _create_config(defaults):
424450 arch_name = cpu ,
425451 os_name = "linux" ,
426452 platform = "linux_{}" .format (cpu ),
453+ want_abis = [],
427454 config_settings = [
428455 "@platforms//os:linux" ,
429456 "@platforms//cpu:{}" .format (cpu ),
430457 ],
431- env = {"platform_version" : "0" },
458+ platform_tags = [
459+ "linux_*_{}" .format (cpu ),
460+ "manylinux_*_{}" .format (cpu ),
461+ ],
462+ env = {
463+ "platform_version" : "0" ,
464+ },
432465 )
433- for cpu in [
434- "aarch64" ,
435- "x86_64" ,
436- ] :
466+ for cpu , platform_tag_cpus in {
467+ "aarch64" : [ "universal2" , "arm64" ] ,
468+ "x86_64" : [ "universal2" , "x86_64" ] ,
469+ }. items () :
437470 _configure (
438471 defaults ,
439472 arch_name = cpu ,
440- # We choose the oldest non-EOL version at the time when we release `rules_python`.
441- # See https://endoflife.date/macos
442473 os_name = "osx" ,
443474 platform = "osx_{}" .format (cpu ),
444475 config_settings = [
445476 "@platforms//os:osx" ,
446477 "@platforms//cpu:{}" .format (cpu ),
447478 ],
448- env = {"platform_version" : "14.0" },
479+ want_abis = [],
480+ platform_tags = [
481+ "macosx_*_{}" .format (suffix )
482+ for suffix in platform_tag_cpus
483+ ],
484+ # We choose the oldest non-EOL version at the time when we release `rules_python`.
485+ # See https://endoflife.date/macos
486+ env = {
487+ "platform_version" : "14.0" ,
488+ },
449489 )
450490
451491 _configure (
@@ -457,7 +497,11 @@ def _create_config(defaults):
457497 "@platforms//os:windows" ,
458498 "@platforms//cpu:x86_64" ,
459499 ],
460- env = {"platform_version" : "0" },
500+ want_abis = [],
501+ platform_tags = ["win_amd64" ],
502+ env = {
503+ "platform_version" : "0" ,
504+ },
461505 )
462506 return struct (** defaults )
463507
@@ -527,14 +571,15 @@ You cannot use both the additive_build_content and additive_build_content_file a
527571 env = tag .env ,
528572 os_name = tag .os_name ,
529573 platform = tag .platform ,
574+ platform_tags = tag .platform_tags ,
575+ want_abis = tag .want_abis ,
530576 override = mod .is_root ,
531577 # TODO @aignas 2025-05-19: add more attr groups:
532578 # * for AUTH - the default `netrc` usage could be configured through a common
533579 # attribute.
534580 # * for index/downloader config. This includes all of those attributes for
535581 # overrides, etc. Index overrides per platform could be also used here.
536- # * for whl selection - selecting preferences of which `platform_tag`s we should use
537- # for what. We could also model the `cp313t` freethreaded as separate platforms.
582+ # * for whl selection - We could also model the `cp313t` freethreaded as separate platforms.
538583 )
539584
540585 config = _create_config (defaults )
@@ -666,7 +711,14 @@ You cannot use both the additive_build_content and additive_build_content_file a
666711 for whl_name , aliases in out .extra_aliases .items ():
667712 extra_aliases [hub_name ].setdefault (whl_name , {}).update (aliases )
668713 exposed_packages .setdefault (hub_name , {}).update (out .exposed_packages )
669- whl_libraries .update (out .whl_libraries )
714+ for whl_name , lib in out .whl_libraries .items ():
715+ if enable_pipstar :
716+ whl_libraries .setdefault (whl_name , lib )
717+ elif whl_name in lib :
718+ fail ("'{}' already in created" .format (whl_name ))
719+ else :
720+ # replicate whl_libraries.update(out.whl_libraries)
721+ whl_libraries [whl_name ] = lib
670722
671723 # TODO @aignas 2024-04-05: how do we support different requirement
672724 # cycles for different abis/oses? For now we will need the users to
@@ -829,25 +881,6 @@ The list of labels to `config_setting` targets that need to be matched for the p
829881selected.
830882""" ,
831883 ),
832- "os_name" : attr .string (
833- doc = """\
834- The OS name to be used.
835-
836- :::{note}
837- Either this or the appropriate `env` keys should be specified.
838- :::
839- """ ,
840- ),
841- "platform" : attr .string (
842- doc = """\
843- A platform identifier which will be used as the unique identifier within the extension evaluation.
844- If you are defining custom platforms in your project and don't want things to clash, use extension
845- [isolation] feature.
846-
847- [isolation]: https://bazel.build/rules/lib/globals/module#use_extension.isolate
848- """ ,
849- ),
850- } | {
851884 "env" : attr .string_dict (
852885 doc = """\
853886 The values to use for environment markers when evaluating an expression.
@@ -873,6 +906,40 @@ This is only used if the {envvar}`RULES_PYTHON_ENABLE_PIPSTAR` is enabled.
873906""" ,
874907 ),
875908 # The values for PEP508 env marker evaluation during the lock file parsing
909+ "os_name" : attr .string (
910+ doc = """\
911+ The OS name to be used.
912+
913+ :::{note}
914+ Either this or the appropriate `env` keys should be specified.
915+ :::
916+ """ ,
917+ ),
918+ "platform" : attr .string (
919+ doc = """\
920+ A platform identifier which will be used as the unique identifier within the extension evaluation.
921+ If you are defining custom platforms in your project and don't want things to clash, use extension
922+ [isolation] feature.
923+
924+ [isolation]: https://bazel.build/rules/lib/globals/module#use_extension.isolate
925+ """ ,
926+ ),
927+ "platform_tags" : attr .string_list (
928+ doc = """\
929+ A list of `platform_tag` matchers so that we can select the best wheel based on the user
930+ preference. Per platform we will select a single wheel and the last match from this list will
931+ take precedence.
932+
933+ The items in this list can contain a single `*` character that is equivalent to `.*` regex match.
934+ """ ,
935+ ),
936+ "want_abis" : attr .string_list (
937+ doc = """\
938+ A list of ABIs to select wheels for. The values can be either strings or include template
939+ parameters like `{0}` which will be replaced with python version parts. e.g. `cp{0}{1}` will
940+ result in `cp313` given the full python version is `3.13.5`.
941+ """ ,
942+ ),
876943}
877944
878945_SUPPORTED_PEP508_KEYS = [
0 commit comments