Use proto_toolchain in proto_library

Change --incompatible_enable_proto_toolchain_resolution flag to a loading time flag. This is partial revert of https://github.com/bazelbuild/bazel/commit/11cf1b756b77c6159fbb5c9ab480b742ea85b5b6. We need a load time flag, because toolchain type might not exist at current versions of rules repos users use.

When the flag is set, proto_library defines the toolchain and doesn't use an implicit dependency at the same time.

In Bazel the flag may only be flipped after all the rules_* repo are upgraded to define toolchain type and protobuf repository registers the toolchains.

Issue: https://github.com/bazelbuild/rules_proto/issues/179
PiperOrigin-RevId: 567296665
Change-Id: Ib3fc27751dd14589fa403f45d2cbbad22537b9a3
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java
index f95336c..bd3d56d 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java
@@ -34,13 +34,19 @@
   public static void setup(MockToolsConfig config) throws IOException {
     createNetProto2(config);
     setupWorkspace(config);
-    config.append("tools/proto/toolchains/BUILD");
+    registerProtoToolchain(config);
   }
 
-  /**
-   * Create a dummy "net/proto2 compiler and proto APIs for all languages
-   * and versions.
-   */
+  private static void registerProtoToolchain(MockToolsConfig config) throws IOException {
+    config.append("WORKSPACE", "register_toolchains('tools/proto/toolchains:all')");
+    config.append(
+        "tools/proto/toolchains/BUILD",
+        TestConstants.LOAD_PROTO_TOOLCHAIN,
+        "proto_toolchain(name = 'protoc_sources',"
+            + "proto_compiler = '//net/proto2/compiler/public:protocol_compiler')");
+  }
+
+  /** Create a dummy "net/proto2 compiler and proto APIs for all languages and versions. */
   private static void createNetProto2(MockToolsConfig config) throws IOException {
     config.create(
         "net/proto2/compiler/public/BUILD",
@@ -203,8 +209,12 @@
           "    path = 'third_party/bazel_rules/rules_proto',",
           ")");
     }
+
     config.create("third_party/bazel_rules/rules_proto/WORKSPACE");
-    config.create("third_party/bazel_rules/rules_proto/proto/BUILD", "licenses(['notice'])");
+    config.create(
+        "third_party/bazel_rules/rules_proto/proto/BUILD",
+        "licenses(['notice'])",
+        "toolchain_type(name = 'toolchain_type', visibility = ['//visibility:public'])");
     config.create(
         "third_party/bazel_rules/rules_proto/proto/defs.bzl",
         "def _add_tags(kargs):",
@@ -216,5 +226,58 @@
         "",
         "def proto_library(**kargs): native.proto_library(**_add_tags(kargs))",
         "def proto_lang_toolchain(**kargs): native.proto_lang_toolchain(**_add_tags(kargs))");
