Skip to content

Commit

Permalink
Transition on edges not self
Browse files Browse the repository at this point in the history
As per bazelbuild/bazel#15157 currently we
can't configure any transition-relevant attributes using select. This is
because we use self-transitions on targets, and when this happens,
configurable attributes aren't passed to the transition, so we make
incorrect transition decisions.

We only actually consult configuration data in `_go_context_data`, so we
only actually need to transition on the edges which (transitively) reach
a `_go_context_data`, which is `_go_context_data` itself and `deps`.
  • Loading branch information
illicitonion committed Apr 19, 2022
1 parent 787d76a commit f811aa0
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 79 deletions.
27 changes: 20 additions & 7 deletions go/private/context.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -361,20 +361,21 @@ def go_context(ctx, attr = None):
coverdata = None
nogo = None
if hasattr(attr, "_go_context_data"):
if CgoContextInfo in attr._go_context_data:
cgo_context_info = attr._go_context_data[CgoContextInfo]
go_config_info = attr._go_context_data[GoConfigInfo]
stdlib = attr._go_context_data[GoStdLib]
coverdata = attr._go_context_data[GoContextInfo].coverdata
nogo = attr._go_context_data[GoContextInfo].nogo
go_context_data = _flatten(attr._go_context_data)
if CgoContextInfo in go_context_data:
cgo_context_info = go_context_data[CgoContextInfo]
go_config_info = go_context_data[GoConfigInfo]
stdlib = go_context_data[GoStdLib]
coverdata = go_context_data[GoContextInfo].coverdata
nogo = go_context_data[GoContextInfo].nogo
if getattr(attr, "_cgo_context_data", None) and CgoContextInfo in attr._cgo_context_data:
cgo_context_info = attr._cgo_context_data[CgoContextInfo]
if getattr(attr, "cgo_context_data", None) and CgoContextInfo in attr.cgo_context_data:
cgo_context_info = attr.cgo_context_data[CgoContextInfo]
if hasattr(attr, "_go_config"):
go_config_info = attr._go_config[GoConfigInfo]
if hasattr(attr, "_stdlib"):
stdlib = attr._stdlib[GoStdLib]
stdlib = _flatten(attr._stdlib)[GoStdLib]

