Skip to content

Commit 6e9a65f

Browse files
authored
refactor(internal): move the os/arch detection to repo_utils (#2075)
This also changes the local_runtime_repo to explicitly check for supported platforms instead of relying on a `None` value returned by the helper method. This makes the behaviour exactly the same to the behaviour before this PR and we can potentially drop the need for the validation in the future if our local_runtime detection is more robust. This also makes the platform detectino in `pypi_repo_utils` not depend on `uname` and only use the `repository_ctx`. Apparently the `module_ctx.watch` throws an error if one attempts to watch files on the system (this is left for `repository_rule` it seems and one can only do `module_ctx.watch` on files within the current workspace. This was surprising, but could have been worked around by just unifying code. This splits out things from #2059 and makes the code more succinct. Work towards #260, #1105, #1868.
1 parent 1f0765d commit 6e9a65f

7 files changed

+64
-92
lines changed

python/private/local_runtime_repo.bzl

-16
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,6 @@ def _local_runtime_repo_impl(rctx):
4545
logger = repo_utils.logger(rctx)
4646
on_failure = rctx.attr.on_failure
4747

48-
platforms_os_name = repo_utils.get_platforms_os_name(rctx)
49-
if not platforms_os_name:
50-
if on_failure == "fail":
51-
fail("Unrecognized host platform '{}': cannot determine OS constraint".format(
52-
rctx.os.name,
53-
))
54-
55-
if on_failure == "warn":
56-
logger.warn(lambda: "Unrecognized host platform '{}': cannot determine OS constraint".format(
57-
rctx.os.name,
58-
))
59-
60-
# else, on_failure must be skip
61-
rctx.file("BUILD.bazel", _expand_incompatible_template())
62-
return
63-
6448
result = _resolve_interpreter_path(rctx)
6549
if not result.resolved_path:
6650
if on_failure == "fail":

python/private/pypi/BUILD.bazel

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ bzl_library(
165165
":requirements_files_by_platform_bzl",
166166
":whl_target_platforms_bzl",
167167
"//python/private:normalize_name_bzl",
168+
"//python/private:repo_utils_bzl",
168169
],
169170
)
170171

@@ -233,8 +234,7 @@ bzl_library(
233234
name = "pypi_repo_utils_bzl",
234235
srcs = ["pypi_repo_utils.bzl"],
235236
deps = [
236-
"//python:versions_bzl",
237-
"//python/private:toolchains_repo_bzl",
237+
"//python/private:repo_utils_bzl",
238238
],
239239
)
240240

python/private/pypi/extension.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s
199199
logger = logger,
200200
)
201201

202-
repository_platform = host_platform(module_ctx.os)
202+
repository_platform = host_platform(module_ctx)
203203
for whl_name, requirements in requirements_by_platform.items():
204204
# We are not using the "sanitized name" because the user
205205
# would need to guess what name we modified the whl name

python/private/pypi/parse_requirements.bzl

