diff options
author | 2016-09-15 16:01:55 +0000 | |
---|---|---|
committer | 2016-09-16 07:58:44 +0000 | |
commit | df960c22f2ba057fc389ebeb6a20d5035efeb6ef (patch) | |
tree | aff500d0538af410d782a4d1d1cc5f2dd17a122d /src/main/java/com/google/devtools/build/lib | |
parent | 4ce70d25cc206bba960015a97902caebfcd0c7bd (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')
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)); + } +} |