您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

编译自己的Gradle插件

前面几节我们学习了 Gradle 的任务及命令,通过这几节的学习我们已经有了一定的 Gradle 基础,今天我们就来学习一下如何一款 Gradle 。我们为什么要 Gradle 呢?那当然是为了我们开发方便呀。如果吃力不讨好谁会去做呢。下面我们进入正题。

Gradle 主要分为两类:脚本和对象。下面我们来看下它们的区别。

脚本就是我们在.gradle [例如 demo.gradle ]中定义自己的编译任务。在项目中的build.gradle中通过apply from:'demo.gradle'就可以使用这个脚本。

下面我们以项目为例子,来简单学习脚本,一般我们将脚本写在项目的根目录下,项目目录结构如下:

我们定义任务 showProjectName ,该的 module 的:

// demo.gradle
task showProjectName{
    doLast {
        println("$project.name")
    }
}

我们需要在对应模块的 build.gradle 中引用,这里我们在 app 模块下的 build.gradle中引用,由于demo.gradle 在 build.gradle 的父目录一级。所以我们需要在前面../,具体如下:

//这行命令需再最前面
apply from: '../demo.gradle'

我们运行这个任务 ,前面定义 Gradle 任务的时候讲过最好使用驼峰命名,我们可以使用以下命令。

//使用任务全拼
$ gradle showProjectName
//使用简写方式
$ gradle sPN

结果如下,我们看到那种结果都会疏忽当前模块的 app。

所谓对象就是指我们定义实现org.gradle.api.Plugin接口的类。这个类就是我们所谓的对象。该类必须实现 Plugin 接口的apply

编写 Gradle 对象的方式有以下 3 种:

我们还是以上面的模块为例,我们定义PluginInGradleScript的类实现Plugin接口:

//app 模块下build.gradle
class PluginInGradleScript implements Plugin<Project> {
    @Override
    void apply(Project target) {
       target.task('showProjectName'){
            doLast {
                println("PluginInGradleScript:Module Name is $target.name")
            }
        }
    }
}

引用该,引用时我们使用apply plugin语句,记住这句还是要在 build.gradle 的最上面两行,具体如下:

apply plugin: PluginInGradleScript

我们到这里就已经将引用到项目中了,下面我们还是执行命令,看看定义的能否正常 module name。

$ gradle showProjectName

> Task :app:showProjectName
PluginInGradleScript:Module Name is app

Deprecated Gradle features were used in this build, making it incompatible with Gradle .
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1s
 actionable task:  executed

如上所示,我们就成功定义了对象,这种定义方式适合项目中比较小巧的,简单的一些。较复杂的还是不建议这种定义方式。

我们首先需要在项目的根目录下创建 buildSrc 的模块,这样如果项目中有多个模块就可以重复使用了。

首先,我们需要创建 Java Library 名字叫做 buildSrc。因为我们需要使用 Groovy 语言写,所以我们需要将 main 目录下的 java 目录为 groovy 目录。
后如下所示:

因为我们创建的是 Java Libiary,这里我们使用的是 Groovy 语言所以,buildSrc 的 build.gradle 我们需要为如下:

//buildSrc/build.gradle
apply plugin: 'groovy'
dependencies {
    compile gradleApi()
    compile localGroovy()
}

紧接着我们需要定义 Plugin ,我们还是以 module name 为例:

package com.bthvi.buildsrc
import org.gradle.api.Project
import org.gradle.api.Plugin

class CustomPluginInBuildSrc implements Plugin<Project> {
    @Override
    void apply(Project project) {
        project.task('showCustomPluginInBuildSrc') {
            doLast {
                println("InBuildSrc: Module Name is $project.name")
            }
        }
    }
}

我们引用可以使用如下两种方式引用:
第一种: 我们直接按照类名和包名路径引用

import com.bthvi.buildsrc.CustomPluginInBuildSrc
apply plugin: CustomPluginInBuildSrc
//或者直接引用全路径
apply plugin: com.bthvi.buildsrc.CustomPluginInBuildSrc

第二种: 我们按照如下目录创建 resources 目录及 xxx.properties ,这里的 xxx 就是我们要引用的。我们这里创建 myplugin.properties。并将id对应的 Plugin 实现类全路径配置如下:

implementation-class=com.bthvi.buildsrc.CustomPluginInBuildSrc

下面我们使用 gradle 命令来这个,我们直接使用gradle showCustomPluginInBuildSrc来执行这个任务。

D:\AndroidProjects\CustomGradlePlugins>gradle showCustomPluginInBuildSrc

> Task :app:showCustomPluginInBuildSrc
InBuildSrc: Module Name is app

Deprecated Gradle features were used in this build, making it incompatible with Gradle .
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 3s
 actionable task:  executed

Tips: 我们可能会遇到'buildSrc' cannot be used as a project name as it is a reserved name这个,如下图所示。

上面的 buildSrc 模块下定义 Gradle 也只是仅仅限制于当前的项目的各个模块间引用,如果我们想要在多个模块间复用同,我们就需要单独创建工程,并将我们定义的 Gradle 发布到 Maven。

单独工程中定义跟在 buildSrc 中是一样的,唯一不同的就是我们需要配置,这里我们到自己的本地目录’loccal’中,这里我从创建名字为 CustomPluginDemo,目录结构如下:

apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
    compile gradleApi()
    compile localGroovy()
}
group = 'com.bthvi.mplugin'
version = '1.0.0'
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('D:/local'))
        }
    }
}

这里我们配置将至 D 盘的local目录下,配置完成我们同步后会看到如下:

buildscript {
    repositories {
        maven {
            url uri('D:/local')
        }
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.bthvi.mplugin:CustomPluginDemo:1.0.1'
        classpath 'com.android.tools.build:gradle:3.5.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        maven {
            url uri('D:/local')
        }
        google()
        jcenter()
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

然后像 buildSrc 一样我们就可以在 app 下引用的myplugin了。

apply plugin: 'myplugin'

我们执行gradle showCustomPluginInBuildSrc为了区分,我们了语句println("In Projet: Module Name is $project.name"),我们执行后会看到如下:

D:\AndroidProjects\CustomGradlePlugins>gradle showCustomPluginInBuildSrc

> Task :app:showCustomPluginInBuildSrc
In Projet: Module Name is app

Deprecated Gradle features were used in this build, making it incompatible with Gradle .
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 2s
 actionable task:  executed

本节,我们从简单到复杂,首先介绍了脚本,然后我们介绍了对象,先是在脚本中直接定义,但是这种只适用于当前模块,如果项目中多个模块想要共用,我们就需要在 buildSrc 目录下新建供多个模块复用。但是如果想要多个项目共用,我们就需要单独定义 Gradle 项目,并且到 Maven,我们多个项目使用的时候直接 Maven 就好。本文中直接到本地磁盘了,有兴趣的同学可以下来尝试将自己的到 Maven 服务器。


联系我
置顶