Skip to content

Commit da0757e

Browse files
committed
feat:可基于不同 variant 对 bcu 进行配置
1 parent 591e86e commit da0757e

File tree

8 files changed

+114
-79
lines changed

8 files changed

+114
-79
lines changed

app/build.gradle.kts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ plugins {
99
id("bcu-plugin")
1010
}
1111

12-
bytecodeUtil {
13-
loggerLevel = 2
14-
modifiers = arrayOf(
15-
// 将 CustomModifier 添加到 bcu 中
16-
CustomModifier::class.java,
17-
)
18-
notNeed = { entryName ->
12+
bcu {
13+
config { variant ->
14+
loggerLevel = 2
15+
modifiers = arrayOf(
16+
// 将 CustomModifier 添加到 bcu 中
17+
CustomModifier::class.java,
18+
)
19+
}
20+
filterNot { variant, entryName ->
1921
// false
2022
entryName.startsWith("kotlin/")
2123
|| entryName.startsWith("kotlinx/")
@@ -100,17 +102,17 @@ class CustomModifier(
100102
) : IModifier {
101103

102104
private val logger = YLogger.getLogger(javaClass)
103-
override fun initialize(project: Project) {
104-
super.initialize(project)
105+
override fun initialize(project: Project, variant: com.android.build.api.variant.Variant) {
106+
super.initialize(project, variant)
105107
// 初始化阶段,可以通过 project 拿到所需的配置参数
106-
logger.lifecycle("step1:initialize")
108+
logger.lifecycle("step1:initialize. variant=${variant.name}")
107109
// 演示获取自定义参数
108110
logger.lifecycle(project.properties["modifier.custom"].toString())
109111
}
110112

111113
override fun scan(classNode: ClassNode) {
112114
// 扫描阶段,该阶段可以获取到所有过滤后需要处理的 class
113-
logger.lifecycle("step2:scan -->$classNode")
115+
logger.lifecycle("step2:scan --> ${classNode.name}")
114116
// 你可以在这里过收集需要处理的 class
115117
// 注意:该方法非多线程安全,内部处理记得按需加锁
116118
}

lib_bcu_plugin/plugin-api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ dependencies {
2222
api(localGroovy())
2323
api("org.ow2.asm:asm:9.2")
2424
api("org.ow2.asm:asm-tree:9.2")
25+
compileOnly("com.android.tools.build:gradle-api:$ANDROID_GRADLE_VERSION")
2526
}
2627

2728
mavenPublish()

lib_bcu_plugin/plugin-api/src/main/java/com/ysj/lib/bytecodeutil/plugin/api/IModifier.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ysj.lib.bytecodeutil.plugin.api
22

3+
import com.android.build.api.variant.Variant
34
import org.gradle.api.Project
45
import org.objectweb.asm.tree.ClassNode
56
import java.util.concurrent.Executor
@@ -27,7 +28,7 @@ interface IModifier {
2728
/**
2829
* 初始化
2930
*/
30-
fun initialize(project: Project) = Unit
31+
fun initialize(project: Project, variant: Variant) = Unit
3132

3233
/**
3334
* 每扫到一个需要修改的类就会回调一次。

lib_bcu_plugin/src/main/java/com/ysj/lib/bytecodeutil/plugin/BytecodeUtilExtensions.kt

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.ysj.lib.bytecodeutil.plugin
2+
3+
import com.android.build.api.variant.Variant
4+
import com.ysj.lib.bytecodeutil.plugin.api.logger.YLogger
5+
6+
/*
7+
* bcu 相关的扩展
8+
*
9+
* @author Ysj
10+
* Create time: 2021/8/23
11+
*/
12+
13+
const val EXTENSION_NAME = "bcu"
14+
15+
interface BCUExtension {
16+
/**
17+
* 针对每个 [variant] 生成 [Config]。
18+
*/
19+
fun config(callback: Config.(Variant) -> Unit)
20+
21+
/**
22+
* 用于确定哪些 Class 不用处理,返回 true 表示不需要处理。
23+
*/
24+
fun filterNot(callback: (Variant, String) -> Boolean)
25+
}
26+
27+
class Config {
28+
29+
/**
30+
* 设置日志等级 [YLogger](verbose:0 ~ error:5)
31+
*/
32+
var loggerLevel: Int = 0
33+
34+
/**
35+
* 附加的修改器。
36+
*/
37+
var modifiers: Array<Class<*>>? = null
38+
39+
}
40+
41+
internal open class BCUExtensionImpl : BCUExtension {
42+
43+
lateinit var config: Config.(Variant) -> Unit
44+
lateinit var filterNot: (Variant, String) -> Boolean
45+
46+
override fun config(callback: Config.(Variant) -> Unit) {
47+
config = callback
48+
}
49+
50+
override fun filterNot(callback: (Variant, String) -> Boolean) {
51+
filterNot = callback
52+
}
53+
54+
}

lib_bcu_plugin/src/main/java/com/ysj/lib/bytecodeutil/plugin/Main.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@ class Main : Plugin<Project> {
1616

1717
override fun apply(project: Project) {
1818
val bucRootDir = File(project.buildDir, "bcu")
19-
project.extensions.create(BytecodeUtilExtensions.NAME, BytecodeUtilExtensions::class.java)
19+
project.extensions.create(
20+
BCUExtension::class.java,
21+
EXTENSION_NAME,
22+
BCUExtensionImpl::class.java,
23+
)
2024
project.extensions.configure(AndroidComponentsExtension::class.java) { appExt ->
2125
appExt.onVariants { variant ->
2226
project
2327
.extensions
24-
.findByType(BytecodeUtilExtensions::class.java)
28+
.findByType(BCUExtension::class.java)
2529
?: return@onVariants
2630
val transformTask = project.tasks.register(
2731
"${variant.name}BCUTransformTask",
@@ -33,6 +37,7 @@ class Main : Plugin<Project> {
3337
notNeedDir.mkdirs()
3438
}
3539
it.notNeedOutput.set(notNeedDir)
40+
it.variant.set(variant)
3641
}
3742
variant.artifacts
3843
.forScope(ScopedArtifacts.Scope.ALL)

lib_bcu_plugin/src/main/java/com/ysj/lib/bytecodeutil/plugin/ModifierManager.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ysj.lib.bytecodeutil.plugin
22

3+
import com.android.build.api.variant.Variant
34
import com.ysj.lib.bytecodeutil.plugin.api.IModifier
45
import com.ysj.lib.bytecodeutil.plugin.api.logger.YLogger
56
import org.gradle.api.Project
@@ -20,13 +21,13 @@ class ModifierManager(override val executor: Executor) : IModifier {
2021

2122
private val logger = YLogger.getLogger(javaClass)
2223

23-
override fun initialize(project: Project) {
24-
super.initialize(project)
24+
override fun initialize(project: Project, variant: Variant) {
25+
super.initialize(project, variant)
2526
var startTime: Long
2627
for (index in modifiers.indices) {
2728
startTime = System.currentTimeMillis()
2829
val modifier = modifiers[index]
29-
modifier.initialize(project)
30+
modifier.initialize(project, variant)
3031
val time = System.currentTimeMillis() - startTime
3132
logger.lifecycle(">>> ${modifier.javaClass.simpleName} initialize time:$time ms")
3233
}

lib_bcu_plugin/src/main/java/com/ysj/lib/bytecodeutil/plugin/TransformTask.kt

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ysj.lib.bytecodeutil.plugin
22

3+
import com.android.build.api.variant.Variant
34
import com.ysj.lib.bytecodeutil.plugin.api.IModifier
45
import com.ysj.lib.bytecodeutil.plugin.api.logger.YLogger
56
import org.gradle.api.DefaultTask
@@ -8,7 +9,9 @@ import org.gradle.api.file.DirectoryProperty
89
import org.gradle.api.file.RegularFile
910
import org.gradle.api.file.RegularFileProperty
1011
import org.gradle.api.provider.ListProperty
12+
import org.gradle.api.provider.Property
1113
import org.gradle.api.tasks.InputFiles
14+
import org.gradle.api.tasks.Internal
1215
import org.gradle.api.tasks.OutputDirectory
1316
import org.gradle.api.tasks.OutputFile
1417
import org.gradle.api.tasks.TaskAction
@@ -50,19 +53,29 @@ abstract class TransformTask : DefaultTask() {
5053
@get:OutputDirectory
5154
abstract val notNeedOutput: DirectoryProperty
5255

56+
@get:Internal
57+
abstract val variant: Property<Variant>
58+
5359
private val logger = YLogger.getLogger(javaClass)
5460

5561
@TaskAction
5662
fun taskAction() {
57-
val bcuExtra = project.extensions.getByType(BytecodeUtilExtensions::class.java)
58-
YLogger.LOGGER_LEVEL = bcuExtra.loggerLevel
59-
val modifiers = bcuExtra.modifiers
63+
val variant = variant.get()
64+
val bcuExtra = project
65+
.extensions
66+
.getByType(BCUExtension::class.java)
67+
as BCUExtensionImpl
68+
val config = Config()
69+
bcuExtra.config(config, variant)
70+
YLogger.LOGGER_LEVEL = config.loggerLevel
71+
val modifiers = config.modifiers
6072
if (modifiers == null) {
6173
logger.quiet("bcu not found modifier")
6274
return
6375
}
6476
logger.quiet("=================== transform start ===================")
6577
logger.quiet(">>> gradle version: ${project.gradle.gradleVersion}")
78+
logger.quiet(">>> variant: ${variant.name}")
6679
logger.quiet(">>> loggerLevel: ${YLogger.LOGGER_LEVEL}")
6780
// 添加所有 modifier
6881
val useTime = measureTimeMillis {
@@ -82,8 +95,8 @@ abstract class TransformTask : DefaultTask() {
8295
modifierManager.addModifier(clazz as Class<out IModifier>)
8396
logger.quiet(">>> apply modifier: ${clazz.name}")
8497
}
85-
modifierManager.initialize(project)
86-
transform(Transform(bcuExtra, modifierManager, executor))
98+
modifierManager.initialize(project, variant)
99+
transform(Transform(variant, bcuExtra, modifierManager, executor))
87100
} finally {
88101
executor.shutdownNow()
89102
}
@@ -181,7 +194,7 @@ abstract class TransformTask : DefaultTask() {
181194
jos.write(bytes)
182195
jos.closeEntry()
183196
}
184-
} else if (entry.name.notNeedEntries(transform.extensions.notNeed)) {
197+
} else if (transform.filterNot(entry.name)) {
185198
if (!entryFile.isFile) {
186199
val parent = entryFile.parentFile
187200
if (!parent.isDirectory) {
@@ -225,7 +238,7 @@ abstract class TransformTask : DefaultTask() {
225238
val entryName = rootUri
226239
.relativize(file.toURI()).path
227240
.replace(File.separatorChar, '/')
228-
if (entryName.notNeedEntries(transform.extensions.notNeed)) {
241+
if (transform.filterNot(entryName)) {
229242
val entry = JarEntry(entryName)
230243
val bytes = file.readBytes()
231244
synchronized(jos) {
@@ -276,44 +289,28 @@ abstract class TransformTask : DefaultTask() {
276289
ProcessItem(entryName, cr, cv)
277290
}
278291

279-
private fun String.notNeedEntries(notNeed: ((entryName: String) -> Boolean)): Boolean =
280-
endsWith(".class").not()
281-
|| isAndroidRFile(this)
282-
|| startsWith("com/ysj/lib/bytecodeutil/")
283-
|| notNeed.invoke(this)
284-
285-
private fun isAndroidRFile(fileName: String) =
286-
// fileName.endsWith("/R.class") 由于混淆后可能生成 r.class 会冲突,因此单独判断这个
287-
fileName.endsWith("R\$raw.class")
288-
|| fileName.endsWith("R\$styleable.class")
289-
|| fileName.endsWith("R\$layout.class")
290-
|| fileName.endsWith("R\$xml.class")
291-
|| fileName.endsWith("R\$attr.class")
292-
|| fileName.endsWith("R\$color.class")
293-
|| fileName.endsWith("R\$bool.class")
294-
|| fileName.endsWith("R\$mipmap.class")
295-
|| fileName.endsWith("R\$dimen.class")
296-
|| fileName.endsWith("R\$interpolator.class")
297-
|| fileName.endsWith("R\$plurals.class")
298-
|| fileName.endsWith("R\$style.class")
299-
|| fileName.endsWith("R\$integer.class")
300-
|| fileName.endsWith("R\$id.class")
301-
|| fileName.endsWith("R\$animator.class")
302-
|| fileName.endsWith("R\$string.class")
303-
|| fileName.endsWith("R\$drawable.class")
304-
|| fileName.endsWith("R\$anim.class")
305-
306292
private class ProcessItem(
307293
val entryName: String,
308294
val classReader: ClassReader,
309295
val classNode: ClassNode,
310296
)
311297

312298
private class Transform(
313-
val extensions: BytecodeUtilExtensions,
299+
val variant: Variant,
300+
val extensions: BCUExtensionImpl,
314301
val modifierManager: ModifierManager,
315302
val executor: Executor,
316-
)
303+
) {
304+
305+
private val androidRFiletRegex = Regex(".*R\\\$.*.class")
306+
307+
fun filterNot(entry: String): Boolean {
308+
return entry.endsWith(".class").not()
309+
|| androidRFiletRegex.matches(entry)
310+
|| extensions.filterNot(variant, entry)
311+
}
312+
313+
}
317314

318315
private class Worker(workCount: Int, val executor: Executor) {
319316

0 commit comments

Comments
 (0)