转载

带你实现自定义Gradle插件

最近在研究编译插桩的三种方法: AspectJASM 以及 Redex 中的 ASM ,要使用ASM就需要用插件的形式用在项目中,所以这篇的目的是了解并能自己定义一个Gradle插件。

网上现在很很多这样的文章,大家可以结合起来看。

Gradle 插件打包了可重用的构建逻辑,可以在许多不同的项目和构建中使用。

你可以用你喜欢的编码语言来实现一个自定义的Gradle插件,最终都会编译城jvm字节码。现在可以实现插件的语言有 Groovyjavakotlin 等。一般来说,使用java或者kotlin实现的插件将优于使用groovy的相同插件。

实现插件的方式有三种,下面我会一一为大家来介绍。

实现方式

Build Script

你可以直接在 build.gradle 中构建一些简单的插件代码,这样做可以自动编译并包含在构建脚本的类路径中,无需执行任何操作。但是该插件只能用于本项目中,外部不可见。

class GreetingExtension {
    String message = null

}

class GreetingPlugin implements Plugin<Project> {

    @Override
    void apply(Project target) {
        // 利用利用Extension创建greeting 闭包,用于接受外部传递的参数值
        def extension = target.extensions.create("greeting", GreetingExtension)

        target.task("customPlugin") {
            doLast() {
                println(extension.message)
            }
        }
    }
}

/**
 * 使用 greeting{}要放在 apply plugin 之后,apply plugin会执行apply方法进行绑定操作
 * */
apply plugin: GreetingPlugin

greeting {
    message = "Hi this is a cutstom plugin"
}
复制代码

我们可以用命令行 或者AS右边的gradle在app中找到 customPlugin

./gradlew -p app customPlugin --stacktrace
复制代码

看下执行结果是什么:

> Task :app:customPlugin
Hi this is a cutstom plugin

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

复制代码

buildSrc project

将插件源代码放在 rootProjectDir/buildScr/scr/main/groovy 中,这种的优点在于自动编译项目目录下的buildSrc插件源码,不需要手动指定 classpath。同一项目其他模块也可使用。缺点就是对于其他项目不可用。第三种方式就解决了这个缺点。

这里如果想要了解可以看 这里

第三种和这个很类似,区别在于这是一个独立的插件项目,可以供其他项目使用。

Standalone project

这种方式是现在目前大多数在使用的方式。

Android Studio 中新建 Java Library module customPlugin ,用IJ来开发插件会比AS要方便的很多。

用AS中开发插件需要这三步:

  1. 移除java文件。
  2. 增加groovy文件夹,这里放所有插件的代码。
  3. 增加resources文件夹,这用来声明插件指向地址。
  4. 修改build.gradle文件
apply plugin: 'groovy'
apply plugin: 'maven'

repositories {
    mavenCentral()
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation gradleApi() // gradler sdk
    implementation localGroovy() // groovy sdk
}

uploadArchives {
    repositories {
        mavenDeployer {
            //设置插件的GAV参数
            pom.groupId = 'com.lenny.plugin'
            pom.artifactId = 'art'// 这个如果不设置,发布之后应该是com.lenny.plugin.customPlugin
            pom.version = '1.0.3'
            //文件发布到下面目录
            repository(url: uri('../repo'))
        }
    }
}
复制代码

修改后的目录应该是这个样子的:

 ├── build.gradle 
 ├── libs 
 ├── customPlugin.iml 
 └── src     
    └── main
        ├── groovy     
    │          └── com    
    │              └── lenny     
    │                  └── plugin     
    │                      ├── CustomPlugin.groovy     
    │                          
    └── resources         
        └── META-INF             
            └── gradle-plugins                 
            └── com.lenny.plugin.properties


复制代码

CustomPlugin.groovy

package com.lenny.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project

public class CustomPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        println("hello from custom plugin")
    }
}
复制代码

注意文件的后缀。

com.lenny.plugin.properties

implementation-class=com.lenny.plugin.CustomPlugin
复制代码

到这里就算基本完成了,我们同步下代码,就可以在右侧的Gradle中找到 uploadArchives 命令,执行该命令之后就会在项目同级目录下发现:

└── repo    
    └── com
        ├── lenny     
    │          └── plugin    
    │              └── art     
    │                  └── 1.0.3     
    │                      ├── art-1.0.3.jar
    │                      ├── art-1.0.3.jar.md5
    │                      ├── art-1.0.3.jar.sha1
    │                      ├── art-1.0.3.pom
    │                      ├── art-1.0.3.pom.md5
    │                      ├── art-1.0.3.pom.sha1
 
复制代码

然后我们在项目中集成:

工程的 build.gradle

buildscript {
    repositories {
        ...
        maven {
            url uri('repo/')
        }
    }
    dependencies {
        ...
        classpath 'com.lenny.plugin:art:1.0.3'
    }
}
复制代码

app的 build.gradle

apply plugin: 'com.lenny.plugin'
复制代码

如果是发布在上线的,repositoies中就不这么写了。

classpath xxx的由来:groupId:artifactId:version

apply plugin: 'xxx'中则是 properties 的前面的: com.lenny.plugin

执行结果:

> Configure project :app
hello from custom plugin

> Task :app:createMockableJar UP-TO-DATE
> Task :app:preBuild UP-TO-DATE
复制代码
原文  https://juejin.im/post/5db2d1016fb9a0208a3a738f
正文到此结束
Loading...