Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support AGP 8.0+ #411

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br>**
>**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
Expand Down
2 changes: 2 additions & 0 deletions jitpack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
before_install:
- cd ./source
4 changes: 3 additions & 1 deletion source/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
2 changes: 1 addition & 1 deletion source/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 12 additions & 4 deletions source/src/main/groovy/com/kezong/fataar/FatAarPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -27,6 +28,8 @@ class FatAarPlugin implements Plugin<Project> {

private final Collection<Configuration> embedConfigurations = new ArrayList<>()

private MapProperty<String, List<AndroidArchiveLibrary>> variantPackagesProperty;

@Override
void apply(Project project) {
this.project = project
Expand All @@ -42,9 +45,14 @@ class FatAarPlugin implements Plugin<Project> {
}

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() {
Expand All @@ -70,7 +78,7 @@ class FatAarPlugin implements Plugin<Project> {
}

if (!artifacts.isEmpty()) {
def processor = new VariantProcessor(project, variant)
def processor = new VariantProcessor(project, variant, variantPackagesProperty)
processor.processVariant(artifacts, firstLevelDependencies, transform)
}
}
Expand Down
29 changes: 21 additions & 8 deletions source/src/main/groovy/com/kezong/fataar/VariantProcessor.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,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
Expand All @@ -18,6 +20,7 @@ import org.gradle.api.tasks.bundling.Zip
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.stream.Collectors

/**
* Core
Expand All @@ -31,6 +34,8 @@ class VariantProcessor {

private Collection<AndroidArchiveLibrary> mAndroidArchiveLibraries = new ArrayList<>()

private ListProperty<AndroidArchiveLibrary> mAndroidArchiveLibrariesProperty

private Collection<File> mJarFiles = new ArrayList<>()

private Collection<Task> mExplodeTasks = new ArrayList<>()
Expand All @@ -39,14 +44,17 @@ class VariantProcessor {

private TaskProvider mMergeClassTask

VariantProcessor(Project project, LibraryVariant variant) {
VariantProcessor(Project project, LibraryVariant variant, MapProperty<String, List<AndroidArchiveLibrary>> 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) {
Expand Down Expand Up @@ -178,6 +186,7 @@ class VariantProcessor {
}

private void processRClasses(RClassesTransform transform, TaskProvider<Task> bundleTask) {
if (FatUtils.compareVersion(VersionAdapter.AGPVersion, "8.0.0") >= 0) return
TaskProvider reBundleTask = configureReBundleAarTask(bundleTask)
TaskProvider transformTask = mProject.tasks.named("transformClassesWith${transform.name.capitalize()}For${mVariant.name.capitalize()}")
transformTask.configure {
Expand Down Expand Up @@ -351,6 +360,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 {
Expand Down Expand Up @@ -444,6 +456,9 @@ class VariantProcessor {
.withPathSensitivity(PathSensitivity.RELATIVE)
inputs.files(mJarFiles).withPathSensitivity(PathSensitivity.RELATIVE)
}
mProject.tasks.named("transform${mVariant.name.capitalize()}ClassesWithAsm").configure {
dependsOn(mMergeClassTask)
}
extractAnnotationsTask.configure {
mustRunAfter(mMergeClassTask)
}
Expand Down Expand Up @@ -472,13 +487,11 @@ class VariantProcessor {
resourceGenTask.configure {
dependsOn(mExplodeTasks)

mProject.android.sourceSets.each { DefaultAndroidSourceSet sourceSet ->
if (sourceSet.name == mVariant.name) {
for (archiveLibrary in mAndroidArchiveLibraries) {
FatUtils.logInfo("Merge resource,Library res:${archiveLibrary.resFolder}")
sourceSet.res.srcDir(archiveLibrary.resFolder)
}
}
for (archiveLibrary in mAndroidArchiveLibraries) {
FatUtils.logInfo("Merge resource,Library res:${archiveLibrary.resFolder}")
mVariant.registerGeneratedResFolders(
mProject.files(archiveLibrary.resFolder)
)
}
}
}
Expand Down
110 changes: 110 additions & 0 deletions source/src/main/java/com/kezong/fataar/FatAarPluginHelper.java
Original file line number Diff line number Diff line change
@@ -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<String, List<AndroidArchiveLibrary>> variantPackagesProperty) {
AndroidComponentsExtension<?, ?, Variant> 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<RClassAsmTransformerFactory.Params> {

public interface Params extends InstrumentationParameters {

@Input
Property<String> getNamespace();

@Input
@Optional
ListProperty<String> getLibraryNamespaces();
}

@Override
public ClassVisitor createClassVisitor(ClassContext classContext, ClassVisitor classVisitor) {
Params params = getParameters().get();
String namespace = params.getNamespace().get();
List<String> libraryNamespaces = params.getLibraryNamespaces().orElse(Collections.emptyList()).get();

if (libraryNamespaces.isEmpty()) {
return classVisitor;
}

String targetRClass = namespace.replace(".", "/") + "/R";
String targetRSubclass = namespace.replace(".", "/") + "/R$";

Set<String> libraryRClasses = libraryNamespaces.stream()
.map(it -> it.replace(".", "/") + "/R")
.collect(Collectors.toSet());
List<String> 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;
}
}
}
11 changes: 7 additions & 4 deletions source/src/main/java/com/kezong/fataar/RClassesTransform.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -89,12 +88,16 @@ public String getName() {

@Override
public Set<QualifiedContent.ContentType> getInputTypes() {
return TransformManager.CONTENT_CLASS;
HashSet<QualifiedContent.ContentType> set = new HashSet<>();
set.add(QualifiedContent.DefaultContentType.CLASSES);
return set;
}

@Override
public Set<? super QualifiedContent.Scope> getScopes() {
return ImmutableSet.of(QualifiedContent.Scope.PROJECT);
HashSet<QualifiedContent.Scope> scopes = new HashSet<>();
scopes.add(QualifiedContent.Scope.PROJECT);
return scopes;
}

@Override
Expand Down
30 changes: 15 additions & 15 deletions source/upload.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,27 +84,27 @@ publishing {
}
}
}
repositories {
// repositories {
// The repository to publish to, Sonatype/MavenCentral
maven {
// maven {
// This is an arbitrary name, you may also use "mavencentral" or
// any other name that's descriptive for you
name = "fat-aar"
// name = "fat-aar"

def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
// def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
// def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
// You only need this if you want to publish snapshots, otherwise just set the URL
// to the release repo directly
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
// url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl

// The username and password we've fetched earlier
credentials {
username ossrhUsername
password ossrhPassword
}
}
}
// credentials {
// username ossrhUsername
// password ossrhPassword
// }
// }
// }
}
signing {
sign publishing.publications
}
//signing {
// sign publishing.publications
//}