Implement Starlark proto_library.

This is Starlarkification of BazelProtoLibrary and BazelProtoLibraryRule classes.

PiperOrigin-RevId: 407296007
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/BUILD b/src/main/java/com/google/devtools/build/lib/rules/proto/BUILD
index 6c45232..25e7641 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/BUILD
@@ -38,6 +38,7 @@
         "//src/main/java/com/google/devtools/build/lib/analysis:rule_definition_environment",
         "//src/main/java/com/google/devtools/build/lib/analysis:transitive_info_collection",
         "//src/main/java/com/google/devtools/build/lib/analysis:transitive_info_provider",
+        "//src/main/java/com/google/devtools/build/lib/analysis/starlark/annotations",
         "//src/main/java/com/google/devtools/build/lib/analysis/stringtemplate",
         "//src/main/java/com/google/devtools/build/lib/cmdline",
         "//src/main/java/com/google/devtools/build/lib/collect/nestedset",
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoCommon.java b/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoCommon.java
index 618d246..62114d7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoCommon.java
@@ -19,6 +19,7 @@
 import com.google.devtools.build.lib.packages.BazelModuleContext;
 import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.Services;
 import com.google.devtools.build.lib.starlarkbuildapi.proto.ProtoCommonApi;
+import javax.annotation.Nullable;
 import net.starlark.java.annot.Param;
 import net.starlark.java.annot.StarlarkMethod;
 import net.starlark.java.eval.EvalException;
@@ -36,7 +37,9 @@
       name = "create_proto_info",
       documented = false,
       parameters = {@Param(name = "ctx", doc = "The rule context")},
-      useStarlarkThread = true)
+      useStarlarkThread = true,
+      allowReturnNones = true)
+  @Nullable
   public ProtoInfo createProtoInfo(StarlarkRuleContext ruleContext, StarlarkThread thread)
       throws EvalException {
     Label label =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
index e8d2b90..466bbe7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoConfiguration.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.analysis.config.Fragment;
 import com.google.devtools.build.lib.analysis.config.FragmentOptions;
 import com.google.devtools.build.lib.analysis.config.RequiresOptions;
+import com.google.devtools.build.lib.analysis.starlark.annotations.StarlarkConfigurationField;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.starlarkbuildapi.ProtoConfigurationApi;
@@ -218,6 +219,7 @@
     return options.experimentalProtoExtraActions;
   }
 
+  @StarlarkConfigurationField(name = "proto_compiler", doc = "Label for the proto compiler.")
   public Label protoCompiler() {
     return options.protoCompiler;
   }
diff --git a/src/main/starlark/builtins_bzl/common/exports.bzl b/src/main/starlark/builtins_bzl/common/exports.bzl
index b2690c9..07ee892 100644
--- a/src/main/starlark/builtins_bzl/common/exports.bzl
+++ b/src/main/starlark/builtins_bzl/common/exports.bzl
@@ -22,6 +22,7 @@
 load("@_builtins//:common/objc/objc_library.bzl", "objc_library")
 load("@_builtins//:common/objc/apple_static_library.bzl", "apple_static_library")
 load("@_builtins//:common/objc/compilation_support.bzl", "compilation_support")
+load("@_builtins//:common/proto/proto_library.bzl", "proto_library")
 
 exported_toplevels = {
     # This dummy symbol is not part of the public API; it is only used to test
@@ -35,6 +36,7 @@
     "+java_plugin": java_plugin,
     "objc_import": objc_import,
     "objc_library": objc_library,
+    "-proto_library": proto_library,
     "+apple_static_library": apple_static_library,
     "+cc_shared_library": cc_shared_library,
     "+cc_shared_library_permissions": cc_shared_library_permissions,
diff --git a/src/main/starlark/builtins_bzl/common/proto/proto_library.bzl b/src/main/starlark/builtins_bzl/common/proto/proto_library.bzl
new file mode 100644
index 0000000..394939c
--- /dev/null
+++ b/src/main/starlark/builtins_bzl/common/proto/proto_library.bzl
@@ -0,0 +1,77 @@
+# Copyright 2021 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.
+
+"""
+Definition of proto_library rule.
+"""
+
+load(":common/proto/proto_semantics.bzl", "semantics")
+
+ProtoInfo = _builtins.toplevel.ProtoInfo
+proto_common = _builtins.toplevel.proto_common
+
+def _check_srcs_package(target_package, srcs):
+    """Makes sure the given srcs live in the given package."""
+    for src in srcs:
+        if target_package != src.label.package:
+            fail("Proto source with label '%s' must be in same package as consuming rule." % src.label)
+
+def _proto_library_impl(ctx):
+    semantics.preprocess(ctx)
+
+    _check_srcs_package(ctx.label.package, ctx.attr.srcs)
+
+    proto_info = proto_common.create_proto_info(ctx)
+
+    proto_common.write_descriptor_set(ctx, proto_info)
+
+    data_runfiles = ctx.runfiles(
+        files = [proto_info.direct_descriptor_set],
+        transitive_files = depset(transitive = [proto_info.transitive_sources]),
+    )
+
+    return [
+        proto_info,
+        DefaultInfo(
+            files = depset([proto_info.direct_descriptor_set]),
+            default_runfiles = ctx.runfiles(),  # empty
+            data_runfiles = data_runfiles,
+        ),
+    ]
+
+proto_library = rule(
+    _proto_library_impl,
+    attrs = dict({
+        "srcs": attr.label_list(
+            allow_files = [".proto", ".protodevel"],
+            flags = ["DIRECT_COMPILE_TIME_INPUT"],
+        ),
+        "deps": attr.label_list(
+            providers = [ProtoInfo],
+        ),
+        "exports": attr.label_list(
+            providers = [ProtoInfo],
+        ),
+        "strip_import_prefix": attr.string(),
+        "_proto_compiler": attr.label(
+            cfg = "exec",
+            executable = True,
+            allow_files = True,
+            default = configuration_field("proto", "proto_compiler"),
+        ),
+    }, **semantics.EXTRA_ATTRIBUTES),
+    fragments = ["proto"] + semantics.EXTRA_FRAGMENTS,
+    provides = [ProtoInfo],
+    output_to_genfiles = True,  # TODO(b/204266604) move to bin dir
+)
diff --git a/src/main/starlark/builtins_bzl/common/proto/proto_semantics.bzl b/src/main/starlark/builtins_bzl/common/proto/proto_semantics.bzl
new file mode 100644
index 0000000..0cdddcb
--- /dev/null
+++ b/src/main/starlark/builtins_bzl/common/proto/proto_semantics.bzl
@@ -0,0 +1,29 @@
+# Copyright 2021 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.
+
+"""
+Proto Semantics
+"""
+
+def _preprocess(ctx):
+   pass
+
+semantics = struct(
+   PROTO_COMPILER_LABEL = "@com_google_protobuf//:protoc",
+   EXTRA_ATTRIBUTES = {
+      "import_prefix": attr.string(),
+   },
+   EXTRA_FRAGMENTS = [],
+   preprocess = _preprocess,
+ )
\ No newline at end of file