aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
authorGravatar Michael Staib <mstaib@google.com>2015-10-05 15:58:23 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2015-10-06 07:03:20 +0000
commit6817a6fcdd4275f9d3d4c3b9451a6c4144adcee1 (patch)
tree83a0a735ac0c48f777ed4a8ac06881262e2a2e50 /src/main/java/com
parent1c0543c626bf29eda95348c5c97391bc5d372fa3 (diff)
Allow Java libraries to export and propagate proguard_specs.
It may be the case that a library used by Java clients is also used by Android clients, but when used for the latter, it requires a particular Proguard configuration. This change modifies Java library rules to accept Proguard specs and pass them up to Android rules. Note that this does not cause Proguard to be used on normal Java binaries. RELNOTES[NEW]: java_library now supports the proguard_specs attribute for passing Proguard configuration up to Android (not Java) binaries. -- MOS_MIGRATED_REVID=104661799
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java48
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java27
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibrary.java134
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibraryRule.java68
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/ProguardSpecProvider.java (renamed from src/main/java/com/google/devtools/build/lib/rules/android/ProguardSpecProvider.java)2
11 files changed, 226 insertions, 73 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index f85dbac1f1..c315c3cf3f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -95,6 +95,7 @@ import com.google.devtools.build.lib.rules.java.JavaImportBaseRule;
import com.google.devtools.build.lib.rules.java.JavaOptions;
import com.google.devtools.build.lib.rules.java.JavaToolchainRule;
import com.google.devtools.build.lib.rules.java.JvmConfigurationLoader;
+import com.google.devtools.build.lib.rules.java.ProguardLibraryRule;
import com.google.devtools.build.lib.rules.objc.ExperimentalIosTestRule;
import com.google.devtools.build.lib.rules.objc.IosApplicationRule;
import com.google.devtools.build.lib.rules.objc.IosDeviceRule;
@@ -291,6 +292,7 @@ public class BazelRuleClassProvider {
builder.addRuleDefinition(new BazelJavaRuleClasses.BaseJavaBinaryRule());
builder.addRuleDefinition(new BazelJavaRuleClasses.IjarBaseRule());
builder.addRuleDefinition(new BazelJavaRuleClasses.JavaBaseRule());
+ builder.addRuleDefinition(new ProguardLibraryRule());
builder.addRuleDefinition(new JavaImportBaseRule());
builder.addRuleDefinition(new BazelJavaRuleClasses.JavaRule());
builder.addRuleDefinition(new BazelJavaBinaryRule());
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
index 8d48a68eca..4144d46f9f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaLibraryRule.java
@@ -30,6 +30,7 @@ import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
+import com.google.devtools.build.lib.rules.java.ProguardLibraryRule;
/**
* Common attributes for Java rules.
@@ -158,7 +159,7 @@ public final class BazelJavaLibraryRule implements RuleDefinition {
public Metadata getMetadata() {
return RuleDefinition.Metadata.builder()
.name("java_library")
- .ancestors(JavaRule.class)
+ .ancestors(JavaRule.class, ProguardLibraryRule.class)
.factoryClass(BazelJavaLibrary.class)
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index e5bac926f7..876d796fc8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -59,6 +59,7 @@ import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
import com.google.devtools.build.lib.rules.java.JavaTargetAttributes;
+import com.google.devtools.build.lib.rules.java.ProguardSpecProvider;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.PathFragment;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
index 67156b0ba8..bb90189242 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
@@ -17,13 +17,11 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
-import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.OutputGroupProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
-import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -39,10 +37,11 @@ import com.google.devtools.build.lib.rules.java.JavaSkylarkApiProvider;
import com.google.devtools.build.lib.rules.java.JavaSourceInfoProvider;
import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaTargetAttributes;
+import com.google.devtools.build.lib.rules.java.ProguardLibrary;
+import com.google.devtools.build.lib.rules.java.ProguardSpecProvider;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.PathFragment;
-import java.util.Collection;
import java.util.List;
/**
@@ -69,7 +68,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
NestedSet<LinkerInput> transitiveNativeLibraries =
AndroidCommon.collectTransitiveNativeLibraries(deps);
NestedSet<Artifact> transitiveProguardConfigs =
- collectTransitiveProguardConfigs(ruleContext);
+ new ProguardLibrary(ruleContext).collectProguardSpecs();
JavaCommon javaCommon = new JavaCommon(ruleContext, javaSemantics);
AndroidCommon androidCommon = new AndroidCommon(ruleContext, javaCommon);
@@ -238,46 +237,5 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
}
return builder;
}
-
- private NestedSet<Artifact> collectTransitiveProguardConfigs(RuleContext ruleContext) {
- NestedSetBuilder<Artifact> specsBuilder = NestedSetBuilder.naiveLinkOrder();
-
- for (ProguardSpecProvider dep : ruleContext.getPrerequisites(
- "deps", Mode.TARGET, ProguardSpecProvider.class)) {
- specsBuilder.addTransitive(dep.getTransitiveProguardSpecs());
- }
-
- // Pass our local proguard configs through the validator, which checks a whitelist.
- if (!getProguardConfigs(ruleContext).isEmpty()) {
- FilesToRunProvider proguardWhitelister = ruleContext
- .getExecutablePrerequisite("$proguard_whitelister", Mode.HOST);
- for (Artifact specToValidate : getProguardConfigs(ruleContext)) {
- //If we're validating j/a/b/testapp/proguard.cfg, the output will be:
- //j/a/b/testapp/proguard.cfg_valid
- Artifact output = ruleContext.getUniqueDirectoryArtifact(
- "validated_proguard",
- specToValidate.getRootRelativePath().replaceName(
- specToValidate.getFilename() + "_valid"),
- ruleContext.getBinOrGenfilesDirectory());
- ruleContext.registerAction(new SpawnAction.Builder()
- .addInput(specToValidate)
- .setExecutable(proguardWhitelister)
- .setProgressMessage("Validating proguard configuration")
- .setMnemonic("ValidateProguard")
- .addArgument("--path")
- .addArgument(specToValidate.getExecPathString())
- .addArgument("--output")
- .addArgument(output.getExecPathString())
- .addOutput(output)
- .build(ruleContext));
- specsBuilder.add(output);
- }
- }
- return specsBuilder.build();
- }
-
- private Collection<Artifact> getProguardConfigs(RuleContext ruleContext) {
- return ruleContext.getPrerequisiteArtifacts("proguard_specs", Mode.TARGET).list();
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
index 381f684fc3..326a97ebb1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
@@ -20,11 +20,8 @@ import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
import static com.google.devtools.build.lib.syntax.Type.STRING;
-import com.google.devtools.build.lib.Constants;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
-import com.google.devtools.build.lib.packages.Attribute;
-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.RuleClassType;
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidAaptBaseRule;
@@ -32,6 +29,7 @@ import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidBas
import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidResourceSupportRule;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
+import com.google.devtools.build.lib.rules.java.ProguardLibraryRule;
/**
* Rule definition for the android_library rule.
@@ -125,26 +123,6 @@ public final class AndroidLibraryBaseRule implements RuleDefinition {
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("idl_parcelables", LABEL_LIST).direct_compile_time_input()
.allowedFileTypes(AndroidRuleClasses.ANDROID_IDL))
- /* <!-- #BLAZE_RULE(android_library).ATTRIBUTE(proguard_specs) -->
- Files to be used as Proguard specification.
- ${SYNOPSIS}
- These will describe the set of specifications to be used by Proguard. If specified,
- they will be added to any <code>android_binary</code> target depending on this library.
-
- The files included here must only have idempotent rules, namely -dontnote, -dontwarn,
- assumenosideeffects, and rules that start with -keep. Other options can only appear in
- <code>android_binary</code>'s proguard_specs, to ensure non-tautological merges.
- <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
- .add(attr("proguard_specs", LABEL_LIST).legacyAllowAnyFileType())
- .add(attr("$proguard_whitelister", LABEL).cfg(HOST).exec().value(
- new Attribute.ComputedDefault() {
- @Override
- public Object getDefault(AttributeMap rule) {
- return rule.isAttributeValueExplicitlySpecified("proguard_specs")
- ? env.getLabel(Constants.ANDROID_DEP_PREFIX + "proguard_whitelister")
- : null;
- }
- }))
.add(attr("$android_manifest_merge_tool", LABEL).cfg(HOST).exec().value(env.getLabel(
AndroidRuleClasses.MANIFEST_MERGE_TOOL_LABEL)))
.advertiseProvider(JavaCompilationArgsProvider.class)
@@ -159,7 +137,8 @@ public final class AndroidLibraryBaseRule implements RuleDefinition {
.ancestors(
AndroidBaseRule.class,
AndroidAaptBaseRule.class,
- AndroidResourceSupportRule.class)
+ AndroidResourceSupportRule.class,
+ ProguardLibraryRule.class)
.build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java
index e70e4d08f6..88fe0d108a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java
@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.OutputGroupProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -133,6 +134,8 @@ public class JavaImport implements RuleConfiguredTargetFactory {
.setSourceJarsForJarFiles(srcJars)
.build();
+ NestedSet<Artifact> proguardSpecs = new ProguardLibrary(ruleContext).collectProguardSpecs();
+
common.addTransitiveInfoProviders(ruleBuilder, filesToBuild, null);
return ruleBuilder
.setFilesToBuild(filesToBuild)
@@ -150,7 +153,9 @@ public class JavaImport implements RuleConfiguredTargetFactory {
.add(JavaSourceInfoProvider.class, javaSourceInfoProvider)
.add(JavaSourceJarsProvider.class, new JavaSourceJarsProvider(
transitiveJavaSourceJars, srcJars))
+ .add(ProguardSpecProvider.class, new ProguardSpecProvider(proguardSpecs))
.addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveJavaSourceJars)
+ .addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, proguardSpecs)
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
index be6211e25a..eae756a8f7 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
@@ -84,7 +84,7 @@ public class JavaImportBaseRule implements RuleDefinition {
return RuleDefinition.Metadata.builder()
.name("$java_import_base")
.type(RuleClassType.ABSTRACT)
- .ancestors(BaseRuleClasses.RuleBase.class)
+ .ancestors(BaseRuleClasses.RuleBase.class, ProguardLibraryRule.class)
.build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java
index 51ca2fdeb3..38b3b697a3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java
@@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.OutputGroupProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
@@ -225,6 +226,8 @@ public class JavaLibrary implements RuleConfiguredTargetFactory {
common.addTransitiveInfoProviders(builder, filesToBuild, classJar);
common.addGenJarsProvider(builder, genClassJar, genSourceJar);
+ NestedSet<Artifact> proguardSpecs = new ProguardLibrary(ruleContext).collectProguardSpecs();
+
builder
.add(JavaRuleOutputJarsProvider.class, new JavaRuleOutputJarsProvider(
classJar, iJar, srcJar))
@@ -248,7 +251,9 @@ public class JavaLibrary implements RuleConfiguredTargetFactory {
// TODO(bazel-team): this should only happen for java_plugin
.add(JavaPluginInfoProvider.class, new JavaPluginInfoProvider(
exportedProcessorClasses, exportedProcessorClasspath))
- .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars);
+ .add(ProguardSpecProvider.class, new ProguardSpecProvider(proguardSpecs))
+ .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars)
+ .addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, proguardSpecs);
if (ruleContext.hasErrors()) {
return null;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibrary.java
new file mode 100644
index 0000000000..f7e7f6cee7
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibrary.java
@@ -0,0 +1,134 @@
+// Copyright 2015 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.java;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.packages.BuildType;
+
+import java.util.Collection;
+import java.util.Map.Entry;
+
+/**
+ * Helpers for implementing rules which export Proguard specs.
+ *
+ * <p>This is not a ConfiguredTargetFactory; $proguard_library, which this class implements, is an
+ * abstract rule class, and simply contributes this functionality to other rules.
+ */
+public final class ProguardLibrary {
+
+ private static final String LOCAL_SPEC_ATTRIBUTE = "proguard_specs";
+ private static final ImmutableMultimap<Mode, String> DEPENDENCY_ATTRIBUTES =
+ ImmutableMultimap.<Mode, String>builder()
+ .putAll(Mode.TARGET, "deps", "exports", "runtime_deps")
+ .putAll(Mode.HOST, "plugins", "exported_plugins")
+ .build();
+
+ private final RuleContext ruleContext;
+
+ /**
+ * Creates a new ProguardLibrary wrapping the given RuleContext.
+ */
+ public ProguardLibrary(RuleContext ruleContext) {
+ this.ruleContext = ruleContext;
+ }
+
+ /**
+ * Collects the validated proguard specs exported by this rule and its dependencies.
+ */
+ public NestedSet<Artifact> collectProguardSpecs() {
+ NestedSetBuilder<Artifact> specsBuilder = NestedSetBuilder.naiveLinkOrder();
+
+ for (Entry<Mode, String> attribute : DEPENDENCY_ATTRIBUTES.entries()) {
+ specsBuilder.addTransitive(
+ collectProguardSpecsFromAttribute(attribute.getValue(), attribute.getKey()));
+ }
+
+ Collection<Artifact> localSpecs = collectLocalProguardSpecs();
+ if (!localSpecs.isEmpty()) {
+ // Pass our local proguard configs through the validator, which checks a whitelist.
+ FilesToRunProvider proguardWhitelister =
+ ruleContext.getExecutablePrerequisite("$proguard_whitelister", Mode.HOST);
+ for (Artifact specToValidate : localSpecs) {
+ specsBuilder.add(validateProguardSpec(proguardWhitelister, specToValidate));
+ }
+ }
+
+ return specsBuilder.build();
+ }
+
+ /**
+ * Collects the unvalidated proguard specs exported by this rule.
+ */
+ private Collection<Artifact> collectLocalProguardSpecs() {
+ if (!ruleContext.getRule().isAttrDefined(LOCAL_SPEC_ATTRIBUTE, BuildType.LABEL_LIST)) {
+ return ImmutableList.of();
+ }
+ return ruleContext.getPrerequisiteArtifacts(LOCAL_SPEC_ATTRIBUTE, Mode.TARGET).list();
+ }
+
+ /**
+ * Collects the proguard specs exported by dependencies on the given LABEL_LIST attribute.
+ */
+ private NestedSet<Artifact> collectProguardSpecsFromAttribute(String attribute, Mode mode) {
+ if (!ruleContext.getRule().isAttrDefined(attribute, BuildType.LABEL_LIST)) {
+ return NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ }
+ NestedSetBuilder<Artifact> dependencySpecsBuilder = NestedSetBuilder.naiveLinkOrder();
+ for (ProguardSpecProvider provider :
+ ruleContext.getPrerequisites(attribute, mode, ProguardSpecProvider.class)) {
+ dependencySpecsBuilder.addTransitive(provider.getTransitiveProguardSpecs());
+ }
+ return dependencySpecsBuilder.build();
+ }
+
+ /**
+ * Creates an action to run the Proguard whitelister over the given Proguard spec and returns the
+ * validated Proguard spec, ready to be exported.
+ */
+ private Artifact validateProguardSpec(
+ FilesToRunProvider proguardWhitelister, Artifact specToValidate) {
+ // If we're validating j/a/b/testapp/proguard.cfg, the output will be:
+ // j/a/b/testapp/proguard.cfg_valid
+ Artifact output =
+ ruleContext.getUniqueDirectoryArtifact(
+ "validated_proguard",
+ specToValidate
+ .getRootRelativePath()
+ .replaceName(specToValidate.getFilename() + "_valid"),
+ ruleContext.getBinOrGenfilesDirectory());
+ ruleContext.registerAction(
+ new SpawnAction.Builder()
+ .addInput(specToValidate)
+ .setExecutable(proguardWhitelister)
+ .setProgressMessage("Validating proguard configuration")
+ .setMnemonic("ValidateProguard")
+ .addArgument("--path")
+ .addArgument(specToValidate.getExecPathString())
+ .addArgument("--output")
+ .addArgument(output.getExecPathString())
+ .addOutput(output)
+ .build(ruleContext));
+ return output;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibraryRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibraryRule.java
new file mode 100644
index 0000000000..74d84eb198
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/ProguardLibraryRule.java
@@ -0,0 +1,68 @@
+// Copyright 2015 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.java;
+
+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 com.google.devtools.build.lib.analysis.RuleDefinition;
+import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
+import com.google.devtools.build.lib.packages.Attribute;
+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.packages.RuleClass.Builder.RuleClassType;
+
+/**
+ * A base rule for libraries which can provide proguard specs.
+ */
+public final class ProguardLibraryRule implements RuleDefinition {
+
+ @Override
+ public RuleClass build(Builder builder, final RuleDefinitionEnvironment environment) {
+ return builder
+ /* <!-- #BLAZE_RULE($proguard_library).ATTRIBUTE(proguard_specs) -->
+ Files to be used as Proguard specification.
+ ${SYNOPSIS}
+ These will describe the set of specifications to be used by Proguard. If specified,
+ they will be added to any <code>android_binary</code> target depending on this library.
+
+ The files included here must only have idempotent rules, namely -dontnote, -dontwarn,
+ assumenosideeffects, and rules that start with -keep. Other options can only appear in
+ <code>android_binary</code>'s proguard_specs, to ensure non-tautological merges.
+ <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
+ .add(attr("proguard_specs", LABEL_LIST).legacyAllowAnyFileType())
+ .add(attr("$proguard_whitelister", LABEL).cfg(HOST).exec().value(
+ new Attribute.ComputedDefault() {
+ @Override
+ public Object getDefault(AttributeMap rule) {
+ return rule.isAttributeValueExplicitlySpecified("proguard_specs")
+ ? environment.getLabel("//tools/jdk:proguard_whitelister")
+ : null;
+ }
+ }))
+ .build();
+ }
+
+ @Override
+ public Metadata getMetadata() {
+ return RuleDefinition.Metadata.builder()
+ .name("$proguard_library")
+ .type(RuleClassType.ABSTRACT)
+ .build();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ProguardSpecProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/ProguardSpecProvider.java
index b815d1275c..afde15c724 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ProguardSpecProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/ProguardSpecProvider.java
@@ -11,7 +11,7 @@
// 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.android;
+package com.google.devtools.build.lib.rules.java;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;