diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java index fdeb38d7392dc7..f259a48cd167d8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarGeneratorBuilder.java @@ -39,6 +39,7 @@ public class AarGeneratorBuilder { private Artifact manifest; private Artifact rTxt; private Artifact classes; + private ImmutableList proguardSpecs = ImmutableList.of(); private Artifact aarOut; private boolean throwOnResourceConflict; @@ -81,6 +82,11 @@ public AarGeneratorBuilder setAAROut(Artifact aarOut) { return this; } + public AarGeneratorBuilder setProguardSpecs(ImmutableList proguardSpecs) { + this.proguardSpecs = proguardSpecs; + return this; + } + public AarGeneratorBuilder setThrowOnResourceConflict(boolean throwOnResourceConflict) { this.throwOnResourceConflict = throwOnResourceConflict; return this; @@ -118,6 +124,12 @@ public void build(ActionConstructionContext context) { ins.add(classes); } + for (Artifact proguardSpec : proguardSpecs) { + args.add("--proguardSpec"); + args.add(proguardSpec.getExecPathString()); + ins.add(proguardSpec); + } + args.add("--aarOutput"); args.add(aarOut.getExecPathString()); outs.add(aarOut); 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 6aea0db21b4f4e..2a511f2c045821 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 @@ -121,7 +121,8 @@ public ConfiguredTarget create(RuleContext ruleContext) collectTransitiveAars(ruleContext, transitiveAars, transitiveAarArtifacts); NestedSetBuilder proguardConfigsbuilder = NestedSetBuilder.stableOrder(); - proguardConfigsbuilder.addTransitive(new ProguardLibrary(ruleContext).collectProguardSpecs()); + ProguardLibrary proguardLibrary = new ProguardLibrary(ruleContext); + proguardConfigsbuilder.addTransitive(proguardLibrary.collectProguardSpecs()); AndroidIdlHelper.maybeAddSupportLibProguardConfigs(ruleContext, proguardConfigsbuilder); NestedSet transitiveProguardConfigs = proguardConfigsbuilder.build(); @@ -237,6 +238,7 @@ public ConfiguredTarget create(RuleContext ruleContext) .withRtxt(primaryResources.getRTxt()) .withClasses(classesJar) .setAAROut(aarOut) + .setProguardSpecs(proguardLibrary.collectLocalProguardSpecs()) .setThrowOnResourceConflict( ruleContext.getFragment(AndroidConfiguration.class).throwOnResourceConflict()) .build(ruleContext); 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 index b412bb20575bca..cae0ac8ae351dd 100644 --- 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 @@ -89,7 +89,7 @@ public NestedSet collectProguardSpecs(Multimap attribute /** * Collects the unvalidated proguard specs exported by this rule. */ - private Collection collectLocalProguardSpecs() { + public ImmutableList collectLocalProguardSpecs() { if (!ruleContext.attributes().has(LOCAL_SPEC_ATTRIBUTE, BuildType.LABEL_LIST)) { return ImmutableList.of(); } diff --git a/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java b/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java index 347d38dde6dd6f..6d1729769d458f 100644 --- a/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java +++ b/src/test/java/com/google/devtools/build/android/AarGeneratorActionTest.java @@ -22,19 +22,24 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.devtools.build.android.AarGeneratorAction.AarGeneratorOptions; +import com.google.devtools.build.zip.ZipReader; import com.google.devtools.common.options.OptionsParser; import com.google.devtools.common.options.OptionsParsingException; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -87,6 +92,7 @@ private static class Builder { private Path classes; private Map filesToWrite = new HashMap<>(); private Map classesToWrite = new HashMap<>(); + private ImmutableList.Builder proguardSpecs = ImmutableList.builder(); private boolean withEmptyRes = false; private boolean withEmptyAssets = false; @@ -149,9 +155,16 @@ public Builder addClassesFile(String filePackage, String filename, String... lin return this; } + public Builder addProguardSpec(String path, String... lines) { + Path proguardSpecPath = root.resolve(path); + proguardSpecs.add(proguardSpecPath); + filesToWrite.put(proguardSpecPath, String.format("%s", Joiner.on("\n").join(lines))); + return this; + } + public AarData build() throws IOException { writeFiles(); - return new AarData(buildMerged(), manifest, rtxt, classes); + return new AarData(buildMerged(), manifest, rtxt, classes, proguardSpecs.build()); } private MergedAndroidData buildMerged() { @@ -206,12 +219,19 @@ private void writeClassesJar() throws IOException { final Path manifest; final Path rtxt; final Path classes; - - private AarData(MergedAndroidData data, Path manifest, Path rtxt, Path classes) { + final ImmutableList proguardSpecs; + + private AarData( + MergedAndroidData data, + Path manifest, + Path rtxt, + Path classes, + ImmutableList proguardSpecs) { this.data = data; this.manifest = manifest; this.rtxt = rtxt; this.classes = classes; + this.proguardSpecs = proguardSpecs; } } @@ -343,7 +363,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testWriteAar_DefaultTimestamps() throws Exception { @@ -365,7 +386,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); assertThat(getZipEntryTimestamps(aar)).containsExactly(AarGeneratorAction.DEFAULT_TIMESTAMP); assertThat(aar.toFile().lastModified()).isEqualTo(AarGeneratorAction.DEFAULT_TIMESTAMP); @@ -390,7 +412,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); // verify aar archive Set zipEntries = getZipEntries(aar); @@ -418,7 +441,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testMissingRtxt() throws Exception { @@ -439,7 +463,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testMissingClasses() throws Exception { @@ -461,7 +486,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testMissingResources() throws Exception { @@ -482,7 +508,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testEmptyResources() throws Exception { @@ -505,7 +532,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testMissingAssets() throws Exception { @@ -526,7 +554,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testEmptyAssets() throws Exception { @@ -548,7 +577,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { aarData.data, aarData.manifest, aarData.rtxt, - aarData.classes); + aarData.classes, + aarData.proguardSpecs); } @Test public void testFullIntegration() throws Exception { @@ -650,7 +680,8 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { /* filteredResources= */ ImmutableList.of(), true); - AarGeneratorAction.writeAar(aar, mergedData, aarData.manifest, aarData.rtxt, aarData.classes); + AarGeneratorAction.writeAar( + aar, mergedData, aarData.manifest, aarData.rtxt, aarData.classes, aarData.proguardSpecs); // verify aar archive Set zipEntries = getZipEntries(aar); @@ -677,4 +708,37 @@ private Set getZipEntryTimestamps(Path zip) throws IOException { "assets/some/other/ft/data1.txt", "assets/some/other/ft/data2.txt"); } + + @Test public void testProguardSpecs() throws Exception { + Path aar = tempDir.resolve("foo.aar"); + AarData aarData = + new AarData.Builder(tempDir.resolve("data")) + .createManifest("AndroidManifest.xml", "com.google.android.apps.foo.d1", "") + .createRtxt("R.txt", "") + .withEmptyResources(true) + .withEmptyAssets(true) + .createClassesJar("classes.jar") + .addProguardSpec("spec1", "foo", "bar") + .addProguardSpec("spec2", "baz") + .build(); + + AarGeneratorAction.writeAar( + aar, + aarData.data, + aarData.manifest, + aarData.rtxt, + aarData.classes, + aarData.proguardSpecs); + Set zipEntries = getZipEntries(aar); + assertThat(zipEntries).contains("proguard.txt"); + ZipReader aarReader = new ZipReader(aar.toFile()); + List proguardTxtContents = + new BufferedReader( + new InputStreamReader( + aarReader.getInputStream(aarReader.getEntry("proguard.txt")), + StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.toList()); + assertThat(proguardTxtContents).containsExactly("foo", "bar", "baz").inOrder(); + } } diff --git a/src/test/java/com/google/devtools/build/android/BUILD b/src/test/java/com/google/devtools/build/android/BUILD index af7082fcd6c859..37970afa76442f 100644 --- a/src/test/java/com/google/devtools/build/android/BUILD +++ b/src/test/java/com/google/devtools/build/android/BUILD @@ -18,6 +18,7 @@ java_test( srcs = ["AarGeneratorActionTest.java"], deps = [ ":test_utils", + "//src/java_tools/singlejar/java/com/google/devtools/build/zip", "//src/main/java/com/google/devtools/common/options", "//src/tools/android/java/com/google/devtools/build/android:android_builder_lib", "//third_party:android_common_25_0_0", diff --git a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java index 88618ed83500b3..d5bd4944d5579c 100644 --- a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java +++ b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java @@ -13,6 +13,8 @@ // limitations under the License. package com.google.devtools.build.android; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.android.builder.core.VariantType; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; @@ -124,6 +126,18 @@ public static final class AarGeneratorOptions extends OptionsBase { ) public Path classes; + @Option( + name = "proguardSpec", + defaultValue = "", + converter = ExistingPathConverter.class, + allowMultiple = true, + category = "input", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = "Path to proguard spec file." + ) + public List proguardSpecs; + @Option( name = "aarOutput", defaultValue = "null", @@ -179,7 +193,13 @@ public static void main(String[] args) { options.throwOnResourceConflict); logger.fine(String.format("Merging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS))); - writeAar(options.aarOutput, mergedData, options.manifest, options.rtxt, options.classes); + writeAar( + options.aarOutput, + mergedData, + options.manifest, + options.rtxt, + options.classes, + options.proguardSpecs); logger.fine( String.format("Packaging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS))); } catch (MergeConflictException e) { @@ -214,7 +234,12 @@ static void checkFlags(AarGeneratorOptions options) { @VisibleForTesting static void writeAar( - Path aar, final MergedAndroidData data, Path manifest, Path rtxt, Path classes) + Path aar, + final MergedAndroidData data, + Path manifest, + Path rtxt, + Path classes, + List proguardSpecs) throws IOException { try (final ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(aar)))) { @@ -240,6 +265,17 @@ static void writeAar( zipOut.write(Files.readAllBytes(rtxt)); zipOut.closeEntry(); + if (!proguardSpecs.isEmpty()) { + ZipEntry proguardTxt = new ZipEntry("proguard.txt"); + proguardTxt.setTime(DEFAULT_TIMESTAMP); + zipOut.putNextEntry(proguardTxt); + for (Path proguardSpec : proguardSpecs) { + zipOut.write(Files.readAllBytes(proguardSpec)); + zipOut.write("\r\n".getBytes(UTF_8)); + } + zipOut.closeEntry(); + } + if (Files.exists(data.getAssetDir()) && data.getAssetDir().toFile().list().length > 0) { ZipDirectoryWriter assetWriter = new ZipDirectoryWriter(zipOut, data.getAssetDir(), "assets"); diff --git a/tools/cpp/CROSSTOOL.tpl b/tools/cpp/CROSSTOOL.tpl index 3bea6aff228dfd..518bc4453c78ab 100644 --- a/tools/cpp/CROSSTOOL.tpl +++ b/tools/cpp/CROSSTOOL.tpl @@ -22,7 +22,7 @@ default_toolchain { } default_toolchain { - cpu: "local" + cpu: "armeabi-v7a" toolchain_identifier: "stub_armeabi-v7a" } @@ -47,7 +47,7 @@ default_toolchain { } default_toolchain { - cpu: "local" + cpu: "ios_x86_64" toolchain_identifier: "ios_x86_64" }