Migrate almost all Skylark global modules to skylarkbuildapi

There are still a few global @SkylarkSignature-annotated top-level objects that need to be migrated in SkylarkRuleClassFunctions, but this migrates everything else.

RELNOTES: None.
PiperOrigin-RevId: 195652038
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCommandLine.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCommandLine.java
index 6dd7b7f..d967126 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkCommandLine.java
@@ -16,36 +16,13 @@
 
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
-import com.google.devtools.build.lib.skylarkinterface.Param;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkCommandLineApi;
 import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
 
 /** A Skylark module class to create memory efficient command lines. */
-@SkylarkModule(
-  name = "cmd_helper",
-  namespace = true,
-  category = SkylarkModuleCategory.BUILTIN,
-  doc = "Deprecated. Module for creating memory efficient command lines."
-)
-public class SkylarkCommandLine {
+public class SkylarkCommandLine implements SkylarkCommandLineApi {
 
-  @SkylarkCallable(
-    name = "join_paths",
-    doc =
-        "Deprecated. Creates a single command line argument joining the paths of a set "
-            + "of files on the separator string.",
-    parameters = {
-      @Param(name = "separator", type = String.class, doc = "the separator string to join on."),
-      @Param(
-        name = "files",
-        type = SkylarkNestedSet.class,
-        generic1 = Artifact.class,
-        doc = "the files to concatenate."
-      )
-    }
-  )
+  @Override
   public String joinPaths(String separator, SkylarkNestedSet files) {
     NestedSet<Artifact> artifacts = files.getSet(Artifact.class);
     // TODO(bazel-team): lazy evaluate
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkFileType.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkFileType.java
index 814d199..85caec5 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkFileType.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkFileType.java
@@ -17,9 +17,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.skylarkbuildapi.FileTypeApi;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.EvalUtils;
 import com.google.devtools.build.lib.util.FileType;
@@ -27,15 +25,8 @@
 import java.util.List;
 
 /** A wrapper class for FileType and FileTypeSet functionality in Skylark. */
-@SkylarkModule(
-  name = "FileType",
-  category = SkylarkModuleCategory.NONE,
-  doc =
-      "Deprecated. File type for file filtering. Can be used to filter collections of labels "
-          + "for certain file types."
-)
 @AutoCodec
-public class SkylarkFileType {
+public class SkylarkFileType implements FileTypeApi<Artifact> {
 
   private final FileType fileType;
 
@@ -52,16 +43,7 @@
     return FileTypeSet.of(fileType);
   }
 
-  @SkylarkCallable(doc =
-      "Returns a list created from the elements of the parameter containing all the "
-    + "<a href=\"File.html\"><code>File</code></a>s that match the FileType. The parameter "
-    + "must be a <a href=\"depset.html\"><code>depset</code></a> or a "
-    + "<a href=\"list.html\"><code>list</code></a>.")
-  // toIterablesStrict() will ensure the parameter is a SkylarkNestedSet or a java Iterable
-  // (including SkylarkList). If it fails, the error location information will be inserted by the
-  // Skylark interface framework. If there's a dynamic type error on a non-Artifact element, the
-  // error will also be handled by the Skylark interface framework.
-  @SuppressWarnings("unchecked")
+  @Override
   public ImmutableList<Artifact> filter(Object filesUnchecked) throws EvalException {
     return ImmutableList.copyOf(
         FileType.filter(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 59a711a..4933d0a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -32,6 +32,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.analysis.ActionsProvider;
 import com.google.devtools.build.lib.analysis.BaseRuleClasses;
 import com.google.devtools.build.lib.analysis.DefaultInfo;
@@ -71,11 +72,8 @@
 import com.google.devtools.build.lib.packages.TargetUtils;
 import com.google.devtools.build.lib.packages.TestSize;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleFunctionsApi;
 import com.google.devtools.build.lib.skylarkinterface.Param;
-import com.google.devtools.build.lib.skylarkinterface.ParamType;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
 import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -100,8 +98,7 @@
 /**
  * A helper class to provide an easier API for Skylark rule definitions.
  */
-@SkylarkGlobalLibrary
-public class SkylarkRuleClassFunctions {
+public class SkylarkRuleClassFunctions implements SkylarkRuleFunctionsApi<Artifact> {
 
   // TODO(bazel-team): Copied from ConfiguredRuleClassProvider for the transition from built-in
   // rules to skylark extensions. Using the same instance would require a large refactoring.
@@ -293,47 +290,7 @@
   )
   private static final NativeProvider<?> actions = ActionsProvider.SKYLARK_CONSTRUCTOR;
 
-  @SkylarkCallable(
-    name = "provider",
-    doc =
-        "Creates a declared provider 'constructor'. The return value of this "
-            + "function can be used to create \"struct-like\" values. Example:<br>"
-            + "<pre class=\"language-python\">data = provider()\n"
-            + "d = data(x = 2, y = 3)\n"
-            + "print(d.x + d.y) # prints 5</pre>",
-    parameters = {
-      @Param(
-        name = "doc",
-        type = String.class,
-        legacyNamed = true,
-        defaultValue = "''",
-        doc =
-            "A description of the provider that can be extracted by documentation generating tools."
-      ),
-      @Param(
-        name = "fields",
-        doc = "If specified, restricts the set of allowed fields. <br>"
-            + "Possible values are:"
-            + "<ul>"
-            + "  <li> list of fields:<br>"
-            + "       <pre class=\"language-python\">provider(fields = ['a', 'b'])</pre><p>"
-            + "  <li> dictionary field name -> documentation:<br>"
-            + "       <pre class=\"language-python\">provider(\n"
-            + "       fields = { 'a' : 'Documentation for a', 'b' : 'Documentation for b' })</pre>"
-            + "</ul>"
-            + "All fields are optional.",
-        allowedTypes = {
-            @ParamType(type = SkylarkList.class, generic1 = String.class),
-            @ParamType(type = SkylarkDict.class)
-        },
-        noneable = true,
-        named = true,
-        positional = false,
-        defaultValue = "None"
-      )
-    },
-    useLocation = true
-  )
+  @Override
   public Provider provider(String doc, Object fields, Location location) throws EvalException {
     Iterable<String> fieldNames = null;
     if (fields instanceof SkylarkList<?>) {
@@ -355,199 +312,7 @@
   }
 
   // TODO(bazel-team): implement attribute copy and other rule properties
-  @SkylarkCallable(
-    name = "rule",
-    doc =
-        "Creates a new rule, which can be called from a BUILD file or a macro to create targets."
-            + "<p>Rules must be assigned to global variables in a .bzl file; the name of the "
-            + "global variable is the rule's name."
-            + "<p>Test rules are required to have a name ending in <code>_test</code>, while all "
-            + "other rules must not have this suffix. (This restriction applies only to rules, not "
-            + "to their targets.)",
-    parameters = {
-      @Param(
-        name = "implementation",
-        type = BaseFunction.class,
-        legacyNamed = true,
-        doc =
-            "the function implementing this rule, must have exactly one parameter: "
-                + "<a href=\"ctx.html\">ctx</a>. The function is called during the analysis "
-                + "phase for each instance of the rule. It can access the attributes "
-                + "provided by the user. It must create actions to generate all the declared "
-                + "outputs."
-      ),
-      @Param(
-        name = "test",
-        type = Boolean.class,
-        legacyNamed = true,
-        defaultValue = "False",
-        doc =
-            "Whether this rule is a test rule, that is, whether it may be the subject of a "
-                + "<code>blaze test</code> command. All test rules are automatically considered "
-                + "<a href='#rule.executable'>executable</a>; it is unnecessary (and discouraged) "
-                + "to explicitly set <code>executable = True</code> for a test rule. See the "
-                + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> for "
-                + "more information."
-      ),
-      @Param(
-        name = "attrs",
-        type = SkylarkDict.class,
-        legacyNamed = true,
-        noneable = true,
-        defaultValue = "None",
-        doc =
-            "dictionary to declare all the attributes of the rule. It maps from an attribute "
-                + "name to an attribute object (see <a href=\"attr.html\">attr</a> module). "
-                + "Attributes starting with <code>_</code> are private, and can be used to "
-                + "add an implicit dependency on a label. The attribute <code>name</code> is "
-                + "implicitly added and must not be specified. Attributes "
-                + "<code>visibility</code>, <code>deprecation</code>, <code>tags</code>, "
-                + "<code>testonly</code>, and <code>features</code> are implicitly added and "
-                + "cannot be overridden."
-      ),
-      // TODO(bazel-team): need to give the types of these builtin attributes
-      @Param(
-        name = "outputs",
-        type = SkylarkDict.class,
-        legacyNamed = true,
-        callbackEnabled = true,
-        noneable = true,
-        defaultValue = "None",
-        doc =
-            "<b>Experimental:</b> This API is in the process of being redesigned."
-                + "<p>A schema for defining predeclared outputs. Unlike <a href='attr.html#output'>"
-                + "<code>output</code></a> and <a href='attr.html#output_list'><code>output_list"
-                + "</code></a> attributes, the user does not specify the labels for these files. "
-                + "See the <a href='../rules.$DOC_EXT#files'>Rules page</a> for more on "
-                + "predeclared outputs."
-                + "<p>The value of this argument is either a dictionary or a callback function "
-                + "that produces a dictionary. The callback works similar to computed dependency "
-                + "attributes: The function's parameter names are matched against the rule's "
-                + "attributes, so for example if you pass <code>outputs = _my_func</code> with the "
-                + "definition <code>def _my_func(srcs, deps): ...</code>, the function has access "
-                + "to the attributes <code>srcs</code> and <code>deps</code>. Whether the "
-                + "dictionary is specified directly or via a function, it is interpreted as "
-                + "follows."
-                + "<p>Each entry in the dictionary creates a predeclared output where the key is "
-                + "an identifier and the value is a string template that determines the output's "
-                + "label. In the rule's implementation function, the identifier becomes the field "
-                + "name used to access the output's <a href='File.html'><code>File</code></a> in "
-                + "<a href='ctx.html#outputs'><code>ctx.outputs</code></a>. The output's label has "
-                + "the same package as the rule, and the part after the package is produced by "
-                + "substituting each placeholder of the form <code>\"%{ATTR}\"</code> with a "
-                + "string formed from the value of the attribute <code>ATTR</code>:"
-                + "<ul>"
-                + "<li>String-typed attributes are substituted verbatim."
-                + "<li>Label-typed attributes become the part of the label after the package, "
-                + "minus the file extension. For example, the label <code>\"//pkg:a/b.c\"</code> "
-                + "becomes <code>\"a/b\"</code>."
-                + "<li>Output-typed attributes become the part of the label after the package, "
-                + "including the file extension (for the above example, <code>\"a/b.c\"</code>)."
-                + "<li>All list-typed attributes (for example, <code>attr.label_list</code>) used "
-                + "in placeholders are required to have <i>exactly one element</i>. Their "
-                + "conversion is the same as their non-list version (<code>attr.label</code>)."
-                + "<li>Other attribute types may not appear in placeholders."
-                + "<li>The special non-attribute placeholders <code>%{dirname}</code> and <code>"
-                + "%{basename}</code> expand to those parts of the rule's label, excluding its "
-                + "package. For example, in <code>\"//pkg:a/b.c\"</code>, the dirname is <code>"
-                + "a</code> and the basename is <code>b.c</code>."
-                + "</ul>"
-                + "<p>In practice, the most common substitution placeholder is "
-                + "<code>\"%{name}\"</code>. For example, for a target named \"foo\", the outputs "
-                + "dict <code>{\"bin\": \"%{name}.exe\"}</code> predeclares an output named "
-                + "<code>foo.exe</code> that is accessible in the implementation function as "
-                + "<code>ctx.outputs.bin</code>."
-      ),
-      @Param(
-        name = "executable",
-        type = Boolean.class,
-        legacyNamed = true,
-        defaultValue = "False",
-        doc =
-            "Whether this rule is considered executable, that is, whether it may be the subject of "
-                + "a <code>blaze run</code> command. See the "
-                + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> for "
-                + "more information."
-      ),
-      @Param(
-        name = "output_to_genfiles",
-        type = Boolean.class,
-        legacyNamed = true,
-        defaultValue = "False",
-        doc =
-            "If true, the files will be generated in the genfiles directory instead of the "
-                + "bin directory. Unless you need it for compatibility with existing rules "
-                + "(e.g. when generating header files for C++), do not set this flag."
-      ),
-      @Param(
-        name = "fragments",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "List of names of configuration fragments that the rule requires "
-                + "in target configuration."
-      ),
-      @Param(
-        name = "host_fragments",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "List of names of configuration fragments that the rule requires "
-                + "in host configuration."
-      ),
-      @Param(
-        name = "_skylark_testable",
-        type = Boolean.class,
-        legacyNamed = true,
-        defaultValue = "False",
-        doc =
-            "<i>(Experimental)</i><br/><br/>"
-                + "If true, this rule will expose its actions for inspection by rules that "
-                + "depend on it via an <a href=\"globals.html#Actions\">Actions</a> "
-                + "provider. The provider is also available to the rule itself by calling "
-                + "<a href=\"ctx.html#created_actions\">ctx.created_actions()</a>."
-                + "<br/><br/>"
-                + "This should only be used for testing the analysis-time behavior of "
-                + "Skylark rules. This flag may be removed in the future."
-      ),
-      @Param(
-        name = "toolchains",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "<i>(Experimental)</i><br/><br/>"
-                + "If set, the set of toolchains this rule requires. Toolchains will be "
-                + "found by checking the current platform, and provided to the rule "
-                + "implementation via <code>ctx.toolchain</code>."
-      ),
-      @Param(
-        name = "doc",
-        type = String.class,
-        legacyNamed = true,
-        defaultValue = "''",
-        doc = "A description of the rule that can be extracted by documentation generating tools."
-      ),
-      @Param(
-        name = "provides",
-        type = SkylarkList.class,
-        named = true,
-        positional = false,
-        defaultValue = "[]",
-        doc =
-            "A list of providers this rule is guaranteed to provide. "
-                + "It is an error if a provider is listed here and the rule "
-                + "implementation function does not return it."
-      ),
-    },
-    useAst = true,
-    useEnvironment = true
-  )
+  @Override
   @SuppressWarnings({"rawtypes", "unchecked"}) // castMap produces
   // an Attribute.Builder instead of a Attribute.Builder<?> but it's OK.
   public BaseFunction rule(
@@ -690,122 +455,7 @@
     return requiredToolchains.build();
   }
 
-  @SkylarkCallable(
-    name = "aspect",
-    doc =
-        "Creates a new aspect. The result of this function must be stored in a global value. "
-            + "Please see the <a href=\"../aspects.md\">introduction to Aspects</a> for more "
-            + "details.",
-    parameters = {
-      @Param(
-        name = "implementation",
-        type = BaseFunction.class,
-        legacyNamed = true,
-        doc =
-            "the function implementing this aspect. Must have two parameters: "
-                + "<a href=\"Target.html\">Target</a> (the target to which the aspect is "
-                + "applied) and <a href=\"ctx.html\">ctx</a>. Attributes of the target are "
-                + "available via ctx.rule field. The function is called during the analysis "
-                + "phase for each application of an aspect to a target."
-      ),
-      @Param(
-        name = "attr_aspects",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "List of attribute names.  The aspect propagates along dependencies specified "
-                + "by attributes of a target with this name. The list can also contain a single "
-                + "string '*': in that case aspect propagates along all dependencies of a target."
-      ),
-      @Param(
-        name = "attrs",
-        type = SkylarkDict.class,
-        legacyNamed = true,
-        noneable = true,
-        defaultValue = "None",
-        doc =
-            "dictionary to declare all the attributes of the aspect.  "
-                + "It maps from an attribute name to an attribute object "
-                + "(see <a href=\"attr.html\">attr</a> module). "
-                + "Aspect attributes are available to implementation function as fields of ctx "
-                + "parameter. Implicit attributes starting with <code>_</code> must have default "
-                + "values, and have type <code>label</code> or <code>label_list</code>. "
-                + "Explicit attributes must have type <code>string</code>, and must use the "
-                + "<code>values</code> restriction. If explicit attributes are present, the "
-                + "aspect can only be used with rules that have attributes of the same name and "
-                + "type, with valid values."
-      ),
-      @Param(
-        name = "required_aspect_providers",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        defaultValue = "[]",
-        doc =
-            "Allow the aspect to inspect other aspects. If the aspect propagates along "
-                + "a dependency, and the underlying rule sends a different aspect along that "
-                + "dependency, and that aspect provides one of the providers listed here, this "
-                + "aspect will see the providers provided by that aspect. "
-                + "<p>The value should be either a list of providers, or a "
-                + "list of lists of providers. This aspect will 'see'  the underlying aspects that "
-                + "provide  ALL providers from at least ONE of these lists. A single list of "
-                + "providers will be automatically converted to a list containing one list of "
-                + "providers."
-      ),
-      @Param(
-        name = "provides",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        defaultValue = "[]",
-        doc =
-            "A list of providers this aspect is guaranteed to provide. "
-                + "It is an error if a provider is listed here and the aspect "
-                + "implementation function does not return it."
-      ),
-      @Param(
-        name = "fragments",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "List of names of configuration fragments that the aspect requires "
-                + "in target configuration."
-      ),
-      @Param(
-        name = "host_fragments",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "List of names of configuration fragments that the aspect requires "
-                + "in host configuration."
-      ),
-      @Param(
-        name = "toolchains",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc =
-            "<i>(Experimental)</i><br/><br/>"
-                + "If set, the set of toolchains this rule requires. Toolchains will be "
-                + "found by checking the current platform, and provided to the rule "
-                + "implementation via <code>ctx.toolchain</code>."
-      ),
-      @Param(
-        name = "doc",
-        type = String.class,
-        legacyNamed = true,
-        defaultValue = "''",
-        doc = "A description of the aspect that can be extracted by documentation generating tools."
-      )
-    },
-    useEnvironment = true,
-    useAst = true
-  )
+  @Override
   public SkylarkAspect aspect(
       BaseFunction implementation,
       SkylarkList attributeAspects,
@@ -1050,36 +700,7 @@
       ImmutableList.of(
           SkylarkProvider.class, SkylarkDefinedAspect.class, SkylarkRuleFunction.class);
 
-  @SkylarkCallable(
-    name = "Label",
-    doc =
-        "Creates a Label referring to a BUILD target. Use "
-            + "this function only when you want to give a default value for the label attributes. "
-            + "The argument must refer to an absolute label. "
-            + "Example: <br><pre class=language-python>Label(\"//tools:default\")</pre>",
-    parameters = {
-      @Param(name = "label_string", type = String.class, legacyNamed = true,
-          doc = "the label string."),
-      @Param(
-        name = "relative_to_caller_repository",
-        type = Boolean.class,
-        defaultValue = "False",
-        named = true,
-        positional = false,
-        doc =
-            "Deprecated. Do not use. "
-                + "When relative_to_caller_repository is True and the calling thread is a rule's "
-                + "implementation function, then a repo-relative label //foo:bar is resolved "
-                + "relative to the rule's repository.  For calls to Label from any other "
-                + "thread, or calls in which the relative_to_caller_repository flag is False, "
-                + "a repo-relative label is resolved relative to the file in which the "
-                + "Label() call appears."
-      )
-    },
-    useLocation = true,
-    useEnvironment = true
-  )
-  @SkylarkConstructor(objectType = Label.class)
+  @Override
   public Label label(
       String labelString, Boolean relativeToCallerRepository, Location loc, Environment env)
       throws EvalException {
@@ -1100,26 +721,7 @@
     }
   }
 
-  @SkylarkCallable(
-    name = "FileType",
-    doc =
-        "Deprecated. Creates a file filter from a list of strings. For example, to match "
-            + "files ending with .cc or .cpp, use: "
-            + "<pre class=language-python>FileType([\".cc\", \".cpp\"])</pre>",
-    parameters = {
-      @Param(
-        name = "types",
-        type = SkylarkList.class,
-        legacyNamed = true,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc = "a list of the accepted file extensions."
-      )
-    },
-    useLocation = true,
-    useEnvironment = true
-  )
-  @SkylarkConstructor(objectType = SkylarkFileType.class)
+  @Override
   public SkylarkFileType fileType(SkylarkList types, Location loc, Environment env)
       throws EvalException {
     if (env.getSemantics().incompatibleDisallowFileType()) {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
index 4322032..4c9e7d8 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
@@ -16,10 +16,7 @@
 
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.skylarkinterface.Param;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkNativeModuleApi;
 import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
@@ -32,55 +29,9 @@
  * A class for the Skylark native module. TODO(laurentlb): Some definitions are duplicated from
  * PackageFactory.
  */
-@SkylarkModule(
-  name = "native",
-  category = SkylarkModuleCategory.BUILTIN,
-  doc =
-      "A built-in module to support native rules and other package helper functions. "
-          + "All native rules appear as functions in this module, e.g. "
-          + "<code>native.cc_library</code>. "
-          + "Note that the native module is only available in the loading phase "
-          + "(i.e. for macros, not for rule implementations). Attributes will ignore "
-          + "<code>None</code> values, and treat them as if the attribute was unset.<br>"
-          + "The following functions are also available:"
-)
-public class SkylarkNativeModule {
+public class SkylarkNativeModule implements SkylarkNativeModuleApi {
 
-  @SkylarkCallable(
-    name = "glob",
-    doc =
-        "Glob returns a list of every file in the current package that:<ul>\n"
-            + "<li>Matches at least one pattern in <code>include</code>.</li>\n"
-            + "<li>Does not match any of the patterns in <code>exclude</code> "
-            + "(default <code>[]</code>).</li></ul>\n"
-            + "If the <code>exclude_directories</code> argument is enabled (set to <code>1</code>),"
-            + " files of type directory will be omitted from the results (default <code>1</code>).",
-    parameters = {
-      @Param(
-        name = "include",
-        type = SkylarkList.class,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc = "The list of glob patterns to include."
-      ),
-      @Param(
-        name = "exclude",
-        type = SkylarkList.class,
-        generic1 = String.class,
-        defaultValue = "[]",
-        doc = "The list of glob patterns to exclude."
-      ),
-      // TODO(bazel-team): accept booleans as well as integers? (and eventually migrate?)
-      @Param(
-        name = "exclude_directories",
-        type = Integer.class,
-        defaultValue = "1",
-        doc = "A flag whether to exclude directories or not."
-      )
-    },
-    useAst = true,
-    useEnvironment = true
-  )
+  @Override
   public SkylarkList<?> glob(
       SkylarkList<?> include,
       SkylarkList<?> exclude,
@@ -92,17 +43,7 @@
     return PackageFactory.callGlob(null, include, exclude, excludeDirectories != 0, ast, env);
   }
 
-  @SkylarkCallable(
-    name = "existing_rule",
-    doc =
-        "Returns a dictionary representing the attributes of a previously defined rule, "
-            + "or None if the rule does not exist.",
-    parameters = {
-      @Param(name = "name", type = String.class, doc = "The name of the rule.")
-    },
-    useAst = true,
-    useEnvironment = true
-  )
+  @Override
   public Object existingRule(String name, FuncallExpression ast, Environment env)
       throws EvalException, InterruptedException {
     env.checkLoadingOrWorkspacePhase("native.existing_rule", ast.getLocation());
@@ -118,15 +59,7 @@
     If necessary, we could allow filtering by tag (anytag, alltags), name (regexp?), kind ?
     For now, we ignore this, since users can implement it in Skylark.
   */
-  @SkylarkCallable(
-    name = "existing_rules",
-    doc =
-        "Returns a dict containing all the rules instantiated so far. "
-            + "The map key is the name of the rule. The map value is equivalent to the "
-            + "existing_rule output for that rule.",
-    useAst = true,
-    useEnvironment = true
-  )
+  @Override
   public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(
       FuncallExpression ast, Environment env)
       throws EvalException, InterruptedException {
@@ -134,19 +67,7 @@
     return PackageFactory.callGetRulesFunction(ast, env);
   }
 
-  @SkylarkCallable(name = "package_group",
-      doc = "This function defines a set of packages and assigns a label to the group. "
-          + "The label can be referenced in <code>visibility</code> attributes.",
-      parameters = {
-      @Param(name = "name", type = String.class, named = true, positional = false,
-          doc = "The unique name for this rule."),
-      @Param(name = "packages", type = SkylarkList.class, generic1 = String.class,
-          defaultValue = "[]", named = true, positional = false,
-          doc = "A complete enumeration of packages in this group."),
-      @Param(name = "includes", type = SkylarkList.class, generic1 = String.class,
-          defaultValue = "[]", named = true, positional = false,
-          doc = "Other package groups that are included in this one.")},
-      useAst = true, useEnvironment = true)
+  @Override
   public Runtime.NoneType packageGroup(String name, SkylarkList<?> packages,
       SkylarkList<?> includes,
       FuncallExpression ast, Environment env) throws EvalException {
@@ -154,20 +75,7 @@
     return PackageFactory.callPackageFunction(name, packages, includes, ast, env);
   }
 
-  @SkylarkCallable(name = "exports_files",
-    doc = "Specifies a list of files belonging to this package that are exported to other "
-        + "packages but not otherwise mentioned.",
-    parameters = {
-      @Param(name = "srcs", type = SkylarkList.class, generic1 = String.class,
-          doc = "The list of files to export."),
-      // TODO(bazel-team): make it possible to express the precise type ListOf(LabelDesignator)
-      @Param(name = "visibility", type = SkylarkList.class, defaultValue = "None", noneable = true,
-          doc = "A visibility declaration can to be specified. The files will be visible to the "
-              + "targets specified. If no visibility is specified, the files will be visible to "
-              + "every package."),
-      @Param(name = "licenses", type = SkylarkList.class, generic1 = String.class, noneable = true,
-          defaultValue = "None", doc = "Licenses to be specified.")},
-    useAst = true, useEnvironment = true)
+  @Override
   public Runtime.NoneType exportsFiles(SkylarkList<?> srcs, Object visibility, Object licenses,
       FuncallExpression ast, Environment env)
       throws EvalException {
@@ -175,19 +83,7 @@
     return PackageFactory.callExportsFiles(srcs, visibility, licenses, ast, env);
   }
 
-  @SkylarkCallable(
-    name = "package_name",
-    doc =
-        "The name of the package being evaluated. "
-            + "For example, in the BUILD file <code>some/package/BUILD</code>, its value "
-            + "will be <code>some/package</code>. "
-            + "If the BUILD file calls a function defined in a .bzl file, "
-            + "<code>package_name()</code> will match the caller BUILD file package. "
-            + "This function is equivalent to the deprecated variable <code>PACKAGE_NAME</code>.",
-    parameters = {},
-    useAst = true,
-    useEnvironment = true
-  )
+  @Override
   public String packageName(FuncallExpression ast, Environment env)
       throws EvalException {
     env.checkLoadingPhase("native.package_name", ast.getLocation());
@@ -196,19 +92,7 @@
     return packageId.getPackageFragment().getPathString();
   }
 
-  @SkylarkCallable(
-    name = "repository_name",
-    doc =
-        "The name of the repository the rule or build extension is called from. "
-            + "For example, in packages that are called into existence by the WORKSPACE stanza "
-            + "<code>local_repository(name='local', path=...)</code> it will be set to "
-            + "<code>@local</code>. In packages in the main repository, it will be set to "
-            + "<code>@</code>. This function is equivalent to the deprecated variable "
-            + "<code>REPOSITORY_NAME</code>.",
-    parameters = {},
-    useLocation = true,
-    useEnvironment = true
-  )
+  @Override
   public String repositoryName(Location location, Environment env)
       throws EvalException {
     env.checkLoadingPhase("native.repository_name", location);
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/FileTypeApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/FileTypeApi.java
new file mode 100644
index 0000000..cbff500
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/FileTypeApi.java
@@ -0,0 +1,41 @@
+// 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.ImmutableList;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.EvalException;
+
+/**
+ * Interface for an object representing the type of file.
+ */
+@SkylarkModule(
+    name = "FileType",
+    category = SkylarkModuleCategory.NONE,
+    doc =
+        "Deprecated. File type for file filtering. Can be used to filter collections of labels "
+            + "for certain file types."
+)
+public interface FileTypeApi<FileApiT extends FileApi> {
+
+  @SkylarkCallable(doc =
+      "Returns a list created from the elements of the parameter containing all the "
+          + "<a href=\"File.html\"><code>File</code></a>s that match the FileType. The parameter "
+          + "must be a <a href=\"depset.html\"><code>depset</code></a> or a "
+          + "<a href=\"list.html\"><code>list</code></a>.")
+  public ImmutableList<FileApiT> filter(Object filesUnchecked) throws EvalException;
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkCommandLineApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkCommandLineApi.java
new file mode 100644
index 0000000..9d5ee49
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkCommandLineApi.java
@@ -0,0 +1,50 @@
+// 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.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+
+/**
+ * Interface for a module associated with creating efficient command lines.
+ */
+@SkylarkModule(
+    name = "cmd_helper",
+    namespace = true,
+    category = SkylarkModuleCategory.BUILTIN,
+    doc = "Deprecated. Module for creating memory efficient command lines."
+)
+public interface SkylarkCommandLineApi {
+
+  @SkylarkCallable(
+    name = "join_paths",
+    doc =
+        "Deprecated. Creates a single command line argument joining the paths of a set "
+            + "of files on the separator string.",
+    parameters = {
+      @Param(name = "separator", type = String.class, doc = "the separator string to join on."),
+      @Param(
+        name = "files",
+        type = SkylarkNestedSet.class,
+        generic1 = FileApi.class,
+        doc = "the files to concatenate."
+      )
+    }
+  )
+  public String joinPaths(String separator, SkylarkNestedSet files);
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java
new file mode 100644
index 0000000..3e73359
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkNativeModuleApi.java
@@ -0,0 +1,182 @@
+// 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.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+import com.google.devtools.build.lib.syntax.SkylarkList;
+
+/**
+ * Interface for a module with native rule and package helper functions.
+ */
+@SkylarkModule(
+    name = "native",
+    category = SkylarkModuleCategory.BUILTIN,
+    doc =
+        "A built-in module to support native rules and other package helper functions. "
+            + "All native rules appear as functions in this module, e.g. "
+            + "<code>native.cc_library</code>. "
+            + "Note that the native module is only available in the loading phase "
+            + "(i.e. for macros, not for rule implementations). Attributes will ignore "
+            + "<code>None</code> values, and treat them as if the attribute was unset.<br>"
+            + "The following functions are also available:"
+)
+public interface SkylarkNativeModuleApi {
+
+  @SkylarkCallable(
+    name = "glob",
+    doc =
+        "Glob returns a list of every file in the current package that:<ul>\n"
+            + "<li>Matches at least one pattern in <code>include</code>.</li>\n"
+            + "<li>Does not match any of the patterns in <code>exclude</code> "
+            + "(default <code>[]</code>).</li></ul>\n"
+            + "If the <code>exclude_directories</code> argument is enabled (set to <code>1</code>),"
+            + " files of type directory will be omitted from the results (default <code>1</code>).",
+    parameters = {
+      @Param(
+        name = "include",
+        type = SkylarkList.class,
+        generic1 = String.class,
+        defaultValue = "[]",
+        doc = "The list of glob patterns to include."
+      ),
+      @Param(
+        name = "exclude",
+        type = SkylarkList.class,
+        generic1 = String.class,
+        defaultValue = "[]",
+        doc = "The list of glob patterns to exclude."
+      ),
+      // TODO(bazel-team): accept booleans as well as integers? (and eventually migrate?)
+      @Param(
+        name = "exclude_directories",
+        type = Integer.class,
+        defaultValue = "1",
+        doc = "A flag whether to exclude directories or not."
+      )
+    },
+    useAst = true,
+    useEnvironment = true
+  )
+  public SkylarkList<?> glob(
+      SkylarkList<?> include,
+      SkylarkList<?> exclude,
+      Integer excludeDirectories,
+      FuncallExpression ast,
+      Environment env)
+      throws EvalException, InterruptedException;
+
+  @SkylarkCallable(
+    name = "existing_rule",
+    doc =
+        "Returns a dictionary representing the attributes of a previously defined rule, "
+            + "or None if the rule does not exist.",
+    parameters = {
+      @Param(name = "name", type = String.class, doc = "The name of the rule.")
+    },
+    useAst = true,
+    useEnvironment = true
+  )
+  public Object existingRule(String name, FuncallExpression ast, Environment env)
+      throws EvalException, InterruptedException;
+
+  @SkylarkCallable(
+    name = "existing_rules",
+    doc =
+        "Returns a dict containing all the rules instantiated so far. "
+            + "The map key is the name of the rule. The map value is equivalent to the "
+            + "existing_rule output for that rule.",
+    useAst = true,
+    useEnvironment = true
+  )
+  public SkylarkDict<String, SkylarkDict<String, Object>> existingRules(
+      FuncallExpression ast, Environment env)
+      throws EvalException, InterruptedException;
+
+  @SkylarkCallable(name = "package_group",
+      doc = "This function defines a set of packages and assigns a label to the group. "
+          + "The label can be referenced in <code>visibility</code> attributes.",
+      parameters = {
+      @Param(name = "name", type = String.class, named = true, positional = false,
+          doc = "The unique name for this rule."),
+      @Param(name = "packages", type = SkylarkList.class, generic1 = String.class,
+          defaultValue = "[]", named = true, positional = false,
+          doc = "A complete enumeration of packages in this group."),
+      @Param(name = "includes", type = SkylarkList.class, generic1 = String.class,
+          defaultValue = "[]", named = true, positional = false,
+          doc = "Other package groups that are included in this one.")},
+      useAst = true, useEnvironment = true)
+  public Runtime.NoneType packageGroup(String name, SkylarkList<?> packages,
+      SkylarkList<?> includes,
+      FuncallExpression ast, Environment env) throws EvalException;
+
+  @SkylarkCallable(name = "exports_files",
+    doc = "Specifies a list of files belonging to this package that are exported to other "
+        + "packages but not otherwise mentioned.",
+    parameters = {
+      @Param(name = "srcs", type = SkylarkList.class, generic1 = String.class,
+          doc = "The list of files to export."),
+      // TODO(bazel-team): make it possible to express the precise type ListOf(LabelDesignator)
+      @Param(name = "visibility", type = SkylarkList.class, defaultValue = "None", noneable = true,
+          doc = "A visibility declaration can to be specified. The files will be visible to the "
+              + "targets specified. If no visibility is specified, the files will be visible to "
+              + "every package."),
+      @Param(name = "licenses", type = SkylarkList.class, generic1 = String.class, noneable = true,
+          defaultValue = "None", doc = "Licenses to be specified.")},
+    useAst = true, useEnvironment = true)
+  public Runtime.NoneType exportsFiles(SkylarkList<?> srcs, Object visibility, Object licenses,
+      FuncallExpression ast, Environment env)
+      throws EvalException;
+
+  @SkylarkCallable(
+    name = "package_name",
+    doc =
+        "The name of the package being evaluated. "
+            + "For example, in the BUILD file <code>some/package/BUILD</code>, its value "
+            + "will be <code>some/package</code>. "
+            + "If the BUILD file calls a function defined in a .bzl file, "
+            + "<code>package_name()</code> will match the caller BUILD file package. "
+            + "This function is equivalent to the deprecated variable <code>PACKAGE_NAME</code>.",
+    parameters = {},
+    useAst = true,
+    useEnvironment = true
+  )
+  public String packageName(FuncallExpression ast, Environment env)
+      throws EvalException;
+
+  @SkylarkCallable(
+    name = "repository_name",
+    doc =
+        "The name of the repository the rule or build extension is called from. "
+            + "For example, in packages that are called into existence by the WORKSPACE stanza "
+            + "<code>local_repository(name='local', path=...)</code> it will be set to "
+            + "<code>@local</code>. In packages in the main repository, it will be set to "
+            + "<code>@</code>. This function is equivalent to the deprecated variable "
+            + "<code>REPOSITORY_NAME</code>.",
+    parameters = {},
+    useLocation = true,
+    useEnvironment = true
+  )
+  public String repositoryName(Location location, Environment env)
+      throws EvalException;
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
new file mode 100644
index 0000000..53d25e8
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
@@ -0,0 +1,472 @@
+// 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.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.ParamType;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
+import com.google.devtools.build.lib.syntax.BaseFunction;
+import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+import com.google.devtools.build.lib.syntax.SkylarkList;
+
+/**
+ * Interface for a global Skylark library containing rule-related helper and registration functions.
+ */
+@SkylarkGlobalLibrary
+public interface SkylarkRuleFunctionsApi<FileApiT extends FileApi> {
+
+  @SkylarkCallable(
+    name = "provider",
+    doc =
+        "Creates a declared provider 'constructor'. The return value of this "
+            + "function can be used to create \"struct-like\" values. Example:<br>"
+            + "<pre class=\"language-python\">data = provider()\n"
+            + "d = data(x = 2, y = 3)\n"
+            + "print(d.x + d.y) # prints 5</pre>",
+    parameters = {
+      @Param(
+        name = "doc",
+        type = String.class,
+        legacyNamed = true,
+        defaultValue = "''",
+        doc =
+            "A description of the provider that can be extracted by documentation generating tools."
+      ),
+      @Param(
+        name = "fields",
+        doc = "If specified, restricts the set of allowed fields. <br>"
+            + "Possible values are:"
+            + "<ul>"
+            + "  <li> list of fields:<br>"
+            + "       <pre class=\"language-python\">provider(fields = ['a', 'b'])</pre><p>"
+            + "  <li> dictionary field name -> documentation:<br>"
+            + "       <pre class=\"language-python\">provider(\n"
+            + "       fields = { 'a' : 'Documentation for a', 'b' : 'Documentation for b' })</pre>"
+            + "</ul>"
+            + "All fields are optional.",
+        allowedTypes = {
+            @ParamType(type = SkylarkList.class, generic1 = String.class),
+            @ParamType(type = SkylarkDict.class)
+        },
+        noneable = true,
+        named = true,
+        positional = false,
+        defaultValue = "None"
+      )
+    },
+    useLocation = true
+  )
+  public ProviderApi provider(String doc, Object fields, Location location) throws EvalException;
+
+  @SkylarkCallable(
+    name = "rule",
+    doc =
+        "Creates a new rule, which can be called from a BUILD file or a macro to create targets."
+            + "<p>Rules must be assigned to global variables in a .bzl file; the name of the "
+            + "global variable is the rule's name."
+            + "<p>Test rules are required to have a name ending in <code>_test</code>, while all "
+            + "other rules must not have this suffix. (This restriction applies only to rules, not "
+            + "to their targets.)",
+    parameters = {
+      @Param(
+        name = "implementation",
+        type = BaseFunction.class,
+        legacyNamed = true,
+        doc =
+            "the function implementing this rule, must have exactly one parameter: "
+                + "<a href=\"ctx.html\">ctx</a>. The function is called during the analysis "
+                + "phase for each instance of the rule. It can access the attributes "
+                + "provided by the user. It must create actions to generate all the declared "
+                + "outputs."
+      ),
+      @Param(
+        name = "test",
+        type = Boolean.class,
+        legacyNamed = true,
+        defaultValue = "False",
+        doc =
+            "Whether this rule is a test rule, that is, whether it may be the subject of a "
+                + "<code>blaze test</code> command. All test rules are automatically considered "
+                + "<a href='#rule.executable'>executable</a>; it is unnecessary (and discouraged) "
+                + "to explicitly set <code>executable = True</code> for a test rule. See the "
+                + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> for "
+                + "more information."
+      ),
+      @Param(
+        name = "attrs",
+        type = SkylarkDict.class,
+        legacyNamed = true,
+        noneable = true,
+        defaultValue = "None",
+        doc =
+            "dictionary to declare all the attributes of the rule. It maps from an attribute "
+                + "name to an attribute object (see <a href=\"attr.html\">attr</a> module). "
+                + "Attributes starting with <code>_</code> are private, and can be used to "
+                + "add an implicit dependency on a label. The attribute <code>name</code> is "
+                + "implicitly added and must not be specified. Attributes "
+                + "<code>visibility</code>, <code>deprecation</code>, <code>tags</code>, "
+                + "<code>testonly</code>, and <code>features</code> are implicitly added and "
+                + "cannot be overridden."
+      ),
+      // TODO(bazel-team): need to give the types of these builtin attributes
+      @Param(
+        name = "outputs",
+        type = SkylarkDict.class,
+        legacyNamed = true,
+        callbackEnabled = true,
+        noneable = true,
+        defaultValue = "None",
+        doc =
+            "<b>Experimental:</b> This API is in the process of being redesigned."
+                + "<p>A schema for defining predeclared outputs. Unlike <a href='attr.html#output'>"
+                + "<code>output</code></a> and <a href='attr.html#output_list'><code>output_list"
+                + "</code></a> attributes, the user does not specify the labels for these files. "
+                + "See the <a href='../rules.$DOC_EXT#files'>Rules page</a> for more on "
+                + "predeclared outputs."
+                + "<p>The value of this argument is either a dictionary or a callback function "
+                + "that produces a dictionary. The callback works similar to computed dependency "
+                + "attributes: The function's parameter names are matched against the rule's "
+                + "attributes, so for example if you pass <code>outputs = _my_func</code> with the "
+                + "definition <code>def _my_func(srcs, deps): ...</code>, the function has access "
+                + "to the attributes <code>srcs</code> and <code>deps</code>. Whether the "
+                + "dictionary is specified directly or via a function, it is interpreted as "
+                + "follows."
+                + "<p>Each entry in the dictionary creates a predeclared output where the key is "
+                + "an identifier and the value is a string template that determines the output's "
+                + "label. In the rule's implementation function, the identifier becomes the field "
+                + "name used to access the output's <a href='File.html'><code>File</code></a> in "
+                + "<a href='ctx.html#outputs'><code>ctx.outputs</code></a>. The output's label has "
+                + "the same package as the rule, and the part after the package is produced by "
+                + "substituting each placeholder of the form <code>\"%{ATTR}\"</code> with a "
+                + "string formed from the value of the attribute <code>ATTR</code>:"
+                + "<ul>"
+                + "<li>String-typed attributes are substituted verbatim."
+                + "<li>Label-typed attributes become the part of the label after the package, "
+                + "minus the file extension. For example, the label <code>\"//pkg:a/b.c\"</code> "
+                + "becomes <code>\"a/b\"</code>."
+                + "<li>Output-typed attributes become the part of the label after the package, "
+                + "including the file extension (for the above example, <code>\"a/b.c\"</code>)."
+                + "<li>All list-typed attributes (for example, <code>attr.label_list</code>) used "
+                + "in placeholders are required to have <i>exactly one element</i>. Their "
+                + "conversion is the same as their non-list version (<code>attr.label</code>)."
+                + "<li>Other attribute types may not appear in placeholders."
+                + "<li>The special non-attribute placeholders <code>%{dirname}</code> and <code>"
+                + "%{basename}</code> expand to those parts of the rule's label, excluding its "
+                + "package. For example, in <code>\"//pkg:a/b.c\"</code>, the dirname is <code>"
+                + "a</code> and the basename is <code>b.c</code>."
+                + "</ul>"
+                + "<p>In practice, the most common substitution placeholder is "
+                + "<code>\"%{name}\"</code>. For example, for a target named \"foo\", the outputs "
+                + "dict <code>{\"bin\": \"%{name}.exe\"}</code> predeclares an output named "
+                + "<code>foo.exe</code> that is accessible in the implementation function as "
+                + "<code>ctx.outputs.bin</code>."
+      ),
+      @Param(
+        name = "executable",
+        type = Boolean.class,
+        legacyNamed = true,
+        defaultValue = "False",
+        doc =
+            "Whether this rule is considered executable, that is, whether it may be the subject of "
+                + "a <code>blaze run</code> command. See the "
+                + "<a href='../rules.$DOC_EXT#executable-rules-and-test-rules'>Rules page</a> for "
+                + "more information."
+      ),
+      @Param(
+        name = "output_to_genfiles",
+        type = Boolean.class,
+        legacyNamed = true,
+        defaultValue = "False",
+        doc =
+            "If true, the files will be generated in the genfiles directory instead of the "
+                + "bin directory. Unless you need it for compatibility with existing rules "
+                + "(e.g. when generating header files for C++), do not set this flag."
+      ),
+      @Param(
+        name = "fragments",
+        type = SkylarkList.class,
+        legacyNamed = true,
+        generic1 = String.class,
+        defaultValue = "[]",
+        doc =
+            "List of names of configuration fragments that the rule requires "
+                + "in target configuration."
+      ),
+      @Param(
+        name = "host_fragments",
+        type = SkylarkList.class,
+        legacyNamed = true,
+        generic1 = String.class,
+        defaultValue = "[]",
+        doc =
+            "List of names of configuration fragments that the rule requires "
+                + "in host configuration."
+      ),
+      @Param(
+        name = "_skylark_testable",
+        type = Boolean.class,
+        legacyNamed = true,
+        defaultValue = "False",
+        doc =
+            "<i>(Experimental)</i><br/><br/>"
+                + "If true, this rule will expose its actions for inspection by rules that "
+                + "depend on it via an <a href=\"globals.html#Actions\">Actions</a> "
+                + "provider. The provider is also available to the rule itself by calling "
+                + "<a href=\"ctx.html#created_actions\">ctx.created_actions()</a>."
+                + "<br/><br/>"
+                + "This should only be used for testing the analysis-time behavior of "
+                + "Skylark rules. This flag may be removed in the future."
+      ),
+      @Param(
+        name = "toolchains",
+        type = SkylarkList.class,
+        legacyNamed = true,
+        generic1 = String.class,
+        defaultValue = "[]",
+        doc =
+            "<i>(Experimental)</i><br/><br/>"
+                + "If set, the set of toolchains this rule requires. Toolchains will be "
+                + "found by checking the current platform, and provided to the rule "
+                + "implementation via <code>ctx.toolchain</code>."
+      ),
+      @Param(
+        name = "doc",
+        type = String.class,
+        legacyNamed = true,
+        defaultValue = "''",
+        doc = "A description of the rule that can be extracted by documentation generating tools."
+      ),
+      @Param(
+        name = "provides",
+        type = SkylarkList.class,
+        named = true,
+        positional = false,
+        defaultValue = "[]",
+        doc =
+            "A list of providers this rule is guaranteed to provide. "
+                + "It is an error if a provider is listed here and the rule "
+                + "implementation function does not return it."
+      ),
+    },
+    useAst = true,
+    useEnvironment = true
+  )
+  public BaseFunction rule(
+      BaseFunction implementation,
+      Boolean test,
+      Object attrs,
+      Object implicitOutputs,
+      Boolean executable,
+      Boolean outputToGenfiles,
+      SkylarkList<?> fragments,
+      SkylarkList<?> hostFragments,
+      Boolean skylarkTestable,
+      SkylarkList<String> toolchains,
+      String doc,
+      SkylarkList<?> providesArg,
+      FuncallExpression ast,
+      Environment funcallEnv)
+      throws EvalException;
+
+  @SkylarkCallable(
+      name = "aspect",
+      doc =
+          "Creates a new aspect. The result of this function must be stored in a global value. "
+              + "Please see the <a href=\"../aspects.md\">introduction to Aspects</a> for more "
+              + "details.",
+      parameters = {
+          @Param(
+              name = "implementation",
+              type = BaseFunction.class,
+              legacyNamed = true,
+              doc =
+                  "the function implementing this aspect. Must have two parameters: "
+                      + "<a href=\"Target.html\">Target</a> (the target to which the aspect is "
+                      + "applied) and <a href=\"ctx.html\">ctx</a>. Attributes of the target are "
+                      + "available via ctx.rule field. The function is called during the analysis "
+                      + "phase for each application of an aspect to a target."
+          ),
+          @Param(
+              name = "attr_aspects",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              generic1 = String.class,
+              defaultValue = "[]",
+              doc = "List of attribute names.  The aspect propagates along dependencies specified "
+                  + "by attributes of a target with this name. The list can also contain a single "
+                  + "string '*': in that case aspect propagates along all dependencies of a target."
+          ),
+          @Param(
+              name = "attrs",
+              type = SkylarkDict.class,
+              legacyNamed = true,
+              noneable = true,
+              defaultValue = "None",
+              doc = "dictionary to declare all the attributes of the aspect.  "
+                  + "It maps from an attribute name to an attribute object "
+                  + "(see <a href=\"attr.html\">attr</a> module). "
+                  + "Aspect attributes are available to implementation function as fields of ctx "
+                  + "parameter. Implicit attributes starting with <code>_</code> must have default "
+                  + "values, and have type <code>label</code> or <code>label_list</code>. "
+                  + "Explicit attributes must have type <code>string</code>, and must use the "
+                  + "<code>values</code> restriction. If explicit attributes are present, the "
+                  + "aspect can only be used with rules that have attributes of the same name and "
+                  + "type, with valid values."
+          ),
+          @Param(
+              name = "required_aspect_providers",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              defaultValue = "[]",
+              doc = "Allow the aspect to inspect other aspects. If the aspect propagates along "
+                  + "a dependency, and the underlying rule sends a different aspect along that "
+                  + "dependency, and that aspect provides one of the providers listed here, this "
+                  + "aspect will see the providers provided by that aspect. "
+                  + "<p>The value should be either a list of providers, or a "
+                  + "list of lists of providers. This aspect will 'see'  the underlying aspects "
+                  + "that provide  ALL providers from at least ONE of these lists. A single list "
+                  + "of providers will be automatically converted to a list containing one list of "
+                  + "providers."
+          ),
+          @Param(
+              name = "provides",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              defaultValue = "[]",
+              doc =
+                  "A list of providers this aspect is guaranteed to provide. "
+                      + "It is an error if a provider is listed here and the aspect "
+                      + "implementation function does not return it."
+          ),
+          @Param(
+              name = "fragments",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              generic1 = String.class,
+              defaultValue = "[]",
+              doc =
+                  "List of names of configuration fragments that the aspect requires "
+                      + "in target configuration."
+          ),
+          @Param(
+              name = "host_fragments",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              generic1 = String.class,
+              defaultValue = "[]",
+              doc =
+                  "List of names of configuration fragments that the aspect requires "
+                      + "in host configuration."
+          ),
+          @Param(
+              name = "toolchains",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              generic1 = String.class,
+              defaultValue = "[]",
+              doc =
+                  "<i>(Experimental)</i><br/><br/>"
+                      + "If set, the set of toolchains this rule requires. Toolchains will be "
+                      + "found by checking the current platform, and provided to the rule "
+                      + "implementation via <code>ctx.toolchain</code>."
+          ),
+          @Param(
+              name = "doc",
+              type = String.class,
+              legacyNamed = true,
+              defaultValue = "''",
+              doc = "A description of the aspect that can be extracted by documentation generating "
+                  + "tools."
+          )
+      },
+      useEnvironment = true,
+      useAst = true
+  )
+  public SkylarkAspectApi aspect(
+      BaseFunction implementation,
+      SkylarkList attributeAspects,
+      Object attrs,
+      SkylarkList requiredAspectProvidersArg,
+      SkylarkList providesArg,
+      SkylarkList fragments,
+      SkylarkList hostFragments,
+      SkylarkList<String> toolchains,
+      String doc,
+      FuncallExpression ast,
+      Environment funcallEnv)
+      throws EvalException;
+
+  @SkylarkCallable(
+      name = "Label",
+      doc = "Creates a Label referring to a BUILD target. Use "
+          + "this function only when you want to give a default value for the label attributes. "
+          + "The argument must refer to an absolute label. "
+          + "Example: <br><pre class=language-python>Label(\"//tools:default\")</pre>",
+      parameters = {
+          @Param(name = "label_string", type = String.class, legacyNamed = true,
+              doc = "the label string."),
+          @Param(
+              name = "relative_to_caller_repository",
+              type = Boolean.class,
+              defaultValue = "False",
+              named = true,
+              positional = false,
+              doc = "Deprecated. Do not use. "
+                  + "When relative_to_caller_repository is True and the calling thread is a rule's "
+                  + "implementation function, then a repo-relative label //foo:bar is resolved "
+                  + "relative to the rule's repository.  For calls to Label from any other "
+                  + "thread, or calls in which the relative_to_caller_repository flag is False, "
+                  + "a repo-relative label is resolved relative to the file in which the "
+                  + "Label() call appears."
+          )
+      },
+      useLocation = true,
+      useEnvironment = true
+  )
+  @SkylarkConstructor(objectType = Label.class)
+  public Label label(
+      String labelString, Boolean relativeToCallerRepository, Location loc, Environment env)
+      throws EvalException;
+
+  @SkylarkCallable(
+      name = "FileType",
+      doc =
+          "Deprecated. Creates a file filter from a list of strings. For example, to match "
+              + "files ending with .cc or .cpp, use: "
+              + "<pre class=language-python>FileType([\".cc\", \".cpp\"])</pre>",
+      parameters = {
+          @Param(
+              name = "types",
+              type = SkylarkList.class,
+              legacyNamed = true,
+              generic1 = String.class,
+              defaultValue = "[]",
+              doc = "a list of the accepted file extensions."
+          )
+      },
+      useLocation = true,
+      useEnvironment = true
+  )
+  @SkylarkConstructor(objectType = FileTypeApi.class)
+  public FileTypeApi<FileApiT> fileType(SkylarkList<?> types, Location loc, Environment env)
+     throws EvalException;
+}