diff --git a/src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java b/src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java
new file mode 100644
index 00000000000000..f15af962f86ec4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java
@@ -0,0 +1,701 @@
+// Copyright 2024 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package com.google.devtools.build.lib.packages;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.collect.ImmutableMap.toImmutableMap;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.Label.RepoContext;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
+import com.google.devtools.build.lib.skyframe.BzlLoadValue;
+import com.google.devtools.build.lib.skyframe.RepositoryMappingValue;
+import com.google.devtools.build.skyframe.SkyFunction;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+import javax.annotation.Nullable;
+import net.starlark.java.eval.Starlark;
+import net.starlark.java.eval.StarlarkSemantics;
+
+/**
+ * Implementation of --incompatible_autoload_externally.
+ *
+ *
The flag adds loads to external repository for rules and top-level symbols, or removes them.
+ * This class prepares new environment for BzlCompileFunction, BzlLoadFunction and PackageFuntions.
+ *
+ *
Environment for BzlCompileFunction is prepared immediately during construction. Only names of
+ * the symbols are needed and provided. Values of the symbols are set to None.
+ *
+ *
Environments for BzlLoadFunction and PackageFunctions are prepared in StarlarkBuilinsFunction.
+ *
+ *
Cycles are prevented by disallowing autoloads in repos that we autoload from and the repos
+ * they depend on.
+ */
+public class AutoloadSymbols {
+ // Following fields autoloadedSymbols, removedSymbols, partiallyRemovedSymbols,
+ // reposDisallowingAutoloads are empty if autoloads aren't used
+ // Symbols that aren't prefixed with '-', that get loaded from external repositories (in allowed
+ // repositories).
+ private final ImmutableList autoloadedSymbols;
+ // Symbols that are prefixed with '-', that are removed everywhere (from each repository)
+ private final ImmutableList removedSymbols;
+ // Symbols that aren't prefixed with '+', that are removed from everywhere,
+ // except in repositories where autoloaded symbols are defined
+ private final ImmutableList partiallyRemovedSymbols;
+
+ // Repositories where autoloads shouldn't be used
+ private final ImmutableSet reposDisallowingAutoloads;
+
+ // The environment formed by taking BazelStarlarkEnvironment's bzl environment and adding/removing
+ // autoloaded symbols. The values of any added symbols are set to None (i.e. not actually loaded).
+ // This is intended for BzlCompileFunction only.
+ private final ImmutableMap uninjectedBuildBzlEnvWithAutoloads;
+
+ // bzl environment where autoloads aren't used, uninjected (not loaded yet)
+ private final ImmutableMap uninjectedBuildBzlEnvWithoutAutoloads;
+
+ // Used for nicer error messages
+ private final boolean bzlmodEnabled;
+ private final boolean autoloadsEnabled;
+
+ public AutoloadSymbols(RuleClassProvider ruleClassProvider, StarlarkSemantics semantics) {
+ ImmutableList symbolConfiguration =
+ ImmutableList.copyOf(semantics.get(BuildLanguageOptions.INCOMPATIBLE_AUTOLOAD_EXTERNALLY));
+ this.bzlmodEnabled = semantics.getBool(BuildLanguageOptions.ENABLE_BZLMOD);
+ this.autoloadsEnabled = !symbolConfiguration.isEmpty();
+
+ if (!autoloadsEnabled) {
+ ImmutableMap originalBuildBzlEnv =
+ ruleClassProvider.getBazelStarlarkEnvironment().getUninjectedBuildBzlEnv();
+ this.uninjectedBuildBzlEnvWithAutoloads = originalBuildBzlEnv;
+ this.uninjectedBuildBzlEnvWithoutAutoloads = originalBuildBzlEnv;
+ this.reposDisallowingAutoloads = ImmutableSet.of();
+ this.autoloadedSymbols = ImmutableList.of();
+ this.removedSymbols = ImmutableList.of();
+ this.partiallyRemovedSymbols = ImmutableList.of();
+ return;
+ }
+
+ // Validates the inputs
+ Set uniqueSymbols = new HashSet<>();
+ for (String symbol : symbolConfiguration) {
+ String symbolWithoutPrefix =
+ symbol.startsWith("+") || symbol.startsWith("-") ? symbol.substring(1) : symbol;
+ if (!uniqueSymbols.add(symbolWithoutPrefix)) {
+ throw new IllegalStateException(
+ String.format(
+ "Duplicated symbol '%s' in --incompatible_autoload_externally",
+ symbolWithoutPrefix));
+ }
+ if (!AUTOLOAD_CONFIG.containsKey(symbolWithoutPrefix)) {
+ throw new IllegalStateException("Undefined symbol in --incompatible_autoload_externally");
+ }
+ }
+
+ this.autoloadedSymbols = filterSymbols(symbolConfiguration, symbol -> !symbol.startsWith("-"));
+ this.removedSymbols = filterSymbols(symbolConfiguration, symbol -> symbol.startsWith("-"));
+ this.partiallyRemovedSymbols =
+ filterSymbols(symbolConfiguration, symbol -> !symbol.startsWith("+"));
+
+ this.reposDisallowingAutoloads =
+ ImmutableSet.builder()
+ .addAll(PREDECLARED_REPOS_DISALLOWING_AUTOLOADS)
+ .addAll(semantics.get(BuildLanguageOptions.REPOSITORIES_WITHOUT_AUTOLOAD))
+ .build();
+
+ ImmutableMap originalBuildBzlEnv =
+ ruleClassProvider.getBazelStarlarkEnvironment().getUninjectedBuildBzlEnv();
+
+ // Sets up environments for BzlCompile function
+ this.uninjectedBuildBzlEnvWithAutoloads =
+ modifyBuildBzlEnv(
+ /* isWithAutoloads= */ true,
+ originalBuildBzlEnv,
+ /* newSymbols= */ autoloadedSymbols.stream()
+ .collect(toImmutableMap(key -> key, key -> Starlark.NONE)));
+ this.uninjectedBuildBzlEnvWithoutAutoloads =
+ modifyBuildBzlEnv(
+ /* isWithAutoloads= */ false, originalBuildBzlEnv, /* newSymbols= */ ImmutableMap.of());
+
+ // Validate rdeps - this ensures that all the rules using a provider are also removed
+ // Check what's still available in Bazel (some symbols might already be deleted)
+ ImmutableSet allAvailableSymbols =
+ ImmutableSet.builder()
+ .addAll(uninjectedBuildBzlEnvWithoutAutoloads.keySet())
+ .addAll(
+ convertNativeStructToMap(
+ (StarlarkInfo) uninjectedBuildBzlEnvWithoutAutoloads.get("native"))
+ .keySet())
+ .build();
+ for (String symbol : partiallyRemovedSymbols) {
+ ImmutableList unsatisfiedRdeps =
+ AUTOLOAD_CONFIG.get(symbol).getRdeps().stream()
+ .filter(allAvailableSymbols::contains)
+ .collect(toImmutableList());
+ if (!unsatisfiedRdeps.isEmpty()) {
+ throw new IllegalStateException(
+ String.format(
+ "Symbol in '%s' can't be removed, because it's still used by: %s",
+ symbol, String.join(", ", unsatisfiedRdeps)));
+ }
+ }
+ }
+
+ /** An optimisation, checking is autoloads are used at all. */
+ public boolean isEnabled() {
+ return autoloadsEnabled;
+ }
+
+ /** Returns the environment for BzlCompile function */
+ public ImmutableMap getUninjectedBuildBzlEnv(@Nullable Label key) {
+ return autoloadsDisabledForRepo(key)
+ ? uninjectedBuildBzlEnvWithoutAutoloads
+ : uninjectedBuildBzlEnvWithAutoloads;
+ }
+
+ /** Check if autoloads shouldn't be used. */
+ public boolean autoloadsDisabledForRepo(@Nullable Label key) {
+ if (!autoloadsEnabled) {
+ return true;
+ }
+ return key == null || autoloadsDisabledForRepo(key.getRepository().getName());
+ }
+
+ /**
+ * Check if autoloads shouldn't be used in the given repository.
+ *
+ * Autoloads aren't used for repos in {@link #PREDECLARED_REPOS_DISALLOWING_AUTOLOADS},
+ * specified by the --repositories_without_autoloads flag or any of their immediate descendants
+ * (parsing the cannonical repository name to check this).
+ */
+ public boolean autoloadsDisabledForRepo(String repo) {
+ if (!autoloadsEnabled) {
+ return true;
+ }
+ int separatorIndex = repo.contains("~") ? repo.indexOf("~") : repo.indexOf("+");
+ return reposDisallowingAutoloads.contains(
+ separatorIndex >= 0 ? repo.substring(0, separatorIndex) : repo);
+ }
+
+ /**
+ * Modifies the environment for BzlLoad function (returned from StarlarkBuiltinsFunction).
+ *
+ *
{@code originalEnv} contains original environment and {@code newSymbols} is a map from new
+ * symbol name to symbol's value. {@code isWithAutoloads} chooses the semantics, described in
+ * details on --incompatible_autoload_externally flag.
+ */
+ public ImmutableMap modifyBuildBzlEnv(
+ boolean isWithAutoloads,
+ ImmutableMap originalEnv,
+ ImmutableMap newSymbols) {
+ if (isWithAutoloads) {
+ return modifyBuildBzlEnv(originalEnv, /* add= */ newSymbols, /* remove= */ removedSymbols);
+ } else {
+ return modifyBuildBzlEnv(
+ originalEnv, /* add= */ ImmutableMap.of(), /* remove= */ partiallyRemovedSymbols);
+ }
+ }
+
+ /**
+ * Creates modified environment that's used in BzlCompileFunction and StarlarkBuiltinsFunction.
+ *
+ * It starts with the original environment. Adds the symbols to it or removes them.
+ */
+ private ImmutableMap modifyBuildBzlEnv(
+ ImmutableMap originalEnv,
+ ImmutableMap add,
+ ImmutableList remove) {
+ Map envBuilder = new LinkedHashMap<>(originalEnv);
+ Map nativeBindings =
+ convertNativeStructToMap((StarlarkInfo) envBuilder.remove("native"));
+
+ for (Map.Entry symbol : add.entrySet()) {
+ if (AUTOLOAD_CONFIG.get(symbol.getKey()).isRule()) {
+ nativeBindings.put(symbol.getKey(), symbol.getValue());
+ } else {
+ envBuilder.put(symbol.getKey(), symbol.getValue());
+ }
+ }
+ for (String symbol : remove) {
+ if (AUTOLOAD_CONFIG.get(symbol).isRule()) {
+ nativeBindings.remove(symbol);
+ } else {
+ envBuilder.remove(symbol);
+ }
+ }
+ envBuilder.put(
+ "native", StructProvider.STRUCT.create(nativeBindings, "no native function or rule '%s'"));
+ return ImmutableMap.copyOf(envBuilder);
+ }
+
+ /** Modifies the environment for Package function (returned from StarlarkBuiltinsFunction). */
+ public ImmutableMap modifyBuildEnv(
+ boolean isWithAutoloads,
+ ImmutableMap originalEnv,
+ ImmutableMap newSymbols) {
+ final ImmutableMap add;
+ if (isWithAutoloads) {
+ add = newSymbols;
+ } else {
+ add = ImmutableMap.of();
+ }
+ Map envBuilder = new LinkedHashMap<>(originalEnv);
+ for (Map.Entry symbol : add.entrySet()) {
+ if (AUTOLOAD_CONFIG.get(symbol.getKey()).isRule()) {
+ envBuilder.put(symbol.getKey(), symbol.getValue());
+ }
+ }
+ for (String symbol : removedSymbols) {
+ if (AUTOLOAD_CONFIG.get(symbol).isRule()) {
+ envBuilder.remove(symbol);
+ }
+ }
+ return ImmutableMap.copyOf(envBuilder);
+ }
+
+ private static ImmutableList filterSymbols(
+ ImmutableList symbols, Predicate when) {
+ return symbols.stream()
+ .filter(when)
+ .map(
+ symbol ->
+ symbol.startsWith("+") || symbol.startsWith("-") ? symbol.substring(1) : symbol)
+ .collect(toImmutableList());
+ }
+
+ private static Map convertNativeStructToMap(StarlarkInfo struct) {
+ LinkedHashMap destr = new LinkedHashMap<>();
+ for (String field : struct.getFieldNames()) {
+ destr.put(field, struct.getValue(field));
+ }
+ return destr;
+ }
+
+ /**
+ * Returns a list of all the extra .bzl files that need to be loaded
+ *
+ * Keys are coming from {@link AUTOLOAD_CONFIG} table.
+ *
+ *
Actual loading is done in {@link StarlarkBuiltinsValue} and then passed to {@link
+ * #processLoads} for final processing. The parameter {@code autoloadValues} must correspond to
+ * the map returned by * {@link #getLoadKeys}.
+ */
+ @Nullable
+ public ImmutableMap getLoadKeys(SkyFunction.Environment env)
+ throws InterruptedException {
+ RepositoryMappingValue repositoryMappingValue =
+ (RepositoryMappingValue)
+ env.getValue(RepositoryMappingValue.key(RepositoryName.BAZEL_TOOLS));
+
+ if (repositoryMappingValue == null) {
+ return null;
+ }
+
+ RepoContext repoContext =
+ Label.RepoContext.of(
+ RepositoryName.BAZEL_TOOLS, repositoryMappingValue.getRepositoryMapping());
+
+ // Inject loads for rules and symbols removed from Bazel
+ ImmutableMap.Builder loadKeysBuilder =
+ ImmutableMap.builderWithExpectedSize(autoloadedSymbols.size());
+ for (String symbol : autoloadedSymbols) {
+ loadKeysBuilder.put(symbol, AUTOLOAD_CONFIG.get(symbol).getKey(repoContext));
+ }
+ return loadKeysBuilder.buildOrThrow();
+ }
+
+ /**
+ * Processes LoadedValues into a map of symbols
+ *
+ * The parameter {@code autoloadValues} must correspond to the map returned by {@link
+ * #getLoadKeys}. Actual loading is done in {@link StarlarkBuiltinsValue}.
+ *
+ *
Keys are coming from {@link AUTOLOAD_CONFIG} table.
+ */
+ public ImmutableMap processLoads(
+ ImmutableMap autoloadValues) throws AutoloadException {
+ if (autoloadValues.isEmpty()) {
+ return ImmutableMap.of();
+ }
+
+ ImmutableMap.Builder newSymbols =
+ ImmutableMap.builderWithExpectedSize(autoloadValues.size());
+ String workspaceWarning =
+ bzlmodEnabled
+ ? ""
+ : " Most likely you need to upgrade the version of rules repository in the"
+ + " WORKSPACE file.";
+ for (Map.Entry autoload : autoloadValues.entrySet()) {
+ String symbol = autoload.getKey();
+ // Check if the symbol is named differently in the bzl file than natively. Renames are rare:
+ // Example is renaming native.ProguardSpecProvider to ProguardSpecInfo.
+ String newName = AUTOLOAD_CONFIG.get(symbol).getNewName();
+ if (newName == null) {
+ newName = symbol;
+ }
+ BzlLoadValue v = autoload.getValue();
+ Object symbolValue = v.getModule().getGlobal(newName);
+ if (symbolValue == null) {
+ throw new AutoloadException(
+ String.format(
+ "The toplevel symbol '%s' set by --incompatible_load_symbols_externally couldn't"
+ + " be loaded. '%s' not found in auto loaded '%s'.%s",
+ symbol, newName, AUTOLOAD_CONFIG.get(symbol).getLoadLabel(), workspaceWarning));
+ }
+ newSymbols.put(symbol, symbolValue); // Exposed as old name
+ }
+ return newSymbols.buildOrThrow();
+ }
+
+ @Override
+ public final int hashCode() {
+ // These fields are used to generate all other private fields.
+ // Thus, other fields don't need to be included in hash code.
+ return Objects.hash(
+ autoloadedSymbols, removedSymbols, partiallyRemovedSymbols, reposDisallowingAutoloads);
+ }
+
+ @Override
+ public final boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that instanceof AutoloadSymbols) {
+ AutoloadSymbols other = (AutoloadSymbols) that;
+ // These fields are used to generate all other private fields.
+ // Thus, other fields don't need to be included in comparison.
+ return this.autoloadedSymbols.equals(other.autoloadedSymbols)
+ && this.removedSymbols.equals(other.removedSymbols)
+ && this.partiallyRemovedSymbols.equals(other.partiallyRemovedSymbols)
+ && this.reposDisallowingAutoloads.equals(other.reposDisallowingAutoloads);
+ }
+ return false;
+ }
+
+ /** Configuration of a symbol */
+ @AutoValue
+ public abstract static class SymbolRedirect {
+
+ public abstract String getLoadLabel();
+
+ public abstract boolean isRule();
+
+ @Nullable
+ public abstract String getNewName();
+
+ public abstract ImmutableSet getRdeps();
+
+ public BzlLoadValue.Key getKey(RepoContext bazelToolsRepoContext) throws InterruptedException {
+ try {
+ return BzlLoadValue.keyForBuild(
+ Label.parseWithRepoContext(getLoadLabel(), bazelToolsRepoContext));
+ } catch (LabelSyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ /** Indicates a problem performing automatic loads. */
+ public static final class AutoloadException extends Exception {
+
+ AutoloadException(String message) {
+ super(message);
+ }
+ }
+
+ private static SymbolRedirect ruleRedirect(String label) {
+ return new AutoValue_AutoloadSymbols_SymbolRedirect(label, true, null, ImmutableSet.of());
+ }
+
+ private static SymbolRedirect symbolRedirect(String label, String... rdeps) {
+ return new AutoValue_AutoloadSymbols_SymbolRedirect(
+ label, false, null, ImmutableSet.copyOf(rdeps));
+ }
+
+ private static SymbolRedirect renamedSymbolRedirect(
+ String label, String newName, String... rdeps) {
+ return new AutoValue_AutoloadSymbols_SymbolRedirect(
+ label, false, newName, ImmutableSet.copyOf(rdeps));
+ }
+
+ private static final String[] androidRules = {
+ "aar_import", "android_binary", "android_library", "android_local_test", "android_sdk"
+ };
+
+ private static final ImmutableSet PREDECLARED_REPOS_DISALLOWING_AUTOLOADS =
+ ImmutableSet.of(
+ "protobuf",
+ "com_google_protobuf",
+ "rules_android",
+ "rules_cc",
+ "rules_java",
+ "rules_java_builtin",
+ "rules_python",
+ "rules_python_internal",
+ "rules_sh",
+ "apple_common",
+ "bazel_skylib",
+ "bazel_tools");
+
+ private static final ImmutableMap AUTOLOAD_CONFIG =
+ ImmutableMap.builder()
+ .put(
+ "CcSharedLibraryInfo",
+ symbolRedirect(
+ "@rules_cc//cc/common:cc_shared_library_info.bzl", "cc_shared_library"))
+ .put(
+ "CcSharedLibraryHintInfo",
+ symbolRedirect("@rules_cc//cc/common:cc_shared_library_hint_info.bzl", "cc_common"))
+ .put(
+ "cc_proto_aspect",
+ symbolRedirect("@protobuf//bazel/common:cc_proto_library.bzl", "cc_proto_library"))
+ .put(
+ "ProtoInfo",
+ symbolRedirect(
+ "@protobuf//bazel/common:proto_info.bzl",
+ "proto_library",
+ "cc_proto_library",
+ "cc_shared_library",
+ "java_lite_proto_library",
+ "java_proto_library",
+ "proto_lang_toolchain",
+ "java_binary",
+ "py_extension",
+ "proto_common_do_not_use"))
+ .put(
+ "proto_common_do_not_use", symbolRedirect("@protobuf//bazel/common:proto_common.bzl"))
+ .put("cc_common", symbolRedirect("@rules_cc//cc/common:cc_common.bzl"))
+ .put(
+ "CcInfo",
+ symbolRedirect(
+ "@rules_cc//cc/common:cc_info.bzl",
+ "cc_binary",
+ "cc_library",
+ "cc_test",
+ "cc_shared_library",
+ "cc_common",
+ "java_library",
+ "cc_proto_library",
+ "java_import",
+ "java_runtime",
+ "java_binary",
+ "objc_library",
+ "java_common",
+ "JavaInfo",
+ "py_extension",
+ "cc_import",
+ "objc_import",
+ "objc_library",
+ "cc_toolchain",
+ "PyCcLinkParamsProvider",
+ "py_library"))
+ .put(
+ "DebugPackageInfo",
+ symbolRedirect("@rules_cc//cc/common:debug_package_info.bzl", "cc_binary", "cc_test"))
+ .put(
+ "CcToolchainConfigInfo",
+ symbolRedirect(
+ "@rules_cc//cc/toolchains:cc_toolchain_config_info.bzl", "cc_toolchain"))
+ .put("java_common", symbolRedirect("@rules_java//java/common:java_common.bzl"))
+ .put(
+ "JavaInfo",
+ symbolRedirect(
+ "@rules_java//java/common:java_info.bzl",
+ "java_binary",
+ "java_library",
+ "java_test",
+ "java_proto_library",
+ "java_lite_proto_library",
+ "java_plugin",
+ "java_import",
+ "java_common"))
+ .put(
+ "JavaPluginInfo",
+ symbolRedirect(
+ "@rules_java//java/common:java_plugin_info.bzl",
+ "java_plugin",
+ "java_library",
+ "java_binary",
+ "java_test"))
+ .put(
+ "ProguardSpecProvider",
+ renamedSymbolRedirect(
+ "@rules_java//java/common:proguard_spec_info.bzl",
+ "ProguardSpecInfo",
+ "java_lite_proto_library",
+ "java_import",
+ "android_binary",
+ "android_library"))
+ .put("android_common", symbolRedirect("@rules_android//rules:common.bzl"))
+ .put(
+ "AndroidIdeInfo", symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put("ApkInfo", symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidInstrumentationInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidResourcesInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidNativeLibsInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidApplicationResourceInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidBinaryNativeLibsInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidSdkInfo", symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidManifestInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidAssetsInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidLibraryAarInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidProguardInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidIdlInfo", symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidPreDexJarInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidCcLinkParamsInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "DataBindingV2Info",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidLibraryResourceClassJarProvider",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidFeatureFlagSet",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "ProguardMappingInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidBinaryData",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "BaselineProfileProvider",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidNeverLinkLibrariesProvider",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidOptimizedJarInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidDexInfo", symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "AndroidOptimizationInfo",
+ symbolRedirect("@rules_android//rules:providers.bzl", androidRules))
+ .put(
+ "PyInfo",
+ symbolRedirect(
+ "@rules_python//python:py_info.bzl", "py_binary", "py_test", "py_library"))
+ .put(
+ "PyRuntimeInfo",
+ symbolRedirect(
+ "@rules_python//python:py_runtime_info.bzl",
+ "py_binary",
+ "py_test",
+ "py_library"))
+ .put(
+ "PyCcLinkParamsProvider",
+ renamedSymbolRedirect(
+ "@rules_python//python:py_cc_link_params_info.bzl",
+ "PyCcLinkParamsInfo",
+ "py_binary",
+ "py_test",
+ "py_library"))
+ .put("aar_import", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_binary", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_device_script_fixture", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_host_service_fixture", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_library", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_local_test", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_sdk", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("android_tools_defaults_jar", ruleRedirect("@rules_android//rules:rules.bzl"))
+ .put("cc_binary", ruleRedirect("@rules_cc//cc:cc_binary.bzl"))
+ .put("cc_import", ruleRedirect("@rules_cc//cc:cc_import.bzl"))
+ .put("cc_library", ruleRedirect("@rules_cc//cc:cc_library.bzl"))
+ .put("cc_proto_library", ruleRedirect("@protobuf//bazel:cc_proto_library.bzl"))
+ .put("cc_shared_library", ruleRedirect("@rules_cc//cc:cc_shared_library.bzl"))
+ .put("cc_test", ruleRedirect("@rules_cc//cc:cc_test.bzl"))
+ .put("cc_toolchain", ruleRedirect("@rules_cc//cc/toolchains:cc_toolchain.bzl"))
+ .put(
+ "cc_toolchain_suite", ruleRedirect("@rules_cc//cc/toolchains:cc_toolchain_suite.bzl"))
+ .put(
+ "fdo_prefetch_hints", ruleRedirect("@rules_cc//cc/toolchains:fdo_prefetch_hints.bzl"))
+ .put("fdo_profile", ruleRedirect("@rules_cc//cc/toolchains:fdo_profile.bzl"))
+ .put("java_binary", ruleRedirect("@rules_java//java:java_binary.bzl"))
+ .put("java_import", ruleRedirect("@rules_java//java:java_import.bzl"))
+ .put("java_library", ruleRedirect("@rules_java//java:java_library.bzl"))
+ .put(
+ "java_lite_proto_library",
+ ruleRedirect("@protobuf//bazel:java_lite_proto_library.bzl"))
+ .put(
+ "java_package_configuration",
+ ruleRedirect("@rules_java//java/toolchains:java_package_configuration.bzl"))
+ .put("java_plugin", ruleRedirect("@rules_java//java:java_plugin.bzl"))
+ .put("java_proto_library", ruleRedirect("@protobuf//bazel:java_proto_library.bzl"))
+ .put("java_runtime", ruleRedirect("@rules_java//java/toolchains:java_runtime.bzl"))
+ .put("java_test", ruleRedirect("@rules_java//java:java_test.bzl"))
+ .put("java_toolchain", ruleRedirect("@rules_java//java/toolchains:java_toolchain.bzl"))
+ .put("memprof_profile", ruleRedirect("@rules_cc//cc/toolchains:memprof_profile.bzl"))
+ .put("objc_import", ruleRedirect("@rules_cc//cc:objc_import.bzl"))
+ .put("objc_library", ruleRedirect("@rules_cc//cc:objc_library.bzl"))
+ .put(
+ "propeller_optimize", ruleRedirect("@rules_cc//cc/toolchains:propeller_optimize.bzl"))
+ .put(
+ "proto_lang_toolchain",
+ ruleRedirect("@protobuf//bazel/toolchain:proto_lang_toolchain.bzl"))
+ .put("proto_library", ruleRedirect("@protobuf//bazel:proto_library.bzl"))
+ .put("py_binary", ruleRedirect("@rules_python//python:py_binary.bzl"))
+ .put("py_library", ruleRedirect("@rules_python//python:py_library.bzl"))
+ .put("py_runtime", ruleRedirect("@rules_python//python:py_runtime.bzl"))
+ .put("py_test", ruleRedirect("@rules_python//python:py_test.bzl"))
+ .put("sh_binary", ruleRedirect("@rules_sh//sh:sh_binary.bzl"))
+ .put("sh_library", ruleRedirect("@rules_sh//sh:sh_library.bzl"))
+ .put("sh_test", ruleRedirect("@rules_sh//sh:sh_test.bzl"))
+ .put("available_xcodes", ruleRedirect("@apple_support//xcode:available_xcodes.bzl"))
+ .put("xcode_config", ruleRedirect("@apple_support//xcode:xcode_config.bzl"))
+ .put("xcode_config_alias", ruleRedirect("@apple_support//xcode:xcode_config_alias.bzl"))
+ .put("xcode_version", ruleRedirect("@apple_support//xcode:xcode_version.bzl"))
+ // this redirect doesn't exists and probably never will, we still need a configuration for
+ // it, so that it can be removed from Bazels <= 7 if needed
+ .put(
+ "apple_common",
+ symbolRedirect("@apple_support//lib:apple_common.bzl", "objc_import", "objc_library"))
+ .buildOrThrow();
+}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BUILD b/src/main/java/com/google/devtools/build/lib/packages/BUILD
index f98a21b903d533..198511309cea06 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/packages/BUILD
@@ -85,7 +85,10 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/io:file_symlink_exception",
"//src/main/java/com/google/devtools/build/lib/packages/semantics",
"//src/main/java/com/google/devtools/build/lib/profiler",
+ "//src/main/java/com/google/devtools/build/lib/skyframe:bzl_load_value",
"//src/main/java/com/google/devtools/build/lib/skyframe:detailed_exceptions",
+ "//src/main/java/com/google/devtools/build/lib/skyframe:repository_mapping_value",
+ "//src/main/java/com/google/devtools/build/lib/skyframe:starlark_builtins_value",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization:visible-for-serialization",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
diff --git a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java
index fb48c0724341a5..79614d6f46696d 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java
@@ -20,6 +20,7 @@
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.common.options.Converters.CommaSeparatedNonEmptyOptionListConverter;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
+import com.google.devtools.common.options.Converters.CommaSeparatedOptionSetConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
@@ -116,6 +117,58 @@ public final class BuildLanguageOptions extends OptionsBase {
+ "the builtins injection mechanism entirely.")
public String experimentalBuiltinsBzlPath;
+ @Option(
+ name = "incompatible_autoload_externally",
+ converter = CommaSeparatedOptionSetConverter.class,
+ defaultValue = "",
+ documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS,
+ effectTags = {OptionEffectTag.LOSES_INCREMENTAL_STATE, OptionEffectTag.BUILD_FILE_SEMANTICS},
+ metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
+ help =
+ "A comma-separated list of rules (or other symbols) that were previously part of Bazel"
+ + " and which are now to be retrieved from their respective external repositories."
+ + " This flag is intended to be used to facilitate migration of rules out of Bazel."
+ + " See also https://github.com/bazelbuild/bazel/issues/23043.\n"
+ + "A symbol that is autoloaded within a file behaves as if its built-into-Bazel"
+ + " definition were replaced by its canonical new definition in an external"
+ + " repository. For a BUILD file, this essentially means implicitly adding a load()"
+ + " statement. For a .bzl file, it's either a load() statement or a change to a field"
+ + " of the `native` object, depending on whether the autoloaded symbol is a rule.\n"
+ + "Bazel maintains a hardcoded list of all symbols that may be autoloaded; only those"
+ + " symbols may appear in this flag. For each symbol, Bazel knows the new definition"
+ + " location in an external repository, as well as a set of special-cased"
+ + " repositories that must not autoload it to avoid creating cycles.\n"
+ + "A list item of \"+foo\" in this flag causes symbol foo to be autoloaded, except in"
+ + " foo's exempt repositories, within which the Bazel-defined version of foo is still"
+ + " available.\n"
+ + "A list item of \"foo\" triggers autoloading as above, but the Bazel-defined"
+ + " version of foo is not made available to the excluded repositories. This ensures"
+ + " that foo's external repository does not depend on the old Bazel implementation of"
+ + " foo\n"
+ + "A list item of \"-foo\" does not trigger any autoloading, but makes the"
+ + " Bazel-defined version of foo inaccessible throughout the workspace. This is used"
+ + " to validate that the workspace is ready for foo's definition to be deleted from"
+ + " Bazel.\n"
+ + "If a symbol is not named in this flag then it continues to work as normal -- no"
+ + " autoloading is done, nor is the Bazel-defined version suppressed. For"
+ + " configuration see"
+ + " https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java")
+ public List incompatibleAutoloadExternally;
+
+ @Option(
+ name = "repositories_without_autoloads",
+ converter = CommaSeparatedOptionSetConverter.class,
+ defaultValue = "",
+ documentationCategory = OptionDocumentationCategory.STARLARK_SEMANTICS,
+ effectTags = {OptionEffectTag.LOSES_INCREMENTAL_STATE, OptionEffectTag.BUILD_FILE_SEMANTICS},
+ metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
+ help =
+ "A list of additional repositories (beyond the hardcoded ones Bazel knows about) where "
+ + "autoloads are not to be added. This should typically contain repositories that are"
+ + " transitively depended on by a repository that may be loaded automatically "
+ + "(and which can therefore potentially create a cycle).")
+ public List repositoriesWithoutAutoloads;
+
@Option(
name = "experimental_builtins_dummy",
defaultValue = "false",
@@ -790,6 +843,8 @@ public StarlarkSemantics toStarlarkSemantics() {
incompatibleStopExportingLanguageModules)
.setBool(INCOMPATIBLE_ALLOW_TAGS_PROPAGATION, experimentalAllowTagsPropagation)
.set(EXPERIMENTAL_BUILTINS_BZL_PATH, experimentalBuiltinsBzlPath)
+ .set(INCOMPATIBLE_AUTOLOAD_EXTERNALLY, incompatibleAutoloadExternally)
+ .set(REPOSITORIES_WITHOUT_AUTOLOAD, repositoriesWithoutAutoloads)
.setBool(EXPERIMENTAL_BUILTINS_DUMMY, experimentalBuiltinsDummy)
.set(EXPERIMENTAL_BUILTINS_INJECTION_OVERRIDE, experimentalBuiltinsInjectionOverride)
.setBool(EXPERIMENTAL_BZL_VISIBILITY, experimentalBzlVisibility)
@@ -989,6 +1044,10 @@ public StarlarkSemantics toStarlarkSemantics() {
// non-booleans
public static final StarlarkSemantics.Key EXPERIMENTAL_BUILTINS_BZL_PATH =
new StarlarkSemantics.Key<>("experimental_builtins_bzl_path", "%bundled%");
+ public static final StarlarkSemantics.Key> INCOMPATIBLE_AUTOLOAD_EXTERNALLY =
+ new StarlarkSemantics.Key<>("incompatible_autoload_externally", ImmutableList.of());
+ public static final StarlarkSemantics.Key> REPOSITORIES_WITHOUT_AUTOLOAD =
+ new StarlarkSemantics.Key<>("repositories_without_autoloads", ImmutableList.of());
public static final StarlarkSemantics.Key> EXPERIMENTAL_BUILTINS_INJECTION_OVERRIDE =
new StarlarkSemantics.Key<>("experimental_builtins_injection_override", ImmutableList.of());
public static final StarlarkSemantics.Key MAX_COMPUTATION_STEPS =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
index ccc9c2f33a6715..15c420517c11ef 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -2407,6 +2407,7 @@ java_library(
":bzl_load_value",
":repository_mapping_value",
":sky_functions",
+ ":starlark_builtins_value",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:module_extension",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:repo_rule_value",
"//src/main/java/com/google/devtools/build/lib/bazel/bzlmod:resolution",
@@ -2452,17 +2453,6 @@ java_library(
],
)
-java_library(
- name = "bzl_load_failed_exception",
- srcs = ["BzlLoadFailedException.java"],
- deps = [
- ":sane_analysis_exception",
- "//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
- "//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
- "//src/main/protobuf:failure_details_java_proto",
- ],
-)
-
java_library(
name = "state_informing_sky_function_environment",
srcs = ["StateInformingSkyFunctionEnvironment.java"],
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlCompileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlCompileFunction.java
index d18bfe2ca3e699..38c691fce1a27e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlCompileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlCompileFunction.java
@@ -20,6 +20,7 @@
import com.google.devtools.build.lib.cmdline.BazelCompileContext;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.packages.AutoloadSymbols;
import com.google.devtools.build.lib.packages.BazelStarlarkEnvironment;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
@@ -157,7 +158,14 @@ static BzlCompileValue computeInline(
// For WORKSPACE-loaded bzl files, the env isn't quite right not because of injection but
// because the "native" object is different. But A) that will be fixed with #11954, and B) we
// don't care for the same reason as above.
- predeclared = bazelStarlarkEnvironment.getUninjectedBuildBzlEnv();
+
+ // Takes into account --incompatible_autoload_externally, similarly to the comment above, this
+ // only defines the correct set of symbols, but does not load them yet.
+ AutoloadSymbols autoloadSymbols = PrecomputedValue.AUTOLOAD_SYMBOLS.get(env);
+ if (autoloadSymbols == null) {
+ return null;
+ }
+ predeclared = autoloadSymbols.getUninjectedBuildBzlEnv(key.getLabel());
}
// We have all deps. Parse, resolve, and return.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
index fdd2e3f2097e08..587f57e4b25f13 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
@@ -38,6 +38,7 @@
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.io.InconsistentFilesystemException;
+import com.google.devtools.build.lib.packages.AutoloadSymbols;
import com.google.devtools.build.lib.packages.BazelStarlarkEnvironment;
import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
import com.google.devtools.build.lib.packages.BzlInitThreadContext;
@@ -597,13 +598,19 @@ private StarlarkBuiltinsValue getBuiltins(
}
return StarlarkBuiltinsValue.createEmpty(starlarkSemantics);
}
+ AutoloadSymbols autoloadSymbols = PrecomputedValue.AUTOLOAD_SYMBOLS.get(env);
+ if (autoloadSymbols == null) {
+ return null;
+ }
try {
+ boolean withAutoloads = requiresAutoloads(key, autoloadSymbols);
if (inliningState == null) {
return (StarlarkBuiltinsValue)
- env.getValueOrThrow(StarlarkBuiltinsValue.key(), BuiltinsFailedException.class);
+ env.getValueOrThrow(
+ StarlarkBuiltinsValue.key(withAutoloads), BuiltinsFailedException.class);
} else {
return StarlarkBuiltinsFunction.computeInline(
- StarlarkBuiltinsValue.key(),
+ StarlarkBuiltinsValue.key(withAutoloads),
inliningState,
ruleClassProvider.getBazelStarlarkEnvironment(),
/* bzlLoadFunction= */ this);
@@ -623,6 +630,23 @@ private static boolean requiresBuiltinsInjection(BzlLoadValue.Key key) {
&& !(key instanceof BzlLoadValue.KeyForBzlmodBootstrap));
}
+ private static boolean requiresAutoloads(BzlLoadValue.Key key, AutoloadSymbols autoloadSymbols) {
+ // We do autoloads for all BUILD files and BUILD-loaded .bzl files, except for files in
+ // certain rule repos (see AutoloadSymbols#reposDisallowingAutoloads).
+ //
+ // We don't do autoloads for the WORKSPACE file, Bzlmod files, or .bzls loaded by them,
+ // because in general the rules repositories that we would load are not yet available.
+ //
+ // We never do autoloads for builtins bzls.
+ //
+ // We don't do autoloads for the prelude file, but that's a single file so users can migrate it
+ // easily. (We do autoloads in .bzl files that are loaded by the prelude file.)
+ return autoloadSymbols.isEnabled()
+ && key instanceof BzlLoadValue.KeyForBuild
+ && !key.isBuildPrelude()
+ && !autoloadSymbols.autoloadsDisabledForRepo(key.getLabel());
+ }
+
/**
* Given a bzl key, validates that the corresponding package exists (if required) and returns the
* associated compile key based on the package's root. Returns null for a missing Skyframe dep or
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoCycleReporter.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoCycleReporter.java
index 8fc44dd312b46d..16b9296f37e13d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoCycleReporter.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoCycleReporter.java
@@ -188,12 +188,25 @@ public boolean maybeReportCycle(
} else if (Iterables.any(cycle, IS_BZL_LOAD)) {
Label fileLabel =
((BzlLoadValue.Key) Iterables.getLast(Iterables.filter(cycle, IS_BZL_LOAD))).getLabel();
- eventHandler.handle(
- Event.error(
- null,
- String.format(
- "Failed to load .bzl file '%s': possible dependency cycle detected.\n",
- fileLabel)));
+ final String errorMessage;
+ if (cycle.get(0).equals(StarlarkBuiltinsValue.key(true))) {
+ // We know `fileLabel` is the last .bzl visited in the cycle. We also know that
+ // BzlLoadFunction triggered the cycle by requesting StarlarkBuiltinsValue w/autoloads.
+ // We know that we're not in builtins .bzls, because they don't request w/autoloads.
+ // Thus, `fileLabel` is a .bzl transitively depended on by an autoload.
+ errorMessage =
+ String.format(
+ "Cycle caused by autoloads, failed to load .bzl file '%s'.\n"
+ + "Add '%s' to --repositories_without_autoloads or disable autoloads by setting"
+ + " '--incompatible_autoload_externally='\n"
+ + "More information on https://github.com/bazelbuild/bazel/issues/23043.\n",
+ fileLabel, fileLabel.getRepository().getName());
+ } else {
+ errorMessage =
+ String.format(
+ "Failed to load .bzl file '%s': possible dependency cycle detected.\n", fileLabel);
+ }
+ eventHandler.handle(Event.error(null, errorMessage));
return true;
} else if (Iterables.any(cycle, IS_PACKAGE_LOOKUP)) {
PackageIdentifier pkg =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 0ae628042aab90..5a011582d06cd5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -39,6 +39,7 @@
import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable;
import com.google.devtools.build.lib.io.FileSymlinkException;
import com.google.devtools.build.lib.io.InconsistentFilesystemException;
+import com.google.devtools.build.lib.packages.AutoloadSymbols;
import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
import com.google.devtools.build.lib.packages.CachingPackageLocator;
@@ -473,14 +474,21 @@ public SkyValue compute(SkyKey key, Environment env)
StarlarkBuiltinsValue starlarkBuiltinsValue;
try {
+ // Bazel: we do autoloads for all BUILD files if enabled
+ AutoloadSymbols autoloadSymbols = PrecomputedValue.AUTOLOAD_SYMBOLS.get(env);
+ if (autoloadSymbols == null) {
+ return null;
+ }
if (bzlLoadFunctionForInlining == null) {
starlarkBuiltinsValue =
(StarlarkBuiltinsValue)
- env.getValueOrThrow(StarlarkBuiltinsValue.key(), BuiltinsFailedException.class);
+ env.getValueOrThrow(
+ StarlarkBuiltinsValue.key(/* withAutoloads= */ autoloadSymbols.isEnabled()),
+ BuiltinsFailedException.class);
} else {
starlarkBuiltinsValue =
StarlarkBuiltinsFunction.computeInline(
- StarlarkBuiltinsValue.key(),
+ StarlarkBuiltinsValue.key(/* withAutoloads= */ autoloadSymbols.isEnabled()),
BzlLoadFunction.InliningState.create(env),
packageFactory.getRuleClassProvider().getBazelStarlarkEnvironment(),
bzlLoadFunctionForInlining);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
index 9ebeaa31e08c96..e46e934b1f2141 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
@@ -19,6 +19,7 @@
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.packages.AutoloadSymbols;
import com.google.devtools.build.lib.packages.Package.ConfigSettingVisibilityPolicy;
import com.google.devtools.build.lib.packages.RuleVisibility;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
@@ -84,6 +85,10 @@ public static Injected injected(Precomputed precomputed, T value) {
public static final Precomputed STARLARK_SEMANTICS =
new Precomputed<>("starlark_semantics");
+ // Configuration of --incompatible_load_externally
+ public static final Precomputed AUTOLOAD_SYMBOLS =
+ new Precomputed<>("autoload_symbols");
+
static final Precomputed BUILD_ID = new Precomputed<>("build_id", /*shareable=*/ false);
public static final Precomputed