Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83f2255f authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Disambiguate merging of resources

Merging local app resources is slightly different than merging
resources from a static library.

Local app resources may not have a package name set, but we do take interest in the
ID set for the package (should be 0x0 or match the ID of the app we're building).

Static library resources have an explicit package name defined for them, so we
only merge resources from that package.

Change-Id: I95e559ae94cc1df6972e77a347b1b37a93674c4d
parent 27afb9e8
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -148,11 +148,15 @@ static bool compileTable(IAaptContext* context, const CompileOptions& options,
        fin.close();
    }

    ResourceTablePackage* pkg = table.createPackage(context->getCompilationPackage());
    // Ensure we have the compilation package at least.
    table.createPackage(context->getCompilationPackage());

    for (auto& pkg : table.packages) {
        if (!pkg->id) {
            // If no package ID was set while parsing (public identifiers), auto assign an ID.
            pkg->id = context->getPackageId();
        }
    }

    // Assign IDs to prepare the table for flattening.
    IdAssigner idAssigner;
+14 −8
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct LinkOptions {
    std::string manifestPath;
    std::vector<std::string> includePaths;
    Maybe<std::string> generateJavaClassPath;
    std::vector<std::string> extraJavaPackages;
    Maybe<std::string> generateProguardRulesPath;
    bool noAutoVersion = false;
    bool staticLib = false;
@@ -695,6 +696,9 @@ struct LinkCommand {
                options.useFinal = false;
            }

            StringPiece16 actualPackage = mContext.getCompilationPackage();
            StringPiece16 outputPackage = mContext.getCompilationPackage();

            if (mOptions.privateSymbols) {
                // 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.
@@ -706,16 +710,16 @@ struct LinkCommand {
                }

                options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
                if (!writeJavaFile(&mergedTable, mContext.getCompilationPackage(),
                                   mOptions.privateSymbols.value(), options)) {
                    return 1;
                outputPackage = mOptions.privateSymbols.value();
            }

            } else {
                // Emit Everything.
            if (!writeJavaFile(&mergedTable, actualPackage, outputPackage, options)) {
                return 1;
            }

                if (!writeJavaFile(&mergedTable, mContext.getCompilationPackage(),
                                   mContext.getCompilationPackage(), options)) {
            for (std::string& extraPackage : mOptions.extraJavaPackages) {
                if (!writeJavaFile(&mergedTable, actualPackage, util::utf8ToUtf16(extraPackage),
                                   options)) {
                    return 1;
                }
            }
@@ -770,6 +774,8 @@ int link(const std::vector<StringPiece>& args) {
                          "private symbols.\n"
                          "If not specified, public and private symbols will use the application's "
                          "package name", &privateSymbolsPackage)
            .optionalFlagList("--extra-packages", "Generate the same R.java but with different "
                              "package names", &options.extraJavaPackages)
            .optionalSwitch("-v", "Enables verbose logging", &options.verbose);

    if (!flags.parse("aapt2 link", args, &std::cerr)) {
+32 −10
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@ TableMerger::TableMerger(IAaptContext* context, ResourceTable* outTable) :
    assert(mMasterPackage && "package name or ID already taken");
}

/**
 * This will merge packages with the same package name (or no package name).
 */
bool TableMerger::merge(const Source& src, ResourceTable* table) {
    const uint8_t desiredPackageId = mContext->getPackageId();

@@ -46,18 +49,37 @@ bool TableMerger::merge(const Source& src, ResourceTable* table) {
            continue;
        }

        bool manglePackage = false;
        if (!package->name.empty() && mContext->getCompilationPackage() != package->name) {
            manglePackage = true;
            mMergedPackages.insert(package->name);
        }

        if (package->name.empty() || mContext->getCompilationPackage() == package->name) {
            // Merge here. Once the entries are merged and mangled, any references to
            // them are still valid. This is because un-mangled references are
            // mangled, then looked up at resolution time.
            // Also, when linking, we convert references with no package name to use
            // the compilation package name.
        if (!doMerge(src, table, package.get(), manglePackage)) {
            if (!doMerge(src, table, package.get(), false)) {
                error = true;
            }
        }
    }
    return !error;
}

/**
 * This will merge and mangle resources from a static library.
 */
bool TableMerger::mergeAndMangle(const Source& src, const StringPiece16& packageName,
                                 ResourceTable* table) {
    bool error = false;
    for (auto& package : table->packages) {
        // Warn of packages with an unrelated ID.
        if (packageName != package->name) {
            mContext->getDiagnostics()->warn(DiagMessage(src)
                                             << "ignoring package " << package->name);
            continue;
        }

        bool mangle = packageName != mContext->getCompilationPackage();
        mMergedPackages.insert(package->name);
        if (!doMerge(src, table, package.get(), mangle)) {
            error = true;
        }
    }
+8 −0
Original line number Diff line number Diff line
@@ -60,8 +60,16 @@ public:
        return mMergedPackages;
    }

    /**
     * Merges resources from the same or empty package. This is for local sources.
     */
    bool merge(const Source& src, ResourceTable* table);

    /**
     * Merges resources from the given package, mangling the name. This is for static libraries.
     */
    bool mergeAndMangle(const Source& src, const StringPiece16& package, ResourceTable* table);

private:
    IAaptContext* mContext;
    ResourceTable* mMasterTable;
+2 −2
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ TEST_F(TableMergerTest, SimpleMerge) {
    TableMerger merger(mContext.get(), &finalTable);

    ASSERT_TRUE(merger.merge({}, tableA.get()));
    ASSERT_TRUE(merger.merge({}, tableB.get()));
    ASSERT_TRUE(merger.mergeAndMangle({}, u"com.app.b", tableB.get()));

    EXPECT_TRUE(merger.getMergedPackages().count(u"com.app.b") != 0);

@@ -90,7 +90,7 @@ TEST_F(TableMergerTest, MergeFileReferences) {
    TableMerger merger(mContext.get(), &finalTable);

    ASSERT_TRUE(merger.merge({}, tableA.get()));
    ASSERT_TRUE(merger.merge({}, tableB.get()));
    ASSERT_TRUE(merger.mergeAndMangle({}, u"com.app.b", tableB.get()));

    FileReference* f = test::getValue<FileReference>(&finalTable, u"@com.app.a:xml/file");
    ASSERT_NE(f, nullptr);