两个重要的概念

项目

实际上,一个项目是什么取决于你要用 Gradle 做什么?项目通常代表的是构建内容。 例如在 Android 中,一个 module 就是一个项目;

  • 项目是注册在 settings.gradle 中的
  • 通常一个项目有一个 build.gradle

Gradle 构建就是由一个或多个项目组成的。

任务

任务 顾名思义就是一个在构建阶段被执行的操作。它是 Gradle 构建的原子工作单位。例如 编译 Java 源代码;

任务是定义在项目的构建脚本中,并且可以彼此依赖。

一个项目就是由一个个任务组成的。

每一个 Gradle 构建都会按照相同的顺序经历三个不同的阶段:

初始化

Gradle 支持单项目构建和多项目构建。

在这个阶段 Gradle 会确认哪些项目将会参与构建。Gradle 会通过 settings.gradle 确定是多项目还是单项目构建。

Gradle 会为每个项目创建 Project 实例。

配置

在这个阶段执行在初始化阶段中确定的每一个项目的配置脚本,但是并不会执行其中的任务,只会评估任务的依赖性,根据其依赖性创建任务的有向无环图。

Gradle引入了一个称为随需求变配置的特性,该特性使它能够在构建过程中只配置相关和必要的项目。这在大型多项目构建中非常有用,因为它可以大大减少构建时间。

执行

在这个阶段,Gradle 会识别在配置阶段创建的任务的有向无环图。并按照他们的依赖顺序开始执行。

所有的构建工作都是在这个阶段执行的。如编译源码,生成 .class 文件,复制文件等。

settings.gradle

这个文件是由 Gradle 约定命名的,默认名为 settings.gradle ,在初始化阶段被执行。

对于多项目构建,必须在这里声明要参与构建的所有项目。对于单项目构建就是可选的了,可有可无。

Gradle 是如何寻找 settings.gradle 的?

  1. 在当前目录寻找
  2. 没有找到的话就去父目录寻找
  3. 仍然没有找到就是是单项目构建了
  4. 如果找到了就是确定其中的项目,如果当前执行的项目在 settings.gradle 有定义就执行多项目构建,否则就执行单项目构建。

一个脚本的属性访问和方法调用是委托给 Project 类的实例的,类似的 settings.gradle 的属性访问和方法调用是委托给 Settings 类的实例对象的。

单项目构建

对于单项目构建,在初始化后的工作流程很简单,构建脚本针对初始化阶段创建的项目对象执行。查找在命令行传入的任务名称相同的任务。

如果任务存在则作为一个单独的构建按照命令行传递的顺序执行。

多项目构建

多项目构建是在 Gradle 的单个执行过程中构建多个项目的构建。必须把参与构建的项目声明在 settings.gradle 里

项目位置

可以把多项目构建看作一个单根的树。每一个项目都是树上的一个节点。一个项目有一个路径表示在树中的位置。

通常情况下项目的路径和在文件系统中的位置是一致的,当然了这个路径也是可以配置的。

项目树是 settings.gradle 生成的,默认情况下 settings.gradle 的位置就是根项目的位置。但是你可以在 settings.gradle 文件中更改。

构建项目树

在 settings.gradle 设置文件中你可以使用一些列的方法配置构建项目树。分层和平面物理布局都支持。

分层布局

Groovy

include 'project1', 'project2:child', 'project3:child1'

Kotlin

include("project1", "project2:child", "project3:child1")

include 方法使用项目路径作为参数,假定项目路径与相对物理文件系统路径相等。

例如 "project2:child" 默认对应的是相对于根目录的 "project2/child"。

这也意味着包含路径 “services:hotels:api” 将创建3个项目:

  • “services”
  • “services:hotels”
  • “services:hotels:api”

更详细的说明可以 DSL文档

平面布局

Groovy

includeFlat 'project3', 'project4'

Kotlin

includeFlat("project3", "project4")

includeFlat 也是目录名字作为参数。这些目录要和根项目目录同级。

这些目录的位置在项目树中是根项目的子项目。

更改项目树的元素