+5-54
Original file line numberDiff line numberDiff line change
@@ -27,59 +27,11 @@ behavior.
2727
"""
2828

2929
load("//python/private:normalize_name.bzl", "normalize_name")
30+
load("//python/private:repo_utils.bzl", "repo_utils")
3031
load(":index_sources.bzl", "index_sources")
3132
load(":parse_requirements_txt.bzl", "parse_requirements_txt")
3233
load(":whl_target_platforms.bzl", "select_whls")
3334

34-
# This includes the vendored _translate_cpu and _translate_os from
35-
# @platforms//host:extension.bzl at version 0.0.9 so that we don't
36-
# force the users to depend on it.
37-
38-
def _translate_cpu(arch):
39-
if arch in ["i386", "i486", "i586", "i686", "i786", "x86"]:
40-
return "x86_32"
41-
if arch in ["amd64", "x86_64", "x64"]:
42-
return "x86_64"
43-
if arch in ["ppc", "ppc64", "ppc64le"]:
44-
return "ppc"
45-
if arch in ["arm", "armv7l"]:
46-
return "arm"
47-
if arch in ["aarch64"]:
48-
return "aarch64"
49-
if arch in ["s390x", "s390"]:
50-
return "s390x"
51-
if arch in ["mips64el", "mips64"]:
52-
return "mips64"
53-
if arch in ["riscv64"]:
54-
return "riscv64"
55-
return arch
56-
57-
def _translate_os(os):
58-
if os.startswith("mac os"):
59-
return "osx"
60-
if os.startswith("freebsd"):
61-
return "freebsd"
62-
if os.startswith("openbsd"):
63-
return "openbsd"
64-
if os.startswith("linux"):
65-
return "linux"
66-
if os.startswith("windows"):
67-
return "windows"
68-
return os
69-
70-
# TODO @aignas 2024-05-13: consider using the same platform tags as are used in
71-
# the //python:versions.bzl
72-
DEFAULT_PLATFORMS = [
73-
"linux_aarch64",
74-
"linux_arm",
75-
"linux_ppc",
76-
"linux_s390x",
77-
"linux_x86_64",
78-
"osx_aarch64",
79-
"osx_x86_64",
80-
"windows_x86_64",
81-
]
82-
8335
def parse_requirements(
8436
ctx,
8537
*,
@@ -271,20 +223,19 @@ def select_requirement(requirements, *, platform):
271223

272224
return maybe_requirement[0]
273225

274-
def host_platform(repository_os):
226+
def host_platform(ctx):
275227
"""Return a string representation of the repository OS.
276228
277229
Args:
278-
repository_os (struct): The `module_ctx.os` or `repository_ctx.os` attribute.
279-
See https://bazel.build/rules/lib/builtins/repository_os.html
230+
ctx (struct): The `module_ctx` or `repository_ctx` attribute.
280231
281232
Returns:
282233
The string representation of the platform that we can later used in the `pip`
283234
machinery.
284235
"""
285236
return "{}_{}".format(
286-
_translate_os(repository_os.name.lower()),
287-
_translate_cpu(repository_os.arch.lower()),
237+
repo_utils.get_platforms_os_name(ctx),
238+
repo_utils.get_platforms_cpu_name(ctx),
288239
)
289240

290241
def _add_dists(requirement, index_urls, python_version, logger = None):

python/private/pypi/pip_repository.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def _pip_repository_impl(rctx):
8484
)
8585
selected_requirements = {}
8686
options = None
87-
repository_platform = host_platform(rctx.os)
87+
repository_platform = host_platform(rctx)
8888
for name, requirements in requirements_by_platform.items():
8989
r = select_requirement(
9090
requirements,

python/private/pypi/pypi_repo_utils.bzl

+11-10
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414

1515
""
1616

17-
load("//python:versions.bzl", "WINDOWS_NAME")
18-
load("//python/private:toolchains_repo.bzl", "get_host_os_arch")
17+
load("//python/private:repo_utils.bzl", "repo_utils")
1918

2019
def _get_python_interpreter_attr(ctx, *, python_interpreter = None):
2120
"""A helper function for getting the `python_interpreter` attribute or it's default
@@ -30,7 +29,8 @@ def _get_python_interpreter_attr(ctx, *, python_interpreter = None):
3029
if python_interpreter:
3130
return python_interpreter
3231

