Merge "AAPT2: Allow output artifacts to be filtered."

This commit is contained in:
TreeHugger Robot
2017-12-05 20:36:47 +00:00
committed by Android (Google) Code Review
3 changed files with 70 additions and 3 deletions

View File

@@ -75,6 +75,10 @@ struct OptimizeOptions {
TableFlattenerOptions table_flattener_options;
Maybe<PostProcessingConfiguration> configuration;
// Set of artifacts to keep when generating multi-APK splits. If the list is empty, all artifacts
// are kept and will be written as output.
std::unordered_set<std::string> kept_artifacts;
};
class OptimizeContext : public IAaptContext {
@@ -197,9 +201,12 @@ class OptimizeCommand {
if (options_.configuration && options_.output_dir) {
MultiApkGenerator generator{apk.get(), context_};
MultiApkGeneratorOptions generator_options = {options_.output_dir.value(),
options_.configuration.value(),
options_.table_flattener_options};
MultiApkGeneratorOptions generator_options = {
options_.output_dir.value(),
options_.configuration.value(),
options_.table_flattener_options,
options_.kept_artifacts,
};
if (!generator.FromBaseApk(generator_options)) {
return 1;
}
@@ -323,6 +330,7 @@ int Optimize(const std::vector<StringPiece>& args) {
Maybe<std::string> target_abis;
std::vector<std::string> configs;
std::vector<std::string> split_args;
std::unordered_set<std::string> kept_artifacts;
bool verbose = false;
bool print_only = false;
Flags flags =
@@ -356,6 +364,10 @@ int Optimize(const std::vector<StringPiece>& args) {
"Split APK.\nSyntax: path/to/output.apk;<config>[,<config>[...]].\n"
"On Windows, use a semicolon ';' separator instead.",
&split_args)
.OptionalFlagList("--keep-artifacts",
"Comma separated list of artifacts to keep. If none are specified,\n"
"all artifacts will be kept.",
&kept_artifacts)
.OptionalSwitch("--enable-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.",
@@ -438,6 +450,14 @@ int Optimize(const std::vector<StringPiece>& args) {
return 0;
}
if (!kept_artifacts.empty()) {
for (const auto& artifact_str : kept_artifacts) {
for (const auto& artifact : util::Tokenize(artifact_str, ',')) {
options.kept_artifacts.insert(artifact.to_string());
}
}
}
// Since we know that we are going to process the APK (not just print targets), make sure we
// have somewhere to write them to.
if (!options.output_dir) {

View File

@@ -137,6 +137,10 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) {
const StringPiece ext = file::GetExtension(apk_name);
const std::string base_name = apk_name.substr(0, apk_name.rfind(ext.to_string()));
std::unordered_set<std::string> artifacts_to_keep = options.kept_artifacts;
std::unordered_set<std::string> filtered_artifacts;
std::unordered_set<std::string> kept_artifacts;
// For now, just write out the stripped APK since ABI splitting doesn't modify anything else.
for (const Artifact& artifact : config.artifacts) {
SourcePathDiagnostics diag{{apk_name}, context_->GetDiagnostics()};
@@ -163,6 +167,20 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) {
ContextWrapper wrapped_context{context_};
wrapped_context.SetSource({artifact_name});
if (!options.kept_artifacts.empty()) {
const auto& it = artifacts_to_keep.find(artifact_name);
if (it == artifacts_to_keep.end()) {
filtered_artifacts.insert(artifact_name);
if (context_->IsVerbose()) {
context_->GetDiagnostics()->Note(DiagMessage(artifact_name) << "skipping artifact");
}
continue;
} else {
artifacts_to_keep.erase(it);
kept_artifacts.insert(artifact_name);
}
}
std::unique_ptr<ResourceTable> table =
FilterTable(artifact, config, *apk_->GetResourceTable(), &wrapped_context, &filters);
if (!table) {
@@ -197,6 +215,30 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) {
}
}
// Make sure all of the requested artifacts were valid. If there are any kept artifacts left,
// either the config or the command line was wrong.
if (!artifacts_to_keep.empty()) {
context_->GetDiagnostics()->Error(
DiagMessage() << "The configuration and command line to filter artifacts do not match");
context_->GetDiagnostics()->Error(DiagMessage() << kept_artifacts.size() << " kept:");
for (const auto& artifact : kept_artifacts) {
context_->GetDiagnostics()->Error(DiagMessage() << " " << artifact);
}
context_->GetDiagnostics()->Error(DiagMessage() << filtered_artifacts.size() << " filtered:");
for (const auto& artifact : filtered_artifacts) {
context_->GetDiagnostics()->Error(DiagMessage() << " " << artifact);
}
context_->GetDiagnostics()->Error(DiagMessage() << artifacts_to_keep.size() << " missing:");
for (const auto& artifact : artifacts_to_keep) {
context_->GetDiagnostics()->Error(DiagMessage() << " " << artifact);
}
return false;
}
return true;
}

View File

@@ -17,6 +17,10 @@
#ifndef AAPT2_APKSPLITTER_H
#define AAPT2_APKSPLITTER_H
#include <memory>
#include <string>
#include <unordered_set>
#include "Diagnostics.h"
#include "LoadedApk.h"
#include "configuration/ConfigurationParser.h"
@@ -27,6 +31,7 @@ struct MultiApkGeneratorOptions {
std::string out_dir;
configuration::PostProcessingConfiguration config;
TableFlattenerOptions table_flattener_options;
std::unordered_set<std::string> kept_artifacts;
};
/**