Skip to content

Commit d2dbad3

Browse files
iancha1992fmeumWyverald
authored
[7.0.0] Give WORKSPACE toolchains and platforms precedence over non-root mo… (#20430)
…dules RELNOTES[INC]: Toolchains and execution platforms are now registered in the following order with `--enable_bzlmod`: 1. root module's module file 2. `WORKSPACE` or `WORKSPACE.bzlmod` 3. non-root modules' module files 4. default toolchains registered by Bazel (does not apply with `WORKSPACE.bzlmod` or execution platforms) Fixes #20354 Closes #20407. Commit 96b3612#diff-a8d3aed419e661d4dbecb2dc6668444212d7b1707ff61330b7d8aae61e75d4df PiperOrigin-RevId: 587826082 Change-Id: Ia98da6ef07b2fbf589ef369d986af2323af6f72a Co-authored-by: Fabian Meumertzheim <[email protected]> Co-authored-by: Xudong Yang <[email protected]>
1 parent e35c29f commit d2dbad3

File tree

16 files changed

+219
-45
lines changed

16 files changed

+219
-45
lines changed

site/en/external/migration.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,19 @@ toolchain.
453453
register_toolchains("@local_config_sh//:local_sh_toolchain")
454454
```
455455
456+
The toolchains and execution platforms registered in `WORKSPACE`,
457+
`WORKSPACE.bzlmod` and each Bazel module's `MODULE.bazel` file follow this
458+
order of precedence during toolchain selection (from highest to lowest):
459+
460+
1. toolchains and execution platforms registered in the root module's
461+
`MODULE.bazel` file.
462+
2. toolchains and execution platforms registered in the `WORKSPACE` or
463+
`WORKSPACE.bzlmod` file.
464+
3. toolchains and execution platforms registered by modules that are
465+
(transitive) dependencies of the root module.
466+
4. when not using `WORKSPACE.bzlmod`: toolchains registered in the `WORKSPACE`
467+
[suffix](/external/migration#builtin-default-deps).
468+
456469
[register_execution_platforms]: /rules/lib/globals/module#register_execution_platforms
457470
458471
### Introduce local repositories {:#introduce-local-deps}

src/main/java/com/google/devtools/build/lib/packages/Package.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import java.util.Map;
7373
import java.util.Objects;
7474
import java.util.Optional;
75+
import java.util.OptionalInt;
7576
import java.util.Set;
7677
import java.util.TreeMap;
7778
import java.util.concurrent.Semaphore;
@@ -239,7 +240,7 @@ public enum ConfigSettingVisibilityPolicy {
239240

240241
private ImmutableList<TargetPattern> registeredExecutionPlatforms;
241242
private ImmutableList<TargetPattern> registeredToolchains;
242-
243+
private OptionalInt firstWorkspaceSuffixRegisteredToolchain;
243244
private long computationSteps;
244245

245246
// These two fields are mutually exclusive. Which one is set depends on
@@ -402,6 +403,7 @@ private void finishInit(Builder builder) {
402403
this.failureDetail = builder.getFailureDetail();
403404
this.registeredExecutionPlatforms = ImmutableList.copyOf(builder.registeredExecutionPlatforms);
404405
this.registeredToolchains = ImmutableList.copyOf(builder.registeredToolchains);
406+
this.firstWorkspaceSuffixRegisteredToolchain = builder.firstWorkspaceSuffixRegisteredToolchain;
405407
this.repositoryMapping = Preconditions.checkNotNull(builder.repositoryMapping);
406408
this.mainRepositoryMapping = Preconditions.checkNotNull(builder.mainRepositoryMapping);
407409
ImmutableMap.Builder<RepositoryName, ImmutableMap<String, RepositoryName>>
@@ -722,6 +724,23 @@ public ImmutableList<TargetPattern> getRegisteredToolchains() {
722724
return registeredToolchains;
723725
}
724726

727+
public ImmutableList<TargetPattern> getUserRegisteredToolchains() {
728+
return getRegisteredToolchains()
729+
.subList(
730+
0, firstWorkspaceSuffixRegisteredToolchain.orElse(getRegisteredToolchains().size()));
731+
}
732+
733+
public ImmutableList<TargetPattern> getWorkspaceSuffixRegisteredToolchains() {
734+
return getRegisteredToolchains()
735+
.subList(
736+
firstWorkspaceSuffixRegisteredToolchain.orElse(getRegisteredToolchains().size()),
737+
getRegisteredToolchains().size());
738+
}
739+
740+
OptionalInt getFirstWorkspaceSuffixRegisteredToolchain() {
741+
return firstWorkspaceSuffixRegisteredToolchain;
742+
}
743+
725744
@Override
726745
public String toString() {
727746
return "Package("
@@ -936,8 +955,16 @@ default boolean precomputeTransitiveLoads() {
936955
private final List<TargetPattern> registeredToolchains = new ArrayList<>();
937956

938957
/**
939-
* True iff the "package" function has already been called in this package.
958+
* Tracks the index within {@link #registeredToolchains} of the first toolchain registered from
959+
* the WORKSPACE suffixes rather than the WORKSPACE file (if any).
960+
*
961+
* <p>This is needed to distinguish between these toolchains during resolution: toolchains
962+
* registered in WORKSPACE have precedence over those defined in non-root Bazel modules, which
963+
* in turn have precedence over those from the WORKSPACE suffixes.
940964
*/
965+
private OptionalInt firstWorkspaceSuffixRegisteredToolchain = OptionalInt.empty();
966+
967+
/** True iff the "package" function has already been called in this package. */
941968
private boolean packageFunctionUsed;
942969

943970
/**
@@ -1620,10 +1647,18 @@ void addRegisteredExecutionPlatforms(List<TargetPattern> platforms) {
16201647
this.registeredExecutionPlatforms.addAll(platforms);
16211648
}
16221649

1623-
void addRegisteredToolchains(List<TargetPattern> toolchains) {
1650+
void addRegisteredToolchains(List<TargetPattern> toolchains, boolean forWorkspaceSuffix) {
1651+
if (forWorkspaceSuffix && firstWorkspaceSuffixRegisteredToolchain.isEmpty()) {
1652+
firstWorkspaceSuffixRegisteredToolchain = OptionalInt.of(registeredToolchains.size());
1653+
}
16241654
this.registeredToolchains.addAll(toolchains);
16251655
}
16261656

1657+
void setFirstWorkspaceSuffixRegisteredToolchain(
1658+
OptionalInt firstWorkspaceSuffixRegisteredToolchain) {
1659+
this.firstWorkspaceSuffixRegisteredToolchain = firstWorkspaceSuffixRegisteredToolchain;
1660+
}
1661+
16271662
@CanIgnoreReturnValue
16281663
private Builder beforeBuild(boolean discoverAssumedInputFiles) throws NoSuchPackageException {
16291664
Preconditions.checkNotNull(pkg);

src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ public void setParent(
185185
builder.setFailureDetailOverride(aPackage.getFailureDetail());
186186
}
187187
builder.addRegisteredExecutionPlatforms(aPackage.getRegisteredExecutionPlatforms());
188-
builder.addRegisteredToolchains(aPackage.getRegisteredToolchains());
188+
builder.addRegisteredToolchains(
189+
aPackage.getRegisteredToolchains(), /* forWorkspaceSuffix= */ false);
190+
builder.setFirstWorkspaceSuffixRegisteredToolchain(
191+
aPackage.getFirstWorkspaceSuffixRegisteredToolchain());
189192
builder.addRepositoryMappings(aPackage);
190193
for (Rule rule : aPackage.getTargets(Rule.class)) {
191194
try {

src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
/** A helper for the {@link WorkspaceFactory} to create repository rules */
3737
public final class WorkspaceFactoryHelper {
3838

39+
public static final String DEFAULT_WORKSPACE_SUFFIX_FILE = "/DEFAULT.WORKSPACE.SUFFIX";
40+
41+
public static boolean originatesInWorkspaceSuffix(
42+
ImmutableList<StarlarkThread.CallStackEntry> callstack) {
43+
return callstack.get(0).location.file().equals(DEFAULT_WORKSPACE_SUFFIX_FILE);
44+
}
45+
3946
@CanIgnoreReturnValue
4047
public static Rule createAndAddRepositoryRule(
4148
Package.Builder pkg,
@@ -70,7 +77,7 @@ public static Rule createAndAddRepositoryRule(
7077
throw new LabelSyntaxException(e.getMessage());
7178
}
7279
}
73-
pkg.addRegisteredToolchains(toolchains.build());
80+
pkg.addRegisteredToolchains(toolchains.build(), originatesInWorkspaceSuffix(callstack));
7481
return rule;
7582
}
7683

src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.devtools.build.lib.packages;
1616

17+
import static com.google.devtools.build.lib.packages.WorkspaceFactoryHelper.originatesInWorkspaceSuffix;
1718
import static net.starlark.java.eval.Starlark.NONE;
1819

1920
import com.google.common.collect.ImmutableList;
@@ -114,7 +115,9 @@ public void registerToolchains(Sequence<?> toolchainLabels, StarlarkThread threa
114115
// Add to the package definition for later.
115116
Package.Builder builder = PackageFactory.getContext(thread).pkgBuilder;
116117
List<String> patterns = Sequence.cast(toolchainLabels, String.class, "toolchain_labels");
117-
builder.addRegisteredToolchains(parsePatterns(patterns, builder, thread));
118+
builder.addRegisteredToolchains(
119+
parsePatterns(patterns, builder, thread),
120+
originatesInWorkspaceSuffix(thread.getCallStack()));
118121
}
119122

120123
@Override

src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.devtools.build.lib.skyframe;
1616

17+
import static com.google.devtools.build.lib.packages.WorkspaceFactoryHelper.DEFAULT_WORKSPACE_SUFFIX_FILE;
1718
import static com.google.devtools.build.lib.rules.repository.ResolvedFileValue.ATTRIBUTES;
1819
import static com.google.devtools.build.lib.rules.repository.ResolvedFileValue.NATIVE;
1920
import static com.google.devtools.build.lib.rules.repository.ResolvedFileValue.REPOSITORIES;
@@ -220,7 +221,7 @@ public SkyValue compute(SkyKey skyKey, Environment env)
220221
StarlarkFile file =
221222
StarlarkFile.parse(
222223
ParserInput.fromString(
223-
ruleClassProvider.getDefaultWorkspaceSuffix(), "/DEFAULT.WORKSPACE.SUFFIX"),
224+
ruleClassProvider.getDefaultWorkspaceSuffix(), DEFAULT_WORKSPACE_SUFFIX_FILE),
224225
// The DEFAULT.WORKSPACE.SUFFIX file breaks through the usual privacy mechanism.
225226
options.toBuilder().allowLoadPrivateSymbols(true).build());
226227
if (!file.ok()) {

src/main/java/com/google/devtools/build/lib/skyframe/toolchains/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ java_library(
9090
"//src/main/java/com/google/devtools/build/lib/analysis:platform_configuration",
9191
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
9292
"//src/main/java/com/google/devtools/build/lib/analysis/platform:utils",
93+
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common",
9394
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:resolution",
9495
"//src/main/java/com/google/devtools/build/lib/cmdline",
9596
"//src/main/java/com/google/devtools/build/lib/packages",
@@ -160,6 +161,7 @@ java_library(
160161
"//src/main/java/com/google/devtools/build/lib/analysis:platform_configuration",
161162
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
162163
"//src/main/java/com/google/devtools/build/lib/analysis/platform:utils",
164+
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common",
163165
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:exception",
164166
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:resolution",
165167
"//src/main/java/com/google/devtools/build/lib/cmdline",

src/main/java/com/google/devtools/build/lib/skyframe/toolchains/RegisteredExecutionPlatformsFunction.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
2727
import com.google.devtools.build.lib.bazel.bzlmod.BazelDepGraphValue;
2828
import com.google.devtools.build.lib.bazel.bzlmod.Module;
29+
import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey;
2930
import com.google.devtools.build.lib.cmdline.Label;
3031
import com.google.devtools.build.lib.cmdline.LabelConstants;
3132
import com.google.devtools.build.lib.cmdline.RepositoryName;
@@ -104,21 +105,31 @@ public SkyValue compute(SkyKey skyKey, Environment env)
104105
}
105106
}
106107

107-
// Get registered execution platforms from bzlmod.
108-
ImmutableList<TargetPattern> bzlmodExecutionPlatforms =
109-
getBzlmodExecutionPlatforms(starlarkSemantics, env);
110-
if (bzlmodExecutionPlatforms == null) {
108+
// Get registered execution platforms from the root Bazel module.
109+
ImmutableList<TargetPattern> bzlmodRootModuleExecutionPlatforms =
110+
getBzlmodExecutionPlatforms(starlarkSemantics, env, /* forRootModule= */ true);
111+
if (bzlmodRootModuleExecutionPlatforms == null) {
111112
return null;
112113
}
113-
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodExecutionPlatforms));
114+
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodRootModuleExecutionPlatforms));
114115

115116
// Get the registered execution platforms from the WORKSPACE.
117+
// The WORKSPACE suffixes don't register any execution platforms, so we can register all
118+
// platforms in WORKSPACE before those in non-root Bazel modules.
116119
ImmutableList<TargetPattern> workspaceExecutionPlatforms = getWorkspaceExecutionPlatforms(env);
117120
if (workspaceExecutionPlatforms == null) {
118121
return null;
119122
}
120123
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(workspaceExecutionPlatforms));
121124

125+
// Get registered execution platforms from the non-root Bazel modules.
126+
ImmutableList<TargetPattern> bzlmodNonRootModuleExecutionPlatforms =
127+
getBzlmodExecutionPlatforms(starlarkSemantics, env, /* forRootModule= */ false);
128+
if (bzlmodNonRootModuleExecutionPlatforms == null) {
129+
return null;
130+
}
131+
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodNonRootModuleExecutionPlatforms));
132+
122133
// Expand target patterns.
123134
ImmutableList<Label> platformLabels;
124135
try {
@@ -164,7 +175,7 @@ public static ImmutableList<TargetPattern> getWorkspaceExecutionPlatforms(Enviro
164175

165176
@Nullable
166177
private static ImmutableList<TargetPattern> getBzlmodExecutionPlatforms(
167-
StarlarkSemantics semantics, Environment env)
178+
StarlarkSemantics semantics, Environment env, boolean forRootModule)
168179
throws InterruptedException, RegisteredExecutionPlatformsFunctionException {
169180
if (!semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD)) {
170181
return ImmutableList.of();
@@ -176,6 +187,9 @@ private static ImmutableList<TargetPattern> getBzlmodExecutionPlatforms(
176187
}
177188
ImmutableList.Builder<TargetPattern> executionPlatforms = ImmutableList.builder();
178189
for (Module module : bazelDepGraphValue.getDepGraph().values()) {
190+
if (forRootModule != module.getKey().equals(ModuleKey.ROOT)) {
191+
continue;
192+
}
179193
TargetPattern.Parser parser =
180194
new TargetPattern.Parser(
181195
PathFragment.EMPTY_FRAGMENT,

src/main/java/com/google/devtools/build/lib/skyframe/toolchains/RegisteredToolchainsFunction.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.devtools.build.lib.bazel.bzlmod.BazelDepGraphValue;
2929
import com.google.devtools.build.lib.bazel.bzlmod.ExternalDepsException;
3030
import com.google.devtools.build.lib.bazel.bzlmod.Module;
31+
import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey;
3132
import com.google.devtools.build.lib.cmdline.Label;
3233
import com.google.devtools.build.lib.cmdline.LabelConstants;
3334
import com.google.devtools.build.lib.cmdline.RepositoryName;
@@ -95,19 +96,37 @@ public SkyValue compute(SkyKey skyKey, Environment env)
9596
new InvalidToolchainLabelException(e), Transience.PERSISTENT);
9697
}
9798

98-
// Get registered toolchains from bzlmod.
99-
ImmutableList<TargetPattern> bzlmodToolchains = getBzlmodToolchains(starlarkSemantics, env);
100-
if (bzlmodToolchains == null) {
99+
// Get registered toolchains from the root Bazel module.
100+
ImmutableList<TargetPattern> bzlmodRootModuleToolchains =
101+
getBzlmodToolchains(starlarkSemantics, env, /* forRootModule= */ true);
102+
if (bzlmodRootModuleToolchains == null) {
101103
return null;
102104
}
103-
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodToolchains));
105+
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodRootModuleToolchains));
104106

105-
// Get the registered toolchains from the WORKSPACE.
106-
ImmutableList<TargetPattern> workspaceToolchains = getWorkspaceToolchains(env);
107-
if (workspaceToolchains == null) {
107+
// Get the toolchains from the user-supplied WORKSPACE file.
108+
ImmutableList<TargetPattern> userRegisteredWorkspaceToolchains =
109+
getWorkspaceToolchains(env, /* userRegistered= */ true);
110+
if (userRegisteredWorkspaceToolchains == null) {
108111
return null;
109112
}
110-
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(workspaceToolchains));
113+
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(userRegisteredWorkspaceToolchains));
114+
115+
// Get registered toolchains from non-root Bazel modules.
116+
ImmutableList<TargetPattern> bzlmodNonRootModuleToolchains =
117+
getBzlmodToolchains(starlarkSemantics, env, /* forRootModule= */ false);
118+
if (bzlmodNonRootModuleToolchains == null) {
119+
return null;
120+
}
121+
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodNonRootModuleToolchains));
122+
123+
// Get the toolchains from the Bazel-supplied WORKSPACE suffix.
124+
ImmutableList<TargetPattern> workspaceSuffixToolchains =
125+
getWorkspaceToolchains(env, /* userRegistered= */ false);
126+
if (workspaceSuffixToolchains == null) {
127+
return null;
128+
}
129+
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(workspaceSuffixToolchains));
111130

112131
// Expand target patterns.
113132
ImmutableList<Label> toolchainLabels;
@@ -140,21 +159,25 @@ public SkyValue compute(SkyKey skyKey, Environment env)
140159
*/
141160
@Nullable
142161
@VisibleForTesting
143-
public static ImmutableList<TargetPattern> getWorkspaceToolchains(Environment env)
144-
throws InterruptedException {
162+
public static ImmutableList<TargetPattern> getWorkspaceToolchains(
163+
Environment env, boolean userRegistered) throws InterruptedException {
145164
PackageValue externalPackageValue =
146165
(PackageValue) env.getValue(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER);
147166
if (externalPackageValue == null) {
148167
return null;
149168
}
150169

151170
Package externalPackage = externalPackageValue.getPackage();
152-
return externalPackage.getRegisteredToolchains();
171+
if (userRegistered) {
172+
return externalPackage.getUserRegisteredToolchains();
173+
} else {
174+
return externalPackage.getWorkspaceSuffixRegisteredToolchains();
175+
}
153176
}
154177

155178
@Nullable
156179
private static ImmutableList<TargetPattern> getBzlmodToolchains(
157-
StarlarkSemantics semantics, Environment env)
180+
StarlarkSemantics semantics, Environment env, boolean forRootModule)
158181
throws InterruptedException, RegisteredToolchainsFunctionException {
159182
if (!semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD)) {
160183
return ImmutableList.of();
@@ -166,6 +189,9 @@ private static ImmutableList<TargetPattern> getBzlmodToolchains(
166189
}
167190
ImmutableList.Builder<TargetPattern> toolchains = ImmutableList.builder();
168191
for (Module module : bazelDepGraphValue.getDepGraph().values()) {
192+
if (forRootModule != module.getKey().equals(ModuleKey.ROOT)) {
193+
continue;
194+
}
169195
TargetPattern.Parser parser =
170196
new TargetPattern.Parser(
171197
PathFragment.EMPTY_FRAGMENT,

src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,8 @@ public void setupMockClient(MockToolsConfig config, List<String> workspaceConten
501501
"def rules_java_dependencies():",
502502
" pass",
503503
"def rules_java_toolchains():",
504-
" pass");
504+
" native.register_toolchains('//java/toolchains/runtime:all')",
505+
" native.register_toolchains('//java/toolchains/javac:all')");
505506

506507
config.create(
507508
"rules_java_workspace/java/toolchains/runtime/BUILD",

src/test/java/com/google/devtools/build/lib/packages/util/LoadingMock.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ public PackageFactoryBuilderWithSkyframeForTesting getPackageFactoryBuilderForTe
3939
public ConfiguredRuleClassProvider createRuleClassProvider() {
4040
return TestRuleClassProvider.getRuleClassProviderWithClearedSuffix();
4141
}
42+
43+
public ConfiguredRuleClassProvider createRuleClassProviderWithSuffix() {
44+
return TestRuleClassProvider.getRuleClassProvider();
45+
}
4246
}

0 commit comments

Comments
 (0)