+    config.create(
+        "third_party/bazel_rules/rules_proto/proto/proto_toolchain.bzl",
+        "load(':proto_toolchain_rule.bzl', _proto_toolchain_rule = 'proto_toolchain')",
+        "def proto_toolchain(*, name, proto_compiler, exec_compatible_with = []):",
+        "  _proto_toolchain_rule(name = name, proto_compiler = proto_compiler)",
+        "  native.toolchain(",
+        "    name = name + '_toolchain',",
+        "    toolchain_type = '" + TestConstants.PROTO_TOOLCHAIN + "',",
+        "    exec_compatible_with = exec_compatible_with,",
+        "    target_compatible_with = [],",
+        "    toolchain = name,",
+        "  )");
+    config.create(
+        "third_party/bazel_rules/rules_proto/proto/proto_toolchain_rule.bzl",
+        "ProtoLangToolchainInfo = proto_common_do_not_use.ProtoLangToolchainInfo",
+        "def _impl(ctx):",
+        "  return [",
+        "    DefaultInfo(",
+        "      files = depset(),",
+        "      runfiles = ctx.runfiles(),",
+        "    ),",
+        "    platform_common.ToolchainInfo(",
+        "      proto = ProtoLangToolchainInfo(",
+        "        out_replacement_format_flag = ctx.attr.command_line,",
+        "        output_files = ctx.attr.output_files,",
+        "        plugin = None,",
+        "        runtime = None,",
+        "        proto_compiler = ctx.attr.proto_compiler.files_to_run,",
+        "        protoc_opts = ctx.fragments.proto.experimental_protoc_opts,",
+        "        progress_message = ctx.attr.progress_message,",
+        "        mnemonic = ctx.attr.mnemonic,",
+        "        allowlist_different_package = None,",
+        "      ),",
+        "    ),",
+        "  ]",
+        "proto_toolchain = rule(",
+        "  _impl,",
+        "  attrs = {",
+        "     'progress_message': attr.string(default = ",
+        "          'Generating Descriptor Set proto_library %{label}'),",
+        "    'mnemonic': attr.string(default = 'GenProtoDescriptorSet'),",
+        "    'command_line': attr.string(default = '--descriptor_set_out=%s'),",
+        "    'output_files': attr.string(values = ['single', 'multiple', 'legacy'],",
+        "       default = 'single'),",
+        "    'proto_compiler': attr.label(",
+        "       cfg = 'exec',",
+        "       executable = True,",
+        "       allow_files = True,",
+        "     ),",
+        "  },",
+        "  provides = [platform_common.ToolchainInfo],",
+        "  fragments = ['proto'],",
+        ")");
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/proto/StarlarkJavaLiteProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/proto/StarlarkJavaLiteProtoLibraryTest.java
index 153d508..11c351d 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/java/proto/StarlarkJavaLiteProtoLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/java/proto/StarlarkJavaLiteProtoLibraryTest.java
@@ -64,6 +64,7 @@
     scratch.file("proto/BUILD", "licenses(['notice'])", "exports_files(['compiler'])");
 
     mockToolchains();
+    invalidatePackages();
 
     actionsTestUtil = actionsTestUtil();
   }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java
index 161aa6b..2a43a40 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java
@@ -31,6 +31,7 @@
 import com.google.devtools.build.lib.packages.util.MockProtoSupport;
 import com.google.devtools.build.lib.testutil.TestConstants;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import java.util.List;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -55,6 +56,19 @@
   }
 
   @Test
+  public void protoToolchainResolution_enabled() throws Exception {
+    setBuildLanguageOptions("--incompatible_enable_proto_toolchain_resolution");
+    scratch.file(
+        "x/BUILD",
+        TestConstants.LOAD_PROTO_LIBRARY,
+        "proto_library(name='foo', srcs=['foo.proto'])");
+
+    getDescriptorOutput("//x:foo");
+
+    assertNoEvents();
+  }
+
+  @Test
   public void createsDescriptorSets() throws Exception {
     scratch.file(
         "x/BUILD",
@@ -989,6 +1003,7 @@
     assertThat(commandLine).contains("-I" + genfiles + "/external/foo/x/y/_virtual_imports/q");
   }
 
+  @CanIgnoreReturnValue
   private Artifact getDescriptorOutput(String label) throws Exception {
     return getFirstArtifactEndingWith(getFilesToBuild(getConfiguredTarget(label)), ".proto.bin");
   }
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
index 69b11d5..fb71902 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
@@ -26,6 +26,9 @@
 
   public static final String LOAD_PROTO_LIBRARY =
       "load('@rules_proto//proto:defs.bzl', 'proto_library')";
+  public static final String PROTO_TOOLCHAIN =  "@rules_proto//proto:toolchain_type";
+  public static final String LOAD_PROTO_TOOLCHAIN =
+      "load('@rules_proto//proto:proto_toolchain.bzl', 'proto_toolchain')";
   public static final String LOAD_PROTO_LANG_TOOLCHAIN =
       "load('@rules_proto//proto:defs.bzl', 'proto_lang_toolchain')";