Building and Testing with Gradle笔记2——Gradle Tasks

来源:互联网 发布:淘宝分享88元红包 编辑:程序博客网 时间:2024/06/08 11:45

声明一个Task

task hello

执行gradle tasks输出当前Project中所有task

:tasks------------------------------------------------------------All tasks runnable from root project------------------------------------------------------------Build Setup tasks-----------------init - Initializes a new Gradle build. [incubating]wrapper - Generates Gradle wrapper files. [incubating]Help tasks----------components - Displays the components produced by root project 'gradle-test-2'. [incubating]dependencies - Displays all dependencies declared in root project 'gradle-test-2'.dependencyInsight - Displays the insight into a specific dependency in root project 'gradle-test-2'.help - Displays a help message.model - Displays the configuration model of root project 'gradle-test-2'. [incubating]projects - Displays the sub-projects of root project 'gradle-test-2'.properties - Displays the properties of root project 'gradle-test-2'.tasks - Displays the tasks runnable from root project 'gradle-test-2'.Other tasks-----------hello

Gradle每当开始执行一个Task,都会输出一个冒号加上该task的名字,如:tasks。因此tasks也是一个task,正如输出所示。

添加Task要执行的操作

声明后的Task可以作为一个可编程的对象,使用左移操作符给其添加要执行的操作

task hellohello << {    print 'hello, '}hello << {    println 'world'}

配置Task

task initializeDatabaseinitializeDatabase << { println 'connect to database' }initializeDatabase << { println 'update database schema' }initializeDatabase { println 'configuring database connection' }

执行gradle -b scratch.gradle initializeDatabase输出:

configuring database connection:initializeDatabaseconnect to databaseupdate database schema

首先,-b选项可以执行gradle要执行的build文件。
其次,没有使用左移操作符的代码块是指定task的配置部分。在Gradle的声明周期的配置阶段执行,早于task的执行阶段。比配置阶段更早的是初始化阶段。

配置代码块同样可以追加,如下:

task initializeDatabaseinitializeDatabase << { println 'connect to database' }initializeDatabase << { println 'update database schema' }initializeDatabase { print 'configuring ' }initializeDatabase { println 'database connection' }

Task是对象

Task对象的默认类型是DefaultTask,Gradle中的所有Task都是派生自该类型。正如Java中的所有对象都派生自java.lang.Object

DefaultTask的方法

dependsOn(task)

// Declare that world depends on hello// Preserves any previously defined dependencies as welltask loadTestData {    dependsOn createSchema}// An alternate way to express the same dependencytask loadTestData {    dependsOn << createSchema}// Do the same using single quotes (which are usually optional)task loadTestData {    dependsOn 'createSchema'}// Explicitly call the method on the task objecttask loadTestDataloadTestData.dependsOn createSchema// A shortcut for declaring dependenciestask loadTestData(dependsOn: createSchema)

如果一个Task有多个依赖,如下:

// Declare dependencies one at a timetask loadTestData {    dependsOn << compileTestClasses    dependsOn << createSchema}// Pass dependencies as a variable-length listtask world {    dependsOn compileTestClasses, createSchema}// Explicitly call the method on the task objecttask worldworld.dependsOn compileTestClasses, createSchema// A shortcut for dependencies only// Note the Groovy list syntaxtask world(dependsOn: [ compileTestClasses, createSchema ])

doFirst(closure)

传递一个closure在指定Task执行之前执行,注意和Task配置区分。

