aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/packages
diff options
context:
space:
mode:
authorGravatar brandjon <brandjon@google.com>2018-05-01 10:54:58 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-01 10:57:43 -0700
commitb80eb18e66adcdcbfbc1ec62cd1a67db1924504d (patch)
tree66080c778b7b095d3d159ba84855b315be96f4b9 /src/main/java/com/google/devtools/build/lib/packages
parent1de17c2644f8e0f4da0fbc6569db083a8acc56e7 (diff)
Move BazelLibrary from syntax/ to packages/
This helps the Skylark interpreter to not depend on Bazel concepts, though it adds a temporary dependency of Skylint on packages/. The fix for that will be to create a Build API interface for BazelLibrary (e.g., "BazelLibraryAPI"). Refactored some GlobalFrame construction logic to be more uniform. Instead of constructing a whole Environment just to get a frame, we build the frame directly, using ImmutableMap.Builder to accumulate bindings. This convention may further change once we convert MethodLibrary and the like to @SkylarkGlobalLibrary, but for now it's more readable. RELNOTES: None PiperOrigin-RevId: 194960824
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/packages')
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java247
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java1
3 files changed, 247 insertions, 2 deletions
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
new file mode 100644
index 0000000000..205f98f167
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/packages/BazelLibrary.java
@@ -0,0 +1,247 @@
+// Copyright 2016 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.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
+import com.google.devtools.build.lib.syntax.BaseFunction;
+import com.google.devtools.build.lib.syntax.BuiltinFunction;
+import com.google.devtools.build.lib.syntax.Environment.GlobalFrame;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.EvalUtils;
+import com.google.devtools.build.lib.syntax.MethodLibrary;
+import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.SelectorList;
+import com.google.devtools.build.lib.syntax.SelectorValue;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+import com.google.devtools.build.lib.syntax.SkylarkList;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.SkylarkSignatureProcessor;
+import com.google.devtools.build.lib.syntax.SkylarkType;
+
+/**
+ * A helper class containing additional built in functions for Bazel (BUILD files and .bzl files).
+ */
+public class BazelLibrary {
+
+ // TODO(bazel-team): Move to MethodLibrary alongside other pure-Skylark builtins.
+ @SkylarkSignature(
+ name = "type",
+ returnType = String.class,
+ doc =
+ "Returns the type name of its argument. This is useful for debugging and "
+ + "type-checking. Examples:"
+ + "<pre class=\"language-python\">"
+ + "type(2) == \"int\"\n"
+ + "type([1]) == \"list\"\n"
+ + "type(struct(a = 2)) == \"struct\""
+ + "</pre>"
+ + "This function might change in the future. To write Python-compatible code and "
+ + "be future-proof, use it only to compare return values: "
+ + "<pre class=\"language-python\">"
+ + "if type(x) == type([]): # if x is a list"
+ + "</pre>",
+ parameters = {@Param(name = "x", doc = "The object to check type of.")}
+ )
+ private static final BuiltinFunction type =
+ new BuiltinFunction("type") {
+ public String invoke(Object object) {
+ // There is no 'type' type in Skylark, so we return a string with the type name.
+ return EvalUtils.getDataTypeName(object, false);
+ }
+ };
+
+ @SkylarkSignature(
+ name = "depset",
+ returnType = SkylarkNestedSet.class,
+ doc =
+ "Creates a <a href=\"depset.html\">depset</a>. The <code>direct</code> parameter is a list "
+ + "of direct elements of the depset, and <code>transitive</code> parameter is "
+ + "a list of depsets whose elements become indirect elements of the created depset. "
+ + "The order in which elements are returned when the depset is converted to a list "
+ + "is specified by the <code>order</code> parameter. "
+ + "See the <a href=\"../depsets.md\">Depsets overview</a> for more information. "
+ + "<p> All elements (direct and indirect) of a depset must be of the same type. "
+ + "<p> The order of the created depset should be <i>compatible</i> with the order of "
+ + "its <code>transitive</code> depsets. <code>\"default\"</code> order is compatible "
+ + "with any other order, all other orders are only compatible with themselves."
+ + "<p> Note on backward/forward compatibility. This function currently accepts a "
+ + "positional <code>items</code> parameter. It is deprecated and will be removed "
+ + "in the future, and after its removal <code>direct</code> will become a sole "
+ + "positional parameter of the <code>depset</code> function. Thus, both of the "
+ + "following calls are equivalent and future-proof:<br>"
+ + "<pre class=language-python>"
+ + "depset(['a', 'b'], transitive = [...])\n"
+ + "depset(direct = ['a', 'b'], transitive = [...])\n"
+ + "</pre>",
+ parameters = {
+ @Param(
+ name = "items",
+ type = Object.class,
+ defaultValue = "[]",
+ doc =
+ "Deprecated: Either an iterable whose items become the direct elements of "
+ + "the new depset, in left-to-right order, or else a depset that becomes "
+ + "a transitive element of the new depset. In the latter case, "
+ + "<code>transitive</code> cannot be specified."
+ ),
+ @Param(
+ name = "order",
+ type = String.class,
+ defaultValue = "\"default\"",
+ doc =
+ "The traversal strategy for the new depset. See <a href=\"depset.html\">here</a> for "
+ + "the possible values."
+ ),
+ @Param(
+ name = "direct",
+ type = SkylarkList.class,
+ defaultValue = "None",
+ positional = false,
+ named = true,
+ noneable = true,
+ doc = "A list of <i>direct</i> elements of a depset."
+ ),
+ @Param(
+ name = "transitive",
+ named = true,
+ positional = false,
+ type = SkylarkList.class,
+ generic1 = SkylarkNestedSet.class,
+ noneable = true,
+ doc = "A list of depsets whose elements will become indirect elements of the depset.",
+ defaultValue = "None"
+ )
+ },
+ useLocation = true
+ )
+ private static final BuiltinFunction depset =
+ new BuiltinFunction("depset") {
+ public SkylarkNestedSet invoke(
+ Object items, String orderString, Object direct, Object transitive, Location loc)
+ throws EvalException {
+ Order order;
+ try {
+ order = Order.parse(orderString);
+ } catch (IllegalArgumentException ex) {
+ throw new EvalException(loc, ex);
+ }
+
+ if (transitive == Runtime.NONE && direct == Runtime.NONE) {
+ // Legacy behavior.
+ return SkylarkNestedSet.of(order, items, loc);
+ }
+
+ if (direct != Runtime.NONE && !isEmptySkylarkList(items)) {
+ throw new EvalException(
+ loc, "Do not pass both 'direct' and 'items' argument to depset constructor.");
+ }
+
+ // Non-legacy behavior: either 'transitive' or 'direct' were specified.
+ Iterable<Object> directElements;
+ if (direct != Runtime.NONE) {
+ directElements = ((SkylarkList<?>) direct).getContents(Object.class, "direct");
+ } else {
+ SkylarkType.checkType(items, SkylarkList.class, "items");
+ directElements = ((SkylarkList<?>) items).getContents(Object.class, "items");
+ }
+
+ Iterable<SkylarkNestedSet> transitiveList;
+ if (transitive != Runtime.NONE) {
+ SkylarkType.checkType(transitive, SkylarkList.class, "transitive");
+ transitiveList =
+ ((SkylarkList<?>) transitive).getContents(SkylarkNestedSet.class, "transitive");
+ } else {
+ transitiveList = ImmutableList.of();
+ }
+ SkylarkNestedSet.Builder builder = SkylarkNestedSet.builder(order, loc);
+ for (Object directElement : directElements) {
+ builder.addDirect(directElement);
+ }
+ for (SkylarkNestedSet transitiveSet : transitiveList) {
+ builder.addTransitive(transitiveSet);
+ }
+ return builder.build();
+ }
+ };
+
+ private static boolean isEmptySkylarkList(Object o) {
+ return o instanceof SkylarkList && ((SkylarkList) o).isEmpty();
+ }
+
+ /**
+ * Returns a function-value implementing "select" (i.e. configurable attributes) in the specified
+ * package context.
+ */
+ @SkylarkSignature(
+ name = "select",
+ doc =
+ "<code>select()</code> is the helper function that makes a rule attribute "
+ + "<a href=\"$BE_ROOT/common-definitions.html#configurable-attributes\">configurable</a>. "
+ + "See <a href=\"$BE_ROOT/functions.html#select\">build encyclopedia</a> for details.",
+ parameters = {
+ @Param(name = "x", type = SkylarkDict.class, doc = "The parameter to convert."),
+ @Param(
+ name = "no_match_error",
+ type = String.class,
+ defaultValue = "''",
+ doc = "Optional custom error to report if no condition matches."
+ )
+ },
+ useLocation = true
+ )
+ private static final BuiltinFunction select =
+ new BuiltinFunction("select") {
+ public Object invoke(SkylarkDict<?, ?> dict, String noMatchError, Location loc)
+ throws EvalException {
+ for (Object key : dict.keySet()) {
+ if (!(key instanceof String)) {
+ throw new EvalException(
+ loc, String.format("Invalid key: %s. select keys must be label references", key));
+ }
+ }
+ return SelectorList.of(new SelectorValue(dict, noMatchError));
+ }
+ };
+
+ /** Adds bindings for all the builtin functions of this class to the given map builder. */
+ public static void addBindingsToBuilder(ImmutableMap.Builder<String, Object> builder) {
+ for (BaseFunction function : allFunctions) {
+ builder.put(function.getName(), function);
+ }
+ }
+
+ private static final ImmutableList<BaseFunction> allFunctions =
+ ImmutableList.of(select, depset, type);
+
+ /** A global frame containing pure Skylark builtins and some Bazel builtins. */
+ public static final GlobalFrame GLOBALS = createGlobals();
+
+ private static GlobalFrame createGlobals() {
+ ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
+ Runtime.addConstantsToBuilder(builder);
+ MethodLibrary.addBindingsToBuilder(builder);
+ BazelLibrary.addBindingsToBuilder(builder);
+ return GlobalFrame.createForBuiltins(builder.build());
+ }
+
+ static {
+ SkylarkSignatureProcessor.configureSkylarkFunctions(BazelLibrary.class);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 873934e2e7..ac66963090 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -38,7 +38,6 @@ import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.BazelLibrary;
import com.google.devtools.build.lib.syntax.BuildFileAST;
import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.ClassObject;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 6868a98099..73358746d9 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -33,7 +33,6 @@ import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.BazelLibrary;
import com.google.devtools.build.lib.syntax.BuildFileAST;
import com.google.devtools.build.lib.syntax.BuiltinFunction;
import com.google.devtools.build.lib.syntax.ClassObject;