From ebf601d340c570d2666a1293a144975938a063f2 Mon Sep 17 00:00:00 2001 From: Andrew Pellegrini Date: Wed, 20 Jul 2016 17:47:49 +0000 Subject: Add target names for mergee manifests to generate more helpful error messages from manifest merging when using manifest_merger="android" on android_binary rules. -- MOS_MIGRATED_REVID=127962630 --- .../build/android/AndroidResourceProcessor.java | 10 +- .../google/devtools/build/android/Converters.java | 132 ++++++++++++++++++--- .../build/android/ManifestMergerAction.java | 22 ++-- 3 files changed, 137 insertions(+), 27 deletions(-) (limited to 'src/tools/android/java/com/google/devtools') 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 f403aaf708..644b8290df 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 @@ -64,6 +64,7 @@ import com.android.manifmerger.MergingReport; import com.android.manifmerger.PlaceholderHandler; import com.android.manifmerger.XmlDocument; import com.android.sdklib.repository.FullRevision; +import com.android.utils.Pair; import com.android.utils.StdLogger; import org.xml.sax.SAXException; @@ -88,6 +89,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -767,7 +769,7 @@ public class AndroidResourceProcessor { */ public Path mergeManifest( Path manifest, - List mergeeManifests, + Map mergeeManifests, MergeType mergeType, Map values, Path output) throws IOException { @@ -781,9 +783,11 @@ public class AndroidResourceProcessor { } // Add mergee manifests - for (Path mergeeManifest : mergeeManifests) { - manifestMerger.addLibraryManifest(mergeeManifest.toFile()); + List> libraryManifests = new ArrayList<>(); + for (Entry mergeeManifest : mergeeManifests.entrySet()) { + libraryManifests.add(Pair.of(mergeeManifest.getValue(), mergeeManifest.getKey().toFile())); } + manifestMerger.addLibraryManifests(libraryManifests); // Extract SystemProperties from the provided values. Map placeholders = new HashMap<>(values); diff --git a/src/tools/android/java/com/google/devtools/build/android/Converters.java b/src/tools/android/java/com/google/devtools/build/android/Converters.java index e6171e6422..421d7e6d21 100644 --- a/src/tools/android/java/com/google/devtools/build/android/Converters.java +++ b/src/tools/android/java/com/google/devtools/build/android/Converters.java @@ -13,18 +13,17 @@ // limitations under the License. package com.google.devtools.build.android; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.devtools.common.options.Converter; -import com.google.devtools.common.options.EnumConverter; -import com.google.devtools.common.options.OptionsParsingException; - import com.android.builder.core.VariantConfiguration; import com.android.builder.core.VariantConfiguration.Type; import com.android.manifmerger.ManifestMerger2; import com.android.manifmerger.ManifestMerger2.MergeType; import com.android.sdklib.repository.FullRevision; - +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.devtools.common.options.Converter; +import com.google.devtools.common.options.EnumConverter; +import com.google.devtools.common.options.OptionsParsingException; +import java.lang.reflect.ParameterizedType; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -39,6 +38,16 @@ import java.util.Map; * Some convenient converters used by android actions. Note: These are specific to android actions. */ public final class Converters { + private static final Converter IDENTITY_CONVERTER = new Converter() { + @Override public String convert(String input) { + return input; + } + + @Override public String getTypeDescription() { + return "a string"; + } + }; + /** * Converter for {@link UnvalidatedAndroidData}. Relies on * {@code UnvalidatedAndroidData#valueOf(String)} to perform conversion and validation. @@ -253,13 +262,21 @@ public final class Converters { * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values * may contain colons and commas as long as they are escaped with a backslash. */ - public static class StringDictionaryConverter implements Converter> { + private abstract static class DictionaryConverter implements Converter> { + private final Converter keyConverter; + private final Converter valueConverter; + + public DictionaryConverter(Converter keyConverter, Converter valueConverter) { + this.keyConverter = keyConverter; + this.valueConverter = valueConverter; + } + @Override - public Map convert(String input) throws OptionsParsingException { + public Map convert(String input) throws OptionsParsingException { if (input.isEmpty()) { return ImmutableMap.of(); } - Map map = new LinkedHashMap<>(); + Map map = new LinkedHashMap<>(); // Only split on comma and colon that are not escaped with a backslash for (String entry : input.split("(? { + public StringDictionaryConverter() { + super(IDENTITY_CONVERTER, IDENTITY_CONVERTER); + } + // The way {@link OptionsData} checks for generic types requires convert to have literal type + // parameters and not argument type parameters. + @Override public Map convert(String input) throws OptionsParsingException { + return super.convert(input); + } + } + + /** + * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values + * may contain colons and commas as long as they are escaped with a backslash. The key type is + * Path and the value type is String. + */ + public static class PathStringDictionaryConverter extends DictionaryConverter { + public PathStringDictionaryConverter() { + super(new PathConverter(), IDENTITY_CONVERTER); + } + // The way {@link OptionsData} checks for generic types requires convert to have literal type + // parameters and not argument type parameters. + @Override public Map convert(String input) throws OptionsParsingException { + return super.convert(input); + } + } + + /** + * A converter for dictionary arguments of the format key:value[,key:value]*. The keys and values + * may contain colons and commas as long as they are escaped with a backslash. The key type is + * Path and the value type is String. + */ + public static class ExistingPathStringDictionaryConverter + extends DictionaryConverter { + public ExistingPathStringDictionaryConverter() { + super(new ExistingPathConverter(), IDENTITY_CONVERTER); + } + // The way {@link OptionsData} checks for generic types requires convert to have literal type + // parameters and not argument type parameters. + @Override public Map convert(String input) throws OptionsParsingException { + return super.convert(input); + } + } + + /** + * A converter to handle the migration of the --mergeeManifests flag from a list of paths to a + * dictionary of paths to labels. + */ + public static class MergeeManifestsConverter implements Converter> { + @Override + public Map convert(String input) throws OptionsParsingException { + try { + List manifests = new ExistingPathListConverter().convert(input); + Map mergeeManifests = new LinkedHashMap<>(); + for (Path manifest : manifests) { + mergeeManifests.put(manifest, manifest.getFileName().toString()); + } + return ImmutableMap.copyOf(mergeeManifests); + } catch (OptionsParsingException e) { + // Expected if argument change has been released. + return new ExistingPathStringDictionaryConverter().convert(input); + } + } + + @Override + public String getTypeDescription() { + return "a path to string dictionary with fallback to path list using filename as values"; } } } diff --git a/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java b/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java index 3df7900d61..f12fb17293 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java +++ b/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java @@ -15,9 +15,9 @@ package com.google.devtools.build.android; import static java.util.logging.Level.SEVERE; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.android.Converters.ExistingPathConverter; -import com.google.devtools.build.android.Converters.ExistingPathListConverter; +import com.google.devtools.build.android.Converters.MergeeManifestsConverter; import com.google.devtools.build.android.Converters.MergeTypeConverter; import com.google.devtools.build.android.Converters.PathConverter; import com.google.devtools.build.android.Converters.StringDictionaryConverter; @@ -38,8 +38,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.FileTime; -import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; @@ -78,10 +78,12 @@ public class ManifestMergerAction { @Option(name = "mergeeManifests", defaultValue = "", - converter = ExistingPathListConverter.class, + // TODO(apell): switch to ExistingPathStringDictionaryConverter.class after argument change + // has been released. + converter = MergeeManifestsConverter.class, category = "input", - help = "A list of manifests to be merged into manifest.") - public List mergeeManifests; + help = "A dictionary of manifests, and originating target, to be merged into manifest.") + public Map mergeeManifests; @Option(name = "mergeType", defaultValue = "APPLICATION", @@ -161,9 +163,11 @@ public class ManifestMergerAction { // Remove uses-permission tags from mergees before the merge. Path tmp = Files.createTempDirectory("manifest_merge_tmp"); tmp.toFile().deleteOnExit(); - ImmutableList.Builder mergeeManifests = ImmutableList.builder(); - for (Path mergeeManifest : options.mergeeManifests) { - mergeeManifests.add(removePermissions(mergeeManifest, tmp)); + ImmutableMap.Builder mergeeManifests = ImmutableMap.builder(); + for (Entry mergeeManifest : options.mergeeManifests.entrySet()) { + mergeeManifests.put( + removePermissions(mergeeManifest.getKey(), tmp), + mergeeManifest.getValue()); } // Ignore custom package at the binary level. -- cgit v1.2.3