- Github: github.com/gradle/grad…
- gradle.org/kotlin/
- Project API: docs.gradle.org/current/jav…
- Task API: docs.gradle.org/current/jav…
- TaskContainer API: docs.gradle.org/current/jav…
文章涉及到的 demo 代码:github.com/linkaipeng/…html
task 直接写在 build.gradle.kts
文件里面 如:java
tasks.register("buildScriptTask") {
doLast {
println("hello buildScript~")
}
}
复制代码
执行:./gradlew -q buildScriptTaskandroid
-q
: quiet. Log errors only.git
build script 中直接定义的方式,做用范围仅仅是在当前的 build.gradle.kts
文件中,那么若是有的 task 但愿被多个构建脚本所应用,那么能够将其放在独立的项目中,再由 build.gradle.kts
引用。github
一、继承 DefaultTask,使用注解 @TaskAction 指定任务执行的方法api
open class MyHelloTask : DefaultTask() {
@TaskAction
fun hello() {
println("hello MyHelloTask task ~")
}
}
复制代码
二、须要使用到的项目进行依赖,(后面 plugin 会讲到,这里先不讲)bash
三、项目 build.gradle.kts
中引用app
import me.linkaipeng.task.MyHelloTask
...
tasks.register<MyHelloTask>("myHelloTask")
复制代码
执行 ./gradlew -q myHelloTaskmaven
gradle.properties
获取gradle.properties
中加入ide
me.linkaipeng.propertie.hi=hi hi
复制代码
获取代码
val propFromFile = project.properties["me.linkaipeng.propertie.hi"]
println("propFromFile = $propFromFile")
复制代码
在执行任务的命令行后面加上 -Pxxx,好比
./gradlew -q readPropertiesTask -Phi2=tete
复制代码
那么就输入了一个名为 hi2 的参数;
若是要输入多个参数,那么
./gradlew -q readPropertiesTask -Phi2=tete -Phi3=rr
复制代码
task("developTask") {
group = "software"
description = "develop software."
doLast {
println("develop")
}
}
task("compileTask") {
group = "software"
dependsOn("developTask")
doLast {
println("compile")
}
}
复制代码
好比,编译任务要依赖开发任务,那么能够用 dependsOn("developTask")
指定依赖关系;
执行 ./gradlew -q compileTask
结果:
develop
compile
复制代码
task("developTask") {
group = "software"
description = "develop software."
doLast {
println("develop")
}
}
task("compileTask") {
group = "software"
mustRunAfter("developTask")
doLast {
println("compile")
}
}
task("testingTask") {
group = "software"
dependsOn("developTask")
dependsOn("compileTask")
doLast {
println("testing")
}
}
复制代码
好比,执行测试任务的时候,须要依赖到开发和编译任务,可是必需要求开发任务在编译任务以前,那么能够经过mustRunAfter("developTask")
指定
执行 ./gradlew -q testingTask
假如没有指定的话,那么会按照字母顺序执行,结果为:
compile
develop
testing
复制代码
有指定编译任务必须在开发以后执行,那么结果则为:
develop
compile
testing
复制代码
指定任务执行以后,最后执行的任务,好比,测试任务完成后进行打包操做
如今增长打包任务
task("packagingTask") {
group = "software"
doLast {
println("packaging")
}
}
复制代码
而后在测试任务中指定
task("testingTask") {
group = "software"
dependsOn("developTask")
dependsOn("compileTask")
finalizedBy("packagingTask")
doLast {
println("testing")
}
}
复制代码
执行 ./gradlew -q testingTask
结果:
develop
compile
testing
packaging
复制代码
相似 mustRunAfter
,优先级 mustRunAfter
更高
顾名思义,就是条件性的不执行某个任务
相似条件语句,只有知足当前条件,则执行
val skipDemoTask by tasks.registering {
doLast {
println("skipDemoTask ~")
}
}
skipDemoTask {
onlyIf { !project.hasProperty("skip") }
}
复制代码
不跳过,执行 ./gradlew -q skipDemoTask
当检测到参数 skip
,则跳过
跳过,执行 ./gradlew -q skipDemoTask -Pskip
借助异常中止执行
val exceptionDemoTask by tasks.registering {
doLast {
if (project.hasProperty("exception")) {
throw StopExecutionException()
}
println("exceptionDemoTask ~")
}
}
复制代码
./gradlew -q exceptionDemoTask -Pexception
经过控制 task 的 enabled
,达到跳过效果,false 的时候,不执行
val enableDemoTask by tasks.registering {
doLast {
println("enableDemoTask ~")
}
}
enableDemoTask {
enabled = false
}
复制代码
执行 ./gradlew -q enableDemoTask
能够在构建命令后面使用 -P
传入命令
传入参数:
./gradlew -q testTask -Phost=test.test.com
复制代码
获取参数:
project.properties.keys.map {
if("host" == it) {
println("propertie key = $it, value = ${project.properties[it]}")
}
}
复制代码
插件直接写在 build.gradle.kts
文件里面 如:
class TestPlugin: Plugin<Project> {
override fun apply(target: Project) {
target.task("testTask") {
doLast {
print("This is testTask in TestPlugin.")
}
}
}
}
apply<TestPlugin>()
复制代码
执行:./gradlew -q testTask
buildSrc
以独立 module 存在,位置和目录结构以下:
.
├── build.gradle.kts
├── buildSrc
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── kotlin
└── settings.gradle.kts
复制代码
buildSrc/build.gradle.kts
在 build.gradle.kts 中声明插件的 name、id 等信息
gradlePlugin {
plugins {
create("PrintMethodNamePlugin") {
id = "print-method-plugin"
implementationClass = "com.test.plugin.PrintMethodNamePlugin"
}
}
}
复制代码
这样项目中就可使用:
plugins {
id("com.android.application")
...
id("print-method-plugin")
}
复制代码
执行:./gradlew transformClassesWithPrintMethodNameTransformForDebug
costTimePlugin
.
├── build.gradle.kts
├── buildSrc
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── kotlin
│ └── resources
│ └── META-INF.gradle-plugins
│ └── me.linkaipeng.cost-time.properties
└── settings.gradle.kts
复制代码
resources/META-INF.gradle-plugins/me.linkaipeng.cost-time.properties
必须存在,是为了声明插件让项目识别到,内容以下:
implementation-class=me.linkaipeng.plugin.CostTimeStandAlongPlugin
复制代码
build.gradle.kts
文件声明(详细见源代码):
plugins {
...
`maven-publish`
}
group = "me.linkaipeng.plugin"
version = "1.0.3"
...
publishing {
repositories {
maven {
url = uri("../repo")
}
}
publications {
register("mavenJava", MavenPublication::class) {
from(components["java"])
artifact(sourcesJar.get())
}
}
}
复制代码
工程 build.gradle.kts
配置本地 repo 路径和依赖:
repositories {
maven {
url = uri("file:///Users/linkaipeng/Documents/demos/GradleKotlinDemo/repo/")
}
}
dependencies {
...
classpath("me.linkaipeng.plugin:costTimePlugin:1.0.3")
}
复制代码
这样项目中就可使用:
plugins {
id("com.android.application")
...
id("me.linkaipeng.cost-time")
}
复制代码
id 便是 刚刚定义的 properties 文件的文件名
执行:./gradlew transformClassesWithCostTimeStandAlongTransformForDebug
You can include the source for the plugin directly in the build script. This has the benefit that the plugin is automatically compiled and included in the classpath of the build script without you having to do anything. However, the plugin is not visible outside the build script, and so you cannot reuse the plugin outside the build script it is defined in.
buildSrc
projectYou can put the source for the plugin in the rootProjectDir/buildSrc/src/main/groovy directory (or rootProjectDir/buildSrc/src/main/java or rootProjectDir/buildSrc/src/main/kotlin depending on which language you prefer). Gradle will take care of compiling and testing the plugin and making it available on the classpath of the build script. The plugin is visible to every build script used by the build. However, it is not visible outside the build, and so you cannot reuse the plugin outside the build it is defined in.
You can create a separate project for your plugin. This project produces and publishes a JAR which you can then use in multiple builds and share with others. Generally, this JAR might include some plugins, or bundle several related task classes into a single library. Or some combination of the two.
用来定义 transform 任务的名称。
用来限定这个 transform 能处理的文件类型,通常来讲咱们要处理的都是 class 文件,就返回 TransformManager.CONTENT_CLASS,固然若是你是想要处理资源文件,可使用TransformManager.CONTENT_RESOURCES 。
指定的的就是哪些文件了。好比说咱们若是想处理 class 文件,但 class 文件能够是当前module的,也能够是子 module 的,还能够是第三方 jar 包中的.
Type | 做用域 |
---|---|
PROJECT | 只处理当前项目 |
SUB_PROJECTS | 只处理子项目 |
PROJECT_LOCAL_DEPS | 只处理当前项目的本地依赖,例如 jar, aar |
SUB_PROJECTS_LOCAL_DEPS | 只处理子项目的本地依赖,例如 jar, aar |
EXTERNAL_LIBRARIES | 只处理外部的依赖库 |
PROVIDED_ONLY | 只处理本地或远程以provided形式引入的依赖库 |
TESTED_CODE | 测试代码 |
是否支持增量编译。
获取输入的 class 文件,而后作些修改,最后输出修改后的 class 文件。
一种是本 module 本身的 src下的源码编译后的 class 文件,一种是第三方的 jar 包文件,咱们须要分开单独处理。
输入文件有了,咱们要先肯定输出路径,这里要注意,输出路径必须用特殊方式获取,而不能本身随意指定,不然下一个任务就没法获取你此次的输出文件了,编译失败。
对输入的文件进行处理,也是核心的步骤;作代码插入、修改等操做就是在这个步骤进行操做。