AAPT2: Support static lib referencing static lib
When a static library A references static library B,
and app C references both A and B, we get the following symbol merging,
symbols from library B get imported twice.
We must only check that symbol references to library B are valid
when building library A. We should only merge all the symbols
when building final app C.
Change-Id: I23cba33b0901dcbb5328d9c9dfaa6a979c073c36
diff --git a/tools/aapt2/XmlFlattener.cpp b/tools/aapt2/XmlFlattener.cpp
index 650e624..97e4f68 100644
--- a/tools/aapt2/XmlFlattener.cpp
+++ b/tools/aapt2/XmlFlattener.cpp
@@ -300,6 +300,7 @@
elem->attributeCount = sortedAttributes.size();
// Flatten the sorted attributes.
+ uint16_t attributeIndex = 1;
for (auto entry : sortedAttributes) {
android::ResXMLTree_attribute* attr =
out.nextBlock<android::ResXMLTree_attribute>();
@@ -310,44 +311,64 @@
attr->ns.index = -1;
}
- stringRefs.emplace_back(entry.nameRef, &attr->name);
- attr->rawValue.index = -1;
-
StringPool::Ref rawValueRef = pool.makeRef(entry.xmlAttr->value, lowPriority);
- if (entry.attr) {
- std::unique_ptr<Item> value = ResourceParser::parseItemForAttribute(
- entry.xmlAttr->value, *entry.attr);
- if (value) {
- AttributeValueFlattener flattener(
- mResolver,
- &logger,
- &attr->typedValue,
- parser,
- &error,
- rawValueRef,
- &options.defaultPackage,
- &stringRefs);
- value->accept(flattener, {});
- } else if (!(entry.attr->typeMask & android::ResTable_map::TYPE_STRING)) {
- logger.error(parser->getLineNumber())
- << "'"
- << *rawValueRef
- << "' is not compatible with attribute "
- << *entry.attr
- << "."
- << std::endl;
- error = true;
- } else {
- attr->typedValue.dataType = android::Res_value::TYPE_STRING;
- stringRefs.emplace_back(rawValueRef, &attr->rawValue);
- stringRefs.emplace_back(rawValueRef,
- reinterpret_cast<android::ResStringPool_ref*>(
- &attr->typedValue.data));
+ stringRefs.emplace_back(entry.nameRef, &attr->name);
+
+ if (options.keepRawValues) {
+ stringRefs.emplace_back(rawValueRef, &attr->rawValue);
+ } else {
+ attr->rawValue.index = -1;
+ }
+
+ // Assign the indices for specific attributes.
+ if (entry.xmlAttr->namespaceUri == kSchemaAndroid &&
+ entry.xmlAttr->name == u"id") {
+ elem->idIndex = attributeIndex;
+ } else if (entry.xmlAttr->namespaceUri.empty()) {
+ if (entry.xmlAttr->name == u"class") {
+ elem->classIndex = attributeIndex;
+ } else if (entry.xmlAttr->name == u"style") {
+ elem->styleIndex = attributeIndex;
}
+ }
+
+ std::unique_ptr<Item> value;
+ if (entry.attr) {
+ value = ResourceParser::parseItemForAttribute(entry.xmlAttr->value,
+ *entry.attr);
+ } else {
+ bool create = false;
+ value = ResourceParser::tryParseReference(entry.xmlAttr->value, &create);
+ }
+
+ if (mResolver && value) {
+ AttributeValueFlattener flattener(
+ mResolver,
+ &logger,
+ &attr->typedValue,
+ parser,
+ &error,
+ rawValueRef,
+ &options.defaultPackage,
+ &stringRefs);
+ value->accept(flattener, {});
+ } else if (!value && entry.attr &&
+ !(entry.attr->typeMask & android::ResTable_map::TYPE_STRING)) {
+ logger.error(parser->getLineNumber())
+ << "'"
+ << *rawValueRef
+ << "' is not compatible with attribute "
+ << *entry.attr
+ << "."
+ << std::endl;
+ error = true;
} else {
attr->typedValue.dataType = android::Res_value::TYPE_STRING;
- stringRefs.emplace_back(rawValueRef, &attr->rawValue);
+ if (!options.keepRawValues) {
+ // Don't set the string twice.
+ stringRefs.emplace_back(rawValueRef, &attr->rawValue);
+ }
stringRefs.emplace_back(rawValueRef,
reinterpret_cast<android::ResStringPool_ref*>(
&attr->typedValue.data));
@@ -440,6 +461,9 @@
header->header.type = android::RES_XML_TYPE;
header->header.headerSize = sizeof(*header);
+ // Flatten the StringPool.
+ StringPool::flattenUtf16(outBuffer, pool);
+
// Write the array of resource IDs, indexed by StringPool order.
const size_t beforeResIdMapIndex = outBuffer->size();
android::ResChunk_header* resIdMapChunk = outBuffer->nextBlock<android::ResChunk_header>();
@@ -458,10 +482,7 @@
}
resIdMapChunk->size = outBuffer->size() - beforeResIdMapIndex;
- // Flatten the StringPool.
- StringPool::flattenUtf16(outBuffer, pool);
-
- // Move the temporary BigBuffer into outBuffer->
+ // Move the temporary BigBuffer into outBuffer.
outBuffer->appendBuffer(std::move(out));
header->header.size = outBuffer->size() - beforeXmlTreeIndex;