自定义gradle插件

简述

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。

  • 一种可切换的,像maven一样的基于约定的构建框架,却又从不锁住你(约定优于配置)
  • 强大的支持多工程的构建
  • 强大的依赖管理(基于Apache Ivy),提供最大的便利去构建你的工程
  • 全力支持已有的Maven或者Ivy仓库基础建设
  • 支持传递性依赖管理,在不需要远程仓库和pom.xml和ivy配置文件的前提下
  • 基于groovy脚本构建,其build脚本使用groovy语言编写
  • 具有广泛的领域模型支持你的构建

基础知识

基本语法

gradle采用groovy进行编写,语法遵守groovy语法,具体,请右转官网

重要概念

Gradle中的所有内容都基于两个基本概念:项目(Project)和任务(Task)。每个Gradle构建都是由一个或多个project组成。每个project都是有一个或者多个任务组成。任务之间具有依赖关系,保证了任务的执行顺序。任务代表构建执行的一些原子工作。这可能是编译某些类,创建JAR,生成Javadoc或将一些jar或者aar文件发布到maven仓库。

  • project

每个build.gradle 就对应一个project。构建中的每一个project,Gradle都会创建一个Project对象,并将这个对象与构建脚本相关联。简单的说,build.gradle是对一个Project对象的配置。以Android项目为例,在项目的根目录会有一个build.gradle文件,在每个模块的目录下也会有一个build.gradle 文件。
Project与build.gradle是一对一的关系。在构建初始化阶段,Gradle为每个参与构建的项目创建一个Project对象。

  • task

任务是主要的工作执行者。每个任务有多个Action组成,在使用任务时,可以使用dependsOn关键词声明任务与任务的依赖关系。任务依赖的主要意义在于,确定任务与任务之间的执行先后顺序。任务与任务之间构成一个有向无环图(DAG),每个任务最多执行一次

Gradle构建的主要三个阶段:

  • 初始化阶段,对setting.gradle进行处理,生成settings对象,主要有两个时机需要关注:
//1.setting.gradle 执行结束的监听
gradle.settingsEvaluated {
    println "settings.gradle 初始化执行结束"
}
//2.参与构建的Project对象创建完毕的监听
gradle.projectsLoaded {
    Gradle gradle ->
        println "settings.gradle 所有在 settings 中 include 的 Project 都创建完成了"
}
  • 配置阶段

在 settings.gradle 中可以配置需要参与构建的 project ,并且在初始化阶段就已经创建好对应的 project 实例了,每个build.gradle对应project实例。Gradle 的配置阶段就是执行每一个 Project 对应的 build.gradle 的配置代码。

// 每一个 project 在执行配置代码之前都会回调这个方法。
gradle.beforeProject {
    Project project ->
        println ">>>>>>>>gradle beforeProject " + project.name + " 配置开始前回调"
}
// 当前 project在执行配置代码之前的回调
project.afterEvaluate {
    project ->
        println project.name + " 配置结束监听"
}
// 所有的 project 都执行完对应的 build.gradle 的配置代码,准备要去生成对应的 Task 依赖图
gradle.projectsEvaluated {
    gradle ->
        println "所有的project都配置完毕了,准备生成Task依赖关系"
}
// task 依赖关系已经生成
gradle.taskGraph.whenReady {
    TaskExecutionGraph graph ->
        println "task 依赖关系已经生成"
}
  • 执行阶段

Gradle 在配置阶段中会执行每一个 project 的 build.gradle 的配置代码,并且最终生成每一个 Task 任务的依赖关系。下面到了执行阶段就会根据这个依赖关系去执行对应的 Task 任务

// 每一个 Task 任务执行之前回调
gradle.taskGraph.beforeTask {
    Task task ->
        println "Project[${task.project.name}]--->Task[${task.name}] 在执行之前被回调"
}
// 每一个 Task 任务执行之后回调
gradle.taskGraph.afterTask {
    task, TaskState taskState ->
        //第二个参数表示 task 的状态,是可选的参数
        println "Project[${task.project.name}]--->Task[${task.name}] 在执行完毕,taskState[upToDate:${taskState.upToDate},skipped:${taskState.skipped},executed:${taskState.executed},didWork:${taskState.didWork}]"
}
// 当所有的任务执行完毕的回调
gradle.buildFinished {
    BuildResult buildResult ->
        println "构建完毕"
}

