android-fat-aar icon indicating copy to clipboard operation
android-fat-aar copied to clipboard

Android Studio 2.3 transformNative_libsWithSyncJniLibsForRelease task not found error

Open yuchi79 opened this issue 7 years ago • 6 comments

When I update to Android Studio 2.3, I met some errors. so I modify some codes.

/**
 * This is free and unencumbered software released into the public domain.

 Anyone is free to copy, modify, publish, use, compile, sell, or
 distribute this software, either in source code form or as a compiled
 binary, for any purpose, commercial or non-commercial, and by any
 means.

 In jurisdictions that recognize copyright laws, the author or authors
 of this software dedicate any and all copyright interest in the
 software to the public domain. We make this dedication for the benefit
 of the public at large and to the detriment of our heirs and
 successors. We intend this dedication to be an overt act of
 relinquishment in perpetuity of all present and future rights to this
 software under copyright law.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.

 For more information, please refer to 
 */


import com.android.annotations.NonNull
import com.android.manifmerger.ManifestMerger2
import com.android.manifmerger.ManifestMerger2.Invoker
import com.android.manifmerger.ManifestMerger2.MergeType
import com.android.manifmerger.MergingReport
import com.android.manifmerger.PlaceholderEncoder
import com.android.manifmerger.XmlDocument
import com.android.utils.ILogger
import com.google.common.base.Charsets
import com.google.common.io.Files

/**
 * Fat AAR Lib generator v 0.2.1
 * Target Gradle Version :: 2.2.0
 *
 * Latest version available at https://github.com/adwiv/android-fat-aar
 * Please report issues at https://github.com/adwiv/android-fat-aar/issues
 *
 * This code is in public domain.
 *
 * Use at your own risk and only if you understand what it does. You have been warned ! :-)
 */

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:manifest-merger:25.2.0'
    }
}

configurations {
    embedded
}

dependencies {
    compile configurations.embedded
}

// Paths to embedded jar files
ext.embeddedJars = new ArrayList()
// Paths to embedded aar projects
ext.embeddedAarDirs = new ArrayList()
// List of embedded R classes
ext.embeddedRClasses = new ArrayList()

// Change backslash to forward slash on windows
ext.build_dir = buildDir.path.replace(File.separator, '/');
ext.root_dir = project.rootDir.absolutePath.replace(File.separator, '/');
ext.exploded_aar_dir = "$build_dir/intermediates/exploded-aar";
ext.classs_release_dir = "$build_dir/intermediates/classes/release";
ext.manifest_aaapt_dir = "$build_dir/intermediates/manifests/aapt/release";
ext.generated_rsrc_dir = "$build_dir/generated/source/r/release";

ext.base_r2x_dir = "$build_dir/fat-aar/release/";

def apiVersionString
project.rootProject.buildscript.configurations.classpath.each {
    if (it.name.contains("gradle-api"))
        apiVersionString = it.name
}
apiVersionString = apiVersionString.replace('gradle-api-', '').replace('.jar', '');
ext.gradleApiVersion = apiVersionString.substring(0, apiVersionString.lastIndexOf('.')).toFloat()

if (gradleApiVersion >= 2.3f) {
    ext.taskTransformNativeLib = "transformNativeLibsWithSyncJniLibsForRelease"
    ext.bundle_release_dir = "$build_dir/intermediates/bundles/default";
}
else {
    ext.taskTransformNativeLib = "transformNative_libsWithSyncJniLibsForRelease"
    ext.bundle_release_dir = "$build_dir/intermediates/bundles/release";
}


