diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/rules/BUILD index 821706ff4a02f2..d8cf7a1711e57f 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BUILD +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BUILD @@ -92,6 +92,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib/rules/proto", "//src/main/java/com/google/devtools/build/lib/rules/python", "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/android", + "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core", "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp", "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java", "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/objc", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java index b37121206c3815..c11d311c966ba7 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java @@ -53,6 +53,7 @@ import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoLibraryRule; import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaProtoLibraryRule; import com.google.devtools.build.lib.bazel.rules.python.BazelPyBinaryRule; +import com.google.devtools.build.lib.bazel.rules.python.BazelPyBuiltins; import com.google.devtools.build.lib.bazel.rules.python.BazelPyLibraryRule; import com.google.devtools.build.lib.bazel.rules.python.BazelPyRuleClasses; import com.google.devtools.build.lib.bazel.rules.python.BazelPyTestRule; @@ -121,6 +122,7 @@ import com.google.devtools.build.lib.rules.repository.NewLocalRepositoryRule; import com.google.devtools.build.lib.rules.test.TestingSupportRules; import com.google.devtools.build.lib.starlarkbuildapi.android.AndroidBootstrap; +import com.google.devtools.build.lib.starlarkbuildapi.core.ContextGuardedValue; import com.google.devtools.build.lib.starlarkbuildapi.proto.ProtoBootstrap; import com.google.devtools.build.lib.starlarkbuildapi.python.PyBootstrap; import com.google.devtools.build.lib.starlarkbuildapi.stubs.ProviderStub; @@ -137,6 +139,7 @@ import java.util.TreeMap; import java.util.function.Function; import javax.annotation.Nullable; +import net.starlark.java.eval.Starlark; /** A rule class provider implementing the rules Bazel knows. */ public class BazelRuleClassProvider { @@ -457,6 +460,13 @@ public void init(ConfiguredRuleClassProvider.Builder builder) { builder.addRuleDefinition(new BazelPyTestRule()); builder.addRuleDefinition(new PyRuntimeRule()); + // This symbol is overridden by exports.bzl + builder.addStarlarkAccessibleTopLevels( + "py_internal", + ContextGuardedValue.onlyInAllowedRepos( + Starlark.NONE, PyBootstrap.allowedRepositories)); + builder.addStarlarkBuiltinsInternal(BazelPyBuiltins.NAME, new BazelPyBuiltins()); + builder.addStarlarkBootstrap( new PyBootstrap( PyInfo.PROVIDER, PyRuntimeInfo.PROVIDER, PyStarlarkTransitions.INSTANCE)); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyBuiltins.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyBuiltins.java new file mode 100644 index 00000000000000..e84c93b2ed936e --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPyBuiltins.java @@ -0,0 +1,20 @@ +// Copyright 2022 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.bazel.rules.python; + +import com.google.devtools.build.lib.rules.python.PyBuiltins; + +/** PyBuiltins with Bazel-specific functionality. */ +public final class BazelPyBuiltins extends PyBuiltins {} diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java b/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java new file mode 100644 index 00000000000000..5c818134c05f92 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PyBuiltins.java @@ -0,0 +1,23 @@ +// Copyright 2022 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.rules.python; + +import net.starlark.java.annot.StarlarkBuiltin; +import net.starlark.java.eval.StarlarkValue; + +/** Bridge to allow builtins bzl code to call Java code. */ +@StarlarkBuiltin(name = "py_builtins", documented = false) +public abstract class PyBuiltins implements StarlarkValue { + public static final String NAME = "py_builtins"; +} diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core/ContextGuardedValue.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core/ContextGuardedValue.java new file mode 100644 index 00000000000000..7c670f6e9dd360 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/core/ContextGuardedValue.java @@ -0,0 +1,76 @@ +// Copyright 2022 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.starlarkbuildapi.core; + +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.lib.cmdline.BazelCompileContext; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import net.starlark.java.eval.GuardedValue; +import net.starlark.java.eval.StarlarkSemantics; + +/** + * Wrapper on a value in the predeclared lexical block that controls its accessibility to Starlark + * based on the context, in particular the package path the requesting .bzl file falls under. + */ +public final class ContextGuardedValue { + + private ContextGuardedValue() {} + + /** + * Creates a guard which only permits access of the given object when the requesting .bzl file is + * in a specific patckage path. An error is thrown if accessing it is done outside the allowed + * package paths. + */ + public static GuardedValue onlyInAllowedRepos( + Object obj, ImmutableSet allowedPrefixes) { + return new GuardedValue() { + @Override + public boolean isObjectAccessibleUsingSemantics( + StarlarkSemantics semantics, @Nullable Object clientData) { + // Filtering of predeclareds is only done at compile time, when the client data is + // BazelCompileContext and not BazelModuleContext. + if (clientData != null && clientData instanceof BazelCompileContext) { + BazelCompileContext context = (BazelCompileContext) clientData; + Label label = context.label(); + + for (PackageIdentifier prefix : allowedPrefixes) { + if (label.getRepository().equals(prefix.getRepository()) + && label.getPackageFragment().startsWith(prefix.getPackageFragment())) { + return true; + } + } + } + return false; + } + + @Override + public String getErrorFromAttemptingAccess(String name) { + return name + + " may only be used from one of the following repositories or prefixes: " + + allowedPrefixes.stream() + .map(PackageIdentifier::toString) + .collect(Collectors.joining(", ")); + } + + @Override + public Object getObject() { + return obj; + } + }; + } +} diff --git a/src/main/starlark/builtins_bzl/common/exports.bzl b/src/main/starlark/builtins_bzl/common/exports.bzl index 33dc18b24a2a4d..779e4d61dba294 100755 --- a/src/main/starlark/builtins_bzl/common/exports.bzl +++ b/src/main/starlark/builtins_bzl/common/exports.bzl @@ -26,6 +26,7 @@ load("@_builtins//:common/proto/proto_common.bzl", "proto_common_do_not_use") load("@_builtins//:common/proto/proto_library.bzl", "proto_library") load("@_builtins//:common/proto/proto_lang_toolchain_wrapper.bzl", "proto_lang_toolchain") load("@_builtins//:common/python/py_runtime_macro.bzl", "py_runtime") +load("@_builtins//:common/python/py_internal.bzl", "py_internal") load("@_builtins//:common/python/providers.bzl", "PyInfo", "PyRuntimeInfo") load("@_builtins//:common/java/proto/java_lite_proto_library.bzl", "java_lite_proto_library") load("@_builtins//:common/cc/cc_library.bzl", "cc_library") @@ -39,6 +40,7 @@ exported_toplevels = { "proto_common_do_not_use": proto_common_do_not_use, "-PyRuntimeInfo": PyRuntimeInfo, "-PyInfo": PyInfo, + "py_internal": py_internal, } # A list of Starlarkified native rules. diff --git a/src/main/starlark/builtins_bzl/common/python/py_internal.bzl b/src/main/starlark/builtins_bzl/common/python/py_internal.bzl new file mode 100644 index 00000000000000..9b4d4cb763bbb4 --- /dev/null +++ b/src/main/starlark/builtins_bzl/common/python/py_internal.bzl @@ -0,0 +1,20 @@ +# Copyright 2022 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. +"""PYTHON RULE IMPLEMENTATION ONLY: Do not use outside of the rule implementations and their tests. + +Various builtin Starlark defined objects exposed for non-builtin Starlark. +""" + +# This replaces the Java-defined name using exports.bzl toplevels mapping. +py_internal = struct()