自定义构建

脚本构建

脚本构建就是任务放在一个gradle文件,其中定义了很多任务

对象构建

对象构建是指实现了org.gradle.api.Plugin接口的类,实现Plugin接口的apply(T target)这个方法

构建编写方式

  • 在我们构建项目的 build.gradle 脚本中直接编写,这种方式的好处是插件会自动被编译加载到我们的 classpath 中,我们不需要额外做任何的事情,但是它有很明显的局限性,就是除了在包括它的脚本外别的地方无法复用。
  • 在我们构建项目的rootProjectDir/buildSrc/src/main/groovy 目录下编写,Gradle 会自动编译到当前项目的classpath中,该项目下所有编译脚本都可以使用该插件,但是除了当前项目之外的都无法复用。
  • 以单独的工程方式编写,这个工程最终编译发布为一个 JAR 包,它可以在多个项目或不同的团队中共享使用。

自定义任务

对象构建: hello任务

apply plugin: HelloPlugin
class HelloPlugin implements Plugin {
    // 此方法接受一个Project对象
    void apply(Project project) {
        // 向project对象添加hello任务
        project.task('hello') {
            doLast {
                println "Hello from the HelloPlugin"
            }
        }
    }
}

这其实是自定了一个插件HelloPlugin,在插件中定义了任务hello
脚本构建:hello任务

// task hello == task.create('hello') == task('hello') 三种方式都可以
project.task("hello") {
    doFirst {
        println "from gralde hello"
    }
}

其中,每个gradle文件都会创建一个项目对象project;

自定义插件

使用AndroidStudio 新建一个android module,项目中仅保留src/main空目录(子目录全删除),和build.gradle空文件(内容清除),其它目录文件删除

  • src/main下建groovy目录,这个是放置groovy文件的(java目录放置java文件),插件类也是在这里写的
    新建一个文件Hello.groovy,输入如下代码
package china.csu.liutao

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

class Hello implements Plugin {
    @Override
    void apply(Project project) {
        project.task('shenme').doFirst {
            print('hahhahah')
        }
    }
}
  • build.gradle进行配置:下面配置,引入groovy和maven插件,引入本地依赖,建立上传maven仓任务
apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    compile gradleApi()
    compile localGroovy()
}

group='china.csu.liutao'
version='1.0.0'
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('G:/repos'))
        }
    }
}

maven仓上传任务:上传到本地(也可上传到服务器);引入插件使用下面代码方式,配置插件地址,和插件详情(classpath 'group:module-name:version'),group,version就是上传任务的参数,module-name就是插件所在模块名字;这也是应用自定义插件的第一步

buildscript {
    repositories {
        ...
        maven {
            url uri('G:/repos')
        }
    }
    dependencies {
        classpath 'china.csu.liutao:secondgradle:1.0.0'
       
    }
}
  • src/main 下新建resources/META-INF/gradle-plugins/xxx.properties文件,对插件进行配置
    implementation-class=报名+类名;
implementation-class=china.csu.liutao.Hello

xxx表示配置插件的应用id,如下,这是使用的第二步,第三步也就是使用其中的任务了

apply plugin: 'xxx'

为插件添加属性

  • 添加属性
    可以接收一些自定义的属性,然后在 Gradle 脚本文件中配置使用这些属性。我们可以使用 extension objects来现实给插件传参,而每个 Gradle 工程都有一个ExtensionContainer对象,它可以保存我们为插件设置的属性值,如下
class HelloPlugin implements Plugin {
    // 此方法接受一个Project对象
    void apply(Project project) {
        // 向extension container保存greeting参数
        // 该greeting参数为HelloPluginExtension的实体bean
        project.extensions.create("greeting", HelloPluginExtension)
        // 向project对象添加hello任务
        project.task('hello') {
            doLast {
                println "${project.greeting.message} from ${project.greeting.greeter}"
            }
        }
    }
}

// 定义一个实体bean对象
class HelloPluginExtension {
    String message
    String greeter
}
  • 配置属性
apply plugin: HelloPlugin
// 使用闭包方式设置值
greeting {
    message = 'Hi'
    greeter = 'Gradle'
}

你可能感兴趣的:(自定义gradle插件)