| // 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.packages; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; | |
| import com.google.devtools.build.lib.cmdline.Label; | |
| import com.google.devtools.build.lib.cmdline.RepositoryMapping; | |
| import com.google.devtools.build.lib.cmdline.RepositoryName; | |
| import com.google.devtools.build.lib.cmdline.StarlarkThreadContext; | |
| import com.google.errorprone.annotations.CanIgnoreReturnValue; | |
| import java.util.Optional; | |
| import javax.annotation.Nullable; | |
| import net.starlark.java.eval.EvalException; | |
| import net.starlark.java.eval.Starlark; | |
| import net.starlark.java.eval.StarlarkThread; | |
| /** | |
| * Bazel application data for the Starlark thread that evaluates the top-level code in a .bzl (or | |
| * .scl) module (i.e. when evaluating that module's global symbols). | |
| */ | |
| public final class BzlInitThreadContext extends StarlarkThreadContext | |
| implements RuleDefinitionEnvironment { | |
| private final Label bzlFile; | |
| /* Digest of the .bzl file being initialized along with all its transitive loads. */ | |
| private final byte[] transitiveDigest; | |
| // For storing the result of calling `visibility()`. | |
| @Nullable private BzlVisibility bzlVisibility; | |
| private final RepositoryName toolsRepository; | |
| // TODO(b/192694287): Remove once we migrate all tests from the allowlist | |
| private final Optional<Label> networkAllowlistForTests; | |
| private final Optional<Label> noExplicitMnemonicAllowlist; | |
| // Used for `configuration_field`. | |
| private final ImmutableMap<String, Class<?>> fragmentNameToClass; | |
| /** | |
| * Constructs a new context for initializing a .bzl file. | |
| * | |
| * @param bzlFile the name of the .bzl being initialized | |
| * @param transitiveDigest the hash of that file and its transitive load()s | |
| * @param toolsRepository the name of the tools repository, such as "@bazel_tools" | |
| * @param networkAllowlistForTests an allowlist for rule classes created by this thread | |
| * @param noExplicitMnemonicAllowlist an allowlist for explicit mnemonic enforcement | |
| * @param fragmentNameToClass a map from configuration fragment name to configuration fragment | |
| * class, such as "apple" to AppleConfiguration.class | |
| * @param mainRepoMapping the repository mapping of the main repository | |
| */ | |
| public BzlInitThreadContext( | |
| Label bzlFile, | |
| byte[] transitiveDigest, | |
| RepositoryName toolsRepository, | |
| Optional<Label> networkAllowlistForTests, | |
| Optional<Label> noExplicitMnemonicAllowlist, | |
| ImmutableMap<String, Class<?>> fragmentNameToClass, | |
| RepositoryMapping mainRepoMapping) { | |
| super(() -> mainRepoMapping); | |
| this.bzlFile = bzlFile; | |
| this.transitiveDigest = transitiveDigest; | |
| this.toolsRepository = toolsRepository; | |
| this.networkAllowlistForTests = networkAllowlistForTests; | |
| this.noExplicitMnemonicAllowlist = noExplicitMnemonicAllowlist; | |
| this.fragmentNameToClass = fragmentNameToClass; | |
| } | |
| /** | |
| * Retrieves this context from a Starlark thread. If not present, throws {@code EvalException} | |
| * with an error message indicating that {@code what} can't be used in this Starlark environment. | |
| */ | |
| @CanIgnoreReturnValue | |
| public static BzlInitThreadContext fromOrFail(StarlarkThread thread, String what) | |
| throws EvalException { | |
| @Nullable StarlarkThreadContext ctx = thread.getThreadLocal(StarlarkThreadContext.class); | |
| if (!(ctx instanceof BzlInitThreadContext)) { | |
| throw Starlark.errorf( | |
| "%s can only be used during .bzl initialization (top-level evaluation)", what); | |
| } | |
| return (BzlInitThreadContext) ctx; | |
| } | |
| /** | |
| * Retrieves this context from a Starlark thread. If not present, returns {@code null} instead. | |
| */ | |
| @Nullable | |
| public static BzlInitThreadContext fromOrNull(StarlarkThread thread) { | |
| return thread.getThreadLocal(StarlarkThreadContext.class) instanceof BzlInitThreadContext c | |
| ? c | |
| : null; | |
| } | |
| /** | |
| * Returns the label of the .bzl module being initialized. | |
| * | |
| * <p>Note that this is not necessarily the same as the module of the innermost stack frame (i.e., | |
| * {@code BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread)).label()}), | |
| * since the module may call helper functions loaded from elsewhere. | |
| */ | |
| public Label getBzlFile() { | |
| return bzlFile; | |
| } | |
| /** Returns the transitive digest of the .bzl module being initialized. */ | |
| public byte[] getTransitiveDigest() { | |
| return transitiveDigest; | |
| } | |
| /** | |
| * Returns the saved BzlVisibility that was declared for the currently initializing .bzl module. | |
| */ | |
| @Nullable | |
| public BzlVisibility getBzlVisibility() { | |
| return bzlVisibility; | |
| } | |
| /** Sets the BzlVisibility for the currently initializing .bzl module. */ | |
| public void setBzlVisibility(BzlVisibility bzlVisibility) { | |
| this.bzlVisibility = bzlVisibility; | |
| } | |
| /** Returns the name of the tools repository, such as "@bazel_tools". */ | |
| @Override | |
| public RepositoryName getToolsRepository() { | |
| return toolsRepository; | |
| } | |
| /** Returns a label for network allowlist for tests if one should be added. */ | |
| // TODO(b/192694287): Remove once we migrate all tests from the allowlist. | |
| @Override | |
| public Optional<Label> getNetworkAllowlistForTests() { | |
| return networkAllowlistForTests; | |
| } | |
| /** | |
| * Returns a label for explicit mnemonic allowlist if one should be added. | |
| * | |
| * <p>Part of the {@link RuleDefinitionEnvironment} implementation for Starlark rule definitions | |
| * in .bzl files. | |
| */ | |
| @Override | |
| public Optional<Label> getNoExplicitMnemonicAllowlist() { | |
| return noExplicitMnemonicAllowlist; | |
| } | |
| /** Returns a map from configuration fragment name to configuration fragment class. */ | |
| public ImmutableMap<String, Class<?>> getFragmentNameToClass() { | |
| return fragmentNameToClass; | |
| } | |
| } |