两个重要的概念

项目

实际上,一个项目是什么取决于你要用 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. 细说Ansible主机清单inventory

    Ansible是一个系列文章,我会尽量以通俗易懂.诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些. Ansible系列博文直达链接:Ansible入门系列 前言 关于Ansible是 ...

  2. UVA816 Abbott的复仇 Abbott's Revenge

    以此纪念一道用四天时间完结的题 敲了好几次代码的出错点:(以下均为正确做法) memset初始化 真正的出发位置必须找出. 转换东西南北的数组要从0开始. bfs没有初始化第一个d 是否到达要在刚刚取 ...

  3. idea 警告:Warning:java: 源值1.5已过时, 将在未来所有发行版中删除

    在pom.xml文件中添加 <properties>         <maven.compiler.source>1.8</maven.compiler.source& ...

  4. C4.5和ID3的差别

    C4.5和ID3的差别 决策树分为两大类:分类树和回归树,前者用于分类标签值,后者用于预测连续值,常用算法有ID3.C4.5.CART等. 信息熵 信息量:   信息熵: 信息增益 当计算出各个特征属 ...

  5. PhpCms V9中的{date('Y-m-d',$r[inputtime])}问题解决方法

    不少朋友会碰到这个问题:在PhpCms V9中的首页或者文章内容页调用发布时间{date('Y-m-d',$r[inputtime])}调用显示1970-01-01,然后尝试用截断的方法也没有成功,应 ...

  6. jQuery入门二(DOM对象与jQuery对象互相转换)

    - DOM对象与jQuery对象互相转换 第一篇说过,DOM对象不能调用jQuery对象的属性和方法,同样jQuery对象也不能调用DOM对象的属性和方法.但是在实际开发中,可能两者间需要互相调用对方 ...

  7. UnityWebSocket

    !!!转载注明:http://www.cnblogs.com/yinlong1991/p/unity_ylwebsocket.html Unity WebSocket 使用 Demo 线上测试地址 h ...

  8. 第二章 jsp数据交互(一)

    JSP如何处理客户端的请求? 解析:通过jsp内置对象 表单数据被提交到了jsp页面! 什么是JSP内置对象(jsp核心)? Java 内置对象 Java  作用域 解析:jsp内置对象是web容器创 ...

  9. Java初中级程序员面试题宝典

    Java基础部分 &与&&区别? &和&&都是逻辑运算符,都是判断两边同时真则为真,否则为假:但是&&当第一个条件不成之后,后面的条件都 ...

  10. Core CLR 自定义的Host官方推荐的一种形式(第一种)

    .Net Core CLR提供两种Host API访问 托管代码的形式,按照微软官方的说法,一种是通过CoreClr.DLL来直接调用托管生成的DLL程序集,另外一种是通过CoreClr里面的C导出函 ...