咋一看標(biāo)題有點(diǎn)開車嫌疑...
沒錯(cuò),趕緊上車...
Project接口
Project接口中包含了你主要與構(gòu)建交互的api震肮,這些api你可以直接在gradle腳本中使用。每一個(gè)Project對(duì)象與build.gradle構(gòu)建腳本是一對(duì)一的關(guān)系炭臭,Gradle為每個(gè)項(xiàng)目都創(chuàng)建了一個(gè)Project對(duì)象用來參與構(gòu)建负蚊,步驟如下:
- 為構(gòu)建創(chuàng)建Settings實(shí)例
- 解析settings.gradle腳本,如果存在浆兰,就針對(duì)Settings對(duì)象來配置它
- 用配置好的Settings對(duì)象創(chuàng)建Project實(shí)例結(jié)構(gòu)
- 最后解析每個(gè)項(xiàng)目的build.gradle腳本磕仅,來配置它的Project實(shí)例
Tasks
項(xiàng)目本質(zhì)上是Task對(duì)象的集合。每個(gè)task執(zhí)行一些基本的工作簸呈,例如編譯類榕订,或運(yùn)行單元測(cè)試,或壓縮WAR文件蜕便。 可以使用TaskContainer上的create()方法之一將任務(wù)添加到項(xiàng)目中劫恒,并對(duì)其操作
Dependencies
一個(gè)項(xiàng)目為了完成它的工作通常會(huì)有很多依賴項(xiàng)。同樣轿腺,一個(gè)項(xiàng)目通常會(huì)產(chǎn)生許多其他項(xiàng)目可以使用的artifact两嘴。這些依賴項(xiàng)在configuration中分組,可以從repository中檢出和上傳族壳,可以通過getConfigurations()方法返回的ConfigurationContainer來管理configurations憔辫,通過getDependencies()方法返回的DependencyHandler來管理dependencies,通過getArtifacts()方法返回的ArtifactHandler 來管理artifacts决侈,通過getRepositories()方法返回的RepositoryHandler來管理repositories螺垢。
Properties
以下內(nèi)容都可以被看作成Project的屬性
- Project自身的屬性以及方法
- extra屬性
- Extension
- Convention
- Task
- 從父項(xiàng)目中集成來的extra喧务、convention屬性
可以通過Object property(String propertyName)方法獲取會(huì)按以上流程檢索屬性值
從自定義構(gòu)建理解Project
我們?cè)诘谝黄私獾揭粋€(gè)很重要的點(diǎn)赖歌,每一個(gè)Gradle構(gòu)建都是由一個(gè)或多個(gè)Project組成,Project代表的取決于你想用Gradle讓他做什么 功茴。Project又是一系列task的集合庐冯。
假如一個(gè)Project需要打包指定路徑下的資源,并輸出為zip包坎穿,這就是我們需要Gradle為我們做的
直接約定路徑展父,將文件打包,輸出zip
import org.gradle.kotlin.dsl.support.zipTo
task("zipRes") {
group = "output"
doLast {
val resPath = "src/res"
val file = file(resPath)
zipTo(file("output.zip"), file)
}
}
執(zhí)行zipRes task玲昧,將會(huì)完成輸出
使用模板task
向一些常規(guī)的copy栖茉,壓縮操作,Gradle都有內(nèi)置的模板task孵延,我們可以直接使用內(nèi)置的模板task
tasks.register<Zip>("zipRes") {
group = "output"
from("src/res")
this.destinationDir = file("./")
this.archiveName = "output.zip"
this.archiveExtension.set("zip")
}
拓展Task配置
我們上面使用的資源路徑是寫死的吕漂,我們需要將他弄成配置項(xiàng)
import org.gradle.kotlin.dsl.support.zipTo
//創(chuàng)建自定義的ZipRes Task,將配置作為task的屬性
open class ZipResTask : DefaultTask() {
var resPath: String = "src/res"
var outputPath: String = "output.zip"
//task的執(zhí)行任務(wù)
@TaskAction
fun zipRes() {
println(project.name)
println(resPath)
println(outputPath)
val resPath = resPath
val resFile = project.file(resPath)
val zipFile = project.file(outputPath)
zipTo(zipFile, resFile)
}
}
//注冊(cè)任務(wù)
tasks.register("zipRes", ZipResTask::class) {
//配置任務(wù)
resPath = "resSrc"
outputPath = "resOutput.zip"
}
這樣我們?cè)谧?cè)task時(shí)就可以配置這兩個(gè)參數(shù)
構(gòu)建拓展成插件
現(xiàn)在由于很多項(xiàng)目都需要使用這樣構(gòu)建尘应,我們需要將他做成插件的形式
我們把上面的構(gòu)建內(nèi)容寫到custom_build.gradle.kts文件中惶凝,并在build.gradle.kts中進(jìn)行依賴
apply(from = "custom_build.gradle.kts")
這樣一來其他項(xiàng)目依賴這個(gè)腳本就能自動(dòng)實(shí)現(xiàn)上述構(gòu)建邏輯了吼虎,咦,不對(duì)又不能配置了苍鲜,難道我要自己創(chuàng)建task然后去配置resPath思灰、outputPath屬性么
拓展Project的配置
//custom_build.gradle.kts
import org.gradle.kotlin.dsl.support.zipTo
open class ZipResExtensions {
var resPath: String = ""
var outputPath: String = ""
}
extensions.create<ZipResExtensions>("zipRes")
open class ZipResTask : DefaultTask() {
@TaskAction
fun zipRes() {
val zipResExtensions = project.extensions.getByName<ZipResExtensions>("zipRes")
val resPath = zipResExtensions.resPath
val file = project.file(resPath)
zipTo(project.file(zipResExtensions.outputPath), file)
}
}
tasks.register("zipRes", ZipResTask::class)
apply(from = "custom_build.gradle.kts")
//此處由于Kotlin靜態(tài)強(qiáng)類型語言,需要處理依賴關(guān)系混滔,使用反射去配置值
extensions.configure<Any>("zipRes") {
val resPathSetter = this.javaClass.getMethod("setResPath", String::class.java)
resPathSetter.invoke(this, "resSrc")
val outputPathSetter = this.javaClass.getMethod("setOutputPath", String::class.java)
outputPathSetter.invoke(this, "resOutput.zip")
}
如果使用groovy的話代碼就相當(dāng)簡(jiǎn)單了
apply 'from': 'custom.gradle'
zipRes {
resPath = 'resSrc'
outputPath = 'resOutput.zip'
}
上傳輸出文件
項(xiàng)目構(gòu)建的輸出現(xiàn)在需要上傳洒疚,我們添加一個(gè)上傳的task
//custom_build.gradle.kts
import org.gradle.kotlin.dsl.support.zipTo
open class ZipResExtensions {
var resPath: String = ""
var outputPath: String = ""
}
extensions.create<ZipResExtensions>("zipRes")
open class ZipResTask : DefaultTask() {
@TaskAction
fun zipRes() {
val zipResExtensions = project.extensions.getByName<ZipResExtensions>("zipRes")
val resPath = zipResExtensions.resPath
val file = project.file(resPath)
zipTo(project.file(zipResExtensions.outputPath), file)
}
}
//創(chuàng)建配置項(xiàng)
configurations {
create("zipResRelease")
}
//為配置定義artifact
afterEvaluate {
artifacts {
val zipResExtensions = project.extensions.getByName<ZipResExtensions>("zipRes")
add("zipResRelease", project.file(zipResExtensions.outputPath))
}
}
val zipRes = tasks.register("zipRes", ZipResTask::class)
tasks.register("uploadOutput", Upload::class) {
dependsOn(":zipRes")
repositories {
flatDir {
dir("uploadDir")
}
}
configuration = configurations["zipResRelease"]
}
執(zhí)行uploadOutput命令,完成zipRes并上傳
總結(jié)
以上的例子主要是為了對(duì)Gradle構(gòu)建整體有一個(gè)清晰的認(rèn)識(shí)坯屿,整個(gè)構(gòu)建過程其實(shí)就是以下幾個(gè)步驟:
- 建立項(xiàng)目結(jié)構(gòu) - 配置有哪些項(xiàng)目需要參與構(gòu)建
- 配置項(xiàng)目 - 配置Project的實(shí)例拳亿,做一些屬性配置(properties、extensions愿伴、conventions肺魁、extra等),做一些任務(wù)配置(定義項(xiàng)目完成構(gòu)建需要的一系列任務(wù))
- 執(zhí)行任務(wù)隔节,完成構(gòu)建輸出
其實(shí)上面三步就是Gradle的三個(gè)階段:初始化階段鹅经、配置階段、執(zhí)行階段