在设置文件中创建的多项目树由所谓的项目描述符组成。这些项目符号可以随时更改。

可以通过下面这种方式访问描述符

查找项目树的元素

Groovy

println rootProject.name
println project(':projectA').name

Kotlin

println(rootProject.name)
println(project(":projectA").name)

使用这个描述符你可以一个项目的名字,项目目录和构建文件

更改项目树元素

Groovy

rootProject.name = 'main'
project(':projectA').projectDir = new File(settingsDir, '../my-project-a')
project(':projectA').buildFileName = 'projectA.gradle'

Kotlin

rootProject.name = "main"
project(":projectA").projectDir = File(settingsDir, "../my-project-a")
project(":projectA").buildFileName = "projectA.gradle"

更详细的信息可以查看 ProjectDescriptor 类的 API 文档。

接收生命周期事件

构建脚本可以接收生命周期构建进度的通知。

接收这些通知一般是两种形式

  • 实现详细的监听接口
  • 在发送通知时提供一个闭包来执行

项目评估事件

可以在项目评估后马上接到事件通知 使用的是 Project.afterEvaluate 方法,传入一个闭包,Gradle会将评估的项目和状态传递进闭包里。

Kotlin

afterEvaluate {
println("${project.getName()} 评估结果:${state.getExecuted()}")
}

Groovy

afterEvaluate{ project,state->
println "$project 评估成功否:${state.failure==null}"
}

如果是在多项目构建里,可以在 allprojects 的闭包里使用,这样每个项目的评估事件就都接受到了

Groovy

allprojects{
afterEvaluate{ project,state->
println "$project 评估成功否:${state.failure==null}"
}
}

评估前的事件通知使用 Project.beforeEvaluate 照样是传入一个闭包,Gradle会将要评估的项目传递进闭包里

Groovy

allprojects{
afterEvaluate{ project,state->
println "$project 评估成功否:${state.failure==null}"
} beforeEvaluate { project ->
println "开始评估 $project"
} }

这里列出了使用的 api文档。

任务

任务被添加到项目

Groovy

tasks.whenTaskAdded { task ->
println "$task 被添加到项目了。"
}

Kotlin

tasks.whenTaskAdded {
extra["srcDir"] = "src/main/java"
} val a by tasks.registering println("source dir is ${a.get().extra["srcDir"]}")

有向无环图填充完毕

使用的是 TaskExecutionGraph.whenReady 方法

Groovy

gradle.taskGraph.whenReady{ graph->
println "任务图准备好了:\n"
graph.allTasks.each {
print "$it , "
}
}

任务执行

Groovy

task ok

task broken(dependsOn: ok) {
doLast {
throw new RuntimeException('broken')
}
} gradle.taskGraph.beforeTask { Task task ->
println "executing $task ..."
} gradle.taskGraph.afterTask { Task task, TaskState state ->
if (state.failure) {
println "FAILED"
}
else {
println "done"
}
}

这里留一个Gradle API 的查询地址

文档参考

