Move the descriptorset output to the ProtoSourcesProvider and expose it to skylark.
This does mean that the type name 'ProtoSourcesProvider' is a little inaccurate, since descriptorSet() is an output. Alternatively we could expose the DescriptorSetProvider to skylark.
RELNOTES: expose proto_library descriptor set to skylark via <dep>.proto.descriptor_set
--
PiperOrigin-RevId: 142680666
MOS_MIGRATED_REVID=142680666
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibrary.java
index 3557c5f..c524829 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibrary.java
@@ -46,11 +46,6 @@
NestedSet<Artifact> transitiveImports =
ProtoCommon.collectTransitiveImports(ruleContext, protoSources);
- // TODO(bazel-team): this second constructor argument is superfluous and should be removed.
- ProtoSourcesProvider sourcesProvider =
- ProtoSourcesProvider.create(
- transitiveImports, transitiveImports, protoSources, checkDepsProtoSources);
-
NestedSet<Artifact> protosInDirectDeps =
areDepsStrict(ruleContext) ? ProtoCommon.computeProtosInDirectDeps(ruleContext) : null;
@@ -67,10 +62,11 @@
RuleConfiguredTargetBuilder result = new RuleConfiguredTargetBuilder(ruleContext);
+ Artifact descriptorSetOutput = null;
if (checkDepsProtoSources.isEmpty() || !outputDescriptorSetFlagEnabled(ruleContext)) {
result.setFilesToBuild(NestedSetBuilder.<Artifact>create(STABLE_ORDER));
} else {
- Artifact descriptorSetOutput =
+ descriptorSetOutput =
ruleContext.getGenfilesArtifact(
ruleContext.getLabel().getName() + "-descriptor-set.proto.bin");
ProtoCompileActionBuilder.writeDescriptorSet(
@@ -85,9 +81,17 @@
dataRunfiles.addArtifact(descriptorSetOutput);
result.setFilesToBuild(NestedSetBuilder.create(STABLE_ORDER, descriptorSetOutput));
- result.addProvider(DescriptorSetProvider.create(descriptorSetOutput));
}
+ // TODO(bazel-team): this second constructor argument is superfluous and should be removed.
+ ProtoSourcesProvider sourcesProvider =
+ ProtoSourcesProvider.create(
+ transitiveImports,
+ transitiveImports,
+ protoSources,
+ checkDepsProtoSources,
+ descriptorSetOutput);
+
return result
.addProvider(RunfilesProvider.withData(Runfiles.EMPTY, dataRunfiles.build()))
.addProvider(ProtoSourcesProvider.class, sourcesProvider)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/DescriptorSetProvider.java b/src/main/java/com/google/devtools/build/lib/rules/proto/DescriptorSetProvider.java
deleted file mode 100644
index c1d323b..0000000
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/DescriptorSetProvider.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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.rules.proto;
-
-import com.google.auto.value.AutoValue;
-import com.google.devtools.build.lib.actions.Artifact;
-import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
-
-/**
- * A provider that exposes a compiled descriptor set from a proto_library.
- *
- * <p>Produced by passing --descriptor_set_out to the proto-compiler. See
- * https://developers.google.com/protocol-buffers/docs/techniques#self-description
- */
-@AutoValue
-public abstract class DescriptorSetProvider implements TransitiveInfoProvider {
-
- /**
- * Be careful while using this artifact - it is the parsing of the transitive set of .proto files.
- * It's possible to cause a O(n^2) behavior, where n is the length of a proto chain-graph.
- */
- public abstract Artifact descriptorSet();
-
- public static DescriptorSetProvider create(Artifact descriptorSet) {
- return new AutoValue_DescriptorSetProvider(descriptorSet);
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourcesProvider.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourcesProvider.java
index d8624c4..5220e4c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourcesProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourcesProvider.java
@@ -22,7 +22,9 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import javax.annotation.Nullable;
+// TODO(carmi): Rename the class to ProtoInfoProvider.
/**
* Configured target classes that implement this class can contribute .proto files to the
* compilation of proto_library rules.
@@ -38,9 +40,14 @@
NestedSet<Artifact> transitiveImports,
NestedSet<Artifact> transitiveProtoSources,
ImmutableList<Artifact> protoSources,
- ImmutableList<Artifact> checkDepsProtoSources) {
+ ImmutableList<Artifact> checkDepsProtoSources,
+ @Nullable Artifact descriptorSet) {
return new AutoValue_ProtoSourcesProvider(
- transitiveImports, transitiveProtoSources, protoSources, checkDepsProtoSources);
+ transitiveImports,
+ transitiveProtoSources,
+ protoSources,
+ checkDepsProtoSources,
+ descriptorSet);
}
/**
@@ -95,5 +102,20 @@
)
public abstract ImmutableList<Artifact> getCheckDepsProtoSources();
+ /**
+ * Be careful while using this artifact - it is the parsing of the transitive set of .proto files.
+ * It's possible to cause a O(n^2) behavior, where n is the length of a proto chain-graph.
+ */
+ @SkylarkCallable(
+ name = "descriptor_set",
+ doc =
+ "The FileDescriptorSet of all transitive sources. Returns None if "
+ + "--output_descriptor_set isn't enabled or if there are no sources",
+ structField = true,
+ allowReturnNones = true
+ )
+ @Nullable
+ public abstract Artifact descriptorSet();
+
ProtoSourcesProvider() {}
}
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 6761357..40c40b9 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -1220,6 +1220,7 @@
":actions_testutil",
":analysis_testutil",
"//src/main/java/com/google/devtools/build/lib:build-base",
+ "//src/main/java/com/google/devtools/build/lib:proto-rules",
"//src/main/java/com/google/devtools/build/lib/actions",
"//third_party:junit4",
"//third_party:truth",
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 d0a1211..504e07c 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
@@ -40,6 +40,7 @@
Artifact file =
ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".proto.bin");
assertThat(file.getRootRelativePathString()).isEqualTo("x/foo-descriptor-set.proto.bin");
+ assertThat(target.getProvider(ProtoSourcesProvider.class).descriptorSet()).isEqualTo(file);
assertThat(getGeneratingSpawnAction(file).getRemainingArguments())
.containsAllOf(
@@ -73,6 +74,38 @@
ConfiguredTarget target = scratchConfiguredTarget("x", "foo", "proto_library(name='foo')");
assertThat(ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".proto.bin"))
.isNull();
+
+ assertThat(target.getProvider(ProtoSourcesProvider.class).descriptorSet()).isNull();
+ }
+
+ @Test
+ public void testDescriptorSetOutput_noSrcs_transitive() throws Exception {
+ ConfiguredTarget target =
+ scratchConfiguredTarget(
+ "x",
+ "foo",
+ "proto_library(name='foo', deps = [':dep1'])",
+ "proto_library(name='dep1', deps = [':dep2'])",
+ "proto_library(name='dep2')");
+ assertThat(ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".proto.bin"))
+ .isNull();
+
+ assertThat(target.getProvider(ProtoSourcesProvider.class).descriptorSet()).isNull();
+ }
+
+ @Test
+ public void testDescriptorSetOutput_srcs_transitive() throws Exception {
+ ConfiguredTarget target =
+ scratchConfiguredTarget(
+ "x",
+ "foo",
+ "proto_library(name='foo', deps = [':dep1'])",
+ "proto_library(name='dep1', deps = [':dep2'])",
+ "proto_library(name='dep2', srcs=['foo.proto'])");
+ Artifact file =
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".proto.bin");
+ assertThat(file.getRootRelativePathString()).isEqualTo("x/foo-descriptor-set.proto.bin");
+ assertThat(target.getProvider(ProtoSourcesProvider.class).descriptorSet()).isEqualTo(file);
}
@Test