- 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 包文件,咱們須要分開單獨處理。
輸入文件有了,咱們要先肯定輸出路徑,這裏要注意,輸出路徑必須用特殊方式獲取,而不能本身隨意指定,不然下一個任務就沒法獲取你此次的輸出文件了,編譯失敗。
對輸入的文件進行處理,也是核心的步驟;作代碼插入、修改等操做就是在這個步驟進行操做。