afterEvaluate {
    // the list of dependency must be reversed to use the right overlay order.
    def dependencies = new ArrayList(configurations.embedded.resolvedConfiguration.firstLevelModuleDependencies)
    dependencies.reverseEach {
        def aarPath;
        if (gradleApiVersion >= 2.3f)
			aarPath = "${root_dir}/${it.moduleName}/build/intermediates/bundles/default"
		else
			aarPath = "${exploded_aar_dir}/${it.moduleGroup}/${it.moduleName}/${it.moduleVersion}"
        it.moduleArtifacts.each {
            artifact ->
                if (artifact.type == 'aar') {
                    if (!embeddedAarDirs.contains(aarPath)) {
                        embeddedAarDirs.add(aarPath)
                    }
                } else if (artifact.type == 'jar') {
                    def artifactPath = artifact.file
                    if (!embeddedJars.contains(artifactPath))
                        embeddedJars.add(artifactPath)
                } else {
                    throw new Exception("Unhandled Artifact of type ${artifact.type}")
                }
        }
    }

    if (dependencies.size() > 0) {
        // Merge Assets
        generateReleaseAssets.dependsOn embedAssets
        embedAssets.dependsOn prepareReleaseDependencies

        // Embed Resources by overwriting the inputResourceSets
        packageReleaseResources.dependsOn embedLibraryResources
        embedLibraryResources.dependsOn prepareReleaseDependencies

        // Embed JNI Libraries
        bundleRelease.dependsOn embedJniLibs
        embedJniLibs.dependsOn "$taskTransformNativeLib"

        // Merge Embedded Manifests
        bundleRelease.dependsOn embedManifests
        embedManifests.dependsOn processReleaseManifest

        // Merge proguard files
        embedLibraryResources.dependsOn embedProguard
        embedProguard.dependsOn prepareReleaseDependencies

        // Generate R.java files
        compileReleaseJavaWithJavac.dependsOn generateRJava
        generateRJava.dependsOn processReleaseResources

        // Bundle the java classes
        bundleRelease.dependsOn embedJavaJars
        embedJavaJars.dependsOn compileReleaseJavaWithJavac

        // If proguard is enabled, run the tasks that bundleRelease should depend on before proguard
        if (tasks.findByPath('proguardRelease') != null) {
            proguardRelease.dependsOn embedJavaJars
        } else if (tasks.findByPath('transformClassesAndResourcesWithProguardForRelease') != null) {
            transformClassesAndResourcesWithProguardForRelease.dependsOn embedJavaJars
        }
    }
}

task embedLibraryResources 
        try {
            def resname
            if (gradleApiVersion >= 2.3f) {
                def parentProject = project.rootProject.name.toString()
                def startIndex = aarPath.indexOf('/' + parentProject)
                def endIndex = aarPath.indexOf('/build')
                if (startIndex 
        // Merge Assets
        android.sourceSets.main.assets.srcDirs += file("$aarPath/assets")
    }
}

/**
 * Merge proguard.txt files from all library modules
 * @author Marian Klühspies
 */
task embedProguard 
        try {
            def proguardLibFile = file("$aarPath/proguard.txt")
            if (proguardLibFile.exists())
                proguardRelease.append(proguardLibFile.text)
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}


task generateRJava 

        def aarManifest = new XmlParser().parse(file("$aarPath/AndroidManifest.xml"));
        def aarPackageName = aarManifest.@package
        String packagePath = aarPackageName.replace('.', '/')

        // Generate the R.java file and map to current project's R.java
        // This will recreate the class file
        def rTxt = file("$aarPath/R.txt")
        def rMap = new ConfigObject()

        if (rTxt.exists()) {
            rTxt.eachLine {
                line ->
                    //noinspection GroovyUnusedAssignment
                    def (type, subclass, name, value) = line.tokenize(' ')
                    rMap[subclass].putAt(name, type)
            }
        }

        def sb = "package $aarPackageName;" 
                sb 
                        sb 
        // Explode all classes.jar files to classes so that they can be proguarded
        def jar_dir
        if (gradleApiVersion >= 2.3f)
            jar_dir = "$aarPath"
        else
            jar_dir = "$aarPath/jars"
        copy {
            from zipTree(jar_dir + "/classes.jar")
            into classs_release_dir
        }

        // Copy all additional jar files to bundle lib
        FileTree jars = fileTree(dir: jar_dir, include: '*.jar', exclude: 'classes.jar')
        jars += fileTree(dir: jar_dir + "/libs", include: '*.jar')
        jars += fileTree(dir: "$aarPath/libs", include: '*.jar')

        copy {
            from jars
            into file("$bundle_release_dir/libs")
        }

        // Copy all embedded jar files to bundle lib
        copy {
            from embeddedJars
            into file("$bundle_release_dir/libs")
        }
    }
}

/**
 * For some reason, adding to the jniLibs source set does not work. So we simply copy all files.
 */
task embedJniLibs 
        println "======= Copying JNI from $aarPath/jni"
        // Copy JNI Folders
        copy {
            from fileTree(dir: "$aarPath/jni")
            into file("$bundle_release_dir/jni")
        }
    }
}

