Gradle通关系列(三)-深入Project

咋一看标题有点开车嫌疑...

没错,赶紧上车...

Project接口

Project接口中包含了你主要与构建交互的api,这些api你可以直接在gradle脚本中使用。每一个Project对象与build.gradle构建脚本是一对一的关系,Gradle为每个项目都创建了一个Project对象用来参与构建,步骤如下:

  • 为构建创建Settings实例
  • 解析settings.gradle脚本,如果存在,就针对Settings对象来配置它
  • 用配置好的Settings对象创建Project实例结构
  • 最后解析每个项目的build.gradle脚本,来配置它的Project实例

Tasks

项目本质上是Task对象的集合。每个task执行一些基本的工作,例如编译类,或运行单元测试,或压缩WAR文件。 可以使用TaskContainer上的create()方法之一将任务添加到项目中,并对其操作

Dependencies

一个项目为了完成它的工作通常会有很多依赖项。同样,一个项目通常会产生许多其他项目可以使用的artifact。这些依赖项在configuration中分组,可以从repository中检出和上传,可以通过getConfigurations()方法返回的ConfigurationContainer来管理configurations,通过getDependencies()方法返回的DependencyHandler来管理dependencies,通过getArtifacts()方法返回的ArtifactHandler 来管理artifacts,通过getRepositories()方法返回的RepositoryHandler来管理repositories。

Properties

以下内容都可以被看作成Project的属性

  • Project自身的属性以及方法
  • extra属性
  • Extension
  • Convention
  • Task
  • 从父项目中集成来的extra、convention属性

可以通过Object property(String propertyName)方法获取会按以上流程检索属性值

从自定义构建理解Project

我们在第一篇了解到一个很重要的点,每一个Gradle构建都是由一个或多个Project组成,Project代表的取决于你想用Gradle让他做什么 。Project又是一系列task的集合。

假如一个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)
    }
}

执行zipRes task,将会完成输出


WX20210210-233126.png

使用模板task

向一些常规的copy,压缩操作,Gradle都有内置的模板task,我们可以直接使用内置的模板task

tasks.register<Zip>("zipRes") {
    group = "output"
    from("src/res")
    this.destinationDir = file("./")
    this.archiveName = "output.zip"
    this.archiveExtension.set("zip")
}

拓展Task配置

我们上面使用的资源路径是写死的,我们需要将他弄成配置项

import org.gradle.kotlin.dsl.support.zipTo

//创建自定义的ZipRes Task,将配置作为task的属性
open class ZipResTask : DefaultTask() {
    var resPath: String = "src/res"
    var outputPath: String = "output.zip"

    //task的执行任务
    @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)
    }
}

//注册任务
tasks.register("zipRes", ZipResTask::class) {
    //配置任务
    resPath = "resSrc"
    outputPath = "resOutput.zip"
}

这样我们在注册task时就可以配置这两个参数

构建拓展成插件

现在由于很多项目都需要使用这样构建,我们需要将他做成插件的形式

我们把上面的构建内容写到custom_build.gradle.kts文件中,并在build.gradle.kts中进行依赖

apply(from = "custom_build.gradle.kts")

这样一来其他项目依赖这个脚本就能自动实现上述构建逻辑了,咦,不对又不能配置了,难道我要自己创建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静态强类型语言,需要处理依赖关系,使用反射去配置值
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的话代码就相当简单了

apply 'from': 'custom.gradle'

zipRes {
    resPath = 'resSrc'
    outputPath = 'resOutput.zip'
}

上传输出文件

项目构建的输出现在需要上传,我们添加一个上传的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)
    }
}
//创建配置项
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"]
}

执行uploadOutput命令,完成zipRes并上传

总结

以上的例子主要是为了对Gradle构建整体有一个清晰的认识,整个构建过程其实就是以下几个步骤:

  1. 建立项目结构 - 配置有哪些项目需要参与构建
  2. 配置项目 - 配置Project的实例,做一些属性配置(properties、extensions、conventions、extra等),做一些任务配置(定义项目完成构建需要的一系列任务)
  3. 执行任务,完成构建输出

其实上面三步就是Gradle的三个阶段:初始化阶段、配置阶段、执行阶段

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容