From cf3e59d30e56d79163a5006e079e04eadb026541 Mon Sep 17 00:00:00 2001 From: cparsons Date: Wed, 23 May 2018 10:01:20 -0700 Subject: Create GlobalBootstrap and the Bootstrap interface to add portions of the build API to a global environment. RELNOTES: None. PiperOrigin-RevId: 197742427 --- .../lib/analysis/ConfiguredRuleClassProvider.java | 28 ++++++----- .../build/lib/analysis/skylark/SkylarkModules.java | 54 +++++++--------------- .../devtools/build/lib/packages/BazelLibrary.java | 13 ++++-- .../build/lib/skylarkbuildapi/Bootstrap.java | 31 +++++++++++++ .../lib/skylarkbuildapi/TopLevelBootstrap.java | 51 ++++++++++++++++++++ .../google/devtools/build/lib/syntax/Runtime.java | 33 ++++++++++--- 6 files changed, 147 insertions(+), 63 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/skylarkbuildapi/Bootstrap.java create mode 100644 src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java (limited to 'src/main/java/com/google/devtools/build') diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java index efe086b581..04c3c1a1a9 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java @@ -61,8 +61,10 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.Environment.Extension; +import com.google.devtools.build.lib.syntax.Environment.GlobalFrame; import com.google.devtools.build.lib.syntax.Environment.Phase; import com.google.devtools.build.lib.syntax.Mutability; +import com.google.devtools.build.lib.syntax.Runtime; import com.google.devtools.build.lib.syntax.SkylarkSemantics; import com.google.devtools.build.lib.syntax.SkylarkUtils; import com.google.devtools.build.lib.syntax.Type; @@ -239,8 +241,8 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider { private PrerequisiteValidator prerequisiteValidator; private ImmutableMap.Builder skylarkAccessibleTopLevels = ImmutableMap.builder(); - private ImmutableList.Builder> skylarkModules = - ImmutableList.>builder().addAll(SkylarkModules.MODULES); + private ImmutableList.Builder> skylarkModules = + ImmutableList.>builder(); private ImmutableList.Builder nativeProviders = ImmutableList.builder(); private Set reservedActionMnemonics = new TreeSet<>(); private BuildConfiguration.ActionEnvironmentProvider actionEnvironmentProvider = @@ -790,21 +792,17 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider { } private Environment.GlobalFrame createGlobals( - ImmutableMap skylarkAccessibleToplLevels, + ImmutableMap skylarkAccessibleTopLevels, ImmutableList> modules) { - try (Mutability mutability = Mutability.create("ConfiguredRuleClassProvider globals")) { - Environment env = createSkylarkRuleClassEnvironment( - mutability, - SkylarkModules.getGlobals(modules), - SkylarkSemantics.DEFAULT_SEMANTICS, - /*eventHandler=*/ null, - /*astFileContentHashCode=*/ null, - /*importMap=*/ null); - for (Map.Entry entry : skylarkAccessibleToplLevels.entrySet()) { - env.setup(entry.getKey(), entry.getValue()); - } - return env.getGlobals(); + ImmutableMap.Builder envBuilder = ImmutableMap.builder(); + + SkylarkModules.addSkylarkGlobalsToBuilder(envBuilder); + for (Class module : modules) { + Runtime.setupModuleGlobals(envBuilder, module); } + envBuilder.putAll(skylarkAccessibleTopLevels.entrySet()); + + return GlobalFrame.createForBuiltins(envBuilder.build()); } private static ImmutableMap> createFragmentMap( diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java index b57b96bd26..9271102017 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java @@ -14,16 +14,10 @@ package com.google.devtools.build.lib.analysis.skylark; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.packages.BazelLibrary; import com.google.devtools.build.lib.packages.SkylarkNativeModule; -import com.google.devtools.build.lib.syntax.Environment; -import com.google.devtools.build.lib.syntax.Environment.GlobalFrame; -import com.google.devtools.build.lib.syntax.Mutability; -import com.google.devtools.build.lib.syntax.Runtime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.google.devtools.build.lib.skylarkbuildapi.TopLevelBootstrap; /** * The basis for a Skylark Environment with all build-related modules registered. @@ -33,37 +27,21 @@ public final class SkylarkModules { private SkylarkModules() { } /** - * The list of built in Skylark modules. Documentation is generated automatically for all these - * modules. They are also registered with the {@link Environment}. + * A bootstrap for non-rules-specific globals of the build API. */ - public static final ImmutableList> MODULES = - ImmutableList.of( - BazelBuildApiGlobals.class, - SkylarkAttr.class, - SkylarkCommandLine.class, - SkylarkNativeModule.class, - SkylarkRuleClassFunctions.class); + private static TopLevelBootstrap topLevelBootstrap = new TopLevelBootstrap( + BazelBuildApiGlobals.class, + SkylarkAttr.class, + SkylarkCommandLine.class, + SkylarkNativeModule.class, + SkylarkRuleClassFunctions.class); - /** Global bindings for all Skylark modules */ - private static final Map>, GlobalFrame> cache = new HashMap<>(); - - public static Environment.GlobalFrame getGlobals(List> modules) { - if (!cache.containsKey(modules)) { - cache.put(modules, createGlobals(modules)); - } - return cache.get(modules); - } - - private static Environment.GlobalFrame createGlobals(List> modules) { - try (Mutability mutability = Mutability.create("SkylarkModules")) { - Environment env = Environment.builder(mutability) - .useDefaultSemantics() - .setGlobals(BazelLibrary.GLOBALS) - .build(); - for (Class moduleClass : modules) { - Runtime.setupModuleGlobals(env, moduleClass); - } - return env.getGlobals(); - } + /** + * Adds bindings for skylark built-ins and non-rules-specific globals of the build API to + * the given environment map builder. + */ + public static void addSkylarkGlobalsToBuilder(ImmutableMap.Builder envBuilder) { + BazelLibrary.addSkylarkGlobalsToBuilder(envBuilder); + topLevelBootstrap.addBindingsToBuilder(envBuilder); } } diff --git a/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java b/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java index 205f98f167..d660940fb7 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java @@ -235,12 +235,19 @@ public class BazelLibrary { private static GlobalFrame createGlobals() { ImmutableMap.Builder builder = ImmutableMap.builder(); - Runtime.addConstantsToBuilder(builder); - MethodLibrary.addBindingsToBuilder(builder); - BazelLibrary.addBindingsToBuilder(builder); + addSkylarkGlobalsToBuilder(builder); return GlobalFrame.createForBuiltins(builder.build()); } + /** + * Adds bindings for skylark built-ins to the given environment map builder. + */ + public static void addSkylarkGlobalsToBuilder(ImmutableMap.Builder envBuilder) { + Runtime.addConstantsToBuilder(envBuilder); + MethodLibrary.addBindingsToBuilder(envBuilder); + BazelLibrary.addBindingsToBuilder(envBuilder); + } + static { SkylarkSignatureProcessor.configureSkylarkFunctions(BazelLibrary.class); } diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/Bootstrap.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/Bootstrap.java new file mode 100644 index 0000000000..5d531dacbc --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/Bootstrap.java @@ -0,0 +1,31 @@ +// Copyright 2018 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.skylarkbuildapi; + +import com.google.common.collect.ImmutableMap; + +/** + * A helper for registering a portion of the build API to skylark environment globals. + * + *

A global environment may be initialized by tabulating globals into a single map by passing + * a single map builder to {@link #addBindingsToBuilder} for several bootstrap helpers. + */ +public interface Bootstrap { + + /** + * Adds this bootstrap's bindings to the given environment map builder. + */ + public void addBindingsToBuilder(ImmutableMap.Builder builder); +} diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java new file mode 100644 index 0000000000..910a67a39b --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java @@ -0,0 +1,51 @@ +// Copyright 2018 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.skylarkbuildapi; + +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.syntax.Runtime; + +/** + * A {@link Bootstrap} for top-level libraries of the build API. + */ +public class TopLevelBootstrap implements Bootstrap { + private final Class skylarkBuildApiGlobals; + private final Class skylarkAttrApi; + private final Class skylarkCommandLineApi; + private final Class skylarkNativeModuleApi; + private final Class> skylarkRuleFunctionsApi; + + public TopLevelBootstrap( + Class skylarkBuildApiGlobals, + Class skylarkAttrApi, + Class skylarkCommandLineApi, + Class skylarkNativeModuleApi, + Class> skylarkRuleFunctionsApi) { + this.skylarkAttrApi = skylarkAttrApi; + this.skylarkBuildApiGlobals = skylarkBuildApiGlobals; + this.skylarkCommandLineApi = skylarkCommandLineApi; + this.skylarkNativeModuleApi = skylarkNativeModuleApi; + this.skylarkRuleFunctionsApi = skylarkRuleFunctionsApi; + } + + @Override + public void addBindingsToBuilder(ImmutableMap.Builder builder) { + Runtime.setupModuleGlobals(builder, skylarkAttrApi); + Runtime.setupModuleGlobals(builder, skylarkBuildApiGlobals); + Runtime.setupModuleGlobals(builder, skylarkCommandLineApi); + Runtime.setupModuleGlobals(builder, skylarkNativeModuleApi); + Runtime.setupModuleGlobals(builder, skylarkRuleFunctionsApi); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java index 0ada911516..9774ec5bb9 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java @@ -327,7 +327,24 @@ public final class Runtime { } /** - * Registers global (top-level) symbols provided by the given class object. + * Convenience overload of {@link #setupModuleGlobals(ImmutableMap.Builder, Class)} to add + * bindings directly to an {@link Environment}. + * + * @param env the Environment into which to register fields. + * @param moduleClass the Class object containing globals. + */ + public static void setupModuleGlobals(Environment env, Class moduleClass) { + ImmutableMap.Builder envBuilder = ImmutableMap.builder(); + + setupModuleGlobals(envBuilder, moduleClass); + for (Map.Entry envEntry : envBuilder.build().entrySet()) { + env.setup(envEntry.getKey(), envEntry.getValue()); + } + } + + /** + * Adds global (top-level) symbols, provided by the given class object, to the given bindings + * builder. * *

Global symbols may be provided by the given class in the following ways: *

    @@ -345,14 +362,16 @@ public final class Runtime { * multiple global libraries have functions of the same name, two modules of the same name * are given, or if two subclasses of the same module are given. * - * @param env the Environment into which to register fields. - * @param moduleClass the Class object containing globals. + * @param builder the builder for the "bindings" map, which maps from symbol names to objects, + * and which will be built into a global frame + * @param moduleClass the Class object containing globals */ - public static void setupModuleGlobals(Environment env, Class moduleClass) { + public static void setupModuleGlobals(ImmutableMap.Builder builder, + Class moduleClass) { try { SkylarkModule skylarkModule = SkylarkInterfaceUtils.getSkylarkModule(moduleClass); if (skylarkModule != null) { - env.setup( + builder.put( skylarkModule.name(), moduleClass.getConstructor().newInstance()); } @@ -367,14 +386,14 @@ public final class Runtime { if (!(value instanceof BuiltinFunction.Factory || (value instanceof BaseFunction && !annotation.objectType().equals(Object.class)))) { - env.setup(annotation.name(), value); + builder.put(annotation.name(), value); } } } if (SkylarkInterfaceUtils.hasSkylarkGlobalLibrary(moduleClass)) { Object moduleInstance = moduleClass.getConstructor().newInstance(); for (String methodName : FuncallExpression.getMethodNames(moduleClass)) { - env.setup(methodName, FuncallExpression.getBuiltinCallable(moduleInstance, methodName)); + builder.put(methodName, FuncallExpression.getBuiltinCallable(moduleInstance, methodName)); } } } catch (ReflectiveOperationException e) { -- cgit v1.2.3