aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib
diff options
context:
space:
mode:
authorGravatar Rumou Duan <rduan@google.com>2016-09-15 16:01:55 +0000
committerGravatar Dmitry Lomov <dslomov@google.com>2016-09-16 07:58:44 +0000
commitdf960c22f2ba057fc389ebeb6a20d5035efeb6ef (patch)
treeaff500d0538af410d782a4d1d1cc5f2dd17a122d /src/main/java/com/google/devtools/build/lib
parent4ce70d25cc206bba960015a97902caebfcd0c7bd (diff)
Add a common class for filtering proto source files.
-- MOS_MIGRATED_REVID=133267681
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java52
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/objc/ProtoAttributes.java41
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourceFileBlacklist.java159
5 files changed, 183 insertions, 84 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java
index 276743c7a1..d5cc658588 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoAspect.java
@@ -22,18 +22,14 @@ import static com.google.devtools.build.lib.cmdline.Label.parseAbsoluteUnchecked
import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
-import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.rules.java.proto.JavaCompilationArgsAspectProvider.GET_PROVIDER;
import static com.google.devtools.build.lib.rules.java.proto.JavaProtoLibraryTransitiveFilesToBuildProvider.GET_JARS;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
-import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
@@ -59,13 +55,12 @@ import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaToolchainProvider;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder;
import com.google.devtools.build.lib.rules.proto.ProtoConfiguration;
+import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider;
import com.google.devtools.build.lib.rules.proto.ProtoSupportDataProvider;
import com.google.devtools.build.lib.rules.proto.SupportData;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.annotation.Nullable;
/** An Aspect which JavaProtoLibrary injects to build Java SPEED protos. */
@@ -138,11 +133,9 @@ public class JavaProtoAspect extends NativeAspectClass implements ConfiguredAspe
attr(SPEED_PROTO_RUNTIME_ATTR, LABEL)
.legacyAllowAnyFileType()
.value(parseAbsoluteUnchecked(SPEED_PROTO_RUNTIME_LABEL)))
- .add(
- attr(PROTO_SOURCE_FILE_BLACKLIST_ATTR, LABEL_LIST)
- .cfg(HOST)
- .value(
- transformToList(protoSourceFileBlacklistLabels, PARSE_ABSOLUTE_UNCHECKED)))
+ .add(ProtoSourceFileBlacklist.blacklistFilegroupAttribute(
+ PROTO_SOURCE_FILE_BLACKLIST_ATTR,
+ transformToList(protoSourceFileBlacklistLabels, PARSE_ABSOLUTE_UNCHECKED)))
.add(attr(":host_jdk", LABEL).cfg(HOST).value(JavaSemantics.HOST_JDK))
.add(
attr(":java_toolchain", LABEL)
@@ -165,16 +158,6 @@ public class JavaProtoAspect extends NativeAspectClass implements ConfiguredAspe
return Lists.<T>newArrayList(transform(fromIterable, function));
}
- @VisibleForTesting
- public static String createBlacklistedProtosMixError(
- Iterable<String> blacklisted, Iterable<String> nonBlacklisted, String ruleLabel) {
- return String.format(
- "The 'srcs' attribute of '%s' contains protos for which 'java_proto_library' "
- + "shouldn't generate code (%s), in addition to protos for which it should (%s).\n"
- + "Separate '%1$s' into 2 proto_library rules.",
- ruleLabel, Joiner.on(", ").join(blacklisted), Joiner.on(", ").join(nonBlacklisted));
- }
-
private static class Impl {
private final RuleContext ruleContext;
@@ -270,30 +253,9 @@ public class JavaProtoAspect extends NativeAspectClass implements ConfiguredAspe
return false;
}
- Set<Artifact> blacklist =
- Sets.newHashSet(
- ruleContext
- .getPrerequisiteArtifacts(PROTO_SOURCE_FILE_BLACKLIST_ATTR, Mode.HOST)
- .list());
- List<Artifact> blacklisted = new ArrayList<>();
- List<Artifact> nonBlacklisted = new ArrayList<>();
- for (Artifact src : supportData.getDirectProtoSources()) {
- if (blacklist.contains(src)) {
- blacklisted.add(src);
- } else {
- nonBlacklisted.add(src);
- }
- }
- if (!nonBlacklisted.isEmpty() && !blacklisted.isEmpty()) {
- ruleContext.attributeError(
- "srcs",
- createBlacklistedProtosMixError(
- Artifact.toRootRelativePaths(blacklisted),
- Artifact.toRootRelativePaths(nonBlacklisted),
- ruleContext.getLabel().toString()));
- }
-
- return blacklisted.isEmpty();
+ ProtoSourceFileBlacklist protoBlackList =
+ new ProtoSourceFileBlacklist(ruleContext, PROTO_SOURCE_FILE_BLACKLIST_ATTR);
+ return protoBlackList.checkSrcs(supportData.getDirectProtoSources(), "java_proto_library");
}
private void createProtoCompileAction(Artifact sourceJar) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java
index 326ce49f02..2ed8d58eaf 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryRule.java
@@ -24,6 +24,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PROTO_COM
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.PROTO_LIB_ATTR;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
+import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
@@ -32,6 +33,7 @@ import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
+import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileType;
@@ -146,9 +148,9 @@ public class ObjcProtoLibraryRule implements RuleDefinition {
}
}))
.add(
- attr(PROTOBUF_WELL_KNOWN_TYPES, LABEL)
- .cfg(HOST)
- .value(env.getToolsLabel("//tools/objc:protobuf_well_known_types")))
+ ProtoSourceFileBlacklist.blacklistFilegroupAttribute(
+ PROTOBUF_WELL_KNOWN_TYPES,
+ ImmutableList.of(env.getToolsLabel("//tools/objc:protobuf_well_known_types"))))
.add(
attr(XCODE_GEN_ATTR, LABEL)
.cfg(HOST)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
index 2cb8aa213e..103fe54532 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java
@@ -56,6 +56,7 @@ import com.google.devtools.build.lib.rules.apple.AppleToolchain.RequiresXcodeCon
import com.google.devtools.build.lib.rules.apple.Platform;
import com.google.devtools.build.lib.rules.apple.Platform.PlatformType;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
+import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
@@ -891,9 +892,9 @@ public class ObjcRuleClasses {
.cfg(HOST)
.value(env.getToolsLabel("//tools/objc:protobuf_compiler_support")))
.add(
- attr(PROTOBUF_WELL_KNOWN_TYPES, LABEL)
- .cfg(HOST)
- .value(env.getToolsLabel("//tools/objc:protobuf_well_known_types")))
+ ProtoSourceFileBlacklist.blacklistFilegroupAttribute(
+ PROTOBUF_WELL_KNOWN_TYPES,
+ ImmutableList.of(env.getToolsLabel("//tools/objc:protobuf_well_known_types"))))
.override(builder.copy("deps").aspect(objcProtoAspect))
/* <!-- #BLAZE_RULE($objc_linking_rule).ATTRIBUTE(linkopts) -->
Extra flags to pass to the linker.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoAttributes.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoAttributes.java
index 0824d2c107..f9635a946d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoAttributes.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ProtoAttributes.java
@@ -20,7 +20,6 @@ import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AbstractConfiguredTarget;
import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts;
@@ -30,10 +29,10 @@ import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
+import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileType;
-import com.google.devtools.build.lib.vfs.PathFragment;
/** Common rule attributes used by an objc_proto_library. */
final class ProtoAttributes {
@@ -66,8 +65,6 @@ final class ProtoAttributes {
+ "targets. Please migrate your Protocol Buffers 2 objc_proto_library targets to use the "
+ "portable_proto_filters attribute.";
- private static final PathFragment BAZEL_TOOLS_PREFIX = new PathFragment("external/bazel_tools/");
-
private final RuleContext ruleContext;
/**
@@ -230,41 +227,19 @@ final class ProtoAttributes {
* prevent the well known protos from being generated as they are already generated in the runtime
* library.
*/
- ImmutableSet<Artifact> filterWellKnownProtos(Iterable<Artifact> protoFiles) {
- // Since well known protos are already linked in the runtime library, we have to filter them
- // so they don't get generated again.
- ImmutableSet.Builder<Artifact> filteredProtos = new ImmutableSet.Builder<Artifact>();
- for (Artifact protoFile : protoFiles) {
- if (!isProtoWellKnown(protoFile)) {
- filteredProtos.add(protoFile);
- }
- }
- return filteredProtos.build();
+ Iterable<Artifact> filterWellKnownProtos(Iterable<Artifact> protoFiles) {
+ ProtoSourceFileBlacklist wellKnownProtoBlacklist =
+ new ProtoSourceFileBlacklist(ruleContext, ObjcRuleClasses.PROTOBUF_WELL_KNOWN_TYPES);
+ return wellKnownProtoBlacklist.filter(protoFiles);
}
/** Returns whether the given proto is a well known proto or not. */
boolean isProtoWellKnown(Artifact protoFile) {
- return getWellKnownProtoPaths().contains(protoFile.getExecPath());
- }
-
- private ImmutableSet<PathFragment> getWellKnownProtoPaths() {
- ImmutableSet.Builder<PathFragment> wellKnownProtoPathsBuilder = new ImmutableSet.Builder<>();
- Iterable<Artifact> wellKnownProtoFiles =
- ruleContext
- .getPrerequisiteArtifacts(ObjcRuleClasses.PROTOBUF_WELL_KNOWN_TYPES, Mode.HOST)
- .list();
- for (Artifact wellKnownProtoFile : wellKnownProtoFiles) {
- PathFragment execPath = wellKnownProtoFile.getExecPath();
- if (execPath.startsWith(BAZEL_TOOLS_PREFIX)) {
- wellKnownProtoPathsBuilder.add(execPath.relativeTo(BAZEL_TOOLS_PREFIX));
- } else {
- wellKnownProtoPathsBuilder.add(execPath);
- }
- }
- return wellKnownProtoPathsBuilder.build();
+ ProtoSourceFileBlacklist wellKnownProtoBlacklist =
+ new ProtoSourceFileBlacklist(ruleContext, ObjcRuleClasses.PROTOBUF_WELL_KNOWN_TYPES);
+ return wellKnownProtoBlacklist.isBlacklisted(protoFile);
}
-
/** Returns the sets of proto files that were added using proto_library dependencies. */
private NestedSet<Artifact> getProtoDepsSources() {
NestedSetBuilder<Artifact> artifacts = NestedSetBuilder.stableOrder();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourceFileBlacklist.java b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourceFileBlacklist.java
new file mode 100644
index 0000000000..f324ce5fb3
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/proto/ProtoSourceFileBlacklist.java
@@ -0,0 +1,159 @@
+// 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 static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A blacklist of proto source files.
+ *
+ * <p>There are cases where we need to identify proto files that we should not create generated
+ * files for. For example, we should not create generated code for google/protobuf/any.proto, which
+ * is already baked into the language support libraries. This class provides us with the ability
+ * to identify these proto files and avoid linking in their associated generated files.
+ */
+public class ProtoSourceFileBlacklist {
+ private static final PathFragment BAZEL_TOOLS_PREFIX = new PathFragment("external/bazel_tools/");
+ private final RuleContext ruleContext;
+ private final ImmutableSet<PathFragment> blacklistProtoFilePaths;
+
+ private final Predicate<Artifact> isBlacklistProto =
+ new Predicate<Artifact>() {
+ @Override
+ public boolean apply(Artifact protoFile) {
+ return isBlacklisted(protoFile);
+ }
+ };
+
+ /**
+ * Creates a proto source file blacklist.
+ * @param ruleContext the proto rule context.
+ * @param blacklistAttribute the attribute that points to a filegroup containing the blacklisted
+ * protos.
+ */
+ public ProtoSourceFileBlacklist(RuleContext ruleContext, String blacklistAttribute) {
+ this.ruleContext = ruleContext;
+ Iterable<Artifact> blacklistProtoFiles =
+ ruleContext.getPrerequisiteArtifacts(blacklistAttribute, Mode.HOST).list();
+ ImmutableSet.Builder<PathFragment> blacklistProtoFilePathsBuilder =
+ new ImmutableSet.Builder<>();
+ for (Artifact blacklistProtoFile : blacklistProtoFiles) {
+ PathFragment execPath = blacklistProtoFile.getExecPath();
+ // For blacklisted protos bundled with the Bazel tools repository, their exec paths start
+ // with external/bazel_tools/. This prefix needs to be removed first, because the protos in
+ // user repositories will not have that prefix.
+ if (execPath.startsWith(BAZEL_TOOLS_PREFIX)) {
+ blacklistProtoFilePathsBuilder.add(execPath.relativeTo(BAZEL_TOOLS_PREFIX));
+ } else {
+ blacklistProtoFilePathsBuilder.add(execPath);
+ }
+ }
+ blacklistProtoFilePaths = blacklistProtoFilePathsBuilder.build();
+ }
+
+ /**
+ * Filters the blacklisted protos from the given protos.
+ */
+ public Iterable<Artifact> filter(Iterable<Artifact> protoFiles) {
+ return ImmutableSet.copyOf(Iterables.filter(protoFiles, Predicates.not(isBlacklistProto)));
+ }
+
+ /**
+ * Checks the proto sources for mixing blacklisted and non-blacklisted protos in one single
+ * proto_library rule. Registers an attribute error if proto mixing is detected.
+ *
+ * @param protoFiles the protos to filter.
+ * @param topLevelProtoRuleName the name of the top-level rule that generates the protos.
+ * @return whether the proto sources are clean without mixing.
+ */
+ public boolean checkSrcs(Iterable<Artifact> protoFiles, String topLevelProtoRuleName) {
+ List<Artifact> blacklisted = new ArrayList<>();
+ List<Artifact> nonBlacklisted = new ArrayList<>();
+ for (Artifact protoFile : protoFiles) {
+ if (isBlacklisted(protoFile)) {
+ blacklisted.add(protoFile);
+ } else {
+ nonBlacklisted.add(protoFile);
+ }
+ }
+ if (!nonBlacklisted.isEmpty() && !blacklisted.isEmpty()) {
+ ruleContext.attributeError(
+ "srcs",
+ createBlacklistedProtosMixError(
+ Artifact.toRootRelativePaths(blacklisted),
+ Artifact.toRootRelativePaths(nonBlacklisted),
+ ruleContext.getLabel().toString(),
+ topLevelProtoRuleName));
+ }
+
+ return blacklisted.isEmpty();
+ }
+
+ /**
+ * Returns blacklisted protos from the given protos.
+ */
+ private Iterable<Artifact> blacklisted(Iterable<Artifact> protoFiles) {
+ return ImmutableSet.copyOf(Iterables.filter(protoFiles, isBlacklistProto));
+ }
+
+ /**
+ * Returns whether the given proto file is blacklisted.
+ */
+ public boolean isBlacklisted(Artifact protoFile) {
+ return blacklistProtoFilePaths.contains(protoFile.getExecPath());
+ }
+
+ /**
+ * Returns an attribute for the implicit dependency on blacklist proto filegroups.
+ * @param attributeName the name of the attribute.
+ * @param blacklistFileGroups a list of labels pointin to the filegroups containing blacklisted
+ * protos.
+ */
+ public static Attribute.Builder<List<Label>> blacklistFilegroupAttribute(
+ String attributeName, List<Label> blacklistFileGroups) {
+ return attr(attributeName, LABEL_LIST).cfg(HOST).value(blacklistFileGroups);
+ }
+
+ @VisibleForTesting
+ public static String createBlacklistedProtosMixError(
+ Iterable<String> blacklisted, Iterable<String> nonBlacklisted, String protoLibraryRuleLabel,
+ String topLevelProtoRuleName) {
+ return String.format(
+ "The 'srcs' attribute of '%s' contains protos for which '%s' "
+ + "shouldn't generate code (%s), in addition to protos for which it should (%s).\n"
+ + "Separate '%1$s' into 2 proto_library rules.",
+ protoLibraryRuleLabel,
+ topLevelProtoRuleName,
+ Joiner.on(", ").join(blacklisted),
+ Joiner.on(", ").join(nonBlacklisted));
+ }
+}