mirror of
https://github.com/fankes/unmeta-gradle-plugin.git
synced 2025-09-04 10:05:15 +08:00
Rename plugin directory to unmeta
Signed-off-by: You Qi <youqi@axzae.com>
This commit is contained in:
68
plugin-build/unmeta/build.gradle.kts
Normal file
68
plugin-build/unmeta/build.gradle.kts
Normal file
@@ -0,0 +1,68 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
signing
|
||||
kotlin("jvm")
|
||||
`java-gradle-plugin`
|
||||
alias(libs.plugins.pluginPublish)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
implementation(gradleApi())
|
||||
implementation(libs.asm)
|
||||
implementation(libs.androidGradlePlugin)
|
||||
|
||||
testImplementation(libs.junit)
|
||||
testImplementation(libs.truth)
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
signing {
|
||||
val signingKey = System.getenv("GPG_SIGNING_KEY")
|
||||
val signingPassword = System.getenv("GPG_SIGNING_PASSWORD")
|
||||
useInMemoryPgpKeys(signingKey.chunked(64).joinToString("\n"), signingPassword)
|
||||
sign(tasks["jar"])
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create(property("ID").toString()) {
|
||||
id = property("ID").toString()
|
||||
implementationClass = property("IMPLEMENTATION_CLASS").toString()
|
||||
version = property("VERSION").toString()
|
||||
description = property("DESCRIPTION").toString()
|
||||
displayName = property("DISPLAY_NAME").toString()
|
||||
tags.set(listOf("kotlin", "metadata"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
website.set(property("WEBSITE").toString())
|
||||
vcsUrl.set(property("VCS_URL").toString())
|
||||
}
|
||||
|
||||
tasks.create("setupPluginUploadFromEnvironment") {
|
||||
doLast {
|
||||
val key = System.getenv("GRADLE_PUBLISH_KEY")
|
||||
val secret = System.getenv("GRADLE_PUBLISH_SECRET")
|
||||
|
||||
if (key == null || secret == null) {
|
||||
throw GradleException("gradlePublishKey and/or gradlePublishSecret are not defined environment variables")
|
||||
}
|
||||
|
||||
System.setProperty("gradle.publish.key", key)
|
||||
System.setProperty("gradle.publish.secret", secret)
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package com.axzae.unmeta
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.Opcodes
|
||||
|
||||
class UnmetaClassVisitor(
|
||||
val path: String,
|
||||
classVisitor: ClassVisitor,
|
||||
) : ClassVisitor(Opcodes.ASM7, classVisitor), Opcodes {
|
||||
|
||||
var isModified = false
|
||||
private set
|
||||
|
||||
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
|
||||
return when (descriptor) {
|
||||
"Lkotlin/coroutines/jvm/internal/DebugMetadata;" -> {
|
||||
isModified = true
|
||||
null
|
||||
}
|
||||
|
||||
else -> super.visitAnnotation(descriptor, visible)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package com.axzae.unmeta
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import javax.inject.Inject
|
||||
|
||||
const val DEFAULT_IS_ENABLED = true
|
||||
const val DEFAULT_VERBOSE = false
|
||||
const val DEFAULT_OUTPUT_FILE = "outputs/logs/unmeta.txt"
|
||||
|
||||
@Suppress("UnnecessaryAbstractClass")
|
||||
abstract class UnmetaExtension @Inject constructor(project: Project) {
|
||||
|
||||
private val objects = project.objects
|
||||
|
||||
val isEnabled: Property<Boolean> = objects.property(Boolean::class.java)
|
||||
.convention(DEFAULT_IS_ENABLED)
|
||||
|
||||
val verbose: Property<Boolean> = objects.property(Boolean::class.java)
|
||||
.convention(DEFAULT_VERBOSE)
|
||||
|
||||
val outputFile: RegularFileProperty = objects.fileProperty()
|
||||
.convention(project.layout.buildDirectory.file(DEFAULT_OUTPUT_FILE))
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package com.axzae.unmeta
|
||||
|
||||
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.configurationcache.extensions.capitalized
|
||||
|
||||
abstract class UnmetaPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
val extension = project.extensions.create("unmeta", UnmetaExtension::class.java, project)
|
||||
val androidComponents = project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java)
|
||||
androidComponents.onVariants(androidComponents.selector().withBuildType("release")) { variant ->
|
||||
val compileKotlinTaskName = "compile${variant.name.capitalized()}Kotlin"
|
||||
val unmetaTask = project.tasks.create("unmeta${variant.name.capitalized()}", UnmetaTask::class.java).apply {
|
||||
isEnabled = extension.isEnabled.get()
|
||||
verbose.set(extension.verbose.get())
|
||||
variantName.set(variant.name)
|
||||
outputFile.set(extension.outputFile)
|
||||
}
|
||||
project.afterEvaluate {
|
||||
project.tasks.findByName(compileKotlinTaskName)?.finalizedBy(unmetaTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
package com.axzae.unmeta
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.plugins.BasePlugin
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.options.Option
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import java.io.File
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
abstract class UnmetaTask : DefaultTask() {
|
||||
|
||||
init {
|
||||
description = "Drop Kotlin @DebugMetadata from java classes"
|
||||
group = BasePlugin.BUILD_GROUP
|
||||
}
|
||||
|
||||
@get:Input
|
||||
@get:Option(option = "variantName", description = "Android variant (flavor + buildType)")
|
||||
abstract val variantName: Property<String>
|
||||
|
||||
@get:Input
|
||||
@get:Option(option = "verbose", description = "Enable verbose logging")
|
||||
abstract val verbose: Property<Boolean>
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outputFile: RegularFileProperty
|
||||
|
||||
private val fileLogger by lazy { outputFile.get().asFile }
|
||||
|
||||
@TaskAction
|
||||
fun unmetaAction() {
|
||||
if (!isEnabled) {
|
||||
log("unmeta is disabled")
|
||||
return
|
||||
}
|
||||
log("Start dropping @DebugMetadata from kotlin classes")
|
||||
val executionMs = measureTimeMillis {
|
||||
val kotlinClassesPath = project.buildDir.absolutePath + "/tmp/kotlin-classes/${variantName.get()}"
|
||||
File(kotlinClassesPath).listFiles()?.forEach { file ->
|
||||
if (file.isDirectory) removeAnnotation(file)
|
||||
}
|
||||
}
|
||||
log("Unmeta Total Time: ${executionMs}ms")
|
||||
}
|
||||
|
||||
private fun log(message: String) {
|
||||
when (verbose.get()) {
|
||||
true -> logger.lifecycle(message)
|
||||
else -> logger.debug(message)
|
||||
}
|
||||
fileLogger.appendText(message + System.lineSeparator(), Charsets.UTF_8)
|
||||
}
|
||||
|
||||
private fun removeAnnotation(directory: File) {
|
||||
directory.walk()
|
||||
.filter { it.path.contains("classes") && it.path.endsWith(".class") && it.isFile }
|
||||
.forEach {
|
||||
val sourceClassBytes = it.readBytes()
|
||||
val classReader = ClassReader(sourceClassBytes)
|
||||
val classWriter = ClassWriter(classReader, ClassWriter.COMPUTE_MAXS)
|
||||
val unmetaClassVisitor = UnmetaClassVisitor(it.absolutePath, classWriter)
|
||||
classReader.accept(unmetaClassVisitor, ClassReader.SKIP_DEBUG)
|
||||
if (unmetaClassVisitor.isModified) {
|
||||
log("Removed @DebugMetadata annotation from ${unmetaClassVisitor.path}")
|
||||
it.writeBytes(classWriter.toByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package com.axzae.unmeta
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
class UnmetaPluginTest {
|
||||
|
||||
@Test
|
||||
@Ignore("require agp dependency")
|
||||
fun `plugin is applied correctly to the project`() {
|
||||
val project = ProjectBuilder.builder().build()
|
||||
project.pluginManager.apply("com.axzae.unmeta")
|
||||
|
||||
assertThat(project.tasks.getByName("unmetaTask")).isInstanceOf(UnmetaTask::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("require agp dependency")
|
||||
fun `extension unmeta is created correctly`() {
|
||||
val project = ProjectBuilder.builder().build()
|
||||
project.pluginManager.apply("com.axzae.unmeta")
|
||||
|
||||
assertThat(project.extensions.getByName("unmeta")).isNotNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("require agp dependency")
|
||||
fun `parameters are passed correctly from extension to task`() {
|
||||
val project = ProjectBuilder.builder().build()
|
||||
project.pluginManager.apply("com.axzae.unmeta")
|
||||
(project.extensions.getByName("unmeta") as UnmetaExtension).apply {
|
||||
isEnabled.set(false)
|
||||
}
|
||||
|
||||
val task = project.tasks.getByName("unmetaTask") as UnmetaTask
|
||||
assertThat(task.isEnabled).isFalse()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user