AAPT2: Fixup namespace implementation
A few pieces were missing in the namespace mangling implementation.
Namespace aware libraries now work, along with R class generation.
Bug: 64706588
Test: make AaptTestNamespace_App
Change-Id: I12f78d6aa909e782c0faf7ceaa36058f2e6c864a
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 35ab3c6..88e2dc2 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -457,7 +457,8 @@
const Source& src = doc->file.source;
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path);
+ context_->GetDiagnostics()->Note(DiagMessage()
+ << "linking " << src.path << " (" << doc->file.name << ")");
}
XmlReferenceLinker xml_linker;
@@ -505,6 +506,8 @@
std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
for (auto& pkg : table->packages) {
+ CHECK(!pkg->name.empty()) << "Packages must have names when being linked";
+
for (auto& type : pkg->types) {
// Sort by config and name, so that we get better locality in the zip file.
config_sorted_files.clear();
@@ -701,7 +704,7 @@
util::make_unique<AssetManagerSymbolSource>();
for (const std::string& path : options_.include_paths) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path");
+ context_->GetDiagnostics()->Note(DiagMessage() << "including " << path);
}
// First try to load the file as a static lib.
@@ -819,11 +822,9 @@
return app_info;
}
- /**
- * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
- * Postcondition: ResourceTable has only one package left. All others are
- * stripped, or there is an error and false is returned.
- */
+ // Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
+ // Postcondition: ResourceTable has only one package left. All others are
+ // stripped, or there is an error and false is returned.
bool VerifyNoExternalPackages() {
auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
@@ -965,10 +966,94 @@
context_->GetDiagnostics()->Error(DiagMessage()
<< "failed writing to '" << out_path
<< "': " << android::base::SystemErrorCodeToString(errno));
+ return false;
}
return true;
}
+ bool GenerateJavaClasses() {
+ // The set of packages whose R class to call in the main classes onResourcesLoaded callback.
+ std::vector<std::string> packages_to_callback;
+
+ JavaClassGeneratorOptions template_options;
+ template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+ template_options.javadoc_annotations = options_.javadoc_annotations;
+
+ if (context_->GetPackageType() == PackageType::kStaticLib || options_.generate_non_final_ids) {
+ template_options.use_final = false;
+ }
+
+ if (context_->GetPackageType() == PackageType::kSharedLib) {
+ template_options.use_final = false;
+ template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
+ }
+
+ const StringPiece actual_package = context_->GetCompilationPackage();
+ StringPiece output_package = context_->GetCompilationPackage();
+ if (options_.custom_java_package) {
+ // Override the output java package to the custom one.
+ output_package = options_.custom_java_package.value();
+ }
+
+ // Generate the private symbols if required.
+ if (options_.private_symbols) {
+ packages_to_callback.push_back(options_.private_symbols.value());
+
+ // If we defined a private symbols package, we only emit Public symbols
+ // to the original package, and private and public symbols to the private package.
+ JavaClassGeneratorOptions options = template_options;
+ options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
+ if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
+ options)) {
+ return false;
+ }
+ }
+
+ // Generate copies of the original package R class but with different package names.
+ // This is to support non-namespaced builds.
+ for (const std::string& extra_package : options_.extra_java_packages) {
+ packages_to_callback.push_back(extra_package);
+
+ JavaClassGeneratorOptions options = template_options;
+ options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+ if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
+ return false;
+ }
+ }
+
+ // Generate R classes for each package that was merged (static library).
+ // Use the actual package's resources only.
+ for (const std::string& package : table_merger_->merged_packages()) {
+ packages_to_callback.push_back(package);
+
+ JavaClassGeneratorOptions options = template_options;
+ options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+ if (!WriteJavaFile(&final_table_, package, package, options)) {
+ return false;
+ }
+ }
+
+ // Generate the main public R class.
+ JavaClassGeneratorOptions options = template_options;
+
+ // Only generate public symbols if we have a private package.
+ if (options_.private_symbols) {
+ options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
+ }
+
+ if (options.rewrite_callback_options) {
+ options.rewrite_callback_options.value().packages_to_callback =
+ std::move(packages_to_callback);
+ }
+
+ if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
+ options_.generate_text_symbols_path)) {
+ return false;
+ }
+
+ return true;
+ }
+
bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
if (!options_.generate_java_class_path) {
return true;
@@ -1097,15 +1182,17 @@
bool result;
if (options_.no_static_lib_packages) {
- // Merge all resources as if they were in the compilation package. This is
- // the old behavior of aapt.
+ // Merge all resources as if they were in the compilation package. This is the old behavior
+ // of aapt.
- // Add the package to the set of --extra-packages so we emit an R.java for
- // each library package.
+ // Add the package to the set of --extra-packages so we emit an R.java for each library
+ // package.
if (!pkg->name.empty()) {
options_.extra_java_packages.insert(pkg->name);
}
+ // Clear the package name, so as to make the resources look like they are coming from the
+ // local package.
pkg->name = "";
if (override) {
result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get());
@@ -1673,8 +1760,7 @@
bool error = false;
{
- // AndroidManifest.xml has no resource name, but the CallSite is built
- // from the name
+ // AndroidManifest.xml has no resource name, but the CallSite is built from the name
// (aka, which package the AndroidManifest.xml is coming from).
// So we give it a package name so it can see local resources.
manifest_xml->file.name.package = context_->GetCompilationPackage();
@@ -1727,72 +1813,7 @@
}
if (options_.generate_java_class_path) {
- // The set of packages whose R class to call in the main classes
- // onResourcesLoaded callback.
- std::vector<std::string> packages_to_callback;
-
- JavaClassGeneratorOptions template_options;
- template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
- template_options.javadoc_annotations = options_.javadoc_annotations;
-
- if (context_->GetPackageType() == PackageType::kStaticLib ||
- options_.generate_non_final_ids) {
- template_options.use_final = false;
- }
-
- if (context_->GetPackageType() == PackageType::kSharedLib) {
- template_options.use_final = false;
- template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
- }
-
- const StringPiece actual_package = context_->GetCompilationPackage();
- StringPiece output_package = context_->GetCompilationPackage();
- if (options_.custom_java_package) {
- // Override the output java package to the custom one.
- output_package = options_.custom_java_package.value();
- }
-
- // Generate the private symbols if required.
- if (options_.private_symbols) {
- packages_to_callback.push_back(options_.private_symbols.value());
-
- // If we defined a private symbols package, we only emit Public symbols
- // to the original package, and private and public symbols to the
- // private package.
- JavaClassGeneratorOptions options = template_options;
- options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
- if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
- options)) {
- return 1;
- }
- }
-
- // Generate all the symbols for all extra packages.
- for (const std::string& extra_package : options_.extra_java_packages) {
- packages_to_callback.push_back(extra_package);
-
- JavaClassGeneratorOptions options = template_options;
- options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
- if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
- return 1;
- }
- }
-
- // Generate the main public R class.
- JavaClassGeneratorOptions options = template_options;
-
- // Only generate public symbols if we have a private package.
- if (options_.private_symbols) {
- options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
- }
-
- if (options.rewrite_callback_options) {
- options.rewrite_callback_options.value().packages_to_callback =
- std::move(packages_to_callback);
- }
-
- if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
- options_.generate_text_symbols_path)) {
+ if (!GenerateJavaClasses()) {
return 1;
}
}