Gradle干嘛的
Gradle是一款自动化开源构建工具,目前android开发者好像没有谁离开它(当然,有那种大神自己通过命令行编译的,不在范围内)。什么是构建工具,对于android开发者简单来说就是将你的代码和资源等等构建出相应的apk或者aar。下面这张图是android的打包流程图
可以发现是身份复杂的,包括java代码的编译,dex文件的生成,apk签名等等一系列工具过程,如果每一个节点都由开发者自己去做,那无疑对生产效率是大打折扣,而gradle通过自身提供的api可以让这一系列流程结合起来,只需要相应的输入,就给你想要的输出。
构建要素
一个Gradle构建通常包含三个基本构建块:project,task和property。每个构建至少包含一个project,一个project可以包含一个或者多个task,project和task可以暴露属性来控制构建。
project
project在android项目中往往对应一个module,每个project至少包含一个build.gradle。而project中又可以注册多个task。
task
task可以理解为具体的行为动作,无论是打印还是编译java代码,都可以在task中定义和执行,task就是具体的干活人,上面android打包流程图中,几乎每个节点就是一个task,gradle通过构建有向无环图,来顺序执行图中相应的task。
property
project和task都提供了可以通过getter和setter方法访问的属性,外部使用者可以通过属性向构建过程中传递相应的参数,以此来改变构建的不同流程或者结果。
Gradle插件
说了这么半天,那么什么是Gradle插件呢?Gradle插件打包了可重用的构建逻辑,可在许多不同的项目和构建中使用。一般来看,一个Gradle插件往往会包含多个task(当然也可以不包括),我们在项目中看到的
apply plugin: 'com.android.application'
这其实就是我们应用了一个pluginId为com.android.application的插件,我们在编译android项目过程中用到的很多task其实都是在这个plugin中定义的。
如何自定义Gradle插件
目前定义Gradle插件的方式有三种:gradle脚本、 buildSrc项目、Standalone项目,其中gradle脚本和创建buildSrc module的项目不能通过依赖引入,只能拷贝到相应的工程使用,比较麻烦,Standalone项目可以发布项目到maven,然后通过gradle的classpath引入,但是不好调试,这里我们使用buildSrc module编写插件,然后发布生成的jar包到maven,之后其他项目就可以通过gradle引入了。
编写老砒霜Gradle差价
1.新建一个项目,创建buildSrc module
这里注意的是如果创建啊玩builddSrc后编译报错提示:
'buildSrc' cannot be used as a project name as it is a reserved name,那么就把settings.gradle中的include:‘buildSrc'移除掉,因为在Gradle6.3以后buildSrc现在被保留作为一个工程或者子工程的名字。以前Gradle没有阻止使用buildSrc作为一个在 多工程构建或者作为一个被包括在构建列表名称的 子工程的名字。现在,这样已经不允许了。现在buildSrc这个名字被保留给传统的构建额外逻辑的buildSrc工程。这次改变没有影响典型的buildSrc的用法,仅仅影响在setting.gradle文件中使用include(“buildSrc”) or includeBuild(“buildSrc”)方式构建。
2.修改buildSrc中的gradle文件
buildscript {
ext.kotlin_version = "1.4.20"
repositories {
google()
jcenter()
}
dependencies {
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
}
}
apply plugin: 'java-library'
apply plugin: 'kotlin'
java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
repositories {
jcenter()
google()
}
dependencies {
implementation gradleApi()
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
buildSrc module会独立于目前的根项目,所以它的配置不会走最外层的settings.gradle配置,所以需要在这个gradle文件中指定相应的buildSrcipt,也就是编译环境,这里的classpath其实就是对插件的引用。
3.定义plugin
class LaoPiShuangPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("HelloProject", PrintProjectNameTask::class.java)
}
}
open class PrintProjectNameTask : DefaultTask() {
override fun getGroup(): String? = "laopishuang"
@TaskAction
fun execute() {
project.rootProject.subprojects.forEach {
println("hello ${it.name}")
}
}
}
这里我们定义一个名为LaoPiShuangPlugin的plugin,这里我们通过
project.tasks.register("HelloProject", PrintProjectNameTask::class.java)
注册了一个task,task的名称为HelloProject,PrintProjectNameTask执行会打印当前project根project的所有project的名字
4.定义plugin id
按照图示路径添加一个名为laopishuang.properties的文件,其中laopishuang就是plugin id的名称。laopishuang.properties的内容为
implementation-class=com.skateboard.laopishuang.LaoPiShuangPlugin
填入刚才LaoPiShuangPlugin的全类名。
5.使用
在app modul的build.gradle中调用
apply plugin:'laopishuang'
在命令行执行./gradlew HelloProject,就会打印出相应的project name
其中HelloProject就是刚才在plugin中注册的task的名称,或者你可以在gradle面板中在laopishuang下找到该task,双击执行,laopishuang对应刚才定义的PrintProjectNameTask的复写的getGroup()返回的值
结语
之后会围绕android相关的插件编写一个系列,不限于Gradle插件,这期的例子较为简单,下期写一个复杂一些的Gradle插件
欢迎关注我的公众号:"滑板上的老砒霜"