task embedManifests  libraryManifests = new ArrayList()

    embeddedAarDirs.each { aarPath ->
        if (!libraryManifests.contains(aarPath)) {
            libraryManifests.add(file("$aarPath/AndroidManifest.xml"))
        }
    }

    File reportFile = file("${build_dir}/embedManifestReport.txt")

    File origManifest = file("$bundle_release_dir/AndroidManifest.xml")
    File copyManifest = file("$bundle_release_dir/AndroidManifest.orig.xml")
    File aaptManifest = file("$manifest_aaapt_dir/AndroidManifest.xml")

    copy {
        from origManifest.parentFile
        into copyManifest.parentFile
        include origManifest.name
        rename(origManifest.name, copyManifest.name)
    }

    try {
        Invoker manifestMergerInvoker = ManifestMerger2.newMerger(copyManifest, mLogger, MergeType.APPLICATION)

        manifestMergerInvoker.addLibraryManifests(libraryManifests.toArray(new File[libraryManifests.size()]))

        // manifestMergerInvoker.setPlaceHolderValues(placeHolders)
        manifestMergerInvoker.setMergeReportFile(reportFile);

        MergingReport mergingReport = manifestMergerInvoker.merge();

        mLogger.info("Merging result:" + mergingReport.getResult());
        MergingReport.Result result = mergingReport.getResult();
        switch (result) {
            case MergingReport.Result.WARNING:
                mergingReport.log(mLogger);
        // fall through since these are just warnings.
            case MergingReport.Result.SUCCESS:
                XmlDocument xmlDocument = mergingReport.getMergedXmlDocument(MergingReport.MergedManifestKind.MERGED);
                try {
                    String annotatedDocument = mergingReport.getActions().blame(xmlDocument);
                    mLogger.verbose(annotatedDocument);
                } catch (Exception e) {
                    mLogger.error(e, "cannot print resulting xml");
                }
                save(xmlDocument, origManifest);
                mLogger.info("Merged manifest saved to " + origManifest);
                if (aaptManifest.exists()) {
                    new PlaceholderEncoder().visit(xmlDocument);
                    save(xmlDocument, aaptManifest);
                    mLogger.info("Merged aapt safe manifest saved to " + aaptManifest);
                }
                break;
            case MergingReport.Result.ERROR:
                mergingReport.log(mLogger);
                throw new RuntimeException(mergingReport.getReportString());
            default:
                throw new RuntimeException("Unhandled result type : " + mergingReport.getResult());
        }
    } catch (RuntimeException e) {
        // Unacceptable error
        e.printStackTrace()
        throw new RuntimeException(e);
    }
}

private void save(XmlDocument xmlDocument, File out) {
    try {
        Files.write(xmlDocument.prettyPrint(), out, Charsets.UTF_8);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

class MiLogger implements ILogger {

    @Override
    void error(
            @com.android.annotations.Nullable Throwable t,
            @com.android.annotations.Nullable String msgFormat, Object... args) {
        System.err.println(String.format("========== ERROR : " + msgFormat, args))
        if (t) t.printStackTrace(System.err)
    }

    @Override
    void warning(@NonNull String msgFormat, Object... args) {
        System.err.println(String.format("========== WARNING : " + msgFormat, args))
    }

    @Override
    void info(@NonNull String msgFormat, Object... args) {
        System.out.println(String.format("========== INFO : " + msgFormat, args))
    }

    @Override
    void verbose(@NonNull String msgFormat, Object... args) {
        // System.out.println(String.format("========== DEBUG : " + msgFormat, args))
    }
}

yuchi79 avatar Mar 30 '17 06:03 yuchi79

awsome

kingrukawa avatar Mar 30 '17 11:03 kingrukawa

Me too

lifeng1992 avatar Apr 07 '17 05:04 lifeng1992

But when I merge R,it's not work,see my issue 65,hope help

kingrukawa avatar Apr 07 '17 05:04 kingrukawa

Same issue since Gradle Maj. But this fix doesn't work.

It doesn't find the module manifest

nicolasd avatar Apr 07 '17 15:04 nicolasd

Replace it with 'transformNativeLibsWithSyncJniLibsForRelease' will fix the issue

hwdavr avatar Apr 22 '17 12:04 hwdavr

@kingrukawa I've got the same problem with R merge, see the PR #77. Maybe can help you :smile:

mfdeveloper avatar Jul 28 '17 17:07 mfdeveloper