Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Give WORKSPACE toolchains and platforms precedence over non-root modules #20407

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions site/en/external/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,19 @@ toolchain.
register_toolchains("@local_config_sh//:local_sh_toolchain")
```

The toolchains and execution platforms registered in `WORKSPACE`,
`WORKSPACE.bzlmod` and each Bazel module's `MODULE.bazel` file follow this
order of precedence during toolchain selection (from highest to lowest):

1. toolchains and execution platforms registered in the root module's
`MODULE.bazel` file.
2. toolchains and execution platforms registered in the `WORKSPACE` or
`WORKSPACE.bzlmod` file.
3. toolchains and execution platforms registered by modules that are
(transitive) dependencies of the root module.
4. when not using `WORKSPACE.bzlmod`: toolchains registered in the `WORKSPACE`
[suffix]((/external/migration#builtin-default-deps).

[register_execution_platforms]: /rules/lib/globals/module#register_execution_platforms

### Introduce local repositories {:#introduce-local-deps}
Expand Down
41 changes: 39 additions & 2 deletions src/main/java/com/google/devtools/build/lib/packages/Package.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.Set;
import java.util.TreeMap;
Expand Down Expand Up @@ -262,7 +263,7 @@ void setPackageOverhead(OptionalLong packageOverhead) {

private ImmutableList<TargetPattern> registeredExecutionPlatforms;
private ImmutableList<TargetPattern> registeredToolchains;

private OptionalInt firstWorkspaceSuffixRegisteredToolchain;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tracking the index inside registeredToolchains of where the root module ends?

This need a comment explaining that, and why that's being done.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment.

private long computationSteps;

// These two fields are mutually exclusive. Which one is set depends on
Expand Down Expand Up @@ -425,6 +426,7 @@ private void finishInit(Builder builder) {
this.failureDetail = builder.getFailureDetail();
this.registeredExecutionPlatforms = ImmutableList.copyOf(builder.registeredExecutionPlatforms);
this.registeredToolchains = ImmutableList.copyOf(builder.registeredToolchains);
this.firstWorkspaceSuffixRegisteredToolchain = builder.firstWorkspaceSuffixRegisteredToolchain;
this.repositoryMapping = Preconditions.checkNotNull(builder.repositoryMapping);
this.mainRepositoryMapping = Preconditions.checkNotNull(builder.mainRepositoryMapping);
ImmutableMap.Builder<RepositoryName, ImmutableMap<String, RepositoryName>>
Expand Down Expand Up @@ -764,6 +766,23 @@ public ImmutableList<TargetPattern> getRegisteredToolchains() {
return registeredToolchains;
}

public ImmutableList<TargetPattern> getUserRegisteredToolchains() {
return getRegisteredToolchains()
.subList(
0, firstWorkspaceSuffixRegisteredToolchain.orElse(getRegisteredToolchains().size()));
}

public ImmutableList<TargetPattern> getWorkspaceSuffixRegisteredToolchains() {
return getRegisteredToolchains()
.subList(
firstWorkspaceSuffixRegisteredToolchain.orElse(getRegisteredToolchains().size()),
getRegisteredToolchains().size());
}

OptionalInt getFirstWorkspaceSuffixRegisteredToolchain() {
return firstWorkspaceSuffixRegisteredToolchain;
}

@Override
public String toString() {
return "Package("
Expand Down Expand Up @@ -983,6 +1002,16 @@ default boolean precomputeTransitiveLoads() {
private final List<TargetPattern> registeredExecutionPlatforms = new ArrayList<>();
private final List<TargetPattern> registeredToolchains = new ArrayList<>();

/**
* Tracks the index within {@link #registeredToolchains} of the first toolchain registered from
* the WORKSPACE suffixes rather than the WORKSPACE file (if any).
*
* <p>This is needed to distinguish between these toolchains during resolution: toolchains
* registered in WORKSPACE have precedence over those defined in non-root Bazel modules,
* which in turn have precedence over those from the WORKSPACE suffixes.</p>
*/
private OptionalInt firstWorkspaceSuffixRegisteredToolchain = OptionalInt.empty();

/**
* True iff the "package" function has already been called in this package.
*/
Expand Down Expand Up @@ -1670,10 +1699,18 @@ void addRegisteredExecutionPlatforms(List<TargetPattern> platforms) {
this.registeredExecutionPlatforms.addAll(platforms);
}

void addRegisteredToolchains(List<TargetPattern> toolchains) {
void addRegisteredToolchains(List<TargetPattern> toolchains, boolean forWorkspaceSuffix) {
if (forWorkspaceSuffix && firstWorkspaceSuffixRegisteredToolchain.isEmpty()) {
firstWorkspaceSuffixRegisteredToolchain = OptionalInt.of(registeredToolchains.size());
}
this.registeredToolchains.addAll(toolchains);
}

void setFirstWorkspaceSuffixRegisteredToolchain(
OptionalInt firstWorkspaceSuffixRegisteredToolchain) {
this.firstWorkspaceSuffixRegisteredToolchain = firstWorkspaceSuffixRegisteredToolchain;
}

@CanIgnoreReturnValue
private Builder beforeBuild(boolean discoverAssumedInputFiles) throws NoSuchPackageException {
Preconditions.checkNotNull(pkg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,10 @@ public void setParent(
builder.setFailureDetailOverride(aPackage.getFailureDetail());
}
builder.addRegisteredExecutionPlatforms(aPackage.getRegisteredExecutionPlatforms());
builder.addRegisteredToolchains(aPackage.getRegisteredToolchains());
builder.addRegisteredToolchains(
aPackage.getRegisteredToolchains(), /* forWorkspaceSuffix= */ false);
builder.setFirstWorkspaceSuffixRegisteredToolchain(
aPackage.getFirstWorkspaceSuffixRegisteredToolchain());
builder.addRepositoryMappings(aPackage);
for (Rule rule : aPackage.getTargets(Rule.class)) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
/** A helper for the {@link WorkspaceFactory} to create repository rules */
public final class WorkspaceFactoryHelper {

public static final String DEFAULT_WORKSPACE_SUFFIX_FILE = "/DEFAULT.WORKSPACE.SUFFIX";

public static boolean originatesInWorkspaceSuffix(
ImmutableList<StarlarkThread.CallStackEntry> callstack) {
return callstack.get(0).location.file().equals(DEFAULT_WORKSPACE_SUFFIX_FILE);
}

@CanIgnoreReturnValue
public static Rule createAndAddRepositoryRule(
Package.Builder pkg,
Expand Down Expand Up @@ -70,7 +77,7 @@ public static Rule createAndAddRepositoryRule(
throw new LabelSyntaxException(e.getMessage());
}
}
pkg.addRegisteredToolchains(toolchains.build());
pkg.addRegisteredToolchains(toolchains.build(), originatesInWorkspaceSuffix(callstack));
return rule;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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

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

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

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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

import static com.google.devtools.build.lib.packages.WorkspaceFactoryHelper.DEFAULT_WORKSPACE_SUFFIX_FILE;
import static com.google.devtools.build.lib.rules.repository.ResolvedFileValue.ATTRIBUTES;
import static com.google.devtools.build.lib.rules.repository.ResolvedFileValue.NATIVE;
import static com.google.devtools.build.lib.rules.repository.ResolvedFileValue.REPOSITORIES;
Expand All @@ -40,6 +41,7 @@
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.packages.WorkspaceFactory;
import com.google.devtools.build.lib.packages.WorkspaceFactoryHelper;
import com.google.devtools.build.lib.packages.WorkspaceFileValue;
import com.google.devtools.build.lib.packages.WorkspaceFileValue.WorkspaceFileKey;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
Expand Down Expand Up @@ -220,7 +222,7 @@ public SkyValue compute(SkyKey skyKey, Environment env)
StarlarkFile file =
StarlarkFile.parse(
ParserInput.fromString(
ruleClassProvider.getDefaultWorkspaceSuffix(), "/DEFAULT.WORKSPACE.SUFFIX"),
ruleClassProvider.getDefaultWorkspaceSuffix(), DEFAULT_WORKSPACE_SUFFIX_FILE),
// The DEFAULT.WORKSPACE.SUFFIX file breaks through the usual privacy mechanism.
options.toBuilder().allowLoadPrivateSymbols(true).build());
if (!file.ok()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/analysis:platform_configuration",
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
"//src/main/java/com/google/devtools/build/lib/analysis/platform:utils",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:resolution",
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/packages",
Expand Down Expand Up @@ -161,6 +162,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/analysis:platform_configuration",
"//src/main/java/com/google/devtools/build/lib/analysis/platform",
"//src/main/java/com/google/devtools/build/lib/analysis/platform:utils",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:exception",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:resolution",
"//src/main/java/com/google/devtools/build/lib/cmdline",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
import com.google.devtools.build.lib.bazel.bzlmod.BazelDepGraphValue;
import com.google.devtools.build.lib.bazel.bzlmod.Module;
import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.RepositoryName;
Expand Down Expand Up @@ -104,21 +105,31 @@ public SkyValue compute(SkyKey skyKey, Environment env)
}
}

// Get registered execution platforms from bzlmod.
ImmutableList<TargetPattern> bzlmodExecutionPlatforms =
getBzlmodExecutionPlatforms(starlarkSemantics, env);
if (bzlmodExecutionPlatforms == null) {
// Get registered execution platforms from the root Bazel module.
ImmutableList<TargetPattern> bzlmodRootModuleExecutionPlatforms =
getBzlmodExecutionPlatforms(starlarkSemantics, env, /* forRootModule= */ true);
if (bzlmodRootModuleExecutionPlatforms == null) {
return null;
}
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodExecutionPlatforms));
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodRootModuleExecutionPlatforms));

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

// Get registered execution platforms from the non-root Bazel modules.
ImmutableList<TargetPattern> bzlmodNonRootModuleExecutionPlatforms =
getBzlmodExecutionPlatforms(starlarkSemantics, env, /* forRootModule= */ false);
if (bzlmodNonRootModuleExecutionPlatforms == null) {
return null;
}
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodNonRootModuleExecutionPlatforms));

// Expand target patterns.
ImmutableList<Label> platformLabels;
try {
Expand Down Expand Up @@ -164,7 +175,7 @@ public static ImmutableList<TargetPattern> getWorkspaceExecutionPlatforms(Enviro

@Nullable
private static ImmutableList<TargetPattern> getBzlmodExecutionPlatforms(
StarlarkSemantics semantics, Environment env)
StarlarkSemantics semantics, Environment env, boolean forRootModule)
throws InterruptedException, RegisteredExecutionPlatformsFunctionException {
if (!semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD)) {
return ImmutableList.of();
Expand All @@ -176,6 +187,9 @@ private static ImmutableList<TargetPattern> getBzlmodExecutionPlatforms(
}
ImmutableList.Builder<TargetPattern> executionPlatforms = ImmutableList.builder();
for (Module module : bazelDepGraphValue.getDepGraph().values()) {
if (forRootModule != module.getKey().equals(ModuleKey.ROOT)) {
continue;
}
TargetPattern.Parser parser =
new TargetPattern.Parser(
PathFragment.EMPTY_FRAGMENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.google.devtools.build.lib.bazel.bzlmod.BazelDepGraphValue;
import com.google.devtools.build.lib.bazel.bzlmod.ExternalDepsException;
import com.google.devtools.build.lib.bazel.bzlmod.Module;
import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.RepositoryName;
Expand Down Expand Up @@ -95,19 +96,37 @@ public SkyValue compute(SkyKey skyKey, Environment env)
new InvalidToolchainLabelException(e), Transience.PERSISTENT);
}

// Get registered toolchains from bzlmod.
ImmutableList<TargetPattern> bzlmodToolchains = getBzlmodToolchains(starlarkSemantics, env);
if (bzlmodToolchains == null) {
// Get registered toolchains from the root Bazel module.
ImmutableList<TargetPattern> bzlmodRootModuleToolchains =
getBzlmodToolchains(starlarkSemantics, env, /* forRootModule= */ true);
if (bzlmodRootModuleToolchains == null) {
return null;
}
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodToolchains));
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodRootModuleToolchains));

// Get the registered toolchains from the WORKSPACE.
ImmutableList<TargetPattern> workspaceToolchains = getWorkspaceToolchains(env);
if (workspaceToolchains == null) {
// Get the toolchains from the user-supplied WORKSPACE file.
ImmutableList<TargetPattern> userRegisteredWorkspaceToolchains =
getWorkspaceToolchains(env, /* userRegistered= */ true);
if (userRegisteredWorkspaceToolchains == null) {
return null;
}
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(workspaceToolchains));
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(userRegisteredWorkspaceToolchains));

// Get registered toolchains from non-root Bazel modules.
ImmutableList<TargetPattern> bzlmodNonRootModuleToolchains =
getBzlmodToolchains(starlarkSemantics, env, /* forRootModule= */ false);
if (bzlmodNonRootModuleToolchains == null) {
return null;
}
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(bzlmodNonRootModuleToolchains));

// Get the toolchains from the Bazel-supplied WORKSPACE suffix.
ImmutableList<TargetPattern> workspaceSuffixToolchains =
getWorkspaceToolchains(env, /* userRegistered= */ false);
if (workspaceSuffixToolchains == null) {
return null;
}
targetPatternBuilder.addAll(TargetPatternUtil.toSigned(workspaceSuffixToolchains));

// Expand target patterns.
ImmutableList<Label> toolchainLabels;
Expand Down Expand Up @@ -140,21 +159,25 @@ public SkyValue compute(SkyKey skyKey, Environment env)
*/
@Nullable
@VisibleForTesting
public static ImmutableList<TargetPattern> getWorkspaceToolchains(Environment env)
throws InterruptedException {
public static ImmutableList<TargetPattern> getWorkspaceToolchains(
Environment env, boolean userRegistered) throws InterruptedException {
PackageValue externalPackageValue =
(PackageValue) env.getValue(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER);
if (externalPackageValue == null) {
return null;
}

Package externalPackage = externalPackageValue.getPackage();
return externalPackage.getRegisteredToolchains();
if (userRegistered) {
return externalPackage.getUserRegisteredToolchains();
} else {
return externalPackage.getWorkspaceSuffixRegisteredToolchains();
}
}

@Nullable
private static ImmutableList<TargetPattern> getBzlmodToolchains(
StarlarkSemantics semantics, Environment env)
StarlarkSemantics semantics, Environment env, boolean forRootModule)
throws InterruptedException, RegisteredToolchainsFunctionException {
if (!semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD)) {
return ImmutableList.of();
Expand All @@ -166,6 +189,9 @@ private static ImmutableList<TargetPattern> getBzlmodToolchains(
}
ImmutableList.Builder<TargetPattern> toolchains = ImmutableList.builder();
for (Module module : bazelDepGraphValue.getDepGraph().values()) {
if (forRootModule != module.getKey().equals(ModuleKey.ROOT)) {
continue;
}
TargetPattern.Parser parser =
new TargetPattern.Parser(
PathFragment.EMPTY_FRAGMENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ public void setupMockClient(MockToolsConfig config, List<String> workspaceConten
"def rules_java_dependencies():",
" pass",
"def rules_java_toolchains():",
" pass");
" native.register_toolchains('//java/toolchains/runtime:all')",
" native.register_toolchains('//java/toolchains/javac:all')");

config.create(
"rules_java_workspace/java/toolchains/runtime/BUILD",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ public PackageFactoryBuilderWithSkyframeForTesting getPackageFactoryBuilderForTe
public ConfiguredRuleClassProvider createRuleClassProvider() {
return TestRuleClassProvider.getRuleClassProviderWithClearedSuffix();
}

public ConfiguredRuleClassProvider createRuleClassProviderWithSuffix() {
return TestRuleClassProvider.getRuleClassProvider();
}
}
Loading
Loading