独自登高楼 望断天涯路

学lucene 学hadoop,Google/baidu搜:“独自登高楼”,进入本博客

Gradle学习(十八)——构建的生命周期

Gradle的核心是一种依赖可编程的语言,用Gradle术语来说就是你可以定义任务也可以定义任务之间的依赖。Gradle可以保证这些任务按照他们的依赖关系顺序执行,并且每个任务只执行一次。这些任务构成了一个有向无环图,构建工具以这样的依赖关系图来执行任务。在执行任务之前,Gradle需要先构建这样的依赖关系图。这就是Gradle的核心,是很多事情成为可能。

构建脚本配置了这个依赖图,因此严格来说应该叫做构建配置脚本

转载文章请注明出处http://blog.csdn.net/lastsweetop/article/details/79053746

构建的几个阶段

Gradle的构建清晰的分为三个阶段:

  • 初始化阶段
    Gradle提供了单项目和多项目的构建,在初始化阶段,他要决定哪些项目要参与到构建中来,并创建这些项目的实例
  • 配置阶段
    在这个阶段需要参与到本次构建的项目的构建脚本将会被执行,这些项目的对象将被配置,这个特性叫做configuration on demand
  • 执行阶段
    Gradle为在配置阶段创建和配置的任务再次筛选需要执行的任务的子集,这个子集的筛选是由在命令行下传递给Gradle的任务名和目录决定的,子集中的每个任务都会被执行

Settings文件

除构建脚本外,Gradle还定义了个settings文件,按约定应该命名为settings.gradle.这个文件在初始化阶段就会被执行。多项目构建的root项目中必须有settings.gradle文件,因为要在这个文件中定义哪些子项目会被包含进来,而对单项目来说是可选的。除了定义需要构建的项目之外,你可能还需要把一些lib库增加到构建脚本的classpath中。
settings.gradle

rootProject.name = 'buildLifeCycle'
println 'settings.gradle : the initialization phase'

build.gradle

println 'build.gradle : the configuration phase'

task configurated {
    println 'configurated : the configuration phase'
}

task test {
    doLast {
        println 'test : the execution phase'
    }
}

task testBoth {
    doFirst {
        println 'doFirst : the execution phase'
    }
    doLast {
        println 'doLast : the execution phase'
    }
    println 'testBoth : the configuration phase'
}

执行任务:

± % gradle test testBoth
settings.gradle : the initialization phase

> Configure project :
build.gradle : the configuration phase
configurated : the configuration phase
testBoth : the configuration phase

> Task :test
test : the execution phase

> Task :testBoth
doFirst : the execution phase
doLast : the execution phase


BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

就像build.gradle里的属性访问和方法调用被委托给Project对象一样,settings.gradle里的属性访问和方法调用是委托给了一个Settings对象。

多工程构建

多项目构建的意思是Gradle执行一次就可以执行多个项目构建的构建,你必须在settings文件中配置那些项目需要添加到多项目构建之中。

项目位置

多项目构建是有基于一个根项目的树形结构来表示的,其中的每个元素都代表一个项目,项目的路径表示在这棵构建树中所处的位置。在大多数的情况下,项目的路径和实际上这个项目在文件系统中的物理位置是一致的,当然这也是可配置的。项目树将会在settings.gradle文件中创建,默认情况下这个文件在根项目的目录下,当然也是可配置的

构建项目树

在settings文件中可以用多种方法来构建项目树,可以支持分层布局和扁平布局。

分层布局

include 'project1', 'project2:child1', 'project:child2'

include方法接收的参数是项目的路径,项目路径假定和和相对的文件系统的路径是一致的,比如services:api将映射到相对于根项目的services/api目录。你仅仅需要指定树中的叶节点即可,也就是说包含services:hotels:api意味着一次包含了3个项目servicesservices:hotelsservices:hotels:api.

扁平布局

includeFlat 'project4','project5'

includeFlat方法将以目录名为参数,这些目录都是根项目所在目录的同一层目录,或者叫兄弟目录。这些目录的项目在多项目构建中都是以根项目的子项目存在。

在settings文件中多项目树的创建是由项目描述符组成的。你可以在任意时间修改这些项目描述符,通过访问这些项目描述符你可以修改项目的名字,所在的目录还有对应的构建文件。

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

rootProject.name='root'
project(':project5').projectDir = new File(settingsDir,'../antInGradle')
project(':project5').buildFileName = 'temp.gradle'

初始化

Gradle如何知道你需要执行的是单项目构建还是多项目构建呢?如果你是在一个带有settings文件的目录触发多项目构建那相对容易很多,但是Gradle允许在子项目中执行构建。如果你在一个没用settings文件的目录执行Gradle,Gradle就会按照以下顺序来查找settings文件:

  • 首先先查找与当前目录同级的有没有一个master的目录
  • 如果没有,他就找父目录
  • 如果父目录也没有,它就把自己当做一个单项目构建
  • 如果settings文件存在,Gradle就检查当前目录是否是多项目构建的一部分,如果不是,那么就执行单项目构建,反之执行多项目构建

