Implement legacy_symbols
In the repositories that don't have autoloads we also expose native.legacy_symbols.
Those can be used to fallback to the native symbol, whenever it's still available in Bazel.
Fallback using a top-level symbol doesn't work, because BzlCompileFunction would throw an error when it's mentioned.
legacy_symbols aren't available when autoloads are not enabled.
The feature is intended to be used with bazel_features repository, which can correctly report native symbols on all versions of Bazel.
PiperOrigin-RevId: 673741927
Change-Id: I2334030d70cbb944b92784e32a184841ea238d51
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
index e9f08c4..03a9647 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java
@@ -38,6 +38,7 @@
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.annotation.Nullable;
+import net.starlark.java.eval.GuardedValue;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkSemantics;
@@ -232,10 +233,14 @@
ImmutableMap<String, Object> originalEnv,
ImmutableMap<String, Object> newSymbols) {
if (isWithAutoloads) {
- return modifyBuildBzlEnv(originalEnv, /* add= */ newSymbols, /* remove= */ removedSymbols);
+ return modifyBuildBzlEnv(
+ originalEnv, /* add= */ newSymbols, /* remove= */ removedSymbols, isWithAutoloads);
} else {
return modifyBuildBzlEnv(
- originalEnv, /* add= */ ImmutableMap.of(), /* remove= */ partiallyRemovedSymbols);
+ originalEnv,
+ /* add= */ ImmutableMap.of(),
+ /* remove= */ partiallyRemovedSymbols,
+ isWithAutoloads);
}
}
@@ -247,7 +252,8 @@
private ImmutableMap<String, Object> modifyBuildBzlEnv(
ImmutableMap<String, Object> originalEnv,
ImmutableMap<String, Object> add,
- ImmutableList<String> remove) {
+ ImmutableList<String> remove,
+ boolean isWithAutoloads) {
Map<String, Object> envBuilder = new LinkedHashMap<>(originalEnv);
Map<String, Object> nativeBindings =
convertNativeStructToMap((StarlarkInfo) envBuilder.remove("native"));
@@ -266,6 +272,30 @@
envBuilder.remove(symbol);
}
}
+
+ if (!isWithAutoloads) {
+ // In the repositories that don't have autoloads we also expose native.legacy_symbols.
+ // Those can be used to fallback to the native symbol, whenever it's still available in Bazel.
+ // Fallback using a top-level symbol doesn't work, because BzlCompileFunction would throw an
+ // error when it's mentioned.
+ // legacy_symbols aren't available when autoloads are not enabled. The feature is intended to
+ // be use with bazel_features repository, which can correctly report native symbols on all
+ // versions of Bazel.
+ ImmutableMap<String, Object> legacySymbols =
+ envBuilder.entrySet().stream()
+ .filter(entry -> AUTOLOAD_CONFIG.containsKey(entry.getKey()))
+ .collect(
+ toImmutableMap(
+ e -> e.getKey(),
+ // Drop GuardedValue - it doesn't work on non-toplevel symbols
+ e ->
+ e.getValue() instanceof GuardedValue
+ ? ((GuardedValue) e.getValue()).getObject()
+ : e.getValue()));
+ nativeBindings.put(
+ "legacy_symbols", StructProvider.STRUCT.create(legacySymbols, "no native symbol '%s'"));
+ }
+
envBuilder.put(
"native", StructProvider.STRUCT.create(nativeBindings, "no native function or rule '%s'"));
return ImmutableMap.copyOf(envBuilder);
@@ -485,7 +515,8 @@
"rules_sh",
"apple_common",
"bazel_skylib",
- "bazel_tools");
+ "bazel_tools",
+ "bazel_features");
private static final ImmutableMap<String, SymbolRedirect> AUTOLOAD_CONFIG =
ImmutableMap.<String, SymbolRedirect>builder()
diff --git a/src/test/shell/integration/load_removed_symbols_test.sh b/src/test/shell/integration/load_removed_symbols_test.sh
index ba2e070..355fb78 100755
--- a/src/test/shell/integration/load_removed_symbols_test.sh
+++ b/src/test/shell/integration/load_removed_symbols_test.sh
@@ -59,6 +59,26 @@
EOF
}
+
+function mock_rules_java() {
+ rules_java_workspace="${TEST_TMPDIR}/rules_java_workspace"
+ mkdir -p "${rules_java_workspace}/java"
+ touch "${rules_java_workspace}/java/BUILD"
+ touch "${rules_java_workspace}/WORKSPACE"
+ cat > "${rules_java_workspace}/MODULE.bazel" << EOF
+module(name = "rules_java")
+EOF
+ cat >> MODULE.bazel << EOF
+bazel_dep(
+ name = "rules_java",
+)
+local_path_override(
+ module_name = "rules_java",
+ path = "${rules_java_workspace}",
+)
+EOF
+}
+
function disabled_test_removed_rule_loaded() {
setup_module_dot_bazel
mock_rules_android
@@ -413,5 +433,42 @@
bazel query --incompatible_autoload_externally=+@rules_python ':py_library' --output=build >&$TEST_log 2>&1 || fail "build failed"
}
+function test_legacy_symbols() {
+ setup_module_dot_bazel
+ mock_rules_java
+
+ rules_java_workspace="${TEST_TMPDIR}/rules_java_workspace"
+
+ mkdir -p "${rules_java_workspace}/java/common"
+ touch "${rules_java_workspace}/java/common/BUILD"
+ cat > "${rules_java_workspace}/java/common/proguard_spec_info.bzl" << EOF
+def _init(specs):
+ return {"specs": specs}
+
+def _proguard_spec_info():
+ if hasattr(native, "legacy_symbols"):
+ if hasattr(native.legacy_symbols, "ProguardSpecProvider"):
+ print("Native provider")
+ return native.legacy_symbols.ProguardSpecProvider
+ print("Starlark provider")
+ return provider(fields = ["specs"], init = _init)[0]
+
+ProguardSpecInfo = _proguard_spec_info()
+EOF
+
+ cat > BUILD << EOF
+load("@rules_java//java/common:proguard_spec_info.bzl", "ProguardSpecInfo")
+EOF
+
+ bazel build --incompatible_autoload_externally=+ProguardSpecProvider :all >&$TEST_log 2>&1 || fail "build unexpectedly failed"
+ expect_log "Native provider"
+
+
+ bazel build --incompatible_autoload_externally=ProguardSpecProvider,-java_lite_proto_library,-java_import :all >&$TEST_log 2>&1 || fail "build unexpectedly failed"
+ expect_log "Starlark provider"
+}
+
+
+
run_suite "load_removed_symbols"