Do not add a --proto_path argument to the proto compiler invocation there are no .proto sources in it.
This prevents protoc from complaining about a nonexistent directory in sandboxed mode and is good hygiene in any case.
Fixes #7157.
RELNOTES: None.
PiperOrigin-RevId: 256208923
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java
index 1463bbf..cbeeaa2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoCommon.java
@@ -19,6 +19,7 @@
import static com.google.devtools.build.lib.syntax.Type.STRING;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
@@ -136,10 +137,13 @@
* <p>Assumes {@code currentProtoSourceRoot} is the same as the package name.
*/
private static NestedSet<String> computeTransitiveProtoSourceRoots(
- RuleContext ruleContext, String currentProtoSourceRoot) {
+ RuleContext ruleContext, Optional<String> currentProtoSourceRoot) {
NestedSetBuilder<String> protoPath = NestedSetBuilder.stableOrder();
- protoPath.add(currentProtoSourceRoot);
+ if (currentProtoSourceRoot.isPresent()) {
+ protoPath.add(currentProtoSourceRoot.get());
+ }
+
for (ProtoInfo provider :
ruleContext.getPrerequisites("deps", Mode.TARGET, ProtoInfo.PROVIDER)) {
protoPath.addTransitive(provider.getTransitiveProtoSourceRoots());
@@ -159,11 +163,11 @@
static final class Library {
private final ImmutableList<Artifact> sources;
private final ImmutableList<Pair<Artifact, String>> importPathSourcePair;
- private final String sourceRoot;
+ private final Optional<String> sourceRoot;
Library(
ImmutableList<Artifact> sources,
- String sourceRoot,
+ Optional<String> sourceRoot,
ImmutableList<Pair<Artifact, String>> importPathSourcePair) {
this.sources = sources;
this.sourceRoot = sourceRoot;
@@ -178,7 +182,7 @@
return importPathSourcePair;
}
- public String getSourceRoot() {
+ public Optional<String> getSourceRoot() {
return sourceRoot;
}
}
@@ -201,22 +205,38 @@
return null;
}
- // This is the same as getPackageIdentifier().getPathUnderExecRoot() due to the check above for
- // protoSourceRoot == package name, but it's a bit more future-proof.
- String result =
- ruleContext
- .getLabel()
- .getPackageIdentifier()
- .getRepository()
- .getPathUnderExecRoot()
- .getRelative(protoSourceRoot)
- .getPathString();
+ boolean hasNonGeneratedSources = false;
+ for (Artifact artifact : directSources) {
+ if (artifact.isSourceArtifact()) {
+ hasNonGeneratedSources = true;
+ break;
+ }
+ }
+
+ String sourceRoot = "";
+ // Otherwise, we'll direct the proto compiler to the source files using -Ifoo=bar arguments.
+ // Then let's not spam the command line.
+ if (hasNonGeneratedSources) {
+ // This is the same as getPackageIdentifier().getPathUnderExecRoot() due to the check above
+ // for protoSourceRoot == package name, but it's a bit more future-proof.
+ sourceRoot =
+ ruleContext
+ .getLabel()
+ .getPackageIdentifier()
+ .getRepository()
+ .getPathUnderExecRoot()
+ .getRelative(protoSourceRoot)
+ .getPathString();
+ }
ImmutableList.Builder<Pair<Artifact, String>> builder = ImmutableList.builder();
for (Artifact protoSource : directSources) {
builder.add(new Pair<Artifact, String>(protoSource, null));
}
- return new Library(directSources, result.isEmpty() ? "." : result, builder.build());
+ return new Library(
+ directSources,
+ sourceRoot.isEmpty() ? Optional.absent() : Optional.of(sourceRoot),
+ builder.build());
}
private static PathFragment getPathFragmentAttribute(
@@ -327,7 +347,7 @@
.getExecPath()
.getRelative(sourceRootPath)
.getPathString();
- return new Library(symlinks.build(), sourceRoot, protoSourceImportPair.build());
+ return new Library(symlinks.build(), Optional.of(sourceRoot), protoSourceImportPair.build());
}
private static Pair<PathFragment, Artifact> computeImports(
@@ -361,9 +381,11 @@
* <p>Assumes {@code currentProtoSourceRoot} is the same as the package name.
*/
private static NestedSet<String> getProtoSourceRootsOfAttribute(
- RuleContext ruleContext, String currentProtoSourceRoot, String attributeName) {
+ RuleContext ruleContext, Optional<String> currentProtoSourceRoot, String attributeName) {
NestedSetBuilder<String> protoSourceRoots = NestedSetBuilder.stableOrder();
- protoSourceRoots.add(currentProtoSourceRoot);
+ if (currentProtoSourceRoot.isPresent()) {
+ protoSourceRoots.add(currentProtoSourceRoot.get());
+ }
for (ProtoInfo provider :
ruleContext.getPrerequisites(attributeName, Mode.TARGET, ProtoInfo.PROVIDER)) {
@@ -380,7 +402,7 @@
* <p>Assumes {@code currentProtoSourceRoot} is the same as the package name.
*/
private static NestedSet<String> computeStrictImportableProtoSourceRoots(
- RuleContext ruleContext, String currentProtoSourceRoot) {
+ RuleContext ruleContext, Optional<String> currentProtoSourceRoot) {
return getProtoSourceRootsOfAttribute(ruleContext, currentProtoSourceRoot, "deps");
}
@@ -391,7 +413,7 @@
* <p>Assumes {@code currentProtoSourceRoot} is the same as the package name.
*/
private static NestedSet<String> computeExportedProtoSourceRoots(
- RuleContext ruleContext, String currentProtoSourceRoot) {
+ RuleContext ruleContext, Optional<String> currentProtoSourceRoot) {
return getProtoSourceRootsOfAttribute(ruleContext, currentProtoSourceRoot, "exports");
}
@@ -490,7 +512,7 @@
ProtoInfo protoInfo =
new ProtoInfo(
library.getSources(),
- library.getSourceRoot(),
+ library.getSourceRoot().or("."),
transitiveProtoSources,
transitiveProtoSourceRoots,
strictImportableProtosForDependents,
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 225134e..447763b 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
@@ -340,8 +340,34 @@
);
ConfiguredTarget protoTarget = getConfiguredTarget("//x/foo:withdeps");
ProtoInfo sourcesProvider = protoTarget.get(ProtoInfo.PROVIDER);
- assertThat(sourcesProvider.getTransitiveProtoSourceRoots())
- .containsExactly("x/foo", "x/bar", ".");
+ assertThat(sourcesProvider.getTransitiveProtoSourceRoots()).containsExactly("x/foo", "x/bar");
+ }
+
+ @Test
+ public void testExternalRepoWithGeneratedProto() throws Exception {
+ if (!isThisBazel()) {
+ return;
+ }
+
+ FileSystemUtils.appendIsoLatin1(
+ scratch.resolve("WORKSPACE"), "local_repository(name = 'foo', path = '/foo')");
+ invalidatePackages();
+
+ scratch.file("/foo/WORKSPACE");
+ scratch.file(
+ "/foo/x/BUILD",
+ "proto_library(name='x', srcs=['generated.proto'])",
+ "genrule(name='g', srcs=[], outs=['generated.proto'], cmd='')");
+
+ scratch.file("a/BUILD", "proto_library(name='a', srcs=['a.proto'], deps=['@foo//x:x'])");
+
+ ConfiguredTarget a = getConfiguredTarget("//a:a");
+ ProtoInfo aInfo = a.get(ProtoInfo.PROVIDER);
+ assertThat(aInfo.getTransitiveProtoSourceRoots()).isEmpty();
+
+ ConfiguredTarget x = getConfiguredTarget("@foo//x:x");
+ ProtoInfo xInfo = x.get(ProtoInfo.PROVIDER);
+ assertThat(xInfo.getTransitiveProtoSourceRoots()).isEmpty();
}
@Test