(四)Kotlin 领域特定语言 DSL

温馨提示

写博客是为了记录在开发过程中所涉及到的技术以及遇到的问题的解决,如果该博客对您有所帮助,希望可以点个关注/喜欢;如果您对文章中的内容有什么不同的见解,欢迎留言进行讨论。谢谢!

一、领域特定语言 DSL的概念

  • 只在特定领域使用的语言;例如:HTML、Gradle、SQL

二、领域特定语言 DSL的特点

  • 它也是计算机编程语言
  • 具有语言表达能力
  • 表达能力比较有限
  • 关注某个特定领域

三、Html DSL

四、Gradle DSL

以下内容引用自 Kotlin 语言中文站

使用 Gradle

为了用 Gradle 构建 Kotlin,你应该设置好 kotlin-gradle 插件将其应用到你的项目中,并且添加 kotlin-stdlib 依赖。这些操作也可以在 IntelliJ IDEA 中通过调用 Project action 中的 Tools | Kotlin | Configure Kotlin 自动执行。

插件和版本

使用 kotlin-gradle-plugin 编译 Kotlin 源代码和模块.

要使用的 Kotlin 版本通常定义为 kotlin_version 属性:

buildscript {
    ext.kotlin_version = '1.3.11'

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

当通过 Gradle 插件 DSLGradle Kotlin DSL 使用 Kotlin Gradle 插件 1.1.1 及以上版本时,这不是必需的。

针对 JVM

针对 JVM,需要应用 Kotlin 插件:

apply plugin: "kotlin"

或者,从 Kotlin 1.1.1 起,可以使用 Gradle 插件 DSL 来应用该插件:

plugins {
    id "org.jetbrains.kotlin.jvm" version "1.3.11"
}

在这个块中的 version 必须是字面值,并且不能从其他构建脚本中应用。
对于 Gradle Kotlin DSL,请按以下方式应用插件:

plugins {
    kotlin("jvm") version "1.3.11"
}

Kotlin 源代码可以与同一个文件夹或不同文件夹中的 Java 源代码混用。默认约定是使用不同的文件夹:

project
    - src
        - main (root)
            - kotlin
            - java

如果不使用默认约定,那么应该更新相应的 sourceSets 属性:

sourceSets {
    main.kotlin.srcDirs += 'src/main/myKotlin'
    main.java.srcDirs += 'src/main/myJava'
}

对于 Gradle Kotlin DSL,请改用 java.sourceSets { …… } 配置源集。

针对 JavaScript

当针对 JavaScript 时,须应用不同的插件:

apply plugin: "kotlin2js"

这个插件只适用于 Kotlin 文件,因此建议将 Kotlin 和 Java 文件分开(如果是同一项目包含 Java 文件的情况)。与针对 JVM 一样,如果不使用默认约定,我们需要使用 sourceSets 来指定源代码文件夹:

sourceSets {
    main.kotlin.srcDirs += 'src/main/myKotlin'
}

除了输出的 JavaScript 文件,该插件默认会创建一个带二进制描述符的额外 JS 文件。 如果你是构建其他 Kotlin 模块可以依赖的可重用库,那么该文件是必需的,并且应该与转换结果一起分发。 其生成由 kotlinOptions.metaInfo 选项控制:

compileKotlin2Js {
    kotlinOptions.metaInfo = true
}

针对 Android

Android 的 Gradle 模型与普通 Gradle 有点不同,所以如果我们要构建一个用 Kotlin 编写的 Android 项目,我们需要用 kotlin-android 插件取代 kotlin 插件:

buildscript {
    ext.kotlin_version = '1.3.11'

    ……

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

不要忘记配置标准库依赖关系

Android Studio

如果使用 Android Studio,那么需要在 android 下添加以下内容:

android {
  ……

  sourceSets {
    main.java.srcDirs += 'src/main/kotlin'
  }
}

这让 Android Studio 知道该 kotlin 目录是源代码根目录,所以当项目模型加载到 IDE 中时,它会被正确识别。或者,你可以将 Kotlin 类放在 Java 源代码目录中,该目录通常位于 src/main/java

配置依赖

除了上面显示的 kotlin-gradle-plugin 依赖之外,还需要添加 Kotlin 标准库的依赖:

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib"
}

如果针对 JavaScript,请使用 compile "org.jetbrains.kotlin:kotlin-stdlib-js" 替代之。

如果是针对 JDK 7 或 JDK 8,那么可以使用扩展版本的 Kotlin 标准库,其中包含为新版 JDK 增加的额外的扩展函数。使用以下依赖之一来取代 kotlin-stdlib

compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7"
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"

对于 Gradle Kotlin DSL,以下表示法的依赖关系与其等价:

dependencies {
    compile(kotlin("stdlib"))
    // 或者以下之一:
    compile(kotlin("stdlib-jdk7"))
    compile(kotlin("stdlib-jdk8"))
}

在 Kotlin 1.1.x 中,请使用 kotlin-stdlib-jre7kotlin-stdlib-jre8

如果你的项目中使用 Kotlin 反射或者测试设施,你也需要添加相应的依赖:

compile "org.jetbrains.kotlin:kotlin-reflect"
testCompile "org.jetbrains.kotlin:kotlin-test"
testCompile "org.jetbrains.kotlin:kotlin-test-junit"

或者,对于 Gradle Kotlin DSL:

compile(kotlin("reflect"))
testCompile(kotlin("test"))
testCompile(kotlin("test-junit"))

从 Kotlin 1.1.2 起,使用 org.jetbrains.kotlin group 的依赖项默认使用从已应用的插件获得的版本来解析。你可以用完整的依赖关系符号 (如 compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version",或者在 Gradle Kotlin DSL 中用 kotlin("stdlib", kotlinVersion))手动提供其版本。

注解处理

请参见 Kotlin 注解处理工具kapt)的描述。

增量编译

Kotlin 支持 Gradle 中可选的增量编译。 增量编译跟踪构建之间源文件的改动,因此只有受这些改动影响的文件才会被编译。

从 Kotlin 1.1.1 起,默认启用增量编译。

有几种方法来覆盖默认设置:

  1. kotlin.incremental=true 或者 kotlin.incremental=false 行添加到一个 gradle.properties 或者一个 local.properties 文件中;

  2. -Pkotlin.incremental=true-Pkotlin.incremental=false 添加到 Gradle 命令行参数。请注意,这样用法中,该参数必须添加到后续每个子构建,并且任何具有禁用增量编译的构建将使增量缓存失效。

请注意,第一次构建不会是增量的。

Coroutines support

Coroutines support is an experimental feature in Kotlin 1.2, so the Kotlin compiler reports a warning when you use coroutines in your project. To turn off the warning, add the following block to your build.gradle file:

kotlin {
    experimental {
        coroutines 'enable'
    }
}

Or, with Gradle Kotlin DSL:

import org.jetbrains.kotlin.gradle.dsl.Coroutines
// ...

kotlin.experimental.coroutines = Coroutines.ENABLE

Module names

The Kotlin modules that the build produces are named accordingly to the archivesBaseName property of the project. If a project has a broad name like lib or jvm, which is common for subprojects, the Kotlin output files related to the module (*.kotlin_module) might clash with those from third-party modules with the same name. This causes problems when a project is packaged into a single archive (e.g. APK).

To avoid this, consider setting a unique archivesBaseName manually:

archivesBaseName = 'myExampleProject_lib'

With Gradle Kotlin DSL, it is:

setProperty("archivesBaseName", "myExampleProject_lib")

Gradle 构建缓存支持(自 1.2.20 起)

Kotlin 插件支持 Gradle 构建缓存(需要 Gradle 4.3 及以上版本;低版本则禁用缓存)。

由于注解处理器运行的任意代码可能不一定会将任务输入转换为输出、可能访问与修改 Gradle 未跟踪的文件等,因此默认不缓存 kapt 注解处理任务。要启用 kapt 缓存,请将以下列几行添加到构建脚本中:

kapt {
    useBuildCache = true
}

要禁用所有 Kotlin 任务的缓存,请将系统属性标志 kotlin.caching.enabled 设置为 false(运行构建带上参数 -Dkotlin.caching.enabled=false)。

编译器选项

要指定附加的编译选项,请使用 Kotlin 编译任务的 kotlinOptions 属性。

当针对 JVM 时,对于生产代码这些任务称为 compileKotlin 而对于测试代码称为 compileTestKotlin。对于自定义源文件集(source set)这些任务称呼取决于 compile<Name>Kotlin 模式。

Android 项目中的任务名称包含构建变体 名称,并遵循 compile<BuildVariant>Kotlin 的模式,例如 compileDebugKotlincompileReleaseUnitTestKotlin

当针对 JavaScript 时,这些任务分别称为 compileKotlin2JscompileTestKotlin2Js,以及对于自定义源文件集称为 compile<Name>Kotlin2Js

要配置单个任务,请使用其名称。示例:

compileKotlin {
    kotlinOptions.suppressWarnings = true
}

compileKotlin {
    kotlinOptions {
        suppressWarnings = true
    }
}

对于 Gradle Kotlin DSL,首先从项目的 tasks 中获取任务:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
// ……

val compileKotlin: KotlinCompile by tasks

compileKotlin.kotlinOptions.suppressWarnings = true

相应地,为 JS 与 Common 目标使用类型 Kotlin2JsCompileKotlinCompileCommon

也可以在项目中配置所有 Kotlin 编译任务:

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class.java).all {
    kotlinOptions { …… }
}