那么这样做的目的是什么?Gradle需要确定你所在的这个项目是不是多项目的子项目,如果是个子项目,那么仅仅需要这个子项目和它依赖的项目进行构建,但是Gradle还需要为整个多项目构建去创建整个项目的构建配置。你可以在命令行下通过-u选项来跳过去父目录搜索settings.gradle文件,那么当前项目就会被当成单项目构建。如果项目中本来就有settings文件,那么-u选项就没多大意义了,那就以下逻辑来执行了:

  • 如果settings.gradle没有定义多项目构建的层次关系,那么就被当做单项目来执行
  • 如果settings.gradle定义了多项目构建的层次关系,那么就当做多项目来构建

settings.gradle文件的搜索,仅仅支持物理层的分层布局和扁平布局,对于扁平布局的搜索就要使用上面所讲的master目录了。Gradle的多项目构建可以有任意的物理布局,当时其他任意布局的构建你就需要在settings文件所在的目录执行构建了。

Gradle为参与构建的每个项目都创建了Project对象,对于多项目构建来说是在settings文件中指定的项目外加根项目,每个Project对象都以和它所在目录相同名字作为默认名字,除了根项目以外其他的Project对象都有个父项目,所有项目都有子项目。

单项目的配置和执行

对于单项目构建来说,初始化阶段之后的流程就相对简单很多了。在初始化阶段创建的Project对象上执行构建脚本,然后查找与命令行传入的参数一样的任务名,如果这些任务存在,Gradle就按照命令行这些任务的顺序单独执行。多项目的配置和构建我会单独开一篇文章来讲解。

构建脚本对生命周期的呼应

在构建过程的整个生命周期,构建脚本可以都接受到通知。通知可以采取两种方式:一种是实现特定的监听接口,另一种是提供闭包给通知到达的时候调用。我们下面采用闭包的方式来讲解

项目赋值

在项目赋值的之前和之后都会立即收到通知,这可以用来做很多事情,比如构建脚本中的所有定义被应用那么就可以附加一些配置,或者输出一些日志和概要性的分析。
下面是一个给所有hasTests属性为true的工程增加一个test任务的例子:
build.gradle

allprojects {
    afterEvaluate { project ->
        if (project.hasProperty('hasTests') && project.hasTests) {
            println "Adding test task for $project"
            project.task('test') {
                doLast {
                    println "Running test task for $project"
                }
            }
        }
    }
}

project4.gradle

ext {
    hasTests = true
}

然后执行任务:

± % gradle test
> Configure project :project4
Adding test task for project ':project4'
> Task :project4:test
Running test task for project ':project4'

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

这个例子是给Project.afterEvaluate()加个闭包参数,这个闭包会在项目赋值之后执行。

在项目被赋值时候也可以接收到通知,下面的例子就是在项目被赋值时候增加以下日志,要注意的一点是无论项目赋值成功与否,afterProject通知都会收到。

gradle.afterProject { Project project,ProjectState projectState ->
    if(projectState.failure){
        println "Evaluation of $project Failure"
    }else {
        println "Evaluation of $project Success"
    }
}

执行任务:

± % gradle test
> Configure project :project3
Evaluation of project ':project3' Success

> Configure project :project4
Evaluation of project ':project4' Failure

·····

任务创建

在任务被添加到项目的之前和之后也能收到通知,可以用来设置一些默认值,也可以在这些任务可用之前添加一些操作。

下面的例子是在任务创建的时候添加了一个属性srcDir

tasks.whenTaskAdded { Task task ->
    task.ext.srcDir = 'src/main/java'
}

task a

println "a.srcDir = '$a.srcDir'"

执行任务:

± % gradle a -q
a.srcDir = 'src/main/java'

任务执行

你可以在任务执行和执行之后收到通知

下面例子为每个任务在执行之前和之后都添加了点日志,注意不管任务执行成功与否都会收到afterTask通知。

task ok
task broken(dependsOn: ok) {
    doLast {
        throw new Exception('故意的')
    }
}

gradle.taskGraph.beforeTask { Task task ->
    println "Task $task is excuting..."
}

gradle.taskGraph.afterTask { Task task, TaskState taskState ->
    if (taskState.failure) {
        println "Task $task is fail"
    } else {
        println "Task $task is success"
    }
}

执行任务

± % gradle broken -q
Task task ':ok' is excuting...
Task task ':ok' is success
Task task ':broken' is excuting...
Task task ':broken' is fail
......
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lastsweetop/article/details/79053746
文章标签: grade
个人分类: gradle
所属专栏: Gradle学习
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

Gradle学习(十八)——构建的生命周期

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