33-
if "win" in ctx.os.name:
32+
os = repo_utils.get_platforms_os_name(ctx)
33+
if "windows" in os:
3434
return "python.exe"
3535
else:
3636
return "python3"
@@ -39,7 +39,7 @@ def _resolve_python_interpreter(ctx, *, python_interpreter = None, python_interp
3939
"""Helper function to find the python interpreter from the common attributes
4040
4141
Args:
42-
ctx: Handle to the rule repository context.
42+
ctx: Handle to the rule module_ctx or repository_ctx.
4343
python_interpreter: The python interpreter to use.
4444
python_interpreter_target: The python interpreter to use after downloading the label.
4545
@@ -51,11 +51,11 @@ def _resolve_python_interpreter(ctx, *, python_interpreter = None, python_interp
5151
if python_interpreter_target != None:
5252
python_interpreter = ctx.path(python_interpreter_target)
5353

54-
(os, _) = get_host_os_arch(ctx)
54+
os = repo_utils.get_platforms_os_name(ctx)
5555

5656
# On Windows, the symlink doesn't work because Windows attempts to find
5757
# Python DLLs where the symlink is, not where the symlink points.
58-
if os == WINDOWS_NAME:
58+
if "windows" in os:
5959
python_interpreter = python_interpreter.realpath
6060
elif "/" not in python_interpreter:
6161
# It's a plain command, e.g. "python3", to look up in the environment.
@@ -67,22 +67,23 @@ def _resolve_python_interpreter(ctx, *, python_interpreter = None, python_interp
6767
python_interpreter = ctx.path(python_interpreter)
6868
return python_interpreter
6969

70-
def _construct_pypath(rctx, *, entries):
70+
def _construct_pypath(ctx, *, entries):
7171
"""Helper function to construct a PYTHONPATH.
7272
7373
Contains entries for code in this repo as well as packages downloaded from //python/pip_install:repositories.bzl.
7474
This allows us to run python code inside repository rule implementations.
7575
7676
Args:
77-
rctx: Handle to the repository_context.
77+
ctx: Handle to the module_ctx or repository_ctx.
7878
entries: The list of entries to add to PYTHONPATH.
7979
8080
Returns: String of the PYTHONPATH.
8181
"""
8282

83-
separator = ":" if not "windows" in rctx.os.name.lower() else ";"
83+
os = repo_utils.get_platforms_os_name(ctx)
84+
separator = ";" if "windows" in os else ":"
8485
pypath = separator.join([
85-
str(rctx.path(entry).dirname)
86+
str(ctx.path(entry).dirname)
8687
# Use a dict as a way to remove duplicates and then sort it.
8788
for entry in sorted({x: None for x in entries})
8889
])

python/private/repo_utils.bzl

+44-8
Original file line numberDiff line numberDiff line change
@@ -341,25 +341,60 @@ def _outputs_to_str(result):
341341
lines.append("<{} empty>".format(name))
342342
return "\n".join(lines)
343343

344+
# This includes the vendored _translate_cpu and _translate_os from
345+
# @platforms//host:extension.bzl at version 0.0.9 so that we don't
346+
# force the users to depend on it.
347+
344348
def _get_platforms_os_name(rctx):
345349
"""Return the name in @platforms//os for the host os.
346350
347351
Args:
348352
rctx: repository_ctx
349353
350354
Returns:
351-
`str | None`. The target name if it maps to known platforms
352-
value, otherwise None.
355+
`str`. The target name.
353356
"""
354357
os = rctx.os.name.lower()
355-
if "linux" in os:
356-
return os
357-
if "windows" in os:
358-
return "windows"
359-
if "mac" in os:
358+
359+
if os.startswith("mac os"):
360360
return "osx"
361+
if os.startswith("freebsd"):
362+
return "freebsd"
363+
if os.startswith("openbsd"):
364+
return "openbsd"
365+
if os.startswith("linux"):
366+
return "linux"
367+
if os.startswith("windows"):
368+
return "windows"
369+
return os
370+
371+
def _get_platforms_cpu_name(rctx):
372+
"""Return the name in @platforms//cpu for the host arch.
361373
362-
return None
374+
Args:
375+
rctx: repository_ctx
376+
377+
Returns:
378+
`str`. The target name.
379+
"""
380+
arch = rctx.os.arch.lower()
381+
if arch in ["i386", "i486", "i586", "i686", "i786", "x86"]:
382+
return "x86_32"
383+
if arch in ["amd64", "x86_64", "x64"]:
384+
return "x86_64"
385+
if arch in ["ppc", "ppc64", "ppc64le"]:
386+
return "ppc"
387+
if arch in ["arm", "armv7l"]:
388+
return "arm"
389+
if arch in ["aarch64"]:
390+
return "aarch64"
391+
if arch in ["s390x", "s390"]:
392+
return "s390x"
393+
if arch in ["mips64el", "mips64"]:
394+
return "mips64"
395+
if arch in ["riscv64"]:
396+
return "riscv64"
397+
return arch
363398

364399
# TODO: Remove after Bazel 6 support dropped
365400
def _watch(rctx, *args, **kwargs):
@@ -379,6 +414,7 @@ repo_utils = struct(
379414
execute_checked = _execute_checked,
380415
execute_checked_stdout = _execute_checked_stdout,
381416
execute_unchecked = _execute_unchecked,
417+
get_platforms_cpu_name = _get_platforms_cpu_name,
382418
get_platforms_os_name = _get_platforms_os_name,
383419
getenv = _getenv,
384420
is_repo_debug_enabled = _is_repo_debug_enabled,

0 commit comments

Comments
 (0)