I have a py_binary executable target, and want to use this from a custom rule. I am able to get this to work, but only by duplicating the dependencies of my py_binary target with my custom rule. Is there any way to avoid this duplication and automatically include the dependencies of the py_binary?
I have simplified my problem down to the following (reproduce by running the //foo:main target)
greet/BUILD.bazel
:
py_binary(
name = "greet",
srcs = ["greet.py"],
deps = ["@rules_python//python/runfiles"],
visibility = ["//visibility:public"],
)
greet/greet.py
:
from rules_python.python.runfiles import runfiles
print("hello world")
foo/BUILD.bazel
:
load("//bazel:defs.bzl", "foo_binary")
foo_binary(
name = "main",
)
bazel/BUILD.bazel
: (empty)
bazel/defs.bzl
:
def _foo_binary(ctx):
shell_script = ctx.actions.declare_file("run.sh")
ctx.actions.write(
output = shell_script,
content = """#!/bin/bash
$0.runfiles/svkj/{runtime}
""".format(runtime=ctx.executable._greet.short_path),
is_executable = True,
)
return [
DefaultInfo(
executable = shell_script,
runfiles = ctx.runfiles(
files = ctx.files._greet + ctx.files.deps + ctx.files._python,
collect_data = True
),
),
]
foo_binary = rule(
implementation = _foo_binary,
attrs = {
"deps": attr.label_list(
allow_files=True,
),
"_greet": attr.label(
default = "//greet:greet",
cfg = "exec",
executable = True,
),
# TODO - Why is it necessary to add this explicitly?
"_python": attr.label_list(
allow_files=True,
default = ["@python3_9//:python3", "@rules_python//python/runfiles"],
),
},
executable = True,
)
bazel/BUILD.bazel
:
WORKSPACE:
workspace(name = "svkj")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_python",
sha256 = "5fa3c738d33acca3b97622a13a741129f67ef43f5fdfcec63b29374cc0574c29",
strip_prefix = "rules_python-0.9.0",
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.9.0.tar.gz",
)
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
python_register_toolchains(
name = "python3_9",
python_version = "3.9",
)
load("@python3_9//:defs.bzl", "interpreter")
You need to correctly collect the runfiles of the _greet
binary. Instead of just using the _greet
binary itself, try the following to include its dependencies (and data dependencies) aswell:
DefaultInfo(
executable = shell_script,
runfiles = ctx._greet[DefaultInfo].default_runfiles
)