31 五月 2022

使用显式语法理解构建脚本

这些文件来自项目: https://github.com/yxc023/gradle-practice

每一个 project 下都有一个名为 build.gradle 的构建脚本。

每一个 build.gradle 构建脚本背后,都隐含了一个 Project 对象。

这个构建脚本中定义的各种属性或者方法,基本都是这个 project 中包含的。比如你可以在脚本中直接使用 Project 接口中定义好的变量和方法。

当在构建脚本中显示的指定类型后,可以写成下面这种写法

build.gradle
allprojects { Project p ->
    p.group = 'com.yangxiaochen.gradle.practice'
    p.version = '1.0.0-SNAPSHOT'

    p.apply (plugin: 'java')
    p.apply (plugin: 'java-library')
    p.apply plugin: 'eclipse'
    p.apply plugin: 'idea'
    apply plugin: 'pmd'

    p.repositories( { RepositoryHandler rh ->
        rh.maven( { MavenArtifactRepository m ->
            m.url('https://maven.aliyun.com/repository/public')
        })
        mavenCentral()
    })

    // 通过 ext 定义一些变量
    p.ext {
        mysqlVersion = '8.0.18'
        jooqVersion = '3.13.1'
        jooqGenDataSourceDriver = 'com.mysql.jdbc.Driver'
        jooqGenDataSourceUrl = 'jdbc:mysql://127.0.0.1:3306/gp_database'
        jooqGenDataSourceUrlUser = 'gp_database_user'
        jooqGenDataSourceUrlPassword = 'test'
        jooqGenDataSourceInputSchema = 'gp_database'
    }

    dependencies {
        pmd 'com.alibaba.p3c:p3c-pmd:1.3.6'
    }

    tasks.withType(JavaCompile) {
        options.encoding = "UTF-8"
    }
    p.convention.sourceCompatibility = 1.8
    targetCompatibility = 1.8


    p.pmd( { PmdExtension pe ->
        pe.consoleOutput = true
        ...
    })
}

Gradle 目前也支持使用 kotlin 作为构建语言,构建脚本里的语句会更加显式,但我并没有怎么用过。

project 中包含哪些东西

  1. 自身的属性和方法

  2. tasks - 当前 project 中包含的任务实例。引入一些 plugin 时,也会向 project 中添加 task

    // 创建一个名字为 `jooqTask`,类型为 `JooqTask` 的 task
    project.tasks.create("jooqTask", JooqTask.class)
  3. extra property - 通过 ext block 声明的额外变量

    ext {
        mysqlVersion = '8.0.18'
        jooqVersion = '3.13.1'
        jooqGenDataSourceDriver = 'com.mysql.jdbc.Driver'
        jooqGenDataSourceUrl = 'jdbc:mysql://127.0.0.1:3306/gp_database'
        jooqGenDataSourceUrlUser = 'gp_database_user'
        jooqGenDataSourceUrlPassword = 'test'
        jooqGenDataSourceInputSchema = 'gp_database'
    }
  4. extensions - 引入一些 plugin 时, 会向 project 中添加一些 extension 对象,并命名。

    // 创建一个名字为 `$JOOQ_EXTENSION_NAME`,类型为 `JooqExtension` 的 extension。后面两个参数是 `JooqExtension` 的构造参数
    project.extensions.create('jooq', JooqExtension.class, whenConfigurationAdded, 'jooq')

    加入 extension 后,就可以在构建脚本中定义

    jooq {
        version = jooqVersion
        edition = 'OSS'
        generateSchemaSourceOnCompilation = false
    }
  5. convention - 引入一些 plugin 时,会加入一些 convention object,翻译过来叫‘约定’,‘预定大于配置’的‘约定’。convention object 通常是 POJO,为 project 提供一些拓展属性。

    // 这两个变量,在引入 java plugin 之后,就能在构建脚本里够直接定义下面的变量。
    sourceCompatibility = 1.8
    targetCompatibility = 1.8

总之,这些 project 中包含的重要信息的作用,它们定义了 build.gradle 中可以写什么 property 或者 block

build.gradle 中使用了一个 property 或者 block,他的查找顺序是:

  1. 是否是 project 中的属性和方法

    // version 这个变量,即是 project.version
    version = '1.0.0'
  2. 是否是 ext 定义的属性

  3. 是否是 extensions 中的 extension 的名字

  4. 是否是 convention 中定义的 pojo 中的变量

  5. 是否是 task 的名字

  6. 是否在上层 project 的 ext 和 convention 中