aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java65
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java117
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java77
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidDataDeserializer.java71
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java58
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java37
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java203
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java53
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/LibraryRClassGeneratorAction.java3
13 files changed, 488 insertions, 240 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
index 7c340694cb..516db565c0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
@@ -99,17 +99,18 @@ public class AarImport implements RuleConfiguredTargetFactory {
Artifact resourcesZip =
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP);
- ResourceApk resourceApk = androidManifest.packWithDataAndResources(
- ruleContext,
- new LocalResourceContainer.Builder(ruleContext)
- .withResources(ImmutableList.of(resourcesProvider))
- .build(),
- ResourceDependencies.fromRuleDeps(ruleContext, JavaCommon.isNeverLink(ruleContext)),
- ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
- ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_SYMBOLS),
- ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST),
- resourcesZip,
- /* alwaysExportManifest = */ true);
+ ResourceApk resourceApk =
+ androidManifest.packWithDataAndResources(
+ ruleContext,
+ new LocalResourceContainer.Builder(ruleContext)
+ .withResources(ImmutableList.of(resourcesProvider))
+ .build(),
+ ResourceDependencies.fromRuleDeps(ruleContext, JavaCommon.isNeverLink(ruleContext)),
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LOCAL_SYMBOLS),
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST),
+ resourcesZip,
+ /* alwaysExportManifest = */ true);
// There isn't really any use case for building an aar_import target on its own, so the files to
// build could be empty. The resources zip and merged jars are added here as a sanity check for
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 bd57dffab5..f573132b03 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
@@ -96,7 +96,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
true, /* isLibrary */
ResourceDependencies.fromRuleDeps(ruleContext, JavaCommon.isNeverLink(ruleContext)),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
- ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_SYMBOLS),
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_MERGED_SYMBOLS),
ResourceConfigurationFilter.empty(ruleContext),
ImmutableList.<String>of(), /* uncompressedExtensions */
false, /* crunchPng */
@@ -270,3 +270,4 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
return builder;
}
}
+
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
index 3d7886d368..dc84ee5dc5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceMergingActionBuilder.java
@@ -144,10 +144,11 @@ public class AndroidResourceMergingActionBuilder {
ResourceContainerConverter.convertDependencies(
dependencies, builder, inputs, RESOURCE_CONTAINER_TO_ARG, RESOURCE_CONTAINER_TO_ARTIFACTS);
- Preconditions.checkNotNull(classJarOut);
List<Artifact> outs = new ArrayList<>();
- builder.addExecPath("--classJarOutput", classJarOut);
- outs.add(classJarOut);
+ if (classJarOut != null) {
+ builder.addExecPath("--classJarOutput", classJarOut);
+ outs.add(classJarOut);
+ }
if (mergedResourcesOut != null) {
builder.addExecPath("--resourcesOutput", mergedResourcesOut);
@@ -187,8 +188,11 @@ public class AndroidResourceMergingActionBuilder {
.build(context));
// Return the full set of processed transitive dependencies.
- ResourceContainer.Builder result = primary.toBuilder()
- .setJavaClassJar(classJarOut);
+ ResourceContainer.Builder result = primary.toBuilder();
+ if (classJarOut != null) {
+ // ensure the classJar is propgated if it exists. Otherwise, AndroidCommon tries to make it.
+ result.setJavaClassJar(classJarOut);
+ }
if (manifestOut != null) {
result.setManifest(manifestOut);
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index 63a25ef0a5..7b345a16af 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -116,8 +116,8 @@ public final class AndroidRuleClasses {
fromTemplates("%{name}_symbols/R.txt");
public static final SafeImplicitOutputsFunction ANDROID_LOCAL_SYMBOLS =
fromTemplates("%{name}_symbols/local.bin");
- public static final SafeImplicitOutputsFunction ANDROID_SYMBOLS =
- fromTemplates("%{name}_symbols/symbols.bin");
+ public static final SafeImplicitOutputsFunction ANDROID_MERGED_SYMBOLS =
+ fromTemplates("%{name}_symbols/merged.bin");
public static final ImplicitOutputsFunction ANDROID_PROCESSED_MANIFEST =
fromTemplates("%{name}_processed_manifest/AndroidManifest.xml");
public static final SafeImplicitOutputsFunction MOBILE_INSTALL_STUB_APPLICATION_MANIFEST =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
index f5fabfc623..32e78d86e4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
@@ -465,38 +465,43 @@ public final class ApplicationManifest {
if (isLibrary && AndroidCommon.getAndroidConfig(ruleContext).useParallelResourceProcessing()) {
// android_library should only build the APK one way (!incremental).
Preconditions.checkArgument(!incremental);
- Artifact rJavaClassJar = ruleContext.getImplicitOutputArtifact(
- AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR);
-
- if (resourceContainer.getSymbols() != null) {
- new AndroidResourceParsingActionBuilder(ruleContext)
- .withPrimary(resourceContainer)
- .setParse(data)
- .setOutput(resourceContainer.getSymbols())
- .build(ruleContext);
- }
+ Artifact rJavaClassJar =
+ ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR);
- AndroidResourceMergingActionBuilder resourcesMergerBuilder =
- new AndroidResourceMergingActionBuilder(ruleContext)
- .setJavaPackage(resourceContainer.getJavaPackage())
+ ResourceContainer parsed =
+ new AndroidResourceParsingActionBuilder(ruleContext)
+ .setParse(data)
.withPrimary(resourceContainer)
+ .setOutput(resourceContainer.getSymbols())
+ .build(ruleContext);
+
+ ResourceContainer generated =
+ new LibraryRGeneratorActionBuilder()
+ .setJavaPackage(resourceContainer.getJavaPackage())
+ .withPrimary(parsed)
+ .withDependencies(resourceDeps)
+ .setClassJarOut(rJavaClassJar)
+ .build(ruleContext);
+
+ ResourceContainer merged =
+ new AndroidResourceMergingActionBuilder(ruleContext)
+ .setJavaPackage(generated.getJavaPackage())
+ .withPrimary(generated)
.withDependencies(resourceDeps)
.setMergedResourcesOut(mergedResources)
.setManifestOut(manifestOut)
- .setClassJarOut(rJavaClassJar)
- .setDataBindingInfoZip(dataBindingInfoZip);
- ResourceContainer merged = resourcesMergerBuilder.build(ruleContext);
+ .setDataBindingInfoZip(dataBindingInfoZip)
+ .build(ruleContext);
- AndroidResourceValidatorActionBuilder validatorBuilder =
+ processed =
new AndroidResourceValidatorActionBuilder(ruleContext)
.setJavaPackage(merged.getJavaPackage())
- .setDebug(
- ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT)
+ .setDebug(ruleContext.getConfiguration().getCompilationMode() != CompilationMode.OPT)
.setMergedResources(mergedResources)
.withPrimary(merged)
.setSourceJarOut(merged.getJavaSourceJar())
- .setRTxtOut(merged.getRTxt());
- processed = validatorBuilder.build(ruleContext);
+ .setRTxtOut(merged.getRTxt())
+ .build(ruleContext);
} else {
AndroidResourcesProcessorBuilder builder =
new AndroidResourcesProcessorBuilder(ruleContext)
@@ -644,14 +649,16 @@ public final class ApplicationManifest {
aaptActionHelper.createGenerateApkAction(resourceApk,
resourceContainer.getRenameManifestPackage(), additionalAaptOpts.build(), densities);
- ResourceContainer updatedResources = resourceContainer.toBuilder()
- .setLabel(ruleContext.getLabel())
- .setApk(resourceApk)
- .setManifest(getManifest())
- .setJavaSourceJar(javaSourcesJar)
- .setJavaClassJar(null)
- .setSymbols(null)
- .build();
+ ResourceContainer updatedResources =
+ resourceContainer
+ .toBuilder()
+ .setLabel(ruleContext.getLabel())
+ .setApk(resourceApk)
+ .setManifest(getManifest())
+ .setJavaSourceJar(javaSourcesJar)
+ .setJavaClassJar(null)
+ .setSymbols(null)
+ .build();
aaptActionHelper.createGenerateProguardAction(proguardCfg, mainDexProguardCfg);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
new file mode 100644
index 0000000000..361a70a803
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/LibraryRGeneratorActionBuilder.java
@@ -0,0 +1,117 @@
+// Copyright 2017 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.android;
+
+import com.google.common.base.Function;
+import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
+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.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+
+/** Builder for the action that generates the R class for libraries. */
+public class LibraryRGeneratorActionBuilder {
+ static final Function<ResourceContainer, Artifact> TO_SYMBOL_ARTIFACT =
+ new Function<ResourceContainer, Artifact>() {
+ @Override
+ public Artifact apply(ResourceContainer input) {
+ return input.getSymbols();
+ }
+ };
+ static final Function<ResourceContainer, String> TO_SYMBOL_PATH =
+ new Function<ResourceContainer, String>() {
+ @Override
+ public String apply(ResourceContainer container) {
+ return container.getSymbols().getExecPathString();
+ }
+ };
+
+ private String javaPackage;
+ private Iterable<ResourceContainer> deps = ImmutableList.<ResourceContainer>of();
+ private ResourceContainer resourceContainer;
+ private Artifact rJavaClassJar;
+
+ public LibraryRGeneratorActionBuilder setJavaPackage(String javaPackage) {
+ this.javaPackage = javaPackage;
+ return this;
+ }
+
+ public LibraryRGeneratorActionBuilder withPrimary(ResourceContainer resourceContainer) {
+ this.resourceContainer = resourceContainer;
+ return this;
+ }
+
+ public LibraryRGeneratorActionBuilder withDependencies(ResourceDependencies resourceDeps) {
+ this.deps = resourceDeps.getResources();
+ return this;
+ }
+
+ public LibraryRGeneratorActionBuilder setClassJarOut(Artifact rJavaClassJar) {
+ this.rJavaClassJar = rJavaClassJar;
+ return this;
+ }
+
+ public ResourceContainer build(RuleContext ruleContext) {
+ AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
+
+ CustomCommandLine.Builder builder = new CustomCommandLine.Builder();
+ NestedSetBuilder<Artifact> inputs = NestedSetBuilder.naiveLinkOrder();
+ FilesToRunProvider executable =
+ ruleContext.getExecutablePrerequisite("$android_resources_busybox", Mode.HOST);
+ inputs.addAll(executable.getRunfilesSupport().getRunfilesArtifactsWithoutMiddlemen());
+
+ builder.add("--tool").add("GENERATE_LIBRARY_R").add("--");
+
+ if (!Strings.isNullOrEmpty(javaPackage)) {
+ builder.add("--packageForR").add(javaPackage);
+ }
+
+ FluentIterable<ResourceContainer> symbolProviders =
+ FluentIterable.from(deps).append(resourceContainer);
+
+ builder.addJoinStrings(
+ "--symbols",
+ ruleContext.getConfiguration().getHostPathSeparator(),
+ symbolProviders.transform(TO_SYMBOL_PATH));
+ inputs.addTransitive(
+ NestedSetBuilder.wrap(
+ Order.NAIVE_LINK_ORDER, symbolProviders.transform(TO_SYMBOL_ARTIFACT)));
+
+ builder.addExecPath("--classJarOutput", rJavaClassJar);
+
+ builder.addExecPath("--androidJar", sdk.getAndroidJar());
+ inputs.add(sdk.getAndroidJar());
+
+ // Create the spawn action.
+ SpawnAction.Builder spawnActionBuilder = new SpawnAction.Builder();
+ ruleContext.registerAction(
+ spawnActionBuilder
+ .addTransitiveInputs(inputs.build())
+ .addOutputs(ImmutableList.<Artifact>of(rJavaClassJar))
+ .useParameterFile(ParameterFileType.UNQUOTED)
+ .setCommandLine(builder.build())
+ .setExecutable(executable)
+ .setProgressMessage("Generating Library R Classes: " + ruleContext.getLabel())
+ .setMnemonic("LibraryRClassGenerator")
+ .build(ruleContext));
+ return resourceContainer.toBuilder().setJavaClassJar(rJavaClassJar).build();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
index 52cd935e2e..8bba37d7d1 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidLibraryTest.java
@@ -718,8 +718,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
"<resources><string name = 'hello'>Hello Android!</string></resources>");
ConfiguredTarget resource = getConfiguredTarget("//c/b/m/a:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("c/b/m/a/b_/res"), args);
}
@@ -734,8 +736,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
"<resources><string name = 'hello'>Hello Android!</string></resources>");
ConfiguredTarget resource = getConfiguredTarget("//java/android:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/android/res"), args);
}
@@ -752,8 +756,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
"<resources><string name = 'hello'>Hello Android!</string></resources>");
ConfiguredTarget resource = getConfiguredTarget("//java/android:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/android/res"), args);
}
@@ -768,8 +774,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
"exports_files(['res/values/strings.xml'])");
ConfiguredTarget resource = getConfiguredTarget("//java/android:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/other/res"), args);
assertNoEvents();
}
@@ -787,8 +795,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
")");
ConfiguredTarget resource = getConfiguredTarget("//java/android:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/other/res"), args);
assertNoEvents();
}
@@ -807,8 +817,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
"exports_files(['res/values/strings.xml'])");
ConfiguredTarget resource = getConfiguredTarget("//java/android:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/other/res"), args);
assertNoEvents();
}
@@ -829,8 +841,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
")");
ConfiguredTarget resource = getConfiguredTarget("//java/android:r");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/other/res"), args);
assertNoEvents();
}
@@ -1072,22 +1086,27 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
target.getProvider(AndroidResourcesProvider.class).getDirectAndroidResources());
SpawnAction resourceParserAction =
- (SpawnAction)
- actionsTestUtil()
- .getActionForArtifactEndingWith(artifacts,
- "/" + resources.getSymbols().getFilename());
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(target, AndroidRuleClasses.ANDROID_MERGED_SYMBOLS));
+
+ SpawnAction mergeAction =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(target, AndroidRuleClasses.ANDROID_RESOURCES_ZIP));
+
SpawnAction resourceClassJarAction =
(SpawnAction)
actionsTestUtil()
- .getActionForArtifactEndingWith(artifacts,
- "/" + resources.getJavaClassJar().getFilename());
+ .getActionForArtifactEndingWith(
+ artifacts, "/" + resources.getJavaClassJar().getFilename());
+
SpawnAction resourceSrcJarAction =
(SpawnAction)
actionsTestUtil()
- .getActionForArtifactEndingWith(artifacts,
- "/" + resources.getJavaSourceJar().getFilename());
+ .getActionForArtifactEndingWith(
+ artifacts, "/" + resources.getJavaSourceJar().getFilename());
assertThat(resourceParserAction.getMnemonic()).isEqualTo("AndroidResourceParser");
- assertThat(resourceClassJarAction.getMnemonic()).isEqualTo("AndroidResourceMerger");
+ assertThat(mergeAction.getMnemonic()).isEqualTo("AndroidResourceMerger");
+ assertThat(resourceClassJarAction.getMnemonic()).isEqualTo("LibraryRClassGenerator");
assertThat(resourceSrcJarAction.getMnemonic()).isEqualTo("AndroidResourceValidator");
// Validator also generates an R.txt.
assertThat(resourceSrcJarAction.getOutputs()).contains(resources.getRTxt());
@@ -1357,8 +1376,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
" resource_files = ['d2-res/values/strings.xml'],",
" )");
ConfiguredTarget resource = getConfiguredTarget("//java/android/resources/d1:d1");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(resource, ImmutableList.of("java/android/resources/d1/d1-res"), args);
Truth.assertThat(getDirectDependentResourceDirs(resource, args))
.contains("java/android/resources/d2/d2-res");
@@ -1395,8 +1416,10 @@ public class AndroidLibraryTest extends AndroidBuildViewTestCase {
" )");
ConfiguredTarget resource = getConfiguredTarget("//java/android/resources/d1:d1");
- List<String> args = ((SpawnAction) getGeneratingAction(getResourceArtifact(resource)))
- .getArguments();
+ List<String> args =
+ getGeneratingSpawnAction(
+ getImplicitOutputArtifact(resource, AndroidRuleClasses.ANDROID_RESOURCES_ZIP))
+ .getArguments();
assertPrimaryResourceDirs(
resource, ImmutableList.of("java/android/resources/d1/d1-res"), args);
Truth.assertThat(getDirectDependentResourceDirs(resource, args))
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataDeserializer.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataDeserializer.java
index 9ea843d498..7d2dded2e7 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataDeserializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataDeserializer.java
@@ -13,26 +13,65 @@
// limitations under the License.
package com.google.devtools.build.android;
+import com.android.ide.common.res2.MergingException;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.devtools.build.android.ParsedAndroidData.Builder;
import com.google.devtools.build.android.ParsedAndroidData.KeyValueConsumer;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.Header;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
/** Deserializes {@link DataKey}, {@link DataValue} entries from a binary file. */
public class AndroidDataDeserializer {
+ /** Task to deserialize resources from a path. */
+ static final class Deserialize implements Callable<Boolean> {
+
+ private final Path symbolPath;
+
+ private final Builder finalDataBuilder;
+ private final AndroidDataDeserializer deserializer;
+
+ private Deserialize(
+ AndroidDataDeserializer deserializer, Path symbolPath, Builder finalDataBuilder) {
+ this.deserializer = deserializer;
+ this.symbolPath = symbolPath;
+ this.finalDataBuilder = finalDataBuilder;
+ }
+
+ @Override
+ public Boolean call() throws Exception {
+ final Builder parsedDataBuilder = ParsedAndroidData.Builder.newBuilder();
+ deserializer.read(symbolPath, parsedDataBuilder.consumers());
+ // The builder isn't threadsafe, so synchronize the copyTo call.
+ synchronized (finalDataBuilder) {
+ // All the resources are sorted before writing, so they can be aggregated in
+ // whatever order here.
+ parsedDataBuilder.copyTo(finalDataBuilder);
+ }
+ return Boolean.TRUE;
+ }
+ }
+
private static final Logger logger = Logger.getLogger(AndroidDataDeserializer.class.getName());
private final ImmutableSet<String> filteredResources;
@@ -137,5 +176,37 @@ public class AndroidDataDeserializer {
}
}
}
+
+ /** Deserializes a list of serialized resource paths to a {@link ParsedAndroidData}. */
+ public static ParsedAndroidData deserializeSymbolsToData(List<Path> symbolPaths)
+ throws IOException, MergingException {
+ AndroidDataDeserializer deserializer = create();
+ final ListeningExecutorService executorService =
+ MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(15));
+ final Builder deserializedDataBuilder = ParsedAndroidData.Builder.newBuilder();
+ try (Closeable closeable = ExecutorServiceCloser.createWith(executorService)) {
+ List<ListenableFuture<Boolean>> deserializing = new ArrayList<>();
+ for (final Path symbolPath : symbolPaths) {
+ deserializing.add(
+ executorService.submit(
+ new AndroidDataDeserializer.Deserialize(
+ deserializer, symbolPath, deserializedDataBuilder)));
+ }
+ FailedFutureAggregator<MergingException> aggregator =
+ FailedFutureAggregator.createForMergingExceptionWithMessage(
+ "Failure(s) during dependency parsing");
+ aggregator.aggregateAndMaybeThrow(deserializing);
+ }
+ return deserializedDataBuilder.build();
+ }
+
+ public static ParsedAndroidData deserializeSingleAndroidData(SerializedAndroidData data)
+ throws MergingException {
+ final ParsedAndroidData.Builder builder = ParsedAndroidData.Builder.newBuilder();
+ final AndroidDataDeserializer deserializer = create();
+ data.deserialize(deserializer, builder.consumers());
+ return builder.build();
+ }
}
+
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
index 7b5f14d501..433620d144 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
@@ -28,6 +28,7 @@ import com.google.common.collect.Ordering;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
+import com.google.devtools.build.android.AndroidResourceMergingAction.Options;
import com.google.devtools.build.android.xml.Namespaces;
import java.io.BufferedWriter;
import java.io.File;
@@ -103,7 +104,7 @@ public class AndroidDataWriter implements AndroidDataWritingVisitor {
private static final char[] START_RESOURCES_TAG = "<resources".toCharArray();
public static final char[] END_RESOURCES = "</resources>".toCharArray();
private static final char[] LINE_END = "\n".toCharArray();
- private static final PngCruncher NOOP_CRUNCHER =
+ static final PngCruncher NOOP_CRUNCHER =
new PngCruncher() {
@Override
public int start() {
@@ -111,8 +112,7 @@ public class AndroidDataWriter implements AndroidDataWritingVisitor {
}
@Override
- public void end(int key) throws InterruptedException {
- }
+ public void end(int key) throws InterruptedException {}
@Override
public void crunchPng(int key, @NonNull File source, @NonNull File destination)
@@ -126,6 +126,38 @@ public class AndroidDataWriter implements AndroidDataWritingVisitor {
}
};
+ /**
+ * The merged {@link Options#resourcesOutput} is only used for validation and not for running
+ * (unlike the final APK), so the image files do not need to be the true image files. We only need
+ * the filenames to be the same.
+ *
+ * <p>Thus, we only create empty files for PNGs (convenient with a custom PngCruncher object).
+ * This does miss out on other image files like .webp.
+ */
+ static final PngCruncher STUB_CRUNCHER =
+ new PngCruncher() {
+
+ @Override
+ public void crunchPng(int key, File from, File to) throws PngException {
+ try {
+ to.createNewFile();
+ if (!to.setLastModified(System.currentTimeMillis())) {
+ throw new PngException("Could not set milliseconds");
+ }
+ } catch (IOException e) {
+ throw new PngException(e);
+ }
+ }
+
+ @Override
+ public int start() {
+ return 0;
+ }
+
+ @Override
+ public void end(int key) {}
+ };
+
private final Path destination;
private final Map<String, ResourceValuesDefinitions> valueTags = new HashMap<>();
@@ -166,6 +198,26 @@ public class AndroidDataWriter implements AndroidDataWritingVisitor {
NOOP_CRUNCHER,
MoreExecutors.newDirectExecutorService());
}
+
+ /**
+ * Creates a new writer for processing android libraries.
+ *
+ * <p>This writer has stub png cruncher that touches empty files for png resources.
+ *
+ * @param manifestDirectory The base directory for the AndroidManifest.
+ * @param resourceDirectory The directory to copy resources into.
+ * @param assetsDirectory The directory to copy assets into.
+ * @param executorService An execution service for multi-threaded writing.
+ * @return A new {@link AndroidDataWriter}.
+ */
+ public static AndroidDataWriter createForLibrary(
+ Path manifestDirectory,
+ Path resourceDirectory,
+ Path assetsDirectory,
+ ListeningExecutorService executorService) {
+ return createWith(
+ manifestDirectory, resourceDirectory, assetsDirectory, STUB_CRUNCHER, executorService);
+ }
/**
* Creates a new writer.
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
index 6e7d6290a0..c549730dae 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMerger.java
@@ -28,12 +28,13 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
-/** Collects all the functionationality for an action to merge resources. */
+/** Collects all the functionality for an action to merge resources. */
+// TODO(bazel-team): Turn into an instance object, in order to use an external ExecutorService.
public class AndroidResourceMerger {
static final Logger logger = Logger.getLogger(AndroidResourceProcessor.class.getName());
/** Merges all secondary resources with the primary resources. */
- static MergedAndroidData mergeData(
+ public static MergedAndroidData mergeData(
final ParsedAndroidData primary,
final Path primaryManifest,
final List<? extends SerializedAndroidData> direct,
@@ -53,9 +54,14 @@ public class AndroidResourceMerger {
AndroidDataMerger merger =
AndroidDataMerger.createWithPathDeduplictor(executorService, deserializer);
UnwrittenMergedAndroidData merged =
- merger.loadAndMerge(
- transitive, direct, primary, primaryManifest, type != VariantType.LIBRARY);
- logger.fine(String.format("merge finished in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ mergeData(
+ executorService,
+ transitive,
+ direct,
+ primary,
+ primaryManifest,
+ type != VariantType.LIBRARY,
+ deserializer);
timer.reset().start();
if (symbolsOut != null) {
AndroidDataSerializer serializer = AndroidDataSerializer.create();
@@ -84,6 +90,26 @@ public class AndroidResourceMerger {
}
}
+ public static UnwrittenMergedAndroidData mergeData(
+ ListeningExecutorService executorService,
+ List<? extends SerializedAndroidData> transitive,
+ List<? extends SerializedAndroidData> direct,
+ ParsedAndroidData primary,
+ Path primaryManifest,
+ boolean allowPrimaryOverrideAll,
+ AndroidDataDeserializer deserializer)
+ throws MergingException {
+ Stopwatch timer = Stopwatch.createStarted();
+ try {
+ AndroidDataMerger merger =
+ AndroidDataMerger.createWithPathDeduplictor(executorService, deserializer);
+ return merger.loadAndMerge(
+ transitive, direct, primary, primaryManifest, allowPrimaryOverrideAll);
+ } finally {
+ logger.fine(String.format("merge finished in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ }
+ }
+
/**
* Merges all secondary resources with the primary resources, given that the primary resources
* have not yet been parsed and serialized.
@@ -153,3 +179,4 @@ public class AndroidResourceMerger {
}
}
+
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
index f5f49f6894..6db47d1d36 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceMergingAction.java
@@ -14,14 +14,13 @@
package com.google.devtools.build.android;
import com.android.builder.core.VariantType;
-import com.android.ide.common.internal.PngCruncher;
-import com.android.ide.common.internal.PngException;
import com.android.ide.common.res2.MergingException;
import com.android.utils.StdLogger;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
-import com.google.common.io.Files;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import com.google.devtools.build.android.AndroidResourceProcessor.AaptConfigOptions;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.PathConverter;
@@ -30,11 +29,13 @@ import com.google.devtools.build.android.Converters.SerializedAndroidDataListCon
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
-import java.io.File;
+import java.io.Closeable;
import java.io.IOException;
import java.nio.file.FileSystems;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -166,117 +167,115 @@ public class AndroidResourceMergingAction {
Preconditions.checkNotNull(options.primaryData);
Preconditions.checkNotNull(options.primaryManifest);
- Preconditions.checkNotNull(options.classJarOutput);
+
+ final ListeningExecutorService executorService =
+ MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(15));
try (ScopedTemporaryDirectory scopedTmp =
new ScopedTemporaryDirectory("android_resource_merge_tmp")) {
- Path tmp = scopedTmp.getPath();
- Path mergedAssets = tmp.resolve("merged_assets");
- Path mergedResources = tmp.resolve("merged_resources");
- Path generatedSources = tmp.resolve("generated_resources");
- Path processedManifest = tmp.resolve("manifest-processed/AndroidManifest.xml");
-
- logger.fine(String.format("Setup finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
-
- VariantType packageType = VariantType.LIBRARY;
- AndroidResourceClassWriter resourceClassWriter =
- AndroidResourceClassWriter.createWith(aaptConfigOptions.androidJar,
- generatedSources,
- Strings.nullToEmpty(options.packageForR));
- resourceClassWriter.setIncludeClassFile(true);
- resourceClassWriter.setIncludeJavaFile(false);
-
- final MergedAndroidData mergedData =
- AndroidResourceMerger.mergeData(
- options.primaryData,
- options.primaryManifest,
- options.directData,
- options.transitiveData,
- mergedResources,
- mergedAssets,
- new StubPngCruncher(),
- packageType,
- options.symbolsBinOut,
- resourceClassWriter);
-
- logger.fine(String.format("Merging finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
- // Until enough users with manifest placeholders migrate to the new manifest merger,
- // we need to replace ${applicationId} and ${packageName} with options.packageForR to make
- // the manifests compatible with the old manifest merger.
- if (options.manifestOutput != null) {
- MergedAndroidData processedData =
+ try (Closeable closeable = ExecutorServiceCloser.createWith(executorService)) {
+ Path tmp = scopedTmp.getPath();
+ Path mergedAssets = tmp.resolve("merged_assets");
+ Path mergedResources = tmp.resolve("merged_resources");
+ Path generatedSources = tmp.resolve("generated_resources");
+ Path processedManifest = tmp.resolve("manifest-processed/AndroidManifest.xml");
+
+ logger.fine(String.format("Setup finished in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ timer.reset().start();
+ final UnwrittenMergedAndroidData unwrittenMergedData =
+ AndroidResourceMerger.mergeData(
+ executorService,
+ options.transitiveData,
+ options.directData,
+ AndroidDataDeserializer.deserializeSingleAndroidData(options.primaryData),
+ options.primaryManifest,
+ false /* allow binary overrides */,
+ AndroidDataDeserializer.create());
+
+ logger.fine(String.format("merge finished in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ timer.reset().start();
+
+ if (options.symbolsBinOut != null) {
+ AndroidDataSerializer serializer = AndroidDataSerializer.create();
+ unwrittenMergedData.serializeTo(serializer);
+ serializer.flushTo(options.symbolsBinOut);
+ }
+
+ if (options.classJarOutput != null) {
+ AndroidResourceClassWriter resourceClassWriter =
+ AndroidResourceClassWriter.createWith(
+ aaptConfigOptions.androidJar,
+ generatedSources,
+ Strings.nullToEmpty(options.packageForR));
+ resourceClassWriter.setIncludeClassFile(true);
+ resourceClassWriter.setIncludeJavaFile(false);
+ unwrittenMergedData.writeResourceClass(resourceClassWriter);
+ logger.fine(
+ String.format(
+ "Write classes finished in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ timer.reset().start();
+ AndroidResourceOutputs.createClassJar(generatedSources, options.classJarOutput);
+ logger.fine(
+ String.format(
+ "Create classJar finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ timer.reset().start();
+ }
+
+ if (options.resourcesOutput != null) {
+ AndroidDataWriter mergedDataWriter =
+ AndroidDataWriter.createForLibrary(
+ tmp, mergedResources, mergedAssets, executorService);
+ MergedAndroidData mergedData = unwrittenMergedData.write(mergedDataWriter);
+
+ Path resourcesDir =
+ AndroidResourceProcessor.processDataBindings(
+ mergedData.getResourceDir(),
+ options.dataBindingInfoOut,
+ VariantType.LIBRARY,
+ options.packageForR,
+ options.primaryManifest);
+
+ // For now, try compressing the library resources that we pass to the validator.
+ // This takes extra CPU resources to pack and unpack (~2x), but can reduce the
+ // zip size (~4x).
+ try {
+ Files.createDirectories(options.resourcesOutput.getParent());
+ AndroidResourceOutputs.createResourcesZip(
+ resourcesDir,
+ mergedData.getAssetDir(),
+ options.resourcesOutput,
+ true /* compress */);
+ logger.fine(
+ String.format(
+ "Resource Zip finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ timer.reset().start();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ // Until enough users with manifest placeholders migrate to the new manifest merger,
+ // we need to replace ${applicationId} and ${packageName} with options.packageForR to make
+ // the manifests compatible with the old manifest merger.
+ if (options.manifestOutput != null) {
AndroidManifestProcessor.with(stdLogger)
.processManifest(
- packageType,
+ VariantType.LIBRARY,
options.packageForR,
null, /* applicationId */
-1, /* versionCode */
null, /* versionName */
mergedData,
processedManifest);
- AndroidResourceOutputs.copyManifestToOutput(processedData, options.manifestOutput);
- }
-
- AndroidResourceOutputs.createClassJar(generatedSources, options.classJarOutput);
-
- logger.fine(
- String.format("Create classJar finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
-
- if (options.resourcesOutput != null) {
- Path resourcesDir =
- AndroidResourceProcessor.processDataBindings(
- mergedData.getResourceDir(),
- options.dataBindingInfoOut,
- packageType,
- options.packageForR,
- options.primaryManifest);
-
- // For now, try compressing the library resources that we pass to the validator. This takes
- // extra CPU resources to pack and unpack (~2x), but can reduce the zip size (~4x).
- AndroidResourceOutputs.createResourcesZip(
- resourcesDir, mergedData.getAssetDir(), options.resourcesOutput, true /* compress */);
- logger.fine(
- String.format(
- "Create resources.zip finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ AndroidResourceOutputs.copyManifestToOutput(mergedData, options.manifestOutput);
+ }
+ }
+ } catch (MergingException e) {
+ logger.log(Level.SEVERE, "Error during merging resources", e);
+ throw e;
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Unexpected", e);
+ throw e;
}
- } catch (MergingException e) {
- logger.log(Level.SEVERE, "Error during merging resources", e);
- throw e;
- } catch (Exception e) {
- logger.log(Level.SEVERE, "Unexpected", e);
- throw e;
}
- logger.fine(String.format("Resources merged in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
- }
-
- /**
- * The merged {@link Options#resourcesOutput} is only used for validation and not for running
- * (unlike the final APK), so the image files do not need to be the true image files. We only need
- * the filenames to be the same.
- *
- * <p>Thus, we only create empty files for PNGs (convenient with a custom PngCruncher object).
- * This does miss out on other image files like .webp.
- */
- private static final class StubPngCruncher implements PngCruncher {
-
- @Override
- public void crunchPng(int key, File from, File to) throws PngException {
- try {
- Files.touch(to);
- } catch (IOException e) {
- throw new PngException(e);
- }
- }
-
- @Override
- public int start() {
- return 0;
- }
-
- @Override
- public void end(int key) {
- }
-
}
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index 836c3855cb..1c9982aecc 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -28,7 +28,6 @@ import com.android.builder.model.AaptOptions;
import com.android.ide.common.internal.CommandLineRunner;
import com.android.ide.common.internal.ExecutorSingleton;
import com.android.ide.common.internal.LoggedErrorException;
-import com.android.ide.common.res2.MergingException;
import com.android.io.FileWrapper;
import com.android.io.StreamException;
import com.android.repository.Revision;
@@ -46,7 +45,6 @@ import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.RevisionConverter;
-import com.google.devtools.build.android.ParsedAndroidData.Builder;
import com.google.devtools.build.android.SplitConfigurationFilter.UnrecognizedSplitsException;
import com.google.devtools.build.android.resources.RClassGenerator;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
@@ -734,55 +732,4 @@ public class AndroidResourceProcessor {
}
return Files.createDirectories(out);
}
-
- /** Deserializes a list of serialized resource paths to a {@link ParsedAndroidData}. */
- public ParsedAndroidData deserializeSymbolsToData(List<Path> symbolPaths)
- throws IOException, MergingException {
- AndroidDataDeserializer deserializer = AndroidDataDeserializer.create();
- final ListeningExecutorService executorService =
- MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(15));
- final Builder deserializedDataBuilder = ParsedAndroidData.Builder.newBuilder();
- try (Closeable closeable = ExecutorServiceCloser.createWith(executorService)) {
- List<ListenableFuture<Boolean>> deserializing = new ArrayList<>();
- for (final Path symbolPath : symbolPaths) {
- deserializing.add(
- executorService.submit(
- new Deserialize(deserializer, symbolPath, deserializedDataBuilder)));
- }
- FailedFutureAggregator<MergingException> aggregator =
- FailedFutureAggregator.createForMergingExceptionWithMessage(
- "Failure(s) during dependency parsing");
- aggregator.aggregateAndMaybeThrow(deserializing);
- }
- return deserializedDataBuilder.build();
- }
-
- /** Task to deserialize resources from a path. */
- private static final class Deserialize implements Callable<Boolean> {
-
- private final Path symbolPath;
-
- private final Builder finalDataBuilder;
- private final AndroidDataDeserializer deserializer;
-
- private Deserialize(
- AndroidDataDeserializer deserializer, Path symbolPath, Builder finalDataBuilder) {
- this.deserializer = deserializer;
- this.symbolPath = symbolPath;
- this.finalDataBuilder = finalDataBuilder;
- }
-
- @Override
- public Boolean call() throws Exception {
- final Builder parsedDataBuilder = ParsedAndroidData.Builder.newBuilder();
- deserializer.read(symbolPath, parsedDataBuilder.consumers());
- // The builder isn't threadsafe, so synchronize the copyTo call.
- synchronized (finalDataBuilder) {
- // All the resources are sorted before writing, so they can be aggregated in
- // whatever order here.
- parsedDataBuilder.copyTo(finalDataBuilder);
- }
- return Boolean.TRUE;
- }
- }
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/LibraryRClassGeneratorAction.java b/src/tools/android/java/com/google/devtools/build/android/LibraryRClassGeneratorAction.java
index 51c771946b..1cb816c01e 100644
--- a/src/tools/android/java/com/google/devtools/build/android/LibraryRClassGeneratorAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/LibraryRClassGeneratorAction.java
@@ -93,11 +93,10 @@ public class LibraryRClassGeneratorAction {
Strings.nullToEmpty(options.packageForR));
resourceClassWriter.setIncludeClassFile(true);
resourceClassWriter.setIncludeJavaFile(false);
- final AndroidResourceProcessor resourceProcessor = new AndroidResourceProcessor(stdLogger);
logger.fine(String.format("Setup finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
final ParsedAndroidData data =
- resourceProcessor.deserializeSymbolsToData(options.symbols);
+ AndroidDataDeserializer.deserializeSymbolsToData(options.symbols);
logger.fine(
String.format("Deserialization finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));