Gradle使用Day03-Gradle构建

构建基础

  • projectstasksGradle中最重要的两个概念

projects

  • 任何一个Gradle构建都是由一个或多个project组成
  • 每个project包括许多可构建组成部分,这完全取决于要构建些什么
  • 示例:
    • 每个project可能是一个jar包或者一个web应用
    • 也可以是一个由许多其他项目中产生的jar构成的zip压缩包
  • 一个project不仅仅只能进行构建操作,也可以部署应用或搭建环境
  • 通过Gradlebuild-by-convention来具体定义一个project的操作

tasks

  • 每个project都由多个task组成
  • 每个task都代表了构建执行过程中的一个原子性操作:
    • 编译
    • 打包
    • 生成javadoc
    • 发布到某个仓库等操作

构建

  • 可以通过在命令行运行gradle命令来执行构建
  • gradle命令会从当前目录下寻找build.gradle文件来执行构建
    • build.gradle文件为构建脚本
    • 这是一个构建配置脚本
    • 这个构建脚本定义了一个project和一些默认的task

脚本

  • build.gradle:
task me {
    doLast {
        println 'chova'
    }
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q me
  • -q : 该参数用来控制gradle的日志级别,可以保证只输出需要的日志内容
    • 该脚本定义了一个task, 并且添加了一个动作
    • 当执行gradle me,Gralde便会去调用me这个任务来执行给定操作,这些操作就是一个用groovy书写的闭包
    • Gradletasks类似于Ant中的targets, 但是功能更加强大
      • Ant命令中有javac,copy,tasks

任务

  • build.gradle:
task upper << {
    String someString = 'mY_nAmE'
    println "Original: " + someString
    println "Upper case: " + someString.toUpperCase()
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q upper
  • 输出:
Original: mY_nAmE
Upper case: MY_NAME

task count << {
    4.times { print "$it " }
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q count
  • 输出:
0 1 2 3

任务依赖

  • 在两个任务之间指明依赖关系: 添加依赖task也可以不必首先声明被依赖的task
task me << {
    println 'me'
}
task intro(dependsOn: me) << {
    println "chova"
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q intro
  • 输出:
me
chova

延迟依赖

  • 延迟依赖: 依赖的任务可以定义在运行的任务之后
task taskX(dependsOn: 'taskY') << {
    println 'taskX'
}
task taskY << {
    println 'taskY'
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q taskX
  • 输出:
taskY
taskX
  • 这里的taskX是在taskY之前定义的,这在多项目构建中非常有用
  • 注意: 当引用的任务尚未定义的时候不可使用短标记法来运行任务

动态任务

  • Groovy不仅可以定义简单任务,还可以动态定义任务
  • 创建动态任务:
4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
    }
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q task1
  • 输出:
I'm task number 1

任务控制

  • 一旦创建任务之后,就可以通过API进行相互访问:
增加依赖
  • 通过API进行任务之间的通信来增加依赖
4.times { counter ->
    task "task$counter" << {
        println "I'm task number $counter"
    }
}
task0.dependsOn task2, task3
  • 然后在该文件所在目录执行gradle命令:
gradle -q task0
  • 输出:
I'm task number 2
I'm task number 3
I'm task number 0
增加任务行为
  • 通过API进行任务之间的通信来增加任务行为:
task hello << {
    println 'Hello Earth'
}
hello.doFirst {
    println 'Hello Venus'
}
hello.doLast {
    println 'Hello Mars'
}
hello << {
    println 'Hello Jupiter'
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q hello
  • 输出:
Hello Venus
Hello Earth
Hello Mars
Hello Jupiter
  • doFirstdoLast可以进行多次调用,分别被添加在任务的开头和结尾
  • 当任务开始执行时这些动作会按照既定顺序进行
  • << 操作符是doLast的简写形式

短标记法

  • 每个任务都是一个脚本的属性,可以对任务进行访问
以属性的方式访问任务
task hello << {
    println 'Hello world!'
}
hello.doLast {
    println "Greetings from the $hello.name task."
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q hello
  • 输出:
Hello world!
Greetings from the hello task.

增加自定义属性

  • 可以为一个任务添加额外的属性
  • 比如新增一个叫做myProperty的属性,用ext.myProperty的方式给赋初始值
  • 这样就增加了一个自定义属性
为任务增加自定义属性
task myTask {
    ext.myProperty = "myValue"
}

task printTaskProperties << {
    println myTask.myProperty
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q printTaskProperties
  • 输出:
myValue
  • 自定义属性不仅仅可以用在任务上,还可以用于其余操作

调用Ant任务

  • Ant任务是Gradle中的一等公民
  • Gradle借助GroovyAnt任务进行了整合
  • Gradle自带了一个AntBuilder,Gradle中调用Ant任务比在build.xml中调用更加的方便和强大
  • Gradle可以调用Ant任务并且与Ant中的属性进行通信
利用AntBuilder执行ant.loadfile
task loadfile << {
    def files = file('../antLoadfileResources').listFiles().sort()
    files.each { File file ->
        if (file.isFile()) {
            ant.loadfile(srcFile: file, property: file.name)
            println " *** $file.name ***"
            println "${ant.properties[file.name]}"
        }
    }
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q loadfile
  • 输出:
*** agile.manifesto.txt ***
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration  over contract negotiation
Responding to change over following a plan
 *** gradle.manifesto.txt ***
Make the impossible possible, make the possible easy and make the easy elegant.
(inspired by Moshe Feldenkrais)

方法抽取

  • Gradle的强大体现在如何编写脚本逻辑
  • 首先要做的就是要抽取方法
利用方法组织脚本逻辑
task checksum << {
    fileList('../antLoadfileResources').each {File file ->
        ant.checksum(file: file, property: "cs_$file.name")
        println "$file.name Checksum: ${ant.properties["cs_$file.name"]}"
    }
}
task loadfile << {
    fileList('../antLoadfileResources').each {File file ->
        ant.loadfile(srcFile: file, property: file.name)
        println "I'm fond of $file.name"
    }
}
File[] fileList(String dir) {
    file(dir).listFiles({file -> file.isFile() } as FileFilter).sort()
}

定义默认任务

  • Gradle允许在脚本中定义多个默认任务
defaultTasks 'clean', 'run'
task clean << {
    println 'Default Cleaning!'
}
task run << {
    println 'Default Running!'
}
task other << {
    println "I'm not a default task!"
}
  • 然后在该文件所在目录执行gradle命令:
gradle -q
  • 输出:
Default Cleaning!
Default Running!
  • 这与直接调用gradle clean run效果是一样的
  • 在多项目构建中,每个子项目都可以指定单独的默认任务
  • 如果子项目未进行指定将会调用父项目指定的的默认任务

DAG配置

  • 配置阶段后 ,Gradle会获取所有要执行的任务
  • Gradle提供了一个钩子来捕获这些信息
  • 可以为一些变量赋予不同的值
  • 可以用于检查已经执行的任务中有没有被释放
依赖任务的不同输出
task distribution << {
    println "We build the zip with version=$version"
}
task release(dependsOn: 'distribution') << {
    println 'We release now'
}
gradle.taskGraph.whenReady {taskGraph ->
    if (taskGraph.hasTask(release)) {
        version = '1.0'
    } else {
        version = '1.0-SNAPSHOT'
    }
}
  • 在该文件所在目录执行gradle命令:
gradle -q distribution
  • 输出:
We build the zip with version=1.0-SNAPSHOT
  • 在该文件所在目录执行gradle命令:
gradle -q release
  • 输出:
We build the zip with version=1.0
We release now
  • whenReady会在已发布的任务之前影响到已发布任务的执行,即使已发布的任务不是主要任务,即这个任务不是通过命令行直接调用

猜你喜欢

转载自blog.csdn.net/JewaveOxford/article/details/107917001