diff options
6 files changed, 109 insertions, 4 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java index 14f43f9b25..7983256ec6 100644 --- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java +++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java @@ -117,6 +117,13 @@ public class AndroidResourceProcessingAction { help = "Path to where the symbolsTxt should be written.") public Path symbolsTxtOut; + @Option(name = "dataBindingInfoOut", + defaultValue = "null", + converter = PathConverter.class, + category = "output", + help = "Path to where data binding's layout info output should be written.") + public Path dataBindingInfoOut; + @Option(name = "packagePath", defaultValue = "null", converter = PathConverter.class, @@ -306,7 +313,8 @@ public class AndroidResourceProcessingAction { options.mainDexProguardOutput, options.resourcesOutput != null ? processedData.getResourceDir().resolve("values").resolve("public.xml") - : null); + : null, + options.dataBindingInfoOut); logger.fine(String.format("aapt finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS))); if (options.srcJarOutput != null) { 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 53a7057fc6..d5194a098d 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 @@ -15,7 +15,10 @@ package com.google.devtools.build.android; import static java.nio.charset.StandardCharsets.UTF_8; +import android.databinding.AndroidDataBinding; +import android.databinding.cli.ProcessXmlOptions; import com.android.annotations.Nullable; +import com.android.builder.core.DefaultManifestParser; import com.android.builder.core.VariantConfiguration; import com.android.builder.dependency.SymbolFileProvider; import com.android.builder.internal.SymbolLoader; @@ -414,10 +417,13 @@ public class AndroidResourceProcessor { Path packageOut, Path proguardOut, Path mainDexProguardOut, - Path publicResourcesOut) + Path publicResourcesOut, + Path dataBindingInfoOut) throws IOException, InterruptedException, LoggedErrorException, UnrecognizedSplitsException { Path androidManifest = primaryData.getManifest(); - final Path resourceDir = primaryData.getResourceDir(); + final Path resourceDir = processDataBindings(primaryData.getResourceDir(), dataBindingInfoOut, + variantType, customPackageForR, androidManifest); + final Path assetsDir = primaryData.getAssetDir(); if (publicResourcesOut != null) { prepareOutputPath(publicResourcesOut.getParent()); @@ -542,6 +548,62 @@ public class AndroidResourceProcessor { return outputWithSourceContext; } + /** + * If resources exist and a data binding layout info file is requested: processes data binding + * declarations over those resources, populates the output file, and creates a new resources + * directory with data binding expressions stripped out (so aapt, which doesn't understand + * data binding, can properly read them). + * + * <p>Returns the resources directory that aapt should read. + */ + private Path processDataBindings(Path resourceDir, Path dataBindingInfoOut, + VariantConfiguration.Type variantType, String packagePath, Path androidManifest) + throws IOException { + + if (dataBindingInfoOut == null) { + return resourceDir; + } else if (!Files.isDirectory(resourceDir)) { + // No resources: no data binding needed. Create a dummy file to satisfy declared outputs. + Files.createFile(dataBindingInfoOut); + return resourceDir; + } + + // Strip the file name (the data binding library automatically adds it back in). + // ** The data binding library assumes this file is called "layout-info.zip". ** + dataBindingInfoOut = dataBindingInfoOut.getParent(); + if (Files.notExists(dataBindingInfoOut)) { + Files.createDirectory(dataBindingInfoOut); + } + + Path processedResourceDir = resourceDir.resolveSibling("res_without_databindings"); + if (Files.notExists(processedResourceDir)) { + Files.createDirectory(processedResourceDir); + } + + ProcessXmlOptions options = new ProcessXmlOptions(); + options.setAppId(packagePath); + options.setLibrary(variantType == VariantConfiguration.Type.LIBRARY); + options.setResInput(resourceDir.toFile()); + options.setResOutput(processedResourceDir.toFile()); + options.setLayoutInfoOutput(dataBindingInfoOut.toFile()); + options.setZipLayoutInfo(true); // Aggregate data-bound .xml files into a single .zip. + + Object minSdk = new DefaultManifestParser().getMinSdkVersion(androidManifest.toFile()); + if (minSdk instanceof Integer) { + options.setMinSdk(((Integer) minSdk).intValue()); + } else { + // TODO(bazel-team): Enforce the minimum SDK check. + options.setMinSdk(15); + } + + try { + AndroidDataBinding.doRun(options); + } catch (Throwable t) { + throw new RuntimeException(t); + } + return processedResourceDir; + } + /** Task to parse java package from AndroidManifest.xml */ private static final class PackageParsingTask implements Callable<String> { diff --git a/src/tools/android/java/com/google/devtools/build/android/BUILD b/src/tools/android/java/com/google/devtools/build/android/BUILD index aac3a058fa..f4b5689623 100644 --- a/src/tools/android/java/com/google/devtools/build/android/BUILD +++ b/src/tools/android/java/com/google/devtools/build/android/BUILD @@ -80,6 +80,7 @@ java_library( "//third_party:asm", "//third_party:guava", "//third_party:jsr305", + "//third_party/java/android_databinding:exec", "//third_party/protobuf", ], ) diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java index ea5f1225ff..4d0498533f 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java +++ b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java @@ -234,7 +234,8 @@ public class ResourceShrinkerAction { options.shrunkApk, null /* proguardOutput */, null /* mainDexProguardOutput */, - null /* publicResourcesOut */); + null /* publicResourcesOut */, + null /* dataBindingInfoOut */); if (options.shrunkResources != null) { resourceProcessor.createResourcesZip(shrunkResources, resourceFiles.resolve("assets"), options.shrunkResources); diff --git a/third_party/BUILD b/third_party/BUILD index 1de5fbdc12..ec897a375d 100644 --- a/third_party/BUILD +++ b/third_party/BUILD @@ -8,6 +8,7 @@ filegroup( "//third_party/ijar:srcs", "//third_party/iossim:srcs", "//third_party/grpc:srcs", + "//third_party/java/android_databinding:srcs", "//third_party/java/apkbuilder:srcs", "//third_party/java/buck-ios-support:srcs", "//third_party/java/dd_plist:srcs", diff --git a/third_party/java/android_databinding/BUILD b/third_party/java/android_databinding/BUILD new file mode 100644 index 0000000000..9d66f2123d --- /dev/null +++ b/third_party/java/android_databinding/BUILD @@ -0,0 +1,32 @@ +# 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. + +licenses(["notice"]) # Apache License 2.0 + +exports_files(["LICENSE"]) + +package( + default_visibility = ["//visibility:public"], +) + +filegroup( + name = "srcs", + srcs = glob(["**"]), +) + +# Executable for the databinding resource compiler. +java_import( + name = "exec", + jars = ["exec.jar"], +) |