Gradle Plugin 插件的编写及其Debug断点调试技巧

6,520 阅读2分钟

1. 利用gradle init命令生成Gradle Plugin工程

1.1 首先在本机安装Gradle并设置环境变量,这里以Mac为例

brew install gradle

关于gradle安装请参考这里

1.2 创建Gradle Plugin工程

$ cd ~/workspace
$ mkdir sample-plugin2
$ cd sample-plugin2                                                           
$ gradle init                                                                 
Starting a Gradle Daemon, 2 incompatible and 1 stopped Daemons could not be reused, use --status for details
> Task :wrapper

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 4

Select implementation language:
  1: Groovy
  2: Java
  3: Kotlin
Enter selection (default: Java) [1..3] 1

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Project name (default: sample-plugin2): 

Source package (default: sample.plugin2): 


> Task :init
Get more help with your project: https://docs.gradle.org/6.8.3/userguide/custom_plugins.html

BUILD SUCCESSFUL in 29s
2 actionable tasks: 2 executed

当显示BUILD SUCCESSFUL后表示工程创建成功了


2. 将sample-plugin2工程集成到现有的安卓工程(以sample工程为例)

2.1 复制sample-plugin2下的plugin文件夹将其放到sample文件夹下,并改名为sample-plugin

截屏2021-04-08 10.17.19.png

2.2 修改sample-plugin模块下的build.gradle文件

此处的目的是设置该模块打包后的插件名,以及该插件发布到何处

plugins {
    id 'java-gradle-plugin'
    id 'groovy'
    // 使其支持发布到Maven
    id 'maven-publish'
}

repositories {
    jcenter()
}

dependencies {
    testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
}

gradlePlugin {
    // 在此处定义该插件的id和实现类
    plugins {
        greeting {
            id = 'com.paike.sample-plugin'
            implementationClass = 'greeting.GreetingPlugin'
        }
    }
}

sourceSets {
    functionalTest {
    }
}

gradlePlugin.testSourceSets(sourceSets.functionalTest)
configurations.functionalTestImplementation.extendsFrom(configurations.testImplementation)

tasks.register('functionalTest', Test) {
    testClassesDirs = sourceSets.functionalTest.output.classesDirs
    classpath = sourceSets.functionalTest.runtimeClasspath
}

tasks.named('check') {
    dependsOn(tasks.functionalTest)
}
// 此处是maven仓库的配置信息
publishing {
    publications {
        greeting (MavenPublication) {
            // 设置maven坐标信息
            groupId = 'com.paike.sample-plugin'
            artifactId = 'greeting'
            version = '0.0.1'
            from components.java
        }
    }
    repositories {
        maven {
            // 发布到何处,此处为方便,就以本工程的repo目录为例(需手动创建)
            url = "$rootDir/repo"
        }
    }
}

2.2 修改根目录的settings.gradle文件

include ':app'
// 将gradle插件模块包含进来
include ':sample-plugin'
rootProject.name = "sample"

2.3 同步项目,并发布该插件到repo目录

  • 点击Sync按钮
  • 同步完后在右上角Gradle标签内找到publishXXXPublicationToMavenRepository任务
  • 双击或者选中后按回车

企业微信20210408-104959.png

  • 当控制台输出BUILD SUCCESSFUL 时,便能在/repo目录下找到输出产物

企业微信20210408-105353.png

  • 此时插件就打包完成了,我们就可以通过apply plugin ‘xxx’的方式在任意地方使用该插件了

3. 在app模块中使用该插件

3.1 修改根目录下的build.gradle以添加sample-plugin依赖

buildscript {
    ext.kotlin_version = "1.3.72"
    repositories {
        google()
        jcenter()
        maven{ url('./repo')}
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.3"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        classpath "com.paike.sample-plugin:greeting:0.0.1"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

3.2 修改:app模块下的build.gradle, 应用sample-plugin插件

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'com.paike.sample-plugin'
}
...

之后sync同步工程

3.3 运行测试该插件

  • 在Gradle Tasks中找到app/Tasks/other/greeting任务,双击运行
  • 控制台会输出以下内容,表示运行成功
> Task :app:greeting
Hello from plugin 'greeting.greeting'

BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed

到这里,我们插件的编写、发布、测试都ok了,下面开始讲解如何调试插件的代码(GreetingPlugin.groovy文件)

4. Debug插件(groovy)的代码

4.1 我们在println处打上断点

image.png

4.2 创建一个远程的Configuration

企业微信20210408-112256.png

Name随意(此处为sample-plugin-debug),其他不动,之后点ok

企业微信20210408-112435.png

4.3 在终端运行:app:greeting任务

$ export GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
$ ./gradlew --no-daemon :app:greeting  -Dorg.gradle.debug=true

运行之后终端输出如下内容并阻塞住,等待attach(此处不能再直接双击greeting运行了,因为有附加的启动参数)

To honour the JVM settings for this build a single-use Daemon process will be forked. See https://docs.gradle.org/6.8.3/userguide/gradle_daemon.html#sec:disabling_the_daemon.
> Starting Daemon

4.4 工具栏上选中我们添加的configuration并点击Debug按钮(绿色的小甲虫)

企业微信20210408-113332.png

此时终端中的任务会继续运行,直到运行到断点处,然后阻塞住

企业微信20210408-113657.png

到这里,我们成功捕捉到了断点信息,然后我们就能查看当前上下文的变量信息,或者运行Evaluate了,大大提高了代码编写效率!