————————————————
版权声明:本文为CSDN博主「拿节
」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhejiang9/article/details/105241392
Gradle工程编译的过程,就是执行目标task的过程,如果task存在依赖,则先执行依赖task,如此反复,直到触达无依赖的task
就这样,从无依赖task -> 目标task的执行链即建立,接着依次执行task即可,每个task之间数据传输,主要是通过task inputs
和outputs
描述文件来完成的
所以,gradle编译所有task信息的打印,应该包含
- 按task执行顺序打印
task name
- 可以打印task的
inputs
和outputs
数据 - 将
输出json信息
保存到本地文件
我写了一个gradle脚本来完成上述信息输出:
import groovy.json.JsonOutput
//输出数据结构
class TaskItem {
String name
List<String> inputs = new ArrayList<>()
List<String> outputs = new ArrayList<>()
}
class Dumper {
//正则表达式,用于过滤要dump inputs和outputs的task
//这里配置名称包含Jni的task,大家可以根据需要自行配置
String taskInOutDirDumpFilter = "^.*Jni.*|^.*transform.*"
String type
File logOutDir
List<TaskItem> taskList = new ArrayList<>()
File logfile
boolean isAvaliable = false
Dumper(String type, File dir) {
this.type = type
this.logOutDir = dir
}
def makeLogFile() {
logfile = new File(logOutDir, "taskDump-${type}.json")
if (!logOutDir.exists()) {
logOutDir.mkdirs()
}
if (logfile.exists()) {
logfile.delete()
}
logfile.createNewFile()
}
def collectData(Task t) {
t.doFirst {
try {
if (name == "pre${type}Build" && !isAvaliable) {
isAvaliable = true
makeLogFile()
}
} catch (Exception ex) {
ex.printStackTrace()
return
}
if (!isAvaliable) {
return
}
TaskItem item = taskList.find {
it.name == path
}
if (item != null) {
return
}
item = new TaskItem()
item.name = path
taskList.add(item)
def matcher = name =~ taskInOutDirDumpFilter
if (matcher.size() > 0) {
println "-------match task path = ${path}"
t.inputs.each {
it.files.each {
item.inputs.add(it.absolutePath)
}
}
t.outputs.each {
it.files.each {
item.outputs.add(it.absolutePath)
}
}
}
}
}
def dumpData2File() {
// println " ------- dumpData2File " + logfile.getPath()
def s = JsonOutput.toJson(taskList)
logfile.write(s)
}
}
Map<String, Dumper> dumperMap = new HashMap<>()
//数据dump目录
def dumpDir = new File(buildDir, "taskDump")
if (!dumpDir.exists()) {
dumpDir.mkdirs()
}
rootProject.childProjects.each {
it.value.afterEvaluate { Project project ->
def isAndroidLibrary = project.plugins.hasPlugin("com.android.library")
def isApplication = project.plugins.hasPlugin("com.android.application")
if (!(isAndroidLibrary || isApplication)) {
println("dumpTask -> is not android module.")
return
}
def variants = isAndroidLibrary ? project.android.libraryVariants : project.android.applicationVariants
variants.all { def variant ->
// Create variant and target names
def targetName = variant.name.capitalize()
def dumper = dumperMap.get(targetName)
if (dumper == null) {
dumper = new Dumper(targetName, dumpDir)
dumperMap.put(targetName, dumper)
}
project.tasks.each {
dumper.collectData(it)
}
}
}
}
gradle.buildFinished {
dumperMap.each {
if (it.value.isAvaliable) {
try {
it.value.dumpData2File()
} catch (Exception ex) {
println ex.getMessage()
}
}
}
}
将脚本命名并保存到工程目录下,比如 dumptask.gradle,并保存道app module的根目录,接着再app module的build.gradle
引入
apply from: “dumpTask.gradle”
接着执行
./gradlew assembleDebug
执行结束后, dump信息
保存到如下文件
app/build/taskDump/taskDump-Debug.json
[
...
{
"contentHash": "c01a300bf2fd522b5c9c92944ade0672",
"originalClassName": "TaskItem",
"inputs": [],
"outputs": [],
"name": ":Media:prepareLintJarForPublish"
},
{
"contentHash": "c01a300bf2fd522b5c9c92944ade0672",
"originalClassName": "TaskItem",
"inputs": [
"/Users/likunlun/Android/Projects/DeveloperDocuments/AndroidStudy/Modules/Media/build/intermediates/stripped_native_libs/debug/out"
],
"outputs": [
"/Users/likunlun/Android/Projects/DeveloperDocuments/AndroidStudy/Modules/Media/build/intermediates/library_jni/debug/jni"
],
"name": ":Media:copyDebugJniLibsProjectOnly"
},
...
]