Skip to content

Commit ddbac4a

Browse files
ckolli5Yannic
andauthored
Add incompatible flag to disable cfg="host" from Starlark (bazelbuild#15436)
Host transitions are problematic where the host and exec environment are different (e.g., with Remote Execution). This change adds an incompatible flag that fails analysis if Starlark rules use `cfg = "host"`. Migrating is pretty straigt forward (replace `host` with `exec`) and should be automatable by buildifier (although I haven't tried to do so). Closes bazelbuild#14383. PiperOrigin-RevId: 441253060 Co-authored-by: Yannic <[email protected]>
1 parent e239f58 commit ddbac4a

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import com.google.devtools.build.lib.packages.Type;
4242
import com.google.devtools.build.lib.packages.Type.ConversionException;
4343
import com.google.devtools.build.lib.packages.Type.LabelClass;
44+
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
45+
import com.google.devtools.build.lib.starlarkbuildapi.NativeComputedDefaultApi;
4446
import com.google.devtools.build.lib.starlarkbuildapi.StarlarkAttrModuleApi;
4547
import com.google.devtools.build.lib.util.FileType;
4648
import com.google.devtools.build.lib.util.FileTypeSet;
@@ -226,7 +228,16 @@ && containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
226228
"late-bound attributes must not have a split configuration transition");
227229
}
228230
if (trans.equals("host")) {
229-
builder.cfg(HostTransition.createFactory());
231+
boolean disableStarlarkHostTransitions =
232+
thread
233+
.getSemantics()
234+
.getBool(BuildLanguageOptions.INCOMPATIBLE_DISABLE_STARLARK_HOST_TRANSITIONS);
235+
if (disableStarlarkHostTransitions) {
236+
throw new EvalException(
237+
"'cfg = \"host\"' is deprecated and should no longer be used. Please use "
238+
+ "'cfg = \"exec\"' instead.");
239+
}
240+
builder.cfg(ExecutionTransitionFactory.create());
230241
} else if (trans.equals("exec")) {
231242
builder.cfg(ExecutionTransitionFactory.create());
232243
} else if (trans instanceof ExecutionTransitionFactory) {
@@ -252,8 +263,8 @@ && containsNonNoneKey(arguments, ALLOW_SINGLE_FILE_ARG)) {
252263
// android_split_transition because users of those transitions should already know about
253264
// them.
254265
throw Starlark.errorf(
255-
"cfg must be either 'host', 'target', 'exec' or a starlark defined transition defined"
256-
+ " by the exec() or transition() functions.");
266+
"cfg must be either 'target', 'exec' or a starlark defined transition defined by the "
267+
+ "exec() or transition() functions.");
257268
}
258269
}
259270

src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,17 @@ public class BuildLanguageOptions extends OptionsBase implements Serializable {
548548
+ " providers of the aspect.")
549549
public boolean incompatibleTopLevelAspectsRequireProviders;
550550

551+
@Option(
552+
name = "incompatible_disable_starlark_host_transitions",
553+
defaultValue = "false",
554+
documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS,
555+
metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
556+
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
557+
help =
558+
"If set to true, rule attributes cannot set 'cfg = \"host\"'. Rules should set "
559+
+ "'cfg = \"exec\"' instead.")
560+
public boolean incompatibleDisableStarlarkHostTransitions;
561+
551562
/**
552563
* An interner to reduce the number of StarlarkSemantics instances. A single Blaze instance should
553564
* never accumulate a large number of these and being able to shortcut on object identity makes a
@@ -615,6 +626,9 @@ public StarlarkSemantics toStarlarkSemantics() {
615626
.setBool(
616627
INCOMPATIBLE_TOP_LEVEL_ASPECTS_REQUIRE_PROVIDERS,
617628
incompatibleTopLevelAspectsRequireProviders)
629+
.setBool(
630+
INCOMPATIBLE_DISABLE_STARLARK_HOST_TRANSITIONS,
631+
incompatibleDisableStarlarkHostTransitions)
618632
.build();
619633
return INTERNER.intern(semantics);
620634
}
@@ -683,6 +697,8 @@ public StarlarkSemantics toStarlarkSemantics() {
683697
"-incompatible_visibility_private_attributes_at_definition";
684698
public static final String INCOMPATIBLE_TOP_LEVEL_ASPECTS_REQUIRE_PROVIDERS =
685699
"-incompatible_top_level_aspects_require_providers";
700+
public static final String INCOMPATIBLE_DISABLE_STARLARK_HOST_TRANSITIONS =
701+
"-incompatible_disable_starlark_host_transitions";
686702

687703
// non-booleans
688704
public static final StarlarkSemantics.Key<String> EXPERIMENTAL_BUILTINS_BZL_PATH =

src/main/java/com/google/devtools/build/lib/starlarkbuildapi/StarlarkAttrModuleApi.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,14 @@ public interface StarlarkAttrModuleApi extends StarlarkValue {
9292
String CONFIGURATION_ARG = "cfg";
9393
// TODO(b/151742236): Update when new Starlark-based configuration framework is implemented.
9494
String CONFIGURATION_DOC =
95-
"<a href=\"https://docs.bazel.build/versions/main/skylark/rules.html#configurations\">"
96-
+ "Configuration</a> of the attribute. It can be either <code>\"host\"</code>, "
97-
+ "<code>\"exec\"</code>, or <code>\"target\"</code>.";
95+
"<a href=\"https://bazel.build/rules/rules#configurations\">"
96+
+ "Configuration</a> of the attribute. It can be either <code>\"exec\"</code>, which "
97+
+ "indicates that the dependency is built for the <code>execution platform</code>, or "
98+
+ "<code>\"target\"</code>, which indicates that the dependency is build for the "
99+
+ "<code>target platform</code>. A typical example of the difference is when building "
100+
+ "mobile apps, where the <code>target platform</code> is <code>Android</code> or "
101+
+ "<code>iOS</code> while the <code>execution platform</code> is <code>Linux</code>, "
102+
+ "<code>macOS</code>, or <code>Windows</code>.";
98103

99104
String DEFAULT_ARG = "default";
100105
// A trailing space is required because it's often prepended to other sentences

src/test/java/com/google/devtools/build/lib/starlark/StarlarkRuleClassFunctionsTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,14 @@ public void testAttrCfg() throws Exception {
732732
assertThat(attr.getTransitionFactory().isHost()).isTrue();
733733
}
734734

735+
@Test
736+
public void testAttrCfgHostDisabled() throws Exception {
737+
setBuildLanguageOptions("--incompatible_disable_starlark_host_transitions");
738+
739+
EvalException ex = assertThrows(EvalException.class, () -> ev.eval("attr.label(cfg = 'host')"));
740+
assertThat(ex).hasMessageThat().contains("Please use 'cfg = \"exec\"' instead");
741+
}
742+
735743
@Test
736744
public void testAttrCfgTarget() throws Exception {
737745
Attribute attr = buildAttribute("a1", "attr.label(cfg = 'target', allow_files = True)");
@@ -742,7 +750,7 @@ public void testAttrCfgTarget() throws Exception {
742750
public void incompatibleDataTransition() throws Exception {
743751
EvalException expected =
744752
assertThrows(EvalException.class, () -> ev.eval("attr.label(cfg = 'data')"));
745-
assertThat(expected).hasMessageThat().contains("cfg must be either 'host', 'target'");
753+
assertThat(expected).hasMessageThat().contains("cfg must be either 'target', 'exec'");
746754
}
747755

748756
@Test

0 commit comments

Comments
 (0)