Skip to content

Commit 346c78c

Browse files
alexeaglef0rmiga
andauthored
feat: Provide a host platform alias (#635)
* feat: Provide a host platform alias This lets users and repository rules access the interpreter for whatever host the repository is running on. * Apply suggestions from code review Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com>
1 parent d7ac042 commit 346c78c

2 files changed

Lines changed: 88 additions & 10 deletions

File tree

python/private/toolchains_repo.bzl

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,64 @@ PLATFORMS = {
2929
"@platforms//os:macos",
3030
"@platforms//cpu:aarch64",
3131
],
32+
# Matches the value returned from:
33+
# repository_ctx.os.name.lower()
34+
os_name = "mac os",
35+
# Matches the value returned from:
36+
# repository_ctx.execute(["uname", "-m"]).stdout.strip()
37+
arch = "arm64",
3238
),
3339
"x86_64-apple-darwin": struct(
3440
compatible_with = [
3541
"@platforms//os:macos",
3642
"@platforms//cpu:x86_64",
3743
],
44+
# See comments above.
45+
os_name = "mac os",
46+
arch = "x86_64",
3847
),
3948
"x86_64-pc-windows-msvc": struct(
4049
compatible_with = [
4150
"@platforms//os:windows",
4251
"@platforms//cpu:x86_64",
4352
],
53+
# See comments above.
54+
os_name = "windows",
55+
arch = "x86_64",
4456
),
4557
"x86_64-unknown-linux-gnu": struct(
4658
compatible_with = [
4759
"@platforms//os:linux",
4860
"@platforms//cpu:x86_64",
4961
],
62+
# See comments above.
63+
os_name = "linux",
64+
arch = "x86_64",
5065
),
5166
}
5267

68+
def host_platform(rctx):
69+
"""Infer the host platform from a repository context.
70+
71+
Args:
72+
rctx: Bazel's repository_ctx
73+
Returns:
74+
a key from the PLATFORMS dictionary
75+
"""
76+
os_name = rctx.os.name
77+
78+
# We assume the arch for Windows is always x86_64.
79+
if "windows" in os_name:
80+
arch = "x86_64"
81+
else:
82+
# This is not ideal, but bazel doesn't directly expose arch.
83+
arch = rctx.execute(["uname", "-m"]).stdout.strip()
84+
85+
for platform, meta in PLATFORMS.items():
86+
if meta.os_name == os_name and meta.arch == arch:
87+
return platform
88+
fail("No platform declared for host OS {} on arch {}".format(os_name, arch))
89+
5390
def _toolchains_repo_impl(repository_ctx):
5491
build_content = """\
5592
# Generated by toolchains_repo.bzl

python/repositories.bzl

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
For historic reasons, pip_repositories() is defined in //python:pip.bzl.
1818
"""
1919

20-
load("//python/private:toolchains_repo.bzl", "PLATFORMS", "toolchains_repo")
21-
load("//python/private:versions.bzl",
22-
"get_release_url",
20+
load("//python/private:toolchains_repo.bzl", "PLATFORMS", "host_platform", "toolchains_repo")
21+
load(
22+
"//python/private:versions.bzl",
2323
"MINOR_MAPPING",
2424
"TOOL_VERSIONS",
25+
"get_release_url",
2526
)
2627

2728
def py_repositories():
@@ -117,20 +118,16 @@ py_runtime_pair(
117118
rctx.file("BUILD.bazel", build_content)
118119

119120
return {
120-
"sha256": download_result.sha256,
121121
"name": rctx.attr.name,
122122
"platform": platform,
123123
"python_version": python_version,
124+
"sha256": download_result.sha256,
124125
}
125126

126127
python_repository = repository_rule(
127128
_python_repository_impl,
128129
doc = "Fetches the external tools needed for the Python toolchain.",
129130
attrs = {
130-
"sha256": attr.string(
131-
doc = "The SHA256 integrity hash for the Python interpreter tarball.",
132-
mandatory = True,
133-
),
134131
"platform": attr.string(
135132
doc = "The platform name for the Python interpreter tarball.",
136133
mandatory = True,
@@ -141,6 +138,48 @@ python_repository = repository_rule(
141138
mandatory = True,
142139
values = TOOL_VERSIONS.keys() + MINOR_MAPPING.keys(),
143140
),
141+
"sha256": attr.string(
142+
doc = "The SHA256 integrity hash for the Python interpreter tarball.",
143+
mandatory = True,
144+
),
145+
},
146+
)
147+
148+
def _host_os_alias_impl(repository_ctx):
149+
# Base BUILD file for this repository.
150+
repository_ctx.file("BUILD.bazel", """\
151+
# Generated by python/repositories.bzl
152+
package(default_visibility = ["//visibility:public"])
153+
alias(name = "files", actual = "@{py_repository}_{host_platform}//:files")
154+
alias(name = "py3_runtime", actual = "@{py_repository}_{host_platform}//:py3_runtime")
155+
alias(name = "python_runtimes", actual = "@{py_repository}_{host_platform}//:python_runtimes")
156+
alias(name = "python3", actual = "@{py_repository}_{host_platform}//:bin/python3")
157+
""".format(
158+
py_repository = repository_ctx.attr.user_repository_name,
159+
host_platform = host_platform(repository_ctx),
160+
))
161+
162+
# Expose a Starlark file so rules can know what host platform we used and where to find an interpreter
163+
# when using repository_ctx.path, which doesn't understand aliases.
164+
repository_ctx.file("defs.bzl", content = """\
165+
# Generated by python/repositories.bzl
166+
host_platform="{host_platform}"
167+
interpreter="@{py_repository}_{host_platform}//:bin/python3"
168+
""".format(
169+
py_repository = repository_ctx.attr.user_repository_name,
170+
host_platform = host_platform(repository_ctx),
171+
))
172+
173+
_host_os_alias = repository_rule(
174+
_host_os_alias_impl,
175+
doc = """Creates a repository with a shorter name meant for the host platform, which contains
176+
a BUILD.bazel file declaring aliases to the host platform's targets.
177+
""",
178+
attrs = {
179+
"user_repository_name": attr.string(
180+
mandatory = True,
181+
doc = "The base name for all created repositories, like 'python38'.",
182+
),
144183
},
145184
)
146185

@@ -150,8 +189,6 @@ def python_register_toolchains(name, python_version, **kwargs):
150189
151190
- Create a repository for each built-in platform like "python_linux_amd64" -
152191
this repository is lazily fetched when Python is needed for that platform.
153-
- TODO(f0rmiga): create a convenience repository for the host platform like
154-
"python_host".
155192
- Create a repository exposing toolchains for each platform like
156193
"python_platforms".
157194
- Register a toolchain pointing at each platform.
@@ -185,6 +222,10 @@ def python_register_toolchains(name, python_version, **kwargs):
185222
platform = platform,
186223
))
187224

225+
_host_os_alias(
226+
name = "{name}_host".format(name = name),
227+
user_repository_name = name,
228+
)
188229
toolchains_repo(
189230
name = "{name}_toolchains".format(name = name),
190231
user_repository_name = name,

0 commit comments

Comments
 (0)