Skip to content

Commit

Permalink
Propogate proguard specs from aar_import rule
Browse files Browse the repository at this point in the history
**Background**
bazelbuild#3778
Add support for `proguard.txt` in `aar_import`

**Changes**
* Add new action and python script to extract `proguard.txt` from an aar if it exists
* Add proguard spec to `aar_import` rule's output through a `ProguardSpecProvider`

**Test Plan**
* Tested with https://github.sc-corp.net/Snapchat/rules_kotlin/pull/71
---
Automatic squash commit from https://github.sc-corp.net/Snapchat/bazel/pull/85
Cooled by bromano
  • Loading branch information
benjaminRomano committed Dec 23, 2020
1 parent 43d7be0 commit 45a5789
Show file tree
Hide file tree
Showing 12 changed files with 264 additions and 11 deletions.
18 changes: 9 additions & 9 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ distdir_tar(
"1.25.0.zip",
# rules_nodejs
"rules_nodejs-1.3.0.tar.gz",
"android_tools_pkg-0.19.0rc3-snap-3.tar.gz",
"android_tools_pkg-0.19.0rc3-snap-4.tar.gz",
# bazelbuild/bazel-skylib
"2d4c9528e0f453b5950eeaeac11d8d09f5a504d4.tar.gz",
# bazelbuild/platforms
Expand Down Expand Up @@ -193,7 +193,7 @@ distdir_tar(
"1.25.0.zip": "c78be58f5e0a29a04686b628cf54faaee0094322ae0ac99da5a8a8afca59a647",
# rules_nodejs
"rules_nodejs-1.3.0.tar.gz": "b6670f9f43faa66e3009488bbd909bc7bc46a5a9661a33f6bc578068d1837f37",
"android_tools_pkg-0.19.0rc3-snap-3.tar.gz": "d07f851bcc59c153a2578d942caef7d8d7ca35e39aa3b908c8064c0708901e83",
"android_tools_pkg-0.19.0rc3-snap-4.tar.gz": "d07f851bcc59c153a2578d942caef7d8d7ca35e39aa3b908c8064c0708901e83",
# bazelbuild/bazel-skylib
"2d4c9528e0f453b5950eeaeac11d8d09f5a504d4.tar.gz": "c00ceec469dbcf7929972e3c79f20c14033824538038a554952f5c31d8832f96",
# bazelbuild/platforms
Expand Down Expand Up @@ -246,8 +246,8 @@ distdir_tar(
"https://mirror.bazel.build/github.com/bazelbuild/rules_nodejs/releases/download/1.3.0/rules_nodejs-1.3.0.tar.gz",
"https://github.com/bazelbuild/rules_nodejs/releases/download/1.3.0/rules_nodejs-1.3.0.tar.gz",
],
"android_tools_pkg-0.19.0rc3-snap-3.tar.gz": [
"https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-3.tar.gz",
"android_tools_pkg-0.19.0rc3-snap-4.tar.gz": [
"https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-4.tar.gz",
],
# bazelbuild/bazel-skylib
"2d4c9528e0f453b5950eeaeac11d8d09f5a504d4.tar.gz": [
Expand Down Expand Up @@ -535,7 +535,7 @@ distdir_tar(
"zulu11.37.48-ca-jdk11.0.6-linux_aarch64.tar.gz",
"zulu11.37.17-ca-jdk11.0.6-macosx_x64.tar.gz",
"zulu11.37.17-ca-jdk11.0.6-win_x64.zip",
"android_tools_pkg-0.19.0rc3-snap-3.tar.gz",
"android_tools_pkg-0.19.0rc3-snap-4.tar.gz",
# bazelbuild/bazel-skylib
"2d4c9528e0f453b5950eeaeac11d8d09f5a504d4.tar.gz",
# bazelbuild/platforms
Expand Down Expand Up @@ -565,7 +565,7 @@ distdir_tar(
"zulu11.37.48-ca-jdk11.0.6-linux_aarch64.tar.gz": "a452f1b9682d9f83c1c14e54d1446e1c51b5173a3a05dcb013d380f9508562e4",
"zulu11.37.17-ca-jdk11.0.6-macosx_x64.tar.gz": "e1fe56769f32e2aaac95e0a8f86b5a323da5af3a3b4bba73f3086391a6cc056f",
"zulu11.37.17-ca-jdk11.0.6-win_x64.zip": "a9695617b8374bfa171f166951214965b1d1d08f43218db9a2a780b71c665c18",
"android_tools_pkg-0.19.0rc3-snap-3.tar.gz": "d07f851bcc59c153a2578d942caef7d8d7ca35e39aa3b908c8064c0708901e83",
"android_tools_pkg-0.19.0rc3-snap-4.tar.gz": "d07f851bcc59c153a2578d942caef7d8d7ca35e39aa3b908c8064c0708901e83",
# bazelbuild/bazel-skylib
"2d4c9528e0f453b5950eeaeac11d8d09f5a504d4.tar.gz": "c00ceec469dbcf7929972e3c79f20c14033824538038a554952f5c31d8832f96",
# bazelbuild/platforms
Expand Down Expand Up @@ -594,8 +594,8 @@ distdir_tar(
"zulu11.37.48-ca-jdk11.0.6-linux_aarch64.tar.gz": ["https://mirror.bazel.build/openjdk/azul-zulu11.37.48-ca-jdk11.0.6/zulu11.37.48-ca-jdk11.0.6-linux_aarch64.tar.gz"],
"zulu11.37.17-ca-jdk11.0.6-macosx_x64.tar.gz": ["https://mirror.bazel.build/openjdk/azul-zulu11.37.17-ca-jdk11.0.6/zulu11.37.17-ca-jdk11.0.6-macosx_x64.tar.gz"],
"zulu11.37.17-ca-jdk11.0.6-win_x64.zip": ["https://mirror.bazel.build/openjdk/azul-zulu11.37.17-ca-jdk11.0.6/zulu11.37.17-ca-jdk11.0.6-win_x64.zip"],
"android_tools_pkg-0.19.0rc3-snap-3.tar.gz": [
"https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-3.tar.gz",
"android_tools_pkg-0.19.0rc3-snap-4.tar.gz": [
"https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-4.tar.gz",
],
# bazelbuild/bazel-skylib
"2d4c9528e0f453b5950eeaeac11d8d09f5a504d4.tar.gz": [
Expand Down Expand Up @@ -717,7 +717,7 @@ http_archive(
patch_cmds = EXPORT_WORKSPACE_IN_BUILD_FILE,
patch_cmds_win = EXPORT_WORKSPACE_IN_BUILD_FILE_WIN,
sha256 = "ea5c0589a01e2a9f43c20e5c145d3530e3b3bdbe7322789bc5da38d0ca49b837", # DO_NOT_REMOVE_THIS_ANDROID_TOOLS_UPDATE_MARKER
url = "https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-3.tar.gz",
url = "https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-4.tar.gz",
)

# This must be kept in sync with src/main/java/com/google/devtools/build/lib/bazel/rules/coverage.WORKSPACE.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "android_tools",
sha256 = "d07f851bcc59c153a2578d942caef7d8d7ca35e39aa3b908c8064c0708901e83",
url = "https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-3.tar.gz",
url = "https://storage.googleapis.com/snap-bazel-releases/bazel_android_tools/android_tools_pkg-0.19.0rc3-snap-4.tar.gz",
auth_patterns = {
"storage.googleapis.com": "Bearer <password>",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package com.google.devtools.build.lib.rules.android;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
Expand Down Expand Up @@ -46,8 +47,13 @@
import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaStarlarkApiProvider;
import com.google.devtools.build.lib.rules.java.JavaToolchainProvider;
import com.google.devtools.build.lib.rules.java.ProguardLibrary;
import com.google.devtools.build.lib.rules.java.ProguardSpecProvider;
import com.google.devtools.build.lib.starlarkbuildapi.android.DataBindingV2ProviderApi;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;

/**
Expand All @@ -62,6 +68,7 @@
public class AarImport implements RuleConfiguredTargetFactory {
private static final String ANDROID_MANIFEST = "AndroidManifest.xml";
private static final String MERGED_JAR = "classes_and_libs_merged.jar";
private static final String PROGUARD_SPEC = "proguard.txt";

private final JavaSemantics javaSemantics;
private final AndroidSemantics androidSemantics;
Expand Down Expand Up @@ -250,6 +257,7 @@ public ConfiguredTarget create(RuleContext ruleContext)
JavaStarlarkApiProvider.NAME, JavaStarlarkApiProvider.fromRuleContext())
.addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY)
.addNativeDeclaredProvider(dataBindingV2Provider)
.addNativeDeclaredProvider(new ProguardSpecProvider(extractProguardSpecs(ruleContext, aar)))
.addNativeDeclaredProvider(
new AndroidNativeLibsInfo(
AndroidCommon.collectTransitiveNativeLibs(ruleContext).add(nativeLibs).build()))
Expand Down Expand Up @@ -369,6 +377,47 @@ private static Action[] createAarEmbeddedJarsExtractorActions(
.build(ruleContext);
}

/**
* Collect Proguard Specs from transitives and proguard.txt if it exists in the AAR file.
* In the case the proguard.txt file does exists, we need to extract it from the AAR file
*/
private NestedSet<Artifact> extractProguardSpecs(RuleContext ruleContext, Artifact aar) {

NestedSet<Artifact> proguardSpecs = new ProguardLibrary(ruleContext)
.collectProguardSpecs(ImmutableSet.of("exports"));

Artifact proguardSpecArtifact = createAarArtifact(ruleContext, PROGUARD_SPEC);

ruleContext.registerAction(
createAarEmbeddedProguardExtractorActions(ruleContext, aar, proguardSpecArtifact));

NestedSetBuilder<Artifact> builder = NestedSetBuilder.naiveLinkOrder();
return builder.addTransitive(proguardSpecs).add(proguardSpecArtifact).build();
}

/**
* Create action to extract embedded Proguard.txt from an AAR. If the file is not found, an empty file will be created
*/
private static Action[] createAarEmbeddedProguardExtractorActions(
RuleContext ruleContext,
Artifact aar,
Artifact proguardSpecArtifact) {
return new SpawnAction.Builder()
.useDefaultShellEnvironment()
.setExecutable(
ruleContext.getExecutablePrerequisite(AarImportBaseRule.AAR_EMBEDDED_PROGUARD_EXTACTOR))
.setMnemonic("AarEmbeddedProguardExtractor")
.setProgressMessage("Extracting proguard.txt from %s", aar.getFilename())
.addInput(aar)
.addOutput(proguardSpecArtifact)
.addCommandLine(
CustomCommandLine.builder()
.addExecPath("--input_aar", aar)
.addExecPath("--output_proguard_file", proguardSpecArtifact)
.build())
.build(ruleContext);
}

private static Action[] createAarJarsMergingActions(
RuleContext ruleContext, Artifact jarsTreeArtifact, Artifact mergedJar, Artifact paramFile) {
return singleJarSpawnActionBuilder(ruleContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
public class AarImportBaseRule implements RuleDefinition {

static final String AAR_EMBEDDED_JARS_EXTACTOR = "$aar_embedded_jars_extractor";
static final String AAR_EMBEDDED_PROGUARD_EXTACTOR = "$aar_embedded_proguard_extractor";
static final String AAR_NATIVE_LIBS_ZIP_CREATOR = "$aar_native_libs_zip_creator";
static final String AAR_RESOURCES_EXTRACTOR = "$aar_resources_extractor";
static final String ZIPPER = "$zipper";
Expand Down Expand Up @@ -61,6 +62,11 @@ public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env)
attr("srcjar", LABEL)
.allowedFileTypes(JavaSemantics.SOURCE_JAR, JavaSemantics.JAR)
.direct_compile_time_input())
.add(
attr(AAR_EMBEDDED_PROGUARD_EXTACTOR, LABEL)
.cfg(HostTransition.createFactory())
.exec()
.value(env.getToolsLabel("//tools/android:aar_embedded_proguard_extractor")))
.add(
attr(AAR_EMBEDDED_JARS_EXTACTOR, LABEL)
.cfg(HostTransition.createFactory())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ private ImmutableList<String> createAndroidBuildContents() {
.add("java_import(name = 'ZipFilterAction_import',")
.add(" jars = [ 'ZipFilterAction_deploy.jar' ])")
.add("sh_binary(name = 'aar_resources_extractor', srcs = ['empty.sh'])")
.add("sh_binary(name = 'aar_embedded_proguard_extractor', srcs = ['empty.sh'])")
.add("sh_binary(name = 'aar_embedded_jars_extractor', srcs = ['empty.sh'])")
.add("java_import(name = 'idlclass_import',")
.add(" jars = [ 'idlclass.jar' ])")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.OutputJar;
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.ProguardSpecProvider;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -140,6 +141,46 @@ public void setup() throws Exception {
getAnalysisMock().ccSupport().setupCcToolchainConfigForCpu(mockToolsConfig, "armeabi-v7a");
}

@Test
public void proguardSpecsProvided() throws Exception {
ConfiguredTarget binaryTarget = getConfiguredTarget("//a:bar");

NestedSet<Artifact> transitiveProguardSpecs =
binaryTarget.get(ProguardSpecProvider.PROVIDER).getTransitiveProguardSpecs();

assertThat(
transitiveProguardSpecs.toSet().stream()
.map(Artifact::getRootRelativePathString)
.collect(Collectors.toSet()))
.containsExactly("a/_aar/bar/proguard.txt", "a/_aar/foo/proguard.txt");
}


@Test
public void testProguardExtractor() throws Exception {
Artifact proguardSpecsAritfact =
getConfiguredTarget("//a:bar")
.get(ProguardSpecProvider.PROVIDER)
.getTransitiveProguardSpecs()
.toList()
.get(0);

Artifact aarProguardExtractor =
getHostConfiguredTarget(
ruleClassProvider.getToolsRepository() + "//tools/android:aar_embedded_proguard_extractor")
.getProvider(FilesToRunProvider.class)
.getExecutable();

assertThat(getGeneratingSpawnAction(proguardSpecsAritfact).getArguments())
.containsExactly(
aarProguardExtractor.getExecPathString(),
"--input_aar",
"a/bar.aar",
"--output_proguard_file",
proguardSpecsAritfact.getExecPathString()
);
}

@Test
public void aapt2RTxtProvided() throws Exception {
useConfiguration("--android_sdk=//aapt2/sdk:sdk");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ java_test(
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
"//src/main/java/com/google/devtools/build/lib/rules/android",
"//src/main/java/com/google/devtools/build/lib/rules/java:java-compilation",
"//src/main/java/com/google/devtools/build/lib/rules/java:java-rules",
"//src/test/java/com/google/devtools/build/lib/actions/util",
"//src/test/java/com/google/devtools/build/lib/analysis/util",
"//third_party:guava",
Expand Down
15 changes: 15 additions & 0 deletions tools/android/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ py_test(
],
)

py_binary(
name = "aar_embedded_proguard_extractor",
srcs = ["aar_embedded_proguard_extractor.py"],
deps = [
":junction_lib",
"//third_party/py/abseil",
],
)

py_test(
name = "aar_embedded_proguard_extractor_test",
srcs = ["aar_embedded_proguard_extractor_test.py"],
deps = [":aar_embedded_proguard_extractor"],
)

py_binary(
name = "aar_embedded_jars_extractor",
srcs = ["aar_embedded_jars_extractor.py"],
Expand Down
10 changes: 10 additions & 0 deletions tools/android/BUILD.tools
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,16 @@ py_binary(
],
)

py_binary(
name = "aar_embedded_proguard_extractor",
srcs = ["aar_embedded_proguard_extractor.py"],
python_version = PY_BINARY_VERSION,
deps = [
":junction_lib",
"//third_party/py/abseil",
],
)

py_binary(
name = "aar_embedded_jars_extractor",
srcs = ["aar_embedded_jars_extractor.py"],
Expand Down
76 changes: 76 additions & 0 deletions tools/android/aar_embedded_proguard_extractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Lint as: python2, python3
# pylint: disable=g-direct-third-party-import
# 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.

"""A tool for extracting proguard spec from an AAR
An AAR may contain proguard spec at proguard.txt
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import re
import sys
import zipfile

# Do not edit this line. Copybara replaces it with PY2 migration helper.
from absl import app
from absl import flags
import six

from tools.android import junction

FLAGS = flags.FLAGS

flags.DEFINE_string("input_aar", None, "Input AAR")
flags.mark_flag_as_required("input_aar")
flags.DEFINE_string("output_proguard_file", None,
"Output parameter file for proguard")
flags.mark_flag_as_required("output_proguard_file")

def ExtractEmbeddedProguard(aar, output):
proguard_spec = "proguard.txt"

if proguard_spec in aar.namelist():
output.write(aar.read(proguard_spec))

def _Main(input_aar, output_proguard_file):
with zipfile.ZipFile(input_aar, "r") as aar:
with open(output_proguard_file, 'wb') as output:
ExtractEmbeddedProguard(aar, output)

def main(unused_argv):
if os.name == "nt":
# Shorten paths unconditionally, because the extracted paths in
# ExtractEmbeddedJars (which we cannot yet predict, because they depend on
# the names of the Zip entries) may be longer than MAX_PATH.
aar_long = os.path.abspath(FLAGS.input_aar)
proguard_long = os.path.abspath(FLAGS.output_proguard_file)

with junction.TempJunction(os.path.dirname(aar_long)) as aar_junc:
with junction.TempJunction(os.path.dirname(proguard_long)) as proguard_junc:
_Main(
os.path.join(aar_junc, os.path.basename(aar_long)),
os.path.join(proguard_junc, os.path.basename(proguard_long)))
else:
_Main(FLAGS.input_aar, FLAGS.output_proguard_file)


if __name__ == "__main__":
FLAGS(sys.argv)
app.run(main)
Loading

0 comments on commit 45a5789

Please sign in to comment.