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
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 f85dbac..c315c3c 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.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 @@
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 8d48a68..4144d46 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.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 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 e5bac92..876d796 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.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 67156b0..bb90189 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.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.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 @@
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 @@
}
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 381f684..326a97e 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.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.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 @@
<!-- #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 @@
.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 e70e4d0..88fe0d1 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.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 @@
.setSourceJarsForJarFiles(srcJars)
.build();
+ NestedSet<Artifact> proguardSpecs = new ProguardLibrary(ruleContext).collectProguardSpecs();
+
common.addTransitiveInfoProviders(ruleBuilder, filesToBuild, null);
return ruleBuilder
.setFilesToBuild(filesToBuild)
@@ -150,7 +153,9 @@
.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 be6211e..eae756a 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 @@
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 51ca2fd..38b3b69 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.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 @@
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 @@
// 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 0000000..f7e7f6c
--- /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 0000000..74d84eb
--- /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
similarity index 95%
rename from src/main/java/com/google/devtools/build/lib/rules/android/ProguardSpecProvider.java
rename to src/main/java/com/google/devtools/build/lib/rules/java/ProguardSpecProvider.java
index b815d12..afde15c 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;
diff --git a/src/test/shell/bazel/test-setup.sh b/src/test/shell/bazel/test-setup.sh
index e9697fb..204a4fb 100755
--- a/src/test/shell/bazel/test-setup.sh
+++ b/src/test/shell/bazel/test-setup.sh
@@ -126,11 +126,6 @@
)
sh_binary(
- name = "proguard_whitelister",
- srcs = ["fail.sh"],
-)
-
-sh_binary(
name = "build_incremental_dexmanifest",
srcs = ["fail.sh"],
)
diff --git a/src/test/shell/bazel/testenv.sh b/src/test/shell/bazel/testenv.sh
index de02693..bf6b548 100755
--- a/src/test/shell/bazel/testenv.sh
+++ b/src/test/shell/bazel/testenv.sh
@@ -110,6 +110,16 @@
chmod -R +w .
mkdir -p tools/defaults
touch tools/defaults/BUILD
+
+ mkdir -p third_party/py/gflags
+ cat > third_party/py/gflags/BUILD <<EOF
+licenses(["notice"])
+package(default_visibility = ["//visibility:public"])
+
+py_library(
+ name = "gflags",
+)
+EOF
}
# Report whether a given directory name corresponds to a tools directory.
diff --git a/tools/android/BUILD b/tools/android/BUILD
index c2aeb9a..02e5e93 100644
--- a/tools/android/BUILD
+++ b/tools/android/BUILD
@@ -60,25 +60,6 @@
)
py_binary(
- name = "proguard_whitelister",
- srcs = [
- "proguard_whitelister.py",
- ],
- deps = [
- "//third_party/py/gflags",
- ],
-)
-
-py_test(
- name = "proguard_whitelister_test",
- srcs = ["proguard_whitelister_test.py"],
- data = ["proguard_whitelister_test_input.cfg"],
- deps = [
- ":proguard_whitelister",
- ],
-)
-
-py_binary(
name = "build_incremental_dexmanifest",
srcs = [":build_incremental_dexmanifest.py"],
deps = [],
diff --git a/tools/jdk/BUILD b/tools/jdk/BUILD
index 3326081..b8f0419 100644
--- a/tools/jdk/BUILD
+++ b/tools/jdk/BUILD
@@ -103,10 +103,34 @@
filegroup(
name = "srcs",
- srcs = ["BUILD"], # Tools are build from the workspace for tests.
+ srcs = [
+ "BUILD", # Tools are build from the workspace for tests.
+ "proguard_whitelister.py",
+ "proguard_whitelister_test.py",
+ "proguard_whitelister_test_input.cfg",
+ ],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
)
+
+py_binary(
+ name = "proguard_whitelister",
+ srcs = [
+ "proguard_whitelister.py",
+ ],
+ deps = [
+ "//third_party/py/gflags",
+ ],
+)
+
+py_test(
+ name = "proguard_whitelister_test",
+ srcs = ["proguard_whitelister_test.py"],
+ data = ["proguard_whitelister_test_input.cfg"],
+ deps = [
+ ":proguard_whitelister",
+ ],
+)
diff --git a/tools/android/proguard_whitelister.py b/tools/jdk/proguard_whitelister.py
similarity index 90%
rename from tools/android/proguard_whitelister.py
rename to tools/jdk/proguard_whitelister.py
index e5b000f..6c95360 100644
--- a/tools/android/proguard_whitelister.py
+++ b/tools/jdk/proguard_whitelister.py
@@ -15,8 +15,10 @@
"""Checks for proguard configuration rules that cannot be combined across libs.
The only valid proguard arguments for a library are -keep, -assumenosideeffects,
-and -dontnote and -dontwarn and -checkdiscard when they are provided with
-arguments.
+and -dontnote and -dontwarn when they are provided with arguments.
+Limiting libraries to using these flags prevents drastic, sweeping effects
+(such as obfuscation being disabled) from being inadvertently applied to a
+binary through a library dependency.
"""
import re
diff --git a/tools/android/proguard_whitelister_test.py b/tools/jdk/proguard_whitelister_test.py
similarity index 97%
rename from tools/android/proguard_whitelister_test.py
rename to tools/jdk/proguard_whitelister_test.py
index 2229cfb..6a24501 100644
--- a/tools/android/proguard_whitelister_test.py
+++ b/tools/jdk/proguard_whitelister_test.py
@@ -15,7 +15,7 @@
import os
import unittest
-from tools.android import proguard_whitelister
+from tools.jdk import proguard_whitelister
class ProguardConfigValidatorTest(unittest.TestCase):
diff --git a/tools/android/proguard_whitelister_test_input.cfg b/tools/jdk/proguard_whitelister_test_input.cfg
similarity index 100%
rename from tools/android/proguard_whitelister_test_input.cfg
rename to tools/jdk/proguard_whitelister_test_input.cfg