Gradle通關(guān)系列(三)-深入Project

咋一看標(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ì)完成輸出


WX20210210-233126.png

使用模板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è)步驟:

  1. 建立項(xiàng)目結(jié)構(gòu) - 配置有哪些項(xiàng)目需要參與構(gòu)建
  2. 配置項(xiàng)目 - 配置Project的實(shí)例拳亿,做一些屬性配置(properties、extensions愿伴、conventions肺魁、extra等),做一些任務(wù)配置(定義項(xiàng)目完成構(gòu)建需要的一系列任務(wù))
  3. 執(zhí)行任務(wù)隔节,完成構(gòu)建輸出

其實(shí)上面三步就是Gradle的三個(gè)階段:初始化階段鹅经、配置階段、執(zhí)行階段

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怎诫,一起剝皮案震驚了整個(gè)濱河市瘾晃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌幻妓,老刑警劉巖蹦误,帶你破解...
    沈念sama閱讀 212,332評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異肉津,居然都是意外死亡强胰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門妹沙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偶洋,“玉大人,你說我怎么就攤上這事距糖⌒眩” “怎么了?”我有些...
    開封第一講書人閱讀 157,812評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵悍引,是天一觀的道長(zhǎng)恩脂。 經(jīng)常有香客問我,道長(zhǎng)趣斤,這世上最難降的妖魔是什么俩块? 我笑而不...
    開封第一講書人閱讀 56,607評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上典阵,老公的妹妹穿的比我還像新娘奋渔。我一直安慰自己,他們只是感情好壮啊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,728評(píng)論 6 386
  • 文/花漫 我一把揭開白布嫉鲸。 她就那樣靜靜地躺著,像睡著了一般歹啼。 火紅的嫁衣襯著肌膚如雪玄渗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,919評(píng)論 1 290
  • 那天狸眼,我揣著相機(jī)與錄音藤树,去河邊找鬼。 笑死拓萌,一個(gè)胖子當(dāng)著我的面吹牛岁钓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播微王,決...
    沈念sama閱讀 39,071評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼屡限,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了炕倘?” 一聲冷哼從身側(cè)響起钧大,我...
    開封第一講書人閱讀 37,802評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罩旋,沒想到半個(gè)月后啊央,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,256評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涨醋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,576評(píng)論 2 327
  • 正文 我和宋清朗相戀三年瓜饥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片东帅。...
    茶點(diǎn)故事閱讀 38,712評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡压固,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出靠闭,到底是詐尸還是另有隱情,我是刑警寧澤坎炼,帶...
    沈念sama閱讀 34,389評(píng)論 4 332
  • 正文 年R本政府宣布愧膀,位于F島的核電站,受9級(jí)特大地震影響谣光,放射性物質(zhì)發(fā)生泄漏檩淋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,032評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蟀悦。 院中可真熱鬧媚朦,春花似錦、人聲如沸日戈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浙炼。三九已至份氧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弯屈,已是汗流浹背蜗帜。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留资厉,地道東北人厅缺。 一個(gè)月前我還...
    沈念sama閱讀 46,473評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宴偿,于是被迫代替她去往敵國和親店归。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,606評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容