gradle构建工具学习系列


定义类

跟上一章一样首先创建一个gradle项目,然后在构造脚本中定义一个类

class ProjectVersion {
    Integer major
    Integer minor
    Boolean release

    ProjectVersion(Integer major, Integer minor) {
        this.major = major
        this.minor = minor
        this.release = Boolean.FALSE
    }

    ProjectVersion(Integer major, Integer minor, Boolean release) {
        this(major, minor)
        this.release = release
    }

    @Override
    String toString() {
        "$major.$minor${release ? '' : '-SNAPSHOT'}"
    }
}

读取配置文件并实例化类

再在根目录添加一个配置文件version.properties,内容如下

major=0
minor=1
release=false

接下里创建一个任务,用于在初始化阶段读取配置文件

ext.versionFile = file('version.properties')

task loadVersion {
    project.version = readVersion();
}

ProjectVersion readVersion() {
    logger.quiet 'Reading the version file.'
    if (!versionFile.exists()) {
        throw new GradleException("Required version file does not exists : $versionFile.canonicalPath")
    }
    Properties versionProps = new Properties();
    versionFile.withInputStream {
        stream -> versionProps.load(stream)
    }
    new ProjectVersion(versionProps.major.toInteger(), versionProps.minor.toInteger(), versionProps.release.toBoolean())
}

注意这里的loadVersion中执行readVersion方法是在初始化阶段,因为这段代码是属于task配置,而不是在doLast当中作为执行代码。

在上面的代码当中通过读取配置文件中的属性,然后构造了一个ProjectVersion实例,并赋值了version属性。
再创建一个打印版本的任务

task printVersion(group: 'versioning', description: 'Prints project version.') {
    doLast {
        logger.quiet "Version : $version"
//		println "Version : $version"
    }
}

在这里插入图片描述
从上面你的执行结果可以看出,在任务执行时打印了版本信息,同时在配置项目阶段,打印了读取版本文件的日志。

Gradle明确区分了task动作和task配置。task动作,通过闭包doFirst和doLast定义,在执行阶段执行。那些不在task动作中定义的代码被认为是配置,因此在配置阶段提前执行。

Gradle构建生命周期阶段

无论什么时候执行Gradle构建,都会运行三个不同的生命周期阶段:初始化、配置和运行。

比如上面的loadVersion当中都是配置代码,只在配置阶段执行一次,而在printVersion当中都是动作代码(doLast或者doFirst当中的代码),动作代码只有在任务执行当中才会执行。

在初始化阶段,Gradle为项目创建了一个Project实例,在给定的构建脚本当中只定义了一个项目。在多项目构建中,这个构建阶段变得更加重要,根据你正在执行的项目,Gradle找出哪些项目依赖需要参与到构建中,注意,在这个构建阶段当前已有的构建脚本代码都不会执行。

初始化阶段后面紧接着就是配置阶段。Gradle构造了一个模型来代表任务,并参与到构建中来。增量式构建决定了模型中的task是否需要被执行。这个阶段非常适合为项目或指定task设置所需的配置。

项目每一次构建的任何配置代码都可以被执行——即使你只执行gradle tasks

在执行阶段,所有的task都应该以正确的顺序被执行。执行顺序由它们的依赖决定的。如果任务被任务没有修改过,将被跳过。比如,如果taskB依赖于taskA,那么当在命令行运行gradle B时执行顺序是A->B

增量式构建

以上只是读取文件,如果想修改这个版本文件呢?可以定义如下任务

task makeReleaseVersion(group: 'versioning', description: 'Makes project a realease version') {
    // 动作代码
    doLast {
        version.release = true
        ant.propertyfile(file: versionFile) {
            entry(key: 'release', type: 'string', operation: '=', value: 'true')
        }
    }
}

以上代码是没有问题的。可以对于这个操作来说,执行多遍的效果其实和一遍是一样的,尤其是当配置文件当中的release属性已经为true的情况下,这个任务是不需要真实执行的。也就是说要基于增量式进行构建。

那么怎么保证增量式构建呢?其实Gradle是通过比较两个任务的inputs和outputs来决定task是否是最新的。

输入可以是一个目录、一个或多个文件,或者是一个任意属性。一个task的输出是通过一个目录或1 ~ n个文件来定义的。inputs和outputs在DefaultTask类中被定义为属性或者有一个直接类来表示。
在这里插入图片描述
在这里插入图片描述
现在修改一下makeReleaseVersion任务

task makeReleaseVersion(group: 'versioning', description: 'Makes project a realease version') {
    // 配置代码
    // 声明版本的release属性作为输入
    inputs.property('release', version.release)
    // 声明版本文件作为输出属性
    outputs.file versionFile
    // 动作代码
    doLast {
        version.release = true
        ant.propertyfile(file: versionFile) {
            entry(key: 'release', type: 'string', operation: '=', value: 'true')
        }
    }
}

多次执行makeReleaseVersion任务。
在这里插入图片描述
在第二次,Gradle已经知道项目版本被设置为发布版本,而且自动跳过task的第二次执行。如果你没有手动修改属性文件的release属性,那么makeReleaseVersion将被标记为最新的,永远会被跳过执行。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