task setupDatabaseTests << {    // This is the task's existing action    println 'load test data'}setupDatabaseTests.doFirst {    println 'create schema'}

执行gradle setupDatabaseTests输出,

:setupDatabaseTestscreate schemaload test data

当然,这个closure可以在Task配置块中指定:

task setupDatabaseTests << {    println 'load test data'}setupDatabaseTests {    doFirst {        println 'create schema'    }}

doFirst也可以追加closure:

task setupDatabaseTests << {    println 'load test data'}setupDatabaseTests.doFirst {    println 'create database schema'}setupDatabaseTests.doFirst {    println 'drop database schema'}

输出如下:

:setupDatabaseTestsdrop database schemacreate database schemaload test data

doLast(closure)

示例如下:

task setupDatabaseTests << {    println 'create database schema'}setupDatabaseTests.doLast {    println 'load test data'}setupDatabaseTests.doLast {    println 'update version table'}

本质上,<<操作符等同于doLast方法。

onlyIf(closure)

在Task执行以前,进行判断,是否要执行该Task。

task createSchema << {    println 'create database schema'}task loadTestData(dependsOn: createSchema) << {    println 'load test data'}loadTestData.onlyIf {    System.properties['load.data'] == 'true'}

直接执行build loadTestData输出:

:createSchemacreate database schema:loadTestData SKIPPED

指定一个系统属性并执行gradle -Dload.data=true loadTestData,输出:

:createSchemacreate database schema:loadTestDataload test data

DefaultTask的属性

didWork

判断一个Task是否执行成功

apply plugin: 'java'task emailMe(dependsOn: compileJava) << {    if(tasks.compileJava.didWork) {        println 'SEND EMAIL ANNOUNCING SUCCESS'    }}

enabled

是否启用Task

task templates << {    println 'process email templates'}task sendEmails(dependsOn: templates) << {    println 'send emails'}sendEmails.enabled = false

执行gradle -b enabled.gradle sendEmails,输出:

:templatesprocess email templates:sendEmails SKIPPED

path

task echoMyPath << {    println "THIS TASK'S PATH IS ${path}"}

执行gradle -b path.gradle echoMyPath,输出:

THIS TASK'S PATH IS :echoMyPath

这表示该Task位于顶层Project,如果是子项目subProject的Task,那么path应该是:subProject:echoMyPath

logger

Gradle内部的logger引用,看代码:

task logLevel << {    def levels = ['DEBUG',                'INFO',                'LIFECYCLE',                'QUIET',                'WARN',                'ERROR']    levels.each { level ->        logging.level = level        def logMessage = "SETTING LogLevel=${level}"        logger.error logMessage        logger.error '-' * logMessage.size()        logger.debug 'DEBUG ENABLED'        logger.info 'INFO ENABLED'        logger.lifecycle 'LIFECYCLE ENABLED'        logger.warn 'WARN ENABLED'        logger.quiet 'QUIET ENABLED'        logger.error 'ERROR ENABLED'        println 'THIS IS println OUTPUT'        logger.error ' '    }}

总而言之,logger的级别优先级,从低到高。

logging

description

设置一个Task的描述信息:

task helloWorld(description: 'Says hello to the world') << {    println 'hello, world'}

或者

task helloWorld << {    println 'hello, world'}helloWorld {    description = 'Says hello to the world'}

又或者:

task helloWorld << {    println 'hello, world'}helloWorld.description = 'Says hello to the world'

temporaryDir

以File对象的形式返回属于当前build文件的一个临时目录

动态属性

每个Task除了上述固有属性外还可以任意添加属性,本质上就是添加键值对。

task copyFiles {    // Find files from wherever, copy them    // (then hardcode a list of files for illustration)    fileManifest = [ 'data.csv', 'config.json' ]}task createArtifact(dependsOn: copyFiles) << {    println "FILES IN MANIFEST: ${copyFiles.fileManifest}"}

执行gradle -b dynamic.gradle createArtifact,输出:

FILES IN MANIFEST: [data.csv, config.json]

Task类型

除了DefaultTask,还有一些用于复制,打包,执行程序的Task类型。声明一个Task类型就好像在面向对象编程中扩展一个类。

Copy

task copyFiles(type: Copy) {    from 'resources'    into 'target'    include '**/*.xml', '**/*.txt', '**/*.properties'}

from,into,和include方法都是继承自Copy。

Jar

这是java插件中引入的一个Task,Jar用于将源码打包成一个jar文件。我们同样可以扩展这个Task。

apply plugin: 'java'task customJar(type: Jar) {    manifest {        attributes firstKey: 'firstValue', secondKey: 'secondValue'    }    archiveName = 'hello.jar'    destinationDir = file("${buildDir}/jars")    from sourceSets.main.classes}

jar包的清单文件属性可以轻易的使用Groovy的map字面量创建。file方法用于从字符串构造一个java.io.File对象。from方法是Jar从Copy继承而来。

JavaExec

该Task用于执行一个带有main方法的Java类

apply plugin: 'java'repositories {    mavenCentral()}dependencies {    runtime 'commons-codec:commons-codec:1.5'}task encode(type: JavaExec, dependsOn: classes) {    main = 'org.gradle.example.commandline.MetaphoneEncoder'    args = "The rain in Spain falls mainly in the plain".split().toList()    classpath sourceSets.main.classesDir    classpath configurations.runtime}

自定义Task类型

在build文件中创建自定义Task类型

task createDatabase(type: MySqlTask) {    sql = 'CREATE DATABASE IF NOT EXISTS example'}task createUser(type: MySqlTask, dependsOn: createDatabase) {    sql = "GRANT ALL PRIVILEGES ON example.* TO exampleuser@localhost IDENTIFIED BY 'passw0rd'"}task createTable(type: MySqlTask, dependsOn: createUser) {    username = 'exampleuser'    password = 'passw0rd'    database = 'example'    sql = 'CREATE TABLE IF NOT EXISTS users(id BIGINT PRIMARY KEY, username VARCHAR(100))'}class MySqlTask extends DefaultTask {    def hostname = 'localhost'    def port = 3306    def sql    def database    def username = 'root'    def password = 'password'    @TaskAction    def runQuery() {        def cmd        if(database) {            cmd = "mysql -u ${username} -p ${password} -h ${hostname} -P ${port} ${database} -e "        } else {            cmd = "mysql -u ${username} -p ${password} -h ${hostname} -P ${port} -e "        }        project.exec {            commandLine = cmd.split().toList() + sql        }    }}

上面定义的每个Task都用于执行一条sql语句。

在源码树中创建自定义Task类型

如果自定的Task较为复杂,应该将它们保存为单独的Groovy文件。上面的例子还可以写成这样,将build文件中的class移到一个单独的文件中MySqlTask.groovy,项目的结构如下:

|---build.gradle\---buildSrc    \---src        \---main            \---groovy                \---org                    \---gradle                        \---example                            \---task                                \---MySqlTask.groovy
0 0