对于 Gradle 任务的完整选项列表如下:

JVM、JS 与 JS DCE 的公共属性
名称 描述 可能的值 默认值
allWarningsAsErrors 任何警告都报告为错误 false
suppressWarnings 不生成警告 false
verbose 启用详细日志输出 false
freeCompilerArgs 附加编译器参数的列表 []
JVM 与 JS 的公共属性
Name Description Possible values Default value
apiVersion 只允许使用来自捆绑库的指定版本中的声明 "1.0"、 "1.1"、 "1.2"、 "1.3"、 "1.4 (EXPERIMENTAL)"
languageVersion 提供与指定语言版本源代码兼容性 "1.0"、 "1.1"、 "1.2"、 "1.3"、 "1.4 (EXPERIMENTAL)"
JVM 特有的属性
名称 描述 可能的值 默认值
javaParameters 为方法参数生成 Java 1.8 反射的元数据 false
jdkHome 要包含到 classpath 中的 JDK 主目录路径,如果与默认 JAVA_HOME 不同的话
jvmTarget 生成的 JVM 字节码的目标版本(1.6 或 1.8),默认为 1.6 "1.6"、 "1.8" "1.6"
noJdk 不要在 classpath 中包含 Java 运行时 false
noReflect 不要在 classpath 中包含 Kotlin 反射实现 true
noStdlib 不要在 classpath 中包含 Kotlin 运行时 true
JS 特有的属性
名称 描述 可能的值 默认值
friendModulesDisabled 禁用内部声明导出 false
main 是否要调用 main 函数 "call"、 "noCall" "call"
metaInfo 使用元数据生成 .meta.js 与 .kjsm 文件。用于创建库 true
moduleKind 编译器生成的模块类型 "plain"、 "amd"、 "commonjs"、 "umd" "plain"
noStdlib 不使用捆绑的 Kotlin stdlib true
outputFile 输出文件路径
sourceMap 生成源代码映射(source map) false
sourceMapEmbedSources 将源代码嵌入到源代码映射中 "never"、 "always"、 "inlining"
sourceMapPrefix 源代码映射中路径的前缀
target 生成指定 ECMA 版本的 JS 文件 "v5" "v5"
typedArrays 将原生数组转换为 JS 带类型数组 true
生成文档

要生成 Kotlin 项目的文档,请使用 Dokka; 相关配置说明请参见 Dokka README 。Dokka 支持混合语言项目,并且可以生成多种格式的输出 ,包括标准 JavaDoc。

OSGi

关于 OSGi 支持请参见 Kotlin OSGi 页

使用 Gradle Kotlin DSL

使用 Gradle Kotlin DSL 时,请使用 plugins { …… } 块应用 Kotlin 插件。如果使用 apply { plugin(……) } 来应用的话,可能会遇到未解析的到由 Gradle Kotlin DSL 所生成扩展的引用问题。为了解决这个问题,可以注释掉出错的用法,运行 Gradle 任务 kotlinDslAccessorsSnapshot,然后解除该用法注释并重新运行构建或者重新将项目导入到 IDE 中。

上一篇:(三)Kotlin 高阶函数

下一篇:(五)协程 Coroutine

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容