Gradle-构建生命周期的更多相关文章

  1. Gradle 庖丁解牛(构建生命周期核心托付对象创建源代码浅析)

    [工匠若水 http://blog.csdn.net/yanbober 未经同意严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 上一篇<Gradle 庖丁解牛(构建源头源代码浅析)> ...

  2. 002-Apache Maven 构建生命周期

    Maven - 构建生命周期 什么是构建生命周期 构建生命周期是一组阶段的序列(sequence of phases),每个阶段定义了目标被执行的顺序.这里的阶段是生命周期的一部分. 举例说明,一个典 ...

  3. Maven 使用了一个标准的目录结构和一个默认的构建生命周期。

    Maven 使用了一个标准的目录结构和一个默认的构建生命周期. 约定优于配置 当创建 Maven 工程时,Maven 会创建默认的工程结构.开发者只需要合理的放置文件,而在 pom.xml 中不再需要 ...

  4. Maven 构建生命周期

    构建生命周期是什么? 构建生命周期阶段的目标是执行顺序是一个良好定义的序列.这里使用一个例子,一个典型的 Maven 构建生命周期是由下列顺序的阶段: 阶段 处理 描述 准备资源 资源复制 资源复制可 ...

  5. Maven学习(十三)-----Maven 构建生命周期

    Maven 构建生命周期 构建生命周期是什么? 构建生命周期阶段的目标是执行顺序是一个良好定义的序列. 这里使用一个例子,一个典型的 Maven 构建生命周期是由下列顺序的阶段: 阶段 处理 描述 准 ...

  6. Java-Maven-Runoob:Maven构建生命周期

    ylbtech-Java-Maven-Runoob:Maven构建生命周期 1.返回顶部 1. Maven 构建生命周期 Maven 构建生命周期定义了一个项目构建跟发布的过程. 一个典型的 Mave ...

  7. Apache Maven(二):构建生命周期

    Maven 约定的目录结构 我要遵循Maven已经约定好的目录结构,才能让maven在自动构建过程中找到对应的资源进行构建处理.以下是maven约定的目录结构: 项目名称 |-- pom.xml :M ...

  8. Maven的构建生命周期理解

    以下引用官方的生命周期解释https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html: 一.构建生命 ...

  9. maven 学习---Maven构建生命周期

    构建生命周期是一组阶段的序列(sequence of phases),每个阶段定义了目标被执行的顺序.这里的阶段是生命周期的一部分. 举例说明,一个典型的 Maven 构建生命周期是由以下几个阶段的序 ...

  10. Maven构建生命周期

    以下引用官方的生命周期解释https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html: 一.构建生命 ...

随机推荐

  1. 个人永久性免费-Excel催化剂功能第92波-地理地址与经纬度互转功能

    GPS设备和手机LBS的兴起,在地理信息存储过程中,在程序.应用级别是需要用经纬度去定位,而在数据分析的级别,特别是省市区镇街的分析,用到的是人可识别的文本类型存储,从设备中采集下来的数据和人工维护的 ...

  2. 钉钉E应用(小程序)之日历

    唠叨几句:其实钉钉E应用的编写类似支付宝小程序(毕竟是阿里爸爸下的产业),而支付宝小程序又是chao xi 微信小程序(只不过人家是wxml / wxss ,他是 axml / acss罢了),这三者 ...

  3. sonarlint在idea&eclipse中安装与使用

    介绍 ​ 代码质量管理的开源平台,用于管理源代码的质量 通过插件形式,可以支持包括java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groovy等等二十几种编程语言的代码质量管 ...

  4. Eclipse Spring框架配置

    1.从官网下载相应的jar包 (1)下载spring framework包,地址: https://repo.spring.io/webapp/#/artifacts/browse/tree/Gene ...

  5. Java 常见面试题整理

    操作系统 说一下线程和进程,它们的区别 同步和异步的区别 阻塞和非阻塞的区别 操作系统中死锁的四个必要条件 mmap和普通文件读写的区别,mmap的注意点 CPU密集型和IO密集型的区别 Linux ...

  6. sql format 格式化数字(前面补0)

    将一个数字例如33,或1使用t-sql语句转换成033或001 以下是详细分析: 1.select power(10,3)得到1000 2.select cast(1000+33 as varchar ...

  7. php curl问题汇总

    0. curl是个什么东西 复制代码代码如下: PHP supports libcurl, a library created by Daniel Stenberg, that allows you ...

  8. python课堂整理13---函数的作用域及匿名函数

    name = 'alex' def foo(): name = 'jinling' def bar(): print(name) return bar a = foo() print(a) 阅读上述代 ...

  9. bootstrap-treeview后台Json数据的封装及前台的显示

    1.bootStrap-treeview是我们常用的树形结构,页面风格也比较清新,但是后台数据的封装比较麻烦,经过研究终于解决,和大家分享一下. 2.前端代码如下 <script> var ...

  10. Linu基础之权限管理

    二十二.权限管理 22.1)什么是权限 针对某些文件或者进程,对用户进行限制,权限可以理解为用于约束用户能对系统所做的操作. 22.2)权限和用户的关系   [root@centos7 ~]# ll ...