Skip to content

Commit 750d8da

Browse files
committed
Init toolchain
1 parent c6bddea commit 750d8da

13 files changed

+377
-381
lines changed

MODULE.bazel

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,11 @@ pip.parse(
6868
)
6969
use_repo(pip, "rules_python_publish_deps")
7070

71-
uv = use_extension("//python/private/uv:uv.bzl", "uv")
72-
uv.download(
73-
files = {
74-
"uv-aarch64-apple-darwin.tar.gz": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72",
75-
"uv-aarch64-unknown-linux-gnu.tar.gz": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845",
76-
"uv-powerpc64le-unknown-linux-gnu.tar.gz": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923",
77-
"uv-s390x-unknown-linux-gnu.tar.gz": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7",
78-
"uv-x86_64-apple-darwin.tar.gz": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0",
79-
"uv-x86_64-pc-windows-msvc.zip": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1",
80-
"uv-x86_64-unknown-linux-gnu.tar.gz": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f",
81-
},
82-
version = "0.2.13",
83-
)
84-
use_repo(uv, "rules_python_uv")
71+
uv = use_extension("//python:extensions.bzl", "uv")
72+
uv.toolchain(uv_version = "0.2.13")
73+
use_repo(uv, "uv_toolchains")
74+
75+
register_toolchains("@uv_toolchains//:all")
8576

8677
# ===== DEV ONLY DEPS AND SETUP BELOW HERE =====
8778
bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc")

python/BUILD.bazel

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ bzl_library(
222222
],
223223
)
224224

