Skip to content

Commit 5b4de12

Browse files
fmeumcopybara-github
authored andcommitted
Do not clear --platforms on no-op change to --cpu
Resolves a TODO in the code to not unnecessarily fork the configuration when a transition has `--cpu` as a declared output but doesn't change it. Closes bazelbuild#17158. PiperOrigin-RevId: 501021431 Change-Id: Ib942ea9584b2ceb3083b5fec71e2e11b89dcfdb6
1 parent 72216b7 commit 5b4de12

File tree

2 files changed

+66
-14
lines changed

2 files changed

+66
-14
lines changed

src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java

+16-14
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ static ImmutableMap<String, BuildOptions> applyAndValidate(
9999
}
100100

101101
for (Map.Entry<String, Map<String, Object>> entry : transitions.entrySet()) {
102-
Map<String, Object> newValues = handleImplicitPlatformChange(entry.getValue());
102+
Map<String, Object> newValues =
103+
handleImplicitPlatformChange(buildOptions, entry.getValue());
103104
BuildOptions transitionedOptions =
104105
applyTransition(buildOptions, newValues, optionInfoMap, starlarkTransition);
105106
splitBuildOptions.put(entry.getKey(), transitionedOptions);
@@ -127,21 +128,22 @@ static ImmutableMap<String, BuildOptions> applyAndValidate(
127128
* <p>Transitions can also explicitly set --platforms to be clear what platform they set.
128129
*
129130
* <p>Platform mappings: https://bazel.build/concepts/platforms-intro#platform-mappings.
130-
*
131-
* <p>This doesn't check that the changed value is actually different than the source (i.e.
132-
* setting {@code --cpu=foo} when {@code --cpu} is already {@code foo}). That could unnecessarily
133-
* fork configurations that are really the same. That's a possible optimization TODO.
134131
*/
135132
private static Map<String, Object> handleImplicitPlatformChange(
136-
Map<String, Object> originalOutput) {
137-
boolean changesCpu = originalOutput.containsKey(COMMAND_LINE_OPTION_PREFIX + "cpu");
138-
boolean changesPlatforms = originalOutput.containsKey(COMMAND_LINE_OPTION_PREFIX + "platforms");
139-
return changesCpu && !changesPlatforms
140-
? ImmutableMap.<String, Object>builder()
141-
.putAll(originalOutput)
142-
.put(COMMAND_LINE_OPTION_PREFIX + "platforms", ImmutableList.<Label>of())
143-
.build()
144-
: originalOutput;
133+
BuildOptions options, Map<String, Object> rawTransitionOutput) {
134+
Object newCpu = rawTransitionOutput.get(COMMAND_LINE_OPTION_PREFIX + "cpu");
135+
if (newCpu == null || newCpu.equals(options.get(CoreOptions.class).cpu)) {
136+
// No effective change to --cpu, so no need to prevent the platform mapping from resetting it.
137+
return rawTransitionOutput;
138+
}
139+
if (rawTransitionOutput.containsKey(COMMAND_LINE_OPTION_PREFIX + "platforms")) {
140+
// Explicitly setting --platforms overrides the implicit clearing.
141+
return rawTransitionOutput;
142+
}
143+
return ImmutableMap.<String, Object>builder()
144+
.putAll(rawTransitionOutput)
145+
.put(COMMAND_LINE_OPTION_PREFIX + "platforms", ImmutableList.<Label>of())
146+
.build();
145147
}
146148

147149
private static void checkForDenylistedOptions(StarlarkDefinedConfigTransition transition)

src/test/java/com/google/devtools/build/lib/analysis/StarlarkAttrTransitionProviderTest.java

+50
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,56 @@ public void testNoPlatformChange() throws Exception {
25012501
.containsExactly(Label.parseAbsoluteUnchecked("//platforms:my_platform"));
25022502
}
25032503

2504+
/*
2505+
* If the transition claims to change --cpu but doesn't, it doesn't constitute a platform change
2506+
* and also doesn't affect any other options (such as affectedByStarlarkTransition).
2507+
*/
2508+
@Test
2509+
public void testCpuNoOpChangeIsFullyNoOp() throws Exception {
2510+
writeAllowlistFile();
2511+
scratch.file(
2512+
"platforms/BUILD",
2513+
"platform(name = 'my_platform',",
2514+
" parents = ['" + TestConstants.LOCAL_CONFIG_PLATFORM_PACKAGE_ROOT + ":host'],",
2515+
" constraint_values = [],",
2516+
")");
2517+
scratch.file(
2518+
"test/starlark/my_rule.bzl",
2519+
"def transition_func(settings, attr):",
2520+
// Leave --cpu unchanged, but still trigger the full transition logic that would be
2521+
// bypassed by returning {}.
2522+
" return settings",
2523+
"my_transition = transition(implementation = transition_func,",
2524+
" inputs = [",
2525+
" '//command_line_option:cpu',",
2526+
" ],",
2527+
" outputs = [",
2528+
" '//command_line_option:cpu',",
2529+
" ]",
2530+
")",
2531+
"def impl(ctx): ",
2532+
" return []",
2533+
"my_rule = rule(",
2534+
" implementation = impl,",
2535+
" attrs = {",
2536+
" 'dep': attr.label(cfg = my_transition),",
2537+
" '_allowlist_function_transition': attr.label(",
2538+
" default = '//tools/allowlists/function_transition_allowlist',",
2539+
" ),",
2540+
" })");
2541+
scratch.file(
2542+
"test/starlark/BUILD",
2543+
"load('//test/starlark:my_rule.bzl', 'my_rule')",
2544+
"my_rule(name = 'test', dep = ':main1')",
2545+
"cc_binary(name = 'main1', srcs = ['main1.c'])");
2546+
2547+
ConfiguredTarget topLevel = getConfiguredTarget("//test/starlark:test");
2548+
ConfiguredTarget dep =
2549+
getDirectPrerequisite(getConfiguredTarget("//test/starlark:test"), "//test/starlark:main1");
2550+
assertThat(getConfiguration(dep).getOptions())
2551+
.isEqualTo(getConfiguration(topLevel).getOptions());
2552+
}
2553+
25042554
@Test
25052555
public void testEffectiveNoopTransitionTrimsInputBuildSettings() throws Exception {
25062556
writeAllowlistFile();

0 commit comments

Comments
 (0)