Skip to content

Commit 57fc3d2

Browse files
committed
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.
1 parent e2759df commit 57fc3d2

File tree

2 files changed

+64
-14
lines changed

2 files changed

+64
-14
lines changed

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

Lines changed: 16 additions & 14 deletions
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 = handleImplicitPlatformChange(buildOptions,
103+
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> originalOutput) {
134+
Object newCpu = originalOutput.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 originalOutput;
138+
}
139+
if (originalOutput.containsKey(COMMAND_LINE_OPTION_PREFIX + "platforms")) {
140+
// Explicitly setting --platforms overrides the implicit clearing.
141+
return originalOutput;
142+
}
143+
return ImmutableMap.<String, Object>builder()
144+
.putAll(originalOutput)
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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,54 @@ 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+
" return settings",
2521+
"my_transition = transition(implementation = transition_func,",
2522+
" inputs = [",
2523+
" '//command_line_option:cpu',",
2524+
" ],",
2525+
" outputs = [",
2526+
" '//command_line_option:cpu',",
2527+
" ]",
2528+
")",
2529+
"def impl(ctx): ",
2530+
" return []",
2531+
"my_rule = rule(",
2532+
" implementation = impl,",
2533+
" attrs = {",
2534+
" 'dep': attr.label(cfg = my_transition),",
2535+
" '_allowlist_function_transition': attr.label(",
2536+
" default = '//tools/allowlists/function_transition_allowlist',",
2537+
" ),",
2538+
" })");
2539+
scratch.file(
2540+
"test/starlark/BUILD",
2541+
"load('//test/starlark:my_rule.bzl', 'my_rule')",
2542+
"my_rule(name = 'test', dep = ':main1')",
2543+
"cc_binary(name = 'main1', srcs = ['main1.c'])");
2544+
2545+
ConfiguredTarget topLevel = getConfiguredTarget("//test/starlark:test");
2546+
ConfiguredTarget dep =
2547+
getDirectPrerequisite(getConfiguredTarget("//test/starlark:test"), "//test/starlark:main1");
2548+
assertThat(getConfiguration(dep).getOptions()).isEqualTo(
2549+
getConfiguration(topLevel).getOptions());
2550+
}
2551+
25042552
@Test
25052553
public void testEffectiveNoopTransitionTrimsInputBuildSettings() throws Exception {
25062554
writeAllowlistFile();

0 commit comments

Comments
 (0)