mode = get_mode(ctx, toolchain, cgo_context_info, go_config_info)
tags = mode.tags
Expand Down Expand Up @@ -828,3 +829,15 @@ go_config = rule(

def _expand_opts(go, attribute_name, opts):
return [go._ctx.expand_make_variables(attribute_name, opt, {}) for opt in opts]

# Used to get attribute values which may have been transitioned.
# Transitioned attributes end up as lists.
# We never use split-transitions, so we always expect exactly one element in those lists.
# But if the attribute wasn't transitioned, it won't be a list.
def _flatten(maybe_list):
if type(maybe_list) == "list":
if len(maybe_list) == 1:
return maybe_list[0]
else:
fail("Expected exactly one element in list but got {}".format(maybe_list))
return maybe_list
4 changes: 2 additions & 2 deletions go/private/mode.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ def get_mode(ctx, go_toolchain, cgo_context_info, go_config_info):
stamp = go_config_info.stamp if go_config_info else False
debug = go_config_info.debug if go_config_info else False
linkmode = go_config_info.linkmode if go_config_info else LINKMODE_NORMAL
goos = go_toolchain.default_goos
goarch = go_toolchain.default_goarch
goos = go_toolchain.default_goos if getattr(ctx.attr, "goos", "auto") == "auto" else ctx.attr.goos
goarch = go_toolchain.default_goarch if getattr(ctx.attr, "goarch", "auto") == "auto" else ctx.attr.goarch

# TODO(jayconrod): check for more invalid and contradictory settings.
if pure and race:
Expand Down
10 changes: 7 additions & 3 deletions go/private/rules/binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ load(
)
load(
"//go/private/rules:transition.bzl",
"go_transition_rule",
"go_transition",
)
load(
"//go/private:mode.bzl",
Expand Down Expand Up @@ -182,6 +182,7 @@ _go_binary_kwargs = {
doc = """List of Go libraries this package imports directly.
These may be `go_library` rules or compatible rules with the [GoLibrary] provider.
""",
cfg = go_transition,
),
"embed": attr.label_list(
providers = [GoLibrary],
Expand All @@ -194,6 +195,7 @@ _go_binary_kwargs = {
embedding binary may not also have `cgo = True`. See [Embedding] for
more information.
""",
cfg = go_transition,
),
"embedsrcs": attr.label_list(
allow_files = True,
Expand Down Expand Up @@ -357,7 +359,10 @@ _go_binary_kwargs = {
</ul>
""",
),
"_go_context_data": attr.label(default = "//:go_context_data"),
"_go_context_data": attr.label(default = "//:go_context_data", cfg = go_transition),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
"executable": True,
"toolchains": ["@io_bazel_rules_go//go:toolchain"],
Expand All @@ -375,7 +380,6 @@ _go_binary_kwargs = {
}

go_binary = rule(**_go_binary_kwargs)
go_transition_binary = go_transition_rule(**_go_binary_kwargs)

def _go_tool_binary_impl(ctx):
sdk = ctx.attr.sdk[GoSDK]
Expand Down
11 changes: 8 additions & 3 deletions go/private/rules/test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ load(
)
load(
"//go/private/rules:transition.bzl",
"go_transition_rule",
"go_transition",
)
load(
"//go/private:mode.bzl",
Expand Down Expand Up @@ -212,6 +212,7 @@ _go_test_kwargs = {
doc = """List of Go libraries this test imports directly.
These may be go_library rules or compatible rules with the [GoLibrary] provider.
""",
cfg = go_transition,
),
"embed": attr.label_list(
providers = [GoLibrary],
Expand All @@ -223,6 +224,7 @@ _go_test_kwargs = {
and the embedding library may not also have `cgo = True`. See [Embedding]
for more information.
""",
cfg = go_transition,
),
"embedsrcs": attr.label_list(
allow_files = True,
Expand Down Expand Up @@ -392,17 +394,21 @@ _go_test_kwargs = {
See [Cross compilation] for more information.
""",
),
"_go_context_data": attr.label(default = "//:go_context_data"),
"_go_context_data": attr.label(default = "//:go_context_data", cfg = go_transition),
"_testmain_additional_deps": attr.label_list(
providers = [GoLibrary],
default = ["//go/tools/bzltestutil"],
cfg = go_transition,
),
# Workaround for bazelbuild/bazel#6293. See comment in lcov_merger.sh.
"_lcov_merger": attr.label(
executable = True,
default = "//go/tools/builders:lcov_merger",
cfg = "target",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
"executable": True,
"test": True,
Expand Down Expand Up @@ -440,7 +446,6 @@ _go_test_kwargs = {
}

go_test = rule(**_go_test_kwargs)
go_transition_test = go_transition_rule(**_go_test_kwargs)

def _recompile_external_deps(go, external_source, internal_archive, library_labels):
"""Recompiles some archives in order to split internal and external tests.
Expand Down
56 changes: 0 additions & 56 deletions go/private/rules/transition.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -54,62 +54,6 @@ def filter_transition_label(label):
else:
return str(Label(label))

def go_transition_wrapper(kind, transition_kind, name, **kwargs):
"""Wrapper for rules that may use transitions.
This is used in place of instantiating go_binary or go_transition_binary
directly. If one of the transition attributes is set explicitly, it
instantiates the rule with a transition. Otherwise, it instantiates the
regular rule. This prevents targets from being rebuilt for an alternative
configuration identical to the default configuration.
"""
transition_keys = ("goos", "goarch", "pure", "static", "msan", "race", "gotags", "linkmode")
need_transition = any([key in kwargs for key in transition_keys])
if need_transition:
transition_kind(name = name, **kwargs)
else:
kind(name = name, **kwargs)

def go_transition_rule(**kwargs):
"""Like "rule", but adds a transition and mode attributes."""
kwargs = dict(kwargs)
kwargs["attrs"].update({
"goos": attr.string(
default = "auto",
values = ["auto"] + {goos: None for goos, _ in GOOS_GOARCH}.keys(),
),
"goarch": attr.string(
default = "auto",
values = ["auto"] + {goarch: None for _, goarch in GOOS_GOARCH}.keys(),
),
"pure": attr.string(
default = "auto",
values = ["auto", "on", "off"],
),
"static": attr.string(
default = "auto",
values = ["auto", "on", "off"],
),
"msan": attr.string(
default = "auto",
values = ["auto", "on", "off"],
),
"race": attr.string(
default = "auto",
values = ["auto", "on", "off"],
),
"gotags": attr.string_list(default = []),
"linkmode": attr.string(
default = "auto",
values = ["auto"] + LINKMODES,
),
"_whitelist_function_transition": attr.label(
default = "@bazel_tools//tools/whitelists/function_transition_whitelist",
),
})
kwargs["cfg"] = go_transition
return rule(**kwargs)

def _go_transition_impl(settings, attr):
# NOTE(bazelbuild/bazel#11409): Calling fail here for invalid combinations
# of flags reports an error but does not stop the build.
Expand Down
10 changes: 2 additions & 8 deletions go/private/rules/wrappers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,10 @@ load(
load(
"//go/private/rules:binary.bzl",
"go_binary",
"go_transition_binary",
)
load(
"//go/private/rules:test.bzl",
"go_test",
"go_transition_test",
)
load(
"//go/private/rules:transition.bzl",
"go_transition_wrapper",
)

def _cgo(name, kwargs):
Expand All @@ -48,7 +42,7 @@ def go_library_macro(name, **kwargs):
def go_binary_macro(name, **kwargs):
"""See docs/go/core/rules.md#go_binary for full documentation."""
_cgo(name, kwargs)
go_transition_wrapper(go_binary, go_transition_binary, name = name, **kwargs)
go_binary(name = name, **kwargs)
if kwargs.get("linkmode") in (LINKMODE_C_ARCHIVE, LINKMODE_C_SHARED):
# Create an alias to tell users of the `.cc` rule that it is deprecated.
native.alias(
Expand All @@ -62,4 +56,4 @@ def go_binary_macro(name, **kwargs):
def go_test_macro(name, **kwargs):
"""See docs/go/core/rules.md#go_test for full documentation."""
_cgo(name, kwargs)
go_transition_wrapper(go_test, go_transition_test, name = name, **kwargs)
go_test(name = name, **kwargs)

0 comments on commit f811aa0

Please sign in to comment.