Description of the problem / feature request:
In rules_go, we have a customizable static analysis system called nogo. There's a nogo rule that generates a binary that is run alongside the Go compiler when building each go_library. Developers use it to define a binary with a customizable set of static analyzers.
I'd like to migrate nogo to the new Starlark Build Configuration system. Ideally, there should be a label_flag that points to a nogo target to use, and that could be set on the command-line. Currently, each go_binary and go_library implicitly depends on a default nogo target, which is set using some hacks involving repository rules. To break the dependency cycle, nogo targets may only depend on targets defined with go_tool_library, a bootstrap rule similar to go_library except it doesn't depend on nogo in order to break the dependency cycle.
Unfortunately, I'm seeing a different kind of dependency cycle. The workspace below is a minimal, standalone example of what I want to do with nogo.
x_binary is analogous to go_binary.
x_checker is analogous to nogo.
- Every
x_binary implicitly depends on a label_flag (with cfg = "exec") that points to an x_checker that depends on an x_binary.
- The
x_checker has an incoming transition that sets the flag to a special target with no dependencies to break the cycle.
Any build involving the label_flag reports a dependency cycle. It doesn't seem like the current value of the flag is taken into account when the dependency graph is loaded.
This works if checker_flag defaults to //:null_checker and is set to another value. It just doesn't work when checker_flag defaults to a real x_checker target.
Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Run bazel build //:x in this workspace:
-- WORKSPACE --
# empty file
-- BUILD.bazel --
load(":def.bzl", "null_checker", "x_binary", "x_checker")
x_binary(
name = "x",
)
label_flag(
name = "checker_flag",
build_setting_default = "//:checker",
)
x_checker(
name = "checker",
dep = ":checker_bin",
)
x_binary(
name = "checker_bin",
)
null_checker(
name = "null_checker",
)
-- def.bzl --
def _x_binary_impl(ctx):
pass
x_binary = rule(
implementation = _x_binary_impl,
attrs = {
"_checker": attr.label(
default = "//:checker_flag",
cfg = "exec",
),
},
)
def _x_checker_transition(settings, attr):
settings = dict(settings)
settings["//:checker_flag"] = "//:null_checker"
return settings
x_checker_transition = transition(
implementation = _x_checker_transition,
inputs = ["//:checker_flag"],
outputs = ["//:checker_flag"],
)
def _x_checker_impl(ctx):
pass
x_checker = rule(
implementation = _x_checker_impl,
attrs = {
"dep": attr.label(mandatory = True),
"_whitelist_function_transition": attr.label(
default = "@bazel_tools//tools/whitelists/function_transition_whitelist",
),
},
cfg = x_checker_transition,
)
def _null_checker_impl(ctx):
pass
null_checker = rule(
implementation = _null_checker_impl,
)
What operating system are you running Bazel on?
Darwin / amd64 (macOS 10.15.4)
What's the output of bazel info release?
release 3.1.0
cc @juliexxia @gregestren @katre
Description of the problem / feature request:
In rules_go, we have a customizable static analysis system called nogo. There's a
nogorule that generates a binary that is run alongside the Go compiler when building eachgo_library. Developers use it to define a binary with a customizable set of static analyzers.I'd like to migrate nogo to the new Starlark Build Configuration system. Ideally, there should be a
label_flagthat points to anogotarget to use, and that could be set on the command-line. Currently, eachgo_binaryandgo_libraryimplicitly depends on a defaultnogotarget, which is set using some hacks involving repository rules. To break the dependency cycle,nogotargets may only depend on targets defined withgo_tool_library, a bootstrap rule similar togo_libraryexcept it doesn't depend onnogoin order to break the dependency cycle.Unfortunately, I'm seeing a different kind of dependency cycle. The workspace below is a minimal, standalone example of what I want to do with
nogo.x_binaryis analogous togo_binary.x_checkeris analogous tonogo.x_binaryimplicitly depends on alabel_flag(withcfg = "exec") that points to anx_checkerthat depends on anx_binary.x_checkerhas an incoming transition that sets the flag to a special target with no dependencies to break the cycle.Any build involving the
label_flagreports a dependency cycle. It doesn't seem like the current value of the flag is taken into account when the dependency graph is loaded.This works if
checker_flagdefaults to//:null_checkerand is set to another value. It just doesn't work whenchecker_flagdefaults to a realx_checkertarget.Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Run
bazel build //:xin this workspace:What operating system are you running Bazel on?
Darwin / amd64 (macOS 10.15.4)
What's the output of
bazel info release?release 3.1.0
cc @juliexxia @gregestren @katre