-
Notifications
You must be signed in to change notification settings - Fork 4.4k
No-op transition causes dependencies to be rebuilt separately from default configuration #11196
Description
Description of the problem / feature request:
Suppose we have an x_binary rule with an incoming edge transition, which can change build settings based on attributes. Most of the time the attributes are not set, so the transition makes no changes (output settings are identical to inputs).
In cases where the transition makes no changes, Bazel should act as if no transition were applied. That is, if an x_binary depends on a file created by another target (x_library), the file should only be generated once, whether the x_library is a dependency of x_binary or the x_library is built directly in the default configuration.
Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Here's a standalone workspace that reproduces this. x_library runs date and writes the output to a file. x_binary just collects files.
-- WORKSPACE --
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "bazel_skylib",
sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
],
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
-- BUILD.bazel --
load(":def.bzl", "x_binary", "x_library")
load("@bazel_skylib//rules:common_settings.bzl", "string_setting")
x_binary(
name = "bin",
deps = ["lib"],
)
x_library(
name = "lib",
)
string_setting(
name = "x_setting",
build_setting_default = "auto",
)
-- def.bzl --
def _x_transition_impl(settings, attr):
return settings
x_transition = transition(
implementation = _x_transition_impl,
inputs = ["//:x_setting"],
outputs = ["//:x_setting"],
)
def _x_binary_impl(ctx):
return [DefaultInfo(files = depset(ctx.files.deps))]
x_binary = rule(
implementation = _x_binary_impl,
attrs = {
"deps": attr.label_list(),
"_whitelist_function_transition": attr.label(
default = "@bazel_tools//tools/whitelists/function_transition_whitelist",
),
},
cfg = x_transition,
)
def _x_library_impl(ctx):
f = ctx.actions.declare_file(ctx.label.name + ".txt")
ctx.actions.run_shell(
outputs = [f],
command = 'date > "$1"',
arguments = [f.path],
)
return [DefaultInfo(files = depset([f]))]
x_library = rule(
implementation = _x_library_impl,
)
Building the binary produces one file:
$ bazel build :bin
Target //:bin up-to-date:
bazel-out/darwin-fastbuild-ST-a8da75533bb21808e51b80cc48e0fbd4a22ad8179cfa2e2acc3ed4c1a7d740fe/bin/lib.txt
$ cat bazel-out/darwin-fastbuild-ST-a8da75533bb21808e51b80cc48e0fbd4a22ad8179cfa2e2acc3ed4c1a7d740fe/bin/lib.txt
Wed Apr 22 14:10:01 EDT 2020
Building the library produces a different file:
$ bazel build :lib
Target //:lib up-to-date:
bazel-bin/lib.txt
$ cat bazel-bin/lib.txt
Wed Apr 22 14:04:00 EDT 2020
What operating system are you running Bazel on?
macOS 10.15.4
What's the output of bazel info release?
release 3.0.0