225+
bzl_library(
226+
name = "toolchain",
227+
srcs = [":toolchain.bzl"],
228+
visibility = ["//visibility:public"],
229+
)
230+
225231
bzl_library(
226232
name = "versions_bzl",
227233
srcs = ["versions.bzl"],
@@ -336,3 +342,16 @@ exports_files([
336342
current_py_toolchain(
337343
name = "current_py_toolchain",
338344
)
345+
346+
toolchain_type(
347+
name = "uv_toolchain_type",
348+
visibility = ["//visibility:public"],
349+
)
350+
351+
resolved_toolchain(
352+
name = "uv_resolved_toolchain",
353+
# Marked manual so that `bazel test //...` passes
354+
# even if no toolchain is registered.
355+
tags = ["manual"],
356+
visibility = ["//visibility:public"],
357+
)

python/extensions.bzl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Extensions for bzlmod."""
2+
3+
load(":repositories.bzl", "uv_register_toolchains")
4+
5+
_DEFAULT_NAME = "uv"
6+
7+
uv_toolchain = tag_class(attrs = {
8+
"name": attr.string(doc = """\
9+
Base name for generated repositories, allowing more than one uv toolchain to be registered.
10+
Overriding the default is only permitted in the root module.
11+
""", default = "uv"),
12+
"uv_version": attr.string(doc = "Explicit version of uv.", mandatory = True),
13+
})
14+
15+
def _uv_toolchain_extension(module_ctx):
16+
registrations = {}
17+
for mod in module_ctx.modules:
18+
for toolchain in mod.tags.uv_toolchain:
19+
if toolchain.name != _DEFAULT_NAME and not mod.is_root:
20+
fail("""\
21+
Only the root module may override the default name for the uv toolchain.
22+
This prevents conflicting registrations in the global namespace of external repos.
23+
""")
24+
if toolchain.name not in registrations.keys():
25+
registrations[toolchain.name] = []
26+
registrations[toolchain.name].append(toolchain.uv_version)
27+
for name, versions in registrations.items():
28+
if len(versions) > 1:
29+
# TODO: should be semver-aware, using MVS
30+
selected = sorted(versions, reverse = True)[0]
31+
32+
# buildifier: disable=print
33+
print("NOTE: uv toolchain {} has multiple versions {}, selected {}".format(name, versions, selected))
34+
else:
35+
selected = versions[0]
36+
37+
uv_register_toolchains(
38+
name = name,
39+
uv_version = selected,
40+
register = False,
41+
)
42+
43+
uv = module_extension(
44+
implementation = _uv_toolchain_extension,
45+
tag_classes = {"toolchain": uv_toolchain},
46+
)

python/private/pypi/BUILD.bazel

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,21 @@ bzl_library(
236236
srcs = ["whl_target_platforms.bzl"],
237237
deps = [":parse_whl_name_bzl"],
238238
)
239+
240+
bzl_library(
241+
name = "toolchains_repo",
242+
srcs = ["toolchains_repo.bzl"],
243+
visibility = ["//python:__subpackages__"],
244+
)
245+
246+
bzl_library(
247+
name = "versions",
248+
srcs = ["versions.bzl"],
249+
visibility = ["//python:__subpackages__"],
250+
)
251+
252+
bzl_library(
253+
name = "resolved_toolchain",
254+
srcs = ["resolved_toolchain.bzl"],
255+
visibility = ["//python:__subpackages__"],
256+
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2024 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""This module implements an alias rule to the resolved toolchain.
16+
"""
17+
18+
DOC = """\
19+
Exposes a concrete toolchain which is the result of Bazel resolving the
20+
toolchain for the execution or target platform.
21+
Workaround for https://github.com/bazelbuild/bazel/issues/14009
22+
"""
23+
24+
# Forward all the providers
25+
def _uv_resolved_toolchain_impl(ctx):
26+
toolchain_info = ctx.toolchains["//python:uv_toolchain_type"]
27+
return [
28+
toolchain_info,
29+
toolchain_info.defaultinfo,
30+
toolchain_info.templatevariableinfo,
31+
toolchain_info.uvtoolchaininfo,
32+
]
33+
34+
# Copied from java_toolchain_alias
35+
# https://cs.opensource.google/bazel/bazel/+/master:tools/jdk/java_toolchain_alias.bzl
36+
uv_resolved_toolchain = rule(
37+
implementation = _uv_resolved_toolchain_impl,
38+
toolchains = ["//python:uv_toolchain_type"],
39+
incompatible_use_toolchain_transition = True,
40+
doc = DOC,
41+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright 2024 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"Creates a repository to hold toolchains"
16+
17+
UV_PLATFORMS = {
18+
"aarch64-apple-darwin": struct(
19+
compatible_with = [
20+
"@platforms//os:macos",
21+
"@platforms//cpu:aarch64",
22+
],
23+
),
24+
"x86_64-apple-darwin": struct(
25+
compatible_with = [
26+
"@platforms//os:macos",
27+
"@platforms//cpu:x86_64",
28+
],
29+
),
30+
"x86_64-pc-windows-msvc": struct(
31+
compatible_with = [
32+
"@platforms//os:windows",
33+
"@platforms//cpu:x86_64",
34+
],
35+
),
36+
"x86_64-unknown-linux-gnu": struct(
37+
compatible_with = [
38+
"@platforms//os:linux",
39+
"@platforms//cpu:x86_64",
40+
],
41+
),
42+
}
43+
44+
def _toolchains_repo_impl(repository_ctx):
45+
build_content = """# Generated by toolchains_repo.bzl
46+
#
47+
# These can be registered in the workspace file or passed to --extra_toolchains flag.
48+
# By default all these toolchains are registered by the uv_register_toolchains macro
49+
# so you don't normally need to interact with these targets.
50+
51+
"""
52+
53+
for [platform, meta] in UV_PLATFORMS.items():
54+
build_content += """
55+
# Declare a toolchain Bazel will select for running the tool in an action
56+
# on the execution platform.
57+
toolchain(
58+
name = "{platform}_uv_toolchain",
59+
exec_compatible_with = {compatible_with},
60+
toolchain = "@{user_repository_name}_{platform}//:uv_toolchain",
61+
toolchain_type = "@rules_python//python:uv_toolchain_type",
62+
)
63+
""".format(
64+
platform = platform,
65+
user_repository_name = repository_ctx.attr.user_repository_name,
66+
compatible_with = meta.compatible_with,
67+
)
68+
69+
repository_ctx.file("BUILD.bazel", build_content)
70+
71+
uv_toolchains_repo = repository_rule(
72+
_toolchains_repo_impl,
73+
doc = """Creates a repository with toolchain definitions for all known platforms
74+
which can be registered or selected.""",
75+
attrs = {
76+
"user_repository_name": attr.string(doc = "what the user chose for the base name"),
77+
},
78+
)

python/private/pypi/uv_toolchain.bzl

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright 2024 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""This module implements the uv toolchain rule"""
16+
17+
UvToolchainInfo = provider(
18+
doc = "Information about how to invoke the uv executable.",
19+
fields = {
20+
"uv_files": """Files required in runfiles to make the uv executable available.
21+
22+
May be empty if the uv_path points to a locally installed uv binary.""",
23+
"uv_path": "Path to the uv executable.",
24+
},
25+
)
26+
27+
# Avoid using non-normalized paths (workspace/../other_workspace/path)
28+
def _to_manifest_path(ctx, file):
29+
if file.short_path.startswith("../"):
30+
return "external/" + file.short_path[3:]
31+
else:
32+
return ctx.workspace_name + "/" + file.short_path
33+
34+
def _uv_toolchain_impl(ctx):
35+
if ctx.attr.uv_tool and ctx.attr.uv_path:
36+
fail("Can only set one of uv_tool or uv_path but both were set.")
37+
if not ctx.attr.uv_tool and not ctx.attr.uv_path:
38+
fail("Must set one of uv_tool or uv_path.")
39+
40+
uv_files = []
41+
uv_path = ctx.attr.uv_path
42+
43+
if ctx.attr.uv_tool:
44+
uv_files = ctx.attr.uv_tool.files.to_list()
45+
uv_path = _to_manifest_path(ctx, tool_files[0])
46+
47+
# Make the $(UV_BIN) variable available in places like genrules.
48+
# See https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables
49+
templatevariableinfo = platform_common.TemplateVariableInfo({
50+
"UV_BIN": uv_path,
51+
})
52+
defaultinfo = DefaultInfo(
53+
files = depset(uv_files),
54+
runfiles = ctx.runfiles(files = uv_files),
55+
)
56+
uvtoolchaininfo = UvToolchainInfo(
57+
uv_path = uv_path,
58+
uv_files = uv_files,
59+
)
60+
61+
# Export all the providers inside our ToolchainInfo
62+
# so the resolved_toolchain rule can grab and re-export them.
63+
toolchaininfo = platform_common.ToolchainInfo(
64+
uvtoolchaininfo = uvtoolchaininfo,
65+
templatevariableinfo = templatevariableinfo,
66+
defaultinfo = defaultinfo,
67+
)
68+
return [
69+
defaultinfo,
70+
toolchaininfo,
71+
templatevariableinfo,
72+
]
73+
74+
uv_toolchain = rule(
75+
implementation = _uv_toolchain_impl,
76+
attrs = {
77+
"uv_path": attr.string(
78+
doc = "Path to an existing uv executable",
79+
mandatory = False,
80+
),
81+
"uv_tool": attr.label(
82+
doc = "A hermetically downloaded executable target for the target platform.",
83+
mandatory = False,
84+
allow_single_file = True,
85+
),
86+
},
87+
doc = "Defines a uv toolchain.",
88+
)

python/private/pypi/versions.bzl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Version and integrity information for downloaded artifacts"""
2+
3+
# From: https://github.com/astral-sh/uv/releases
4+
UV_TOOL_VERSIONS = {
5+
"0.2.13": {
6+
"aarch64-apple-darwin": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72",
7+
"aarch64-unknown-linux-gnu": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845",
8+
"powerpc64le-unknown-linux-gnu": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923",
9+
"s390x-unknown-linux-gnu": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7",
10+
"x86_64-apple-darwin": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0",
11+
"x86_64-pc-windows-msvc": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1",
12+
"x86_64-unknown-linux-gnu": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f",
13+
},
14+
}

0 commit comments

Comments
 (0)