blob: 2a5d42d1e69d793b1db20b2618fc5caa8289b20f [file] [log] [blame]
// Copyright 2023 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.analysis.starlark;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.ActionsProvider;
import com.google.devtools.build.lib.analysis.DefaultInfo;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RunEnvironmentInfo;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.packages.BuildGlobals;
import com.google.devtools.build.lib.packages.Proto;
import com.google.devtools.build.lib.packages.SelectorList;
import com.google.devtools.build.lib.packages.StarlarkGlobals;
import com.google.devtools.build.lib.packages.StarlarkNativeModule;
import com.google.devtools.build.lib.packages.StructProvider;
import net.starlark.java.eval.Starlark;
import net.starlark.java.lib.json.Json;
/**
* Sole implementation of {@link StarlarkGlobals}.
*
* <p>The reason for the class-interface split is to allow {@link BazelStarlarkEnvironment} to
* retrieve symbols defined and aggregated in the lib/analysis/ dir, without creating a dependency
* from lib/packages/ to lib/analysis.
*/
public final class StarlarkGlobalsImpl implements StarlarkGlobals {
private StarlarkGlobalsImpl() {}
public static final StarlarkGlobalsImpl INSTANCE = new StarlarkGlobalsImpl();
private void addCommonUtilToplevels(ImmutableMap.Builder<String, Object> env) {
// Maintainer's note: Changes to this method are relatively high impact since it's sourced for
// BUILD, .bzl, and even cquery environments.
Starlark.addMethods(env, Depset.DepsetLibrary.INSTANCE);
env.put("json", Json.INSTANCE);
env.put("proto", Proto.INSTANCE);
}
@Override
public ImmutableMap<String, Object> getUtilToplevels() {
// TODO(bazel-team): It's dubious that we include things like depset and select(), but not
// struct() here.
ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
addCommonUtilToplevels(env);
Starlark.addMethods(env, SelectorList.SelectLibrary.INSTANCE);
return env.buildOrThrow();
}
@Override
public ImmutableMap<String, Object> getUtilToplevelsForCquery() {
ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
addCommonUtilToplevels(env);
env.put("struct", StructProvider.STRUCT);
return env.buildOrThrow();
}
@Override
public ImmutableMap<String, Object> getFixedBuildFileToplevelsSharedWithNative() {
return StarlarkNativeModule.BINDINGS_FOR_BUILD_FILES;
}
@Override
public ImmutableMap<String, Object> getFixedBuildFileToplevelsNotInNative() {
ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
env.putAll(getUtilToplevels());
Starlark.addMethods(env, BuildGlobals.INSTANCE);
return env.buildOrThrow();
}
@Override
public ImmutableMap<String, Object> getFixedBzlToplevels() {
ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
env.putAll(getUtilToplevels());
Starlark.addMethods(env, new BazelBuildApiGlobals()); // e.g. configuration_field
Starlark.addMethods(env, new StarlarkRuleClassFunctions()); // e.g. rule
env.put("cmd_helper", new StarlarkCommandLine());
env.put("attr", new StarlarkAttrModule());
env.put("struct", StructProvider.STRUCT);
env.put("OutputGroupInfo", OutputGroupInfo.STARLARK_CONSTRUCTOR);
env.put("Actions", ActionsProvider.INSTANCE);
env.put("DefaultInfo", DefaultInfo.PROVIDER);
env.put("RunEnvironmentInfo", RunEnvironmentInfo.PROVIDER);
return env.buildOrThrow();
}
@Override
public ImmutableMap<String, Object> getSclToplevels() {
// TODO(bazel-team): We only want the visibility() symbol from BazelBuildApiGlobals, nothing
// else, but Starlark#addMethods doesn't allow that kind of granularity, and the Starlark
// interpreter doesn't provide any other way to turn a Java method definition into a
// callable symbol. So we hack it by building the map of all symbols in that class and
// retrieving just the one we want. The alternative of refactoring the class is more churn than
// its worth, given the starlarkbuildapi/ split.
ImmutableMap.Builder<String, Object> bazelBuildApiGlobalsSymbols = ImmutableMap.builder();
Starlark.addMethods(bazelBuildApiGlobalsSymbols, new BazelBuildApiGlobals());
Object visibilitySymbol = bazelBuildApiGlobalsSymbols.buildOrThrow().get("visibility");
ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
env.put("visibility", visibilitySymbol);
env.put("struct", StructProvider.STRUCT);
return env.buildOrThrow();
}
}