开发效率优化之自动化构建系统Gradle(二)下篇
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
本篇文章将继续从自定义 Gradle 插件开发来介绍自动化构建系统Gradle:
Gradle 插件简介
Gradle 插件是一个能够将 Gradle 的构建逻辑(build logic)和构建任务(build task)打包到一起,以便在多个项目的构建脚本(build.gradle)中应用(apply)的工具。
例如,build.gradle
构建脚本文件内 apply plugin: 'java'
、apply plugin: 'com.android.application'
中的 java、com.android.application 就是官方提供的 Gradle 插件,通过应用这些插件,可以丰富项目的构建任务与构建逻辑。
除官方提供的插件外,Gradle 还允许开发者定义自己的 Gradle 插件。开发者可以根据实际需求定义自己的构建逻辑和构建任务,将其打包为 Gradle 插件,从而在多个项目的构建脚本中复用。此外,还可以将自定义的 Gradle 插件发布到 plugin portal或其他仓库中,更为方便的分享给他人使用。
Gradle 插件对编程语言没有太多限制,只要是能够被编译为 JVM 字节码的编程语言,都能用来编写 Gradle 插件。Gradle-API 的被设计为对 Groovy、Java、Koltin 友好的,通常情况下,使用 Java 或 Kotlin 这类静态类型语言实现的 Gradle 插件的性能要比使用 Groovy 实现的相同常见的性能更好。
开始之前
Gradle 作为一个普通的构建工具,本身并不依赖任何可视化 GUI 工具。为简化步骤,本文将采用命令行方式来完成自定义 Gradle 插件的演示。在开始之前,需先将 gradle 命令添加到系统环境变量中。
若读者在 IDEA / Android Studio 使用过 gradle ,则可在当前用户目录下找到 gradle 命令,具体路径如下
- Mac:
/Users/当前用户名/.gradle/wrapper/dists/gradle版本/沙盒路径/gradle版本/bin
- Win:
C:\Users\当前用户名\.gradle\wrapper\dists\gradle版本\沙盒路径\gradle版本\bin
若读者的电脑中尚未安装 gradle,则可在 Gradle 官方 下载安装。
以笔者使用的环境为例,gradle 命令所在目录为
~/.gradle/wrapper/dists/gradle-5.4.1-all/3221gyojl5jsh0helicew7rwx/gradle-5.4.1/bin
将 gradle 命令所在目录添加到环境变量中
- Mac:在
~/.bashrc
中添加
export PATH=~/.gradle/wrapper/dists/gradle-5.4.1-all/3221gyojl5jsh0helicew7rwx/gradle-5.4.1/bin:$PATH
- Win:在系统环境变量中添加
C:\Users\用户名\.gradle\wrapper\dists\gradle-5.4.1-all\805usxkvhgx6e1wbo8o64g0tx\gradle-5.6.1\bin
牛刀小试
在命令行中输入
gradle --version
得到如下输出则表示 gradle 环境设置成功
------------------------------------------------------------
Gradle 5.4.1
------------------------------------------------------------
Build time: 2019-04-26 08:14:42 UTC
Revision: 261d171646b36a6a28d5a19a69676cd098a4c19d
Kotlin: 1.3.21
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM: 1.8.0_171 (Oracle Corporation 25.171-b11)
OS: Mac OS X 10.14.6 x86_64
自定义 Gradle 插件
自定义 gradle 插件可以在以下三个地方创建,分别是:
- 构建脚本内
- buildSrc 模块内
- 单独项目
构建脚本内建方式
在 build.gradle
内直接创建 Gradle 插件
优点:
build.gradle
中创建的插件将<u>被自动编译并包含在 classpath 中</u>,使用时无需在构建脚本内指定 classpath
缺点:
- 此插件仅在当前构建脚本中有效,对外部文件不可见,无法在当前构建脚本以外的其他地方复用此插件
示例
1. 创建 BuildInDemo
目录
mkdir BuildInDemo
2. 在 BuildInDemo
目录内中新建 build.gradle
文件
cd BuildInDemo
touch build.gradle
使用 tree
命令查看创建后的目录结构,如下所示
BuildInDemo
.
└── build.gradle
0 directories, 1 file
3. 在 BuildInDemo/build.gradle
内创建并应用 Gradle 插件,代码如下
// 1. 创建插件 BuildInPlugin
class BuildInPlugin implements Plugin<Project> {
// 2. 应用插件时执行此函数
@Override void apply(Project target) {
println("hello form build-in plugin")
}
}
//3. 应用插件
apply plugin: BuildInPlugin
// 2\. 应用插件时执行此函数
@Override void apply(Project target) {
println("hello form build-in plugin")
}
}
//3\. 应用插件
apply plugin: BuildInPlugin
4. 构建此 build.gradle
文件
gradle build
Gradle 构建时将执行 build.gradle
中的代码,当执行到 apply plugin: BuildInPlugin
时,将会调用 BuildInPlugin 的实例方法 apply(Project p)
。因此在构建过程中,可以看到如下输出,其中第 2 行即为上一步自定义插件中打印的内容,表明插件应用成功
> Configure project :
hello form build-in plugin
> Task :buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
No dependencies
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
buildSrc 模块方式
rootProject/buildSrc 文件夹是 Gradle 的预留目录,用来存放当前项目私有 Gradle 插件的源代码与构建脚本
优点:
- 项目构建时,Gradle 会自动编译项目目录下的 buildSrc 文件夹下的构建脚本和源码,并将其添加到项目构建脚本的 classpath 中,因此在使用 buildSrc 中创建的插件时,无需再手动指定 classpath
- buildSrc 文件夹中构建脚本和 Gradle 插件同一项目均可见,因此同一项目中的其他模块也可以使用 buildSrc 中创建的插件
缺点:
- 此处创建的插件对外部项目不可见,无法在其他项目中复用
示例
1. 创建 PluginBuildSrcDemo
项目模块
创建 PluginBuildSrcDemo
目录,并在该目录下创建 build.gradle
文件
mkdir PluginBuildSrcDemo && cd PluginBuildSrcDemo && touch build.gradle
2. 创建 buildSrc
子模块
2.1 在 PluginBuildSrcDemo
目录下创建 buildSrc
目录
mkdir buildSrc
2.2 在 PluginBuildSrcDemo/buildSrc
目录下创建 buildSrc 子模块的构建脚本文件 build.gradle
cd buildSrc
touch build.gradle
PluginBuildSrcDemo/buildSrc/build.gradle
的内容如下
// 使用 plugins 块语法应用插件
plugins {
// 应用 kotlin 插件
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
}
dependencies {
// 仅在编译时使用 Grdale-API 依赖
compileOnly gradleApi()
// 在插件源码中添加 kotlin 标准库依赖
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
}
2.3 创建 buildSrc 模块的源码目录
cd PluginBuildSrcDemo/buildSrc
mkdir -p /src/main/kotlin/com/example/plugin
2.4 创建插件文件 PluginBuildSrc.kt
cd PluginBuildSrcDemo/buildSrc/src/main/kotlin/com/example/plugin
touch PluginBuildSrc.kt
PluginBuildSrc.kt
的代码如下
package com.example.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class PluginBuildSrc : Plugin<Project> {
override fun apply(target: Project) {
println("hello from buildSrc plugin")
}
}
2.5 声明 Gradle 插件的 ID 与实现类
此步骤是可选的:若使用插件 ID 形式应用自定义插件,则必须进行此步骤;若使用插件实现类的形式应用自定义插件,则可跳过此步骤。
完成此步骤的方式有两种,任选其一即可
方式 1. META-INF 方式
创建 PluginBuildSrcDemo/buildSrc/src/main/resources/META-INF/gradle-plugins
目录
cd PluginBuildSrcDemo/buildSrc
mkdir -p src/main/resources/META-INF/gradle-plugins
在 gradle-plugins
目录下创建 com.example.plugin.properties 属性文件,红色部分表示插件的 ID
cd src/main/resources/META-INF/gradle-plugins
touch com.example.plugin.properties
属性文件的内容如下,表示插件 ID 为 com.example.plugin 的插件所对应的实现类为 com.example.plugin.PluginBuildSrc
implementations-class=com.example.plugin.PluginBuildSrc
方式 2. java-gradle-plugin 插件方式
java-gradle-plugin 是一个用于开发 Gradle 插件的辅助插件,它内置了很多辅助功能:
- 为宿主模块添加
gradlePlugin
配置块,可在此处配置插件的 ID 和实现类 - 为宿主模块添加
complile gradleApi()
依赖 - etc…
此处我们主要使用 gradlePlugin
配置块代替 META-INF
目录下的属性文件。java-gradle-plugin
的使用方式非常简单,只需在 PluginBuildSrcDemo/buildSrc/build.gradle
构建脚本文件中简单配置即可,如下所示。
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
+ //1. 应用 java-gradle-plugin 插件
+ id 'java-gradle-plugin'
}
dependencies {
- compileOnly gradleApi() // java-gradle-plugin 插件已为宿主添加 gradleApi 依赖,此行可移除
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
}
+ //2. 添加 gradlePlugin 配置块信息
+ gradlePlugin {
+ plugins{
+ // 此处的 tag 可以为任意名称
+ tag1{
+ id = 'com.example.plugin.buildsrc' //自定义插件的 ID
+ implementationClass = 'com.example.plugin.PluginBuildSrc' //自定义插件的实现类
+ }
+ }
+ }
此时在 PluginBuildSrcDemo 目录下使用 tree
命令,可以看到当前的目录结构如下
PluginBuildSrcDemo
.
├── build.gradle
├── buildSrc
│ ├── build.gradle
│ └── src
│ └── main
│ └── kotlin
│ └── com
│ └── example
│ └── plugin
│ └── PluginBuildSrc.kt
7 directories, 3 files
3. 在 PruginBuildSrcDemo
项目模块中应用 buildSrc
中声明的 Gradle 插件
在 PluginBuildSrcDemo/build.gradle
构建脚本文件中添加如下代码
//apply plugin: '插件 ID'
apply plugin: 'com.example.plugin'
//apply plugin: 实现类
//apply plugin: com.example.plugin.PluginBuildSrc
应用插件时,指定插件 ID 或指定插件的实现类都可以,但指定插件 ID 的形式更为简短及灵活,在实际开发中也更为常见。
在 PluginBuildSrcDemo
目录下执行 gradle build
命令进行构建,可看到如下输出
> Configure project :
hello from buildSrc plugin
> Task :buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
No dependencies
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
其中第 2 行是我们在 buildSrc 模块中定义的 Gradle 插件所打印日志,表明 buildSrc 模块 中的自定义插件在根项目中已生效。
4. 创建 SubModule
子模块
buildSrc 模块中定义的插件可以在同一项目的任意模块的构建脚本中使用,接下来便演示在 SubModule 子模块中的应用。
4.1 创建 SubModule 目录与构建脚本
// 1. 在 PluginBuildSrcDemo 目录下创建 SubModule 目录
cd PluginBuildSrcDemo && mkdir SubModule
// 2. 在 SubModule 目录下新建 gradle 构建脚本
cd SubModule
touch build.gralde
PluginBuildSrcDemo/SubModule/build.gradle
的内容如下
apply plugin: 'com.example.plugin'
4.2 将 SubModule 模块关联到 PluginBuildSrcDemo 项目中
在 PluginBuildSrcDemo
目录下新建 settings.gradle
文件,内容如下
// 将SubModule 子模块添加到 PluginBuildSrcDemo 项目模块中
include ':SubModule'
此时在 PluginBuildSrcDemo
目录下使用 tree
命令,可以看到项目当前的目录结构如下
PluginBuildSrcDemo
.
├── SubModule
│ └── build.gradle
├── build.gradle
├── buildSrc
│ ├── build.gradle
│ └── src
│ └── main
│ └── kotlin
│ └── com
│ └── example
│ └── plugin
│ └── PluginBuildSrc.kt
└── settings.gradle
5. 在 SubModule
模块执行构建命令
cd PluginBuildSrcDemo/SubModule
gradle build
得到如下输出
> Configure project :SubModule
hello from buildSrc plugin
> Task :SubModule:buildEnvironment
------------------------------------------------------------
Project :SubModule
------------------------------------------------------------
classpath
No dependencies
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
独立项目方式
采用 buildSrc 模块方式时,Gradle 会妥善处理 buildSrc 模块的构建脚本与源码,并将其添加到当前项目的 classpath 中。但 buildSrc 方式的插件只能在项目内共享与复用,若要在其他项目中使用该插件,还需要再进行下列操作
- 将插件发布到 maven 仓库(任意仓库)
- 在需要应用该插件的构建脚本中的 repository 部分添加该插件所在的 maven 仓库
- 在需要应用该插件的构建脚本中的 classpath 部分添加该插件对应的 maven 坐标 (group : id : version)
因为是在其他项目中使用该项目 buildSrc 模块 中的自定义 Gradle 插件,所以 Gradle 的 buildSrc 保留目录优势不再。如果将模块名由 buildSrc
修改为其他名称,则可将其称为独立的 Gradle 插件模块。
在本小节中,我们主要学习 gradle 插件的发布与使用。
1. 创建 gradle 插件项目
与 buildSrc 方式相同,先创建构建脚本与自定义插件类
mkdir StandaloneDemo
cd StandaloneDemo
touch build.gradle
mkdir src/main/kotlin/com/example/plugin
touch src/main/kotlin/com/example/plugin/StandalonePlugin.kt
StandaloneDemo/build.gradle
的内容如下
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
id 'java-gradle-plugin'
}
gradlePlugin{
plugins{
sometag{
id = 'com.example.plugin'
implementationClass = 'com.example.plugin.StandalonePlugin'
}
}
}
StandaloneDemo/src/main/kotlin/com/example/plugin/StandalonePlugin.kt
的内容如下
package com.example.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class StandalonePlugin : Plugin<Project> {
override fun apply(target: Project) {
println("hello from standalone plugin")
}
}
2. 将 gradle 插件发布到 maven 仓库
2.1 在 StandaloneDemo/build.gradle
文件中配置发布信息
使用 maven-publish
插件将自定义插件发布到本地 maven 仓库中,如下所示
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
id 'java-gradle-plugin'
+ //1. 应用 maven-publish 插件
+ id 'maven-publish'
}
gradlePlugin{
plugins{
sometag{
id = 'com.example.plugin'
implementationClass = 'com.example.plugin.StandalonePlugin'
}
}
}
+//2. 设置发布相关配置
+publishing {
+ publications {
+ //3. 将插件发布到 maven 仓库
+ maven(MavenPublication) {
+ //4. 设置插件的 maven 坐标
+ groupId 'com.example'//组织 ID
+ artifactId 'plugin' //制品 ID
+ version 'snapshot' //制品版本
+ from components.kotlin
+ }
+ }
+ //5. 设置发布仓库
+ repositories {
+ // 6. 发布到本地 maven 仓库
+ mavenLocal()
+ }
+}
2.2 使用 publishMavenPublicationToMavenLocal
任务将插件发布到本地仓库
cd StandaloneDemo
gradle publishMavenPublicationToMavenLocal
执行以上命令后,gradle 会把 StandaloneDemo
中的代码编译打包后发布到本地 maven 仓库中,本地 maven 仓库通常存放于当前用户目录下,具体路径为
- Mac:
~/.m2/repository
- Win:
C:\Users\当前用户名\.m2\repository
我们可以在此目录下看到刚刚发布的插件,如下图所示
3. 在其他项目中使用本地 maven 仓库中的 gradle 插件
3.1 新建 OtherProject
项目
mkdir OtherProject
cd OtherProject
touch build.gradle
build.gradle
的文件内容如下,相比 buildSrc 方式,应用时多了 11 行的 buildscript 相关的配置信息。
+buildscript {
+ repositories {
+ //1. 为当前构建脚本添加插件所在的 maven 仓库,本例中为 maven 本地仓库
+ mavenLocal()
+ }
+ dependencies {
+ //2. 为当前构建脚本添加如下依赖
+ //`com.exaple`、`plugin`、`snapshot` 是在上一步中设置的 maven 三维坐标
+ classpath 'com.example:plugin:snapshot'
+ }
+}
//3. 应用独立插件项目中的自定义插件
// apply plugin: '插件 ID'
apply plugin: 'com.example.plugin'
3.2 构建 OtherProject
项目
cd OtherProject
gradle build
输入以上命令,得到如下输出
> Configure project :
hello from standalone plugin
> Task :buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
\--- com.example:plugin:snapshot
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
小结
本文演示了 gradle 插件的三种创建方式,相关代码已上传至 github 中,点此即可查看。行文匆忙难免疏忽,如有遗漏还请斧正。
- **本文作者: **Geek5Nan
- 本文链接: http://geek5nan.github.io/2019/09/07/Developing-Gradle-Plugin-1/
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
开发效率优化之自动化构建系统Gradle(二)下篇的更多相关文章
- 开发效率优化之自动化构建系统Gradle(二)上篇
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将以下两个内容来介绍自动化构建系统Gradle: gra ...
- 团队项目·冰球模拟器——cmake 自动化构建系统的配置文件的编写
1 前言 考虑到命令行界面下编译程序并不如在 IDE 那么直观,再考虑到各位队友对 Linux 并不熟悉,如何大幅度地减轻整个项目的开发复杂度就是一个很重要的问题. 在 Linux 下有个很古老但很有 ...
- 开发效率优化之Git分布式版本控制系统(一)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680本篇文章将先从Git分布式版本控制系统来阐述开发效率优化 一,企业 ...
- 基于 Groovy 的自动化构建工具 Gradle 入门(转)
本人工作之初没有使用自动化构建,后来敏捷了,开始使用 Ant - 完全面向过程的定义步骤,不进行依赖管理.再发展到 Maven,面向对象的方式管理工程,有了依赖的管理,JAR 包统一从中央仓库获得,保 ...
- Django学习之十三:提高页面开发效率减少冗余的模板系统
目录 Django 模板 模板语法 逻辑语法 函数式过滤器 内置filter 功能tag 注释 内置tag 导入三方tag and filter(load) 过滤器和功能tag的区别 自定义tag和f ...
- 自动化构建工具gradle安装教程(使用sdkman安装)
gradle是什么?(wiki解释) Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具.它使用一种基于Groovy的特定领域语言来声明项目设置,而不是传统的 ...
- 如何用jenkins实现自动化构建新版本和二维码下载
最近公司开发了自己的app,研发过程中对于测试人员来说,经常会像开发的人员询问,有没有最新的包啊(apk打包后的新版本),以免你测试的时候,提交了一些缺陷,实际上人家已经解决了.当然你也可以说你们公司 ...
- 构建工具-----Gradle(二)-----myeclipse 10和myeclipse2015安装gradle插件----其他版本的myeclipse类似
我们需要给myeclipse安装gradle的插件.这样myeclipse就能识别到gradle项目了,直接加载进去即可. 我们先安装配置系统命令行的gradle,挺简单的,下载后配置环境变量即可,详 ...
- 自动化监控系统(二)连接数据库,创建app,添加model,同步数据库
数据库我使用:mysql5.7 程序连接数据库的模块:pymysql 一.创建数据库: dbname:automatedmonitor 二.使用pip安装pymysql,这里我直接在pycharm上安 ...
随机推荐
- Cocos2d-x之String
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 在Cocos2d-x中能够使用的字符串constchar*.std::string和cocos2d::__String等,其中const ...
- Dubbo 系列(07-4)集群容错 - 集群
BDubbo 系列(07-4)集群容错 - 集群 [toc] Spring Cloud Alibaba 系列目录 - Dubbo 篇 1. 背景介绍 相关文档推荐: Dubbo 集群容错 - 实战 D ...
- c# 自定义控件之 ComboBox
winform 自带的 combobox 无法支持根据输入文本匹配列表中的项目,需要使用自定义控件. public class MyCombobox : ComboBox { //初始化数据项 pri ...
- python学习笔记--类(一)
# 类是为了代码重用 class First: #类 pass #实例 = 类名() obj = First() # 类是一种产生实例的工厂# 类和模块的差异在于,内存中特定的模块只有一个实例(所以我 ...
- elasticsearch 英文数字组合字符串模糊检索
不分词,然后用wildcard查询 { "query": { "wildcard": { "字段名": "*123*" ...
- 转:几款免费的图表js插件
1,ichartjs(国产)(http://www.ichartjs.com/) ===============强烈推荐ichartjs是一款优秀的国产开源插件,作者是王鹤,英文名taylor,毕业 ...
- Codeforces 356D 倍增优化背包
题目链接:http://codeforces.com/contest/356/problem/D 思路(官方题解):http://codeforces.com/blog/entry/9210 此题需要 ...
- 【leetcode】sudokuSolver数独解题
0.摘要 小时候在报纸上玩过数独,那时候觉得很难,前几天在leetcode上遇到了这个题,挺有意思于是记录下来 一般一道数独题,就像他给的例子这样,9*9的格子,满足 行,列 ,宫均取1-9的数,切互 ...
- 03.线程的通知notify与等待wait
wait().notify.notifyAll()方法 wait().notify().notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态. 这三个方法最终调用的都是jv ...
- 新建maven项目index.jsp文件报错处理
最近用eclipse新建了一个maven项目,结果刚新建完成index.jsp页面就报错了,先把错误信息贴出来看看 后来就找资料,结果发现两种解决办法,希望可以帮助用得上的人! 第一种:直接在pom. ...