Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions python/packaging.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

"""Public API for for building wheels."""

load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
load("//python:py_binary.bzl", "py_binary")
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")
load("//python/private:py_package.bzl", "py_package_lib")
Expand Down Expand Up @@ -86,6 +85,39 @@ This also has the advantage that stamping information is included in the wheel's
},
)

def _py_wheel_publish_binary_impl(ctx):
out_name = ctx.attr.out if ctx.attr.out else ctx.label.name
out = ctx.actions.declare_file(out_name)
ctx.actions.symlink(
target_file = ctx.executable.src,
output = out,
is_executable = True,
)
runfiles = ctx.runfiles(files = ctx.files.data)
runfiles = runfiles.merge_all([
dep[DefaultInfo].default_runfiles
for dep in ctx.attr.data + [ctx.attr.src]
])
return [DefaultInfo(executable = out, files = depset([out]), runfiles = runfiles)]

# Like bazel_skylib's native_binary but with cfg = "exec" on src, so the
# twine binary is always built for the exec (host) platform regardless of the
# target platform. This is correct because twine is a developer tool that runs
# on the host to upload wheels to PyPI, never on the cross-compilation target.
_py_wheel_publish_binary = rule(
implementation = _py_wheel_publish_binary_impl,
executable = True,
attrs = {
"src": attr.label(
executable = True,
mandatory = True,
cfg = "exec",
),
Comment on lines +111 to +115

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To ensure full compatibility with bazel_skylib's native_binary and allow passing pre-built binary files directly as src, the src attribute should explicitly set allow_files = True. Without this, passing a file target to src will result in an analysis-phase error.

Suggested change
"src": attr.label(
executable = True,
mandatory = True,
cfg = "exec",
),
"src": attr.label(
executable = True,
allow_files = True,
mandatory = True,
cfg = "exec",
),

"data": attr.label_list(allow_files = True),
"out": attr.string(),
},
Comment on lines +107 to +118
)

def py_wheel(
name,
twine = None,
Expand Down Expand Up @@ -202,7 +234,7 @@ def py_wheel(
twine_args.append("$(rootpath :{})/*".format(dist_target))

if twine_binary:
native_binary(
_py_wheel_publish_binary(
name = "{}.publish".format(name),
src = twine_binary,
out = select({
Expand Down