com.flyjingfish.android_aop_plugin.plugin.CompilePlugin.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android-aop-plugin Show documentation
Show all versions of android-aop-plugin Show documentation
Lightweight Aop for Android platform, you deserve it, action is worse than your heartbeat
package com.flyjingfish.android_aop_plugin.plugin
import com.android.build.gradle.AppExtension
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.DynamicFeaturePlugin
import com.android.build.gradle.LibraryExtension
import com.flyjingfish.android_aop_plugin.config.AndroidAopConfig
import com.flyjingfish.android_aop_plugin.scanner_visitor.WovenIntoCode
import com.flyjingfish.android_aop_plugin.tasks.CompileAndroidAopTask
import com.flyjingfish.android_aop_plugin.tasks.SyncConfigTask
import com.flyjingfish.android_aop_plugin.utils.AndroidConfig
import com.flyjingfish.android_aop_plugin.utils.ClassFileUtils
import com.flyjingfish.android_aop_plugin.utils.InitConfig
import com.flyjingfish.android_aop_plugin.utils.Utils
import com.flyjingfish.android_aop_plugin.utils.adapterOSPath
import org.codehaus.groovy.runtime.DefaultGroovyMethods
import org.gradle.api.Project
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.configurationcache.extensions.capitalized
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTool
import java.io.File
class CompilePlugin(private val root:Boolean): BasePlugin() {
companion object{
private const val ANDROID_EXTENSION_NAME = "android"
}
override fun apply(project: Project) {
super.apply(project)
val isApp = project.plugins.hasPlugin(AppPlugin::class.java)
val logger = project.logger
val isDynamicLibrary = project.plugins.hasPlugin(DynamicFeaturePlugin::class.java)
val androidObject: Any = project.extensions.findByName(ANDROID_EXTENSION_NAME) ?: return
val android = androidObject as BaseExtension
val variants = if (isApp or isDynamicLibrary) {
(android as AppExtension).applicationVariants
} else {
(android as LibraryExtension).libraryVariants
}
val hasConfig = project.extensions.findByName("androidAopConfig") != null
val syncConfig = !root && hasConfig && isApp
if (syncConfig){
val taskName = "${project.name}AndroidAopConfigSyncTask"
project.tasks.register(taskName, SyncConfigTask::class.java)
project.afterEvaluate {
project.tasks.findByName("preBuild")?.finalizedBy(taskName)
}
}
val kotlinCompileFilePathMap = mutableMapOf()
variants.all { variant ->
if (syncConfig){
AndroidAopConfig.syncConfig(project)
}
try {
project.tasks.withType(KotlinCompile::class.java).configureEach { task ->
kotlinCompileFilePathMap[task.name] = task
}
} catch (_: Exception) {
}
val javaCompile: AbstractCompile =
if (DefaultGroovyMethods.hasProperty(variant, "javaCompileProvider") != null) {
//gradle 4.10.1 +
variant.javaCompileProvider.get()
} else if (DefaultGroovyMethods.hasProperty(variant, "javaCompiler") != null) {
variant.javaCompiler as AbstractCompile
} else {
variant.javaCompile as AbstractCompile
}
val variantName = variant.name
val buildTypeName = variant.buildType.name
if (!isIncremental() && javaCompile is JavaCompile && isDebugMode(buildTypeName,variantName)){
javaCompile.options.isIncremental = false
}
// println("CompilePlugin=variant=$variantName,output.name=${variant.buildType.name},isDebug=${isDebugMode(buildTypeName,variantName)}")
if (isApp && isIncremental()){
javaCompile.doFirst{
val enabled = try {
val firstConfig = project.extensions.getByType(AndroidAopConfig::class.java)
firstConfig.enabled
} catch (e: Exception) {
true
}
if (enabled && isDebugMode(buildTypeName,variantName)){
WovenIntoCode.deleteOtherCompileClass(project, variantName)
}
}
}
javaCompile.doLast{
val androidAopConfig : AndroidAopConfig = if (isApp){
val config = project.extensions.getByType(AndroidAopConfig::class.java)
config.initConfig()
config
}else{
var config = InitConfig.optFromJsonString(
InitConfig.readAsString(Utils.configJsonFile(project)),
AndroidAopConfig::class.java)
if (config == null){
config = AndroidAopConfig()
}
config
}
if (androidAopConfig.cutInfoJson){
InitConfig.initCutInfo(project,false)
}
if (androidAopConfig.enabled && isDebugMode(buildTypeName,variantName)){
ClassFileUtils.debugMode = true
val hint = "AndroidAOP提示:打正式包时请注意通过设置 androidAop.debugMode 或 androidAop.debugMode.variantOnlyDebug 关闭debug模式"
if (buildTypeName == "release"){
logger.error(hint)
}else{
logger.warn(hint)
}
val localInput = mutableListOf()
val javaPath = File(javaCompile.destinationDirectory.asFile.orNull.toString())
if (javaPath.exists()){
localInput.add(javaPath)
}
val task = kotlinCompileFilePathMap["compile${variantName.capitalized()}Kotlin"]
val cacheDir = try {
task?.destinationDirectory?.get()?.asFile
} catch (e: Exception) {
null
}
val kotlinPath = cacheDir ?: File(project.buildDir.path + "/tmp/kotlin-classes/".adapterOSPath() + variantName)
if (kotlinPath.exists()){
localInput.add(kotlinPath)
}
val jarInput = mutableListOf()
val androidConfig = AndroidConfig(project)
val list: List = androidConfig.getBootClasspath()
val bootJarPath = mutableSetOf()
for (file in list) {
bootJarPath.add(file.absolutePath)
}
for (file in localInput) {
bootJarPath.add(file.absolutePath)
}
for (file in javaCompile.classpath) {
if (file.absolutePath !in bootJarPath && file.exists()){
if (file.isDirectory){
localInput.add(file)
}else{
jarInput.add(file)
}
}
}
if (localInput.isNotEmpty()){
ClassFileUtils.reflectInvokeMethod = isReflectInvokeMethod(buildTypeName,variantName)
val output = File(javaCompile.destinationDirectory.asFile.orNull.toString())
val task = CompileAndroidAopTask(jarInput,localInput,output,project,isApp,
File(Utils.aopCompileTempDir(project,variantName)),
File(Utils.invokeJsonFile(project,variantName)),
variantName
)
task.taskAction()
}
}
}
}
}
}