diff --git a/README.md b/README.md index 99f98e71..19678f5e 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,14 @@ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/kezong/fat-aar-android/blob/master/LICENSE) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.kezong/fat-aar/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.kezong/fat-aar) -- [中文文档](./README_CN.md) +This fork adds support for AGP 8.0 >**I am no longer engaged in research and development, so the project will not be updated and maintained.
** >**You can try to use the following steps to reference the remote plugin. If it doesn't work on the new version of gradle, you can fork or download this project to modify it, the code of this project is not very complex.** > >**P.S. Hope Google can support this damn feature as soon as possible.** -The solution of merging aar works with [AGP][3] `3.0` and higher. (Tested in AGP 3.0 - 7.1.0, and Gradle 4.9 - 7.3) +The solution of merging aar works with [AGP][3] `3.0` and higher. (Tested in AGP 3.0 - 8.0.0, and Gradle 4.9 - 8.0) ## Getting Started ### Step 1: Add classpath diff --git a/source/build.gradle b/source/build.gradle index 913630b5..a6957adf 100644 --- a/source/build.gradle +++ b/source/build.gradle @@ -18,5 +18,7 @@ dependencies { implementation gradleApi() implementation localGroovy() implementation "org.javassist:javassist:3.27.0-GA" - implementation 'com.android.tools.build:gradle:4.2.0' + implementation 'com.android.tools.build:gradle:7.2.0' + implementation 'com.android.tools:common:30.2.0' + implementation 'org.ow2.asm:asm-commons:9.2' } diff --git a/source/gradle/wrapper/gradle-wrapper.properties b/source/gradle/wrapper/gradle-wrapper.properties index 69a3256f..5b6171c9 100644 --- a/source/gradle/wrapper/gradle-wrapper.properties +++ b/source/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip diff --git a/source/src/main/groovy/com/kezong/fataar/FatAarPlugin.groovy b/source/src/main/groovy/com/kezong/fataar/FatAarPlugin.groovy index 97a49a43..22172f1e 100644 --- a/source/src/main/groovy/com/kezong/fataar/FatAarPlugin.groovy +++ b/source/src/main/groovy/com/kezong/fataar/FatAarPlugin.groovy @@ -7,6 +7,7 @@ import org.gradle.api.ProjectConfigurationException import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.ResolvedDependency +import org.gradle.api.provider.MapProperty /** * plugin entry @@ -27,6 +28,8 @@ class FatAarPlugin implements Plugin { private final Collection embedConfigurations = new ArrayList<>() + private MapProperty> variantPackagesProperty; + @Override void apply(Project project) { this.project = project @@ -42,9 +45,14 @@ class FatAarPlugin implements Plugin { } private registerTransform() { - transform = new RClassesTransform(project) - // register in project.afterEvaluate is invalid. - project.android.registerTransform(transform) + variantPackagesProperty = project.objects.mapProperty(String.class, List.class) + if (FatUtils.compareVersion(VersionAdapter.AGPVersion, "8.0.0") >= 0) { + FatAarPluginHelper.registerAsmTransformation(project, variantPackagesProperty) + } else { + transform = new RClassesTransform(project) + // register in project.afterEvaluate is invalid. + project.android.registerTransform(transform) + } } private void doAfterEvaluate() { @@ -70,7 +78,7 @@ class FatAarPlugin implements Plugin { } if (!artifacts.isEmpty()) { - def processor = new VariantProcessor(project, variant) + def processor = new VariantProcessor(project, variant, variantPackagesProperty) processor.processVariant(artifacts, firstLevelDependencies, transform) } } diff --git a/source/src/main/groovy/com/kezong/fataar/FatUtils.groovy b/source/src/main/groovy/com/kezong/fataar/FatUtils.groovy index fb8dbea6..1b8f756b 100644 --- a/source/src/main/groovy/com/kezong/fataar/FatUtils.groovy +++ b/source/src/main/groovy/com/kezong/fataar/FatUtils.groovy @@ -107,6 +107,13 @@ class FatUtils { } } + /** + * @return true if current AGP version is at least "8.0.0" and false otherwise + */ + static Boolean isAGPVersion8AndAbove(){ + compareVersion(VersionAdapter.AGPVersion, "8.0.0") >= 0 + } + static String formatDataSize(long size) { String result if (size < 1024) { @@ -144,4 +151,4 @@ class FatUtils { output.append("\n${file.getText("UTF-8")}\n") } } -} \ No newline at end of file +} diff --git a/source/src/main/groovy/com/kezong/fataar/FlavorArtifact.groovy b/source/src/main/groovy/com/kezong/fataar/FlavorArtifact.groovy index 50945c79..6cead330 100755 --- a/source/src/main/groovy/com/kezong/fataar/FlavorArtifact.groovy +++ b/source/src/main/groovy/com/kezong/fataar/FlavorArtifact.groovy @@ -58,8 +58,7 @@ class FlavorArtifact { } else { // try included builds ResolvedDependencyResult resolvedResult = configuration.incoming.resolutionResult.allDependencies.find { result -> if (result instanceof ResolvedDependencyResult && result.selected.selectionReason.compositeSubstitution) { - return result.requested.group == unResolvedArtifact.moduleGroup - && result.requested.module == unResolvedArtifact.moduleName + return result.requested.group == unResolvedArtifact.moduleGroup && result.requested.module == unResolvedArtifact.moduleName } return false } diff --git a/source/src/main/groovy/com/kezong/fataar/VariantProcessor.groovy b/source/src/main/groovy/com/kezong/fataar/VariantProcessor.groovy index 7b275f49..626f4304 100755 --- a/source/src/main/groovy/com/kezong/fataar/VariantProcessor.groovy +++ b/source/src/main/groovy/com/kezong/fataar/VariantProcessor.groovy @@ -1,7 +1,6 @@ package com.kezong.fataar import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.api.DefaultAndroidSourceSet import com.android.build.gradle.tasks.ManifestProcessorTask import org.gradle.api.Project import org.gradle.api.Task @@ -9,6 +8,8 @@ import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.ResolvedDependency import org.gradle.api.internal.artifacts.ResolvableDependency import org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.MapProperty import org.gradle.api.tasks.Copy import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskDependency @@ -31,6 +32,8 @@ class VariantProcessor { private Collection mAndroidArchiveLibraries = new ArrayList<>() + private ListProperty mAndroidArchiveLibrariesProperty + private Collection mJarFiles = new ArrayList<>() private Collection mExplodeTasks = new ArrayList<>() @@ -39,14 +42,17 @@ class VariantProcessor { private TaskProvider mMergeClassTask - VariantProcessor(Project project, LibraryVariant variant) { + VariantProcessor(Project project, LibraryVariant variant, MapProperty> variantPackagesProperty) { mProject = project mVariant = variant mVersionAdapter = new VersionAdapter(project, variant) + mAndroidArchiveLibrariesProperty = mProject.objects.listProperty(AndroidArchiveLibrary.class) + variantPackagesProperty.put(mVariant.getName(), mAndroidArchiveLibrariesProperty) } void addAndroidArchiveLibrary(AndroidArchiveLibrary library) { mAndroidArchiveLibraries.add(library) + mAndroidArchiveLibrariesProperty.add(library) } void addJarFile(File jar) { @@ -179,11 +185,11 @@ class VariantProcessor { private void processRClasses(RClassesTransform transform, TaskProvider bundleTask) { TaskProvider reBundleTask = configureReBundleAarTask(bundleTask) - TaskProvider transformTask = mProject.tasks.named("transformClassesWith${transform.name.capitalize()}For${mVariant.name.capitalize()}") - transformTask.configure { - it.dependsOn(mMergeClassTask) - } - if (mProject.fataar.transformR) { + if (mProject.fataar.transformR && !FatUtils.isAGPVersion8AndAbove()) { + TaskProvider transformTask = mProject.tasks.named("transformClassesWith${transform.name.capitalize()}For${mVariant.name.capitalize()}") + transformTask.configure { + it.dependsOn(mMergeClassTask) + } transformRClasses(transform, transformTask, bundleTask, reBundleTask) } else { generateRClasses(bundleTask, reBundleTask) @@ -351,6 +357,9 @@ class VariantProcessor { private TaskProvider handleClassesMergeTask(final boolean isMinifyEnabled) { final TaskProvider task = mProject.tasks.register("mergeClasses" + mVariant.name.capitalize()) { + + outputs.upToDateWhen { false } + dependsOn(mExplodeTasks) dependsOn(mVersionAdapter.getJavaCompileTask()) try { @@ -444,6 +453,12 @@ class VariantProcessor { .withPathSensitivity(PathSensitivity.RELATIVE) inputs.files(mJarFiles).withPathSensitivity(PathSensitivity.RELATIVE) } + // Asm tasks enabled from AGP 8 version + if(FatUtils.isAGPVersion8AndAbove()){ + mProject.tasks.named("transform${mVariant.name.capitalize()}ClassesWithAsm").configure { + dependsOn(mMergeClassTask) + } + } extractAnnotationsTask.configure { mustRunAfter(mMergeClassTask) } diff --git a/source/src/main/java/com/kezong/fataar/FatAarPluginHelper.java b/source/src/main/java/com/kezong/fataar/FatAarPluginHelper.java new file mode 100644 index 00000000..8c3db4e2 --- /dev/null +++ b/source/src/main/java/com/kezong/fataar/FatAarPluginHelper.java @@ -0,0 +1,110 @@ +package com.kezong.fataar; + +import com.android.build.api.instrumentation.AsmClassVisitorFactory; +import com.android.build.api.instrumentation.ClassContext; +import com.android.build.api.instrumentation.ClassData; +import com.android.build.api.instrumentation.InstrumentationParameters; +import com.android.build.api.instrumentation.InstrumentationScope; +import com.android.build.api.variant.AndroidComponentsExtension; +import com.android.build.api.variant.Variant; + +import org.gradle.api.Project; +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.commons.ClassRemapper; +import org.objectweb.asm.commons.Remapper; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import kotlin.Unit; +import kotlin.text.StringsKt; + +import static com.android.build.api.instrumentation.FramesComputationMode.COPY_FRAMES; + +public class FatAarPluginHelper { + + public static void registerAsmTransformation( + Project project, + MapProperty> variantPackagesProperty) { + AndroidComponentsExtension components = + project.getExtensions().getByType(AndroidComponentsExtension.class); + components.onVariants(components.selector().all(), variant -> { + variant.getInstrumentation().transformClassesWith( + RClassAsmTransformerFactory.class, + InstrumentationScope.PROJECT, + params -> { + params.getNamespace().set(variant.getNamespace()); + params.getLibraryNamespaces().set(variantPackagesProperty.getting(variant.getName()) + .map(list -> list.stream().map(it -> it.getPackageName()).collect(Collectors.toList())) + ); + return Unit.INSTANCE; + }); + variant.getInstrumentation().setAsmFramesComputationMode(COPY_FRAMES); + }); + } + + public abstract static class RClassAsmTransformerFactory implements AsmClassVisitorFactory { + + public interface Params extends InstrumentationParameters { + + @Input + Property getNamespace(); + + @Input + @Optional + ListProperty getLibraryNamespaces(); + } + + @Override + public ClassVisitor createClassVisitor(ClassContext classContext, ClassVisitor classVisitor) { + Params params = getParameters().get(); + String namespace = params.getNamespace().get(); + List libraryNamespaces = params.getLibraryNamespaces().orElse(Collections.emptyList()).get(); + + if (libraryNamespaces.isEmpty()) { + return classVisitor; + } + + String targetRClass = namespace.replace(".", "/") + "/R"; + String targetRSubclass = namespace.replace(".", "/") + "/R$"; + + Set libraryRClasses = libraryNamespaces.stream() + .map(it -> it.replace(".", "/") + "/R") + .collect(Collectors.toSet()); + List libraryRSubclasses = libraryNamespaces.stream() + .map(it -> it.replace(".", "/") + "/R$") + .collect(Collectors.toList()); + + Remapper remapper = new Remapper() { + @Override + public String map(String internalName) { + if (internalName == null) { + return null; + } + if (libraryRClasses.contains(internalName)) { + return targetRClass; + } + for (String libraryRSubclass : libraryRSubclasses) { + if (internalName.startsWith(libraryRSubclass)) { + return StringsKt.replaceFirst(internalName, libraryRSubclass, targetRSubclass, false); + } + } + return super.map(internalName); + } + }; + return new ClassRemapper(classVisitor, remapper); + } + + @Override + public boolean isInstrumentable(ClassData classData) { + return true; + } + } +} diff --git a/source/src/main/java/com/kezong/fataar/RClassesTransform.java b/source/src/main/java/com/kezong/fataar/RClassesTransform.java index c21a72d0..d6bfc8ec 100644 --- a/source/src/main/java/com/kezong/fataar/RClassesTransform.java +++ b/source/src/main/java/com/kezong/fataar/RClassesTransform.java @@ -8,8 +8,6 @@ import com.android.build.api.transform.TransformInput; import com.android.build.api.transform.TransformInvocation; import com.android.build.api.transform.TransformOutputProvider; -import com.android.build.gradle.internal.pipeline.TransformManager; -import com.google.common.collect.ImmutableSet; import org.gradle.api.Project; @@ -21,6 +19,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -89,12 +88,16 @@ public String getName() { @Override public Set getInputTypes() { - return TransformManager.CONTENT_CLASS; + HashSet set = new HashSet<>(); + set.add(QualifiedContent.DefaultContentType.CLASSES); + return set; } @Override public Set getScopes() { - return ImmutableSet.of(QualifiedContent.Scope.PROJECT); + HashSet scopes = new HashSet<>(); + scopes.add(QualifiedContent.Scope.PROJECT); + return scopes; } @Override diff --git a/source/upload.gradle b/source/upload.gradle index 03cbfd67..8696836d 100644 --- a/source/upload.gradle +++ b/source/upload.gradle @@ -99,12 +99,12 @@ publishing { // The username and password we've fetched earlier credentials { - username ossrhUsername - password ossrhPassword + //username ossrhUsername + //password ossrhPassword } } } } signing { sign publishing.publications -} \ No newline at end of file +}