Kotlin v2.0.21 Help

配置编译

Kotlin 跨平台项目使用编译来生成构件。每个目标可以有一个或多个编译,例如用于生产和测试目的。

对于每个目标,默认的编译包括:

编译

如果你需要编译生产代码和单元测试之外的内容,例如集成测试或性能测试,你可以创建一个自定义编译

你可以在以下位置配置如何生成构件:

查看可用于所有或特定目标的 编译参数列表编译器选项

配置所有编译

以下示例配置了一个对所有目标通用的编译器选项:

kotlin { targets.all { compilations.all { compilerOptions.configure { allWarningsAsErrors.set(true) } } } }
kotlin { targets.all { compilations.all { compilerOptions.configure { allWarningsAsErrors = true } } } }

或者,你可以使用 compilerOptions {} 顶级块

kotlin { @OptIn(ExperimentalKotlinGradlePluginApi::class) compilerOptions { allWarningsAsErrors.set(true) } }
kotlin { compilerOptions { allWarningsAsErrors = true } }

为单个目标配置编译

kotlin { jvm().compilations.all { compilerOptions.configure { jvmTarget.set(JvmTarget.JVM_1_8) } } }
kotlin { jvm().compilations.all { compilerOptions.configure { jvmTarget = JvmTarget.JVM_1_8 } } }

或者,你可以在目标级别使用 compilerOptions {} 块:

kotlin { jvm { @OptIn(ExperimentalKotlinGradlePluginApi::class) compilerOptions { jvmTarget.set(JvmTarget.JVM_1_8) } } }
kotlin { jvm { compilerOptions { jvmTarget = JvmTarget.JVM_1_8 } } }

配置一个编译

kotlin { jvm { val main by compilations.getting { compilerOptions.configure { jvmTarget.set(JvmTarget.JVM_1_8) } } } }
kotlin { jvm { compilations.main { compilerOptions.configure { jvmTarget = JvmTarget.JVM_1_8 } } } }

创建自定义编译

如果你需要编译生产代码和单元测试之外的内容,例如集成测试或性能测试,可以创建一个自定义编译。

例如,为 jvm() 目标的集成测试创建一个自定义编译,可以向 compilations 集合中添加一个新项。

kotlin { jvm() { compilations { val main by getting val integrationTest by compilations.creating { defaultSourceSet { dependencies { // 依赖于 main 编译的编译类路径和输出进行编译: implementation(main.compileDependencyFiles + main.output.classesDirs) implementation(kotlin("test-junit")) /* ... */ } } // 创建一个测试任务来运行此编译产生的测试: tasks.register<Test>("integrationTest") { // 使用包含编译依赖项(包括 'main')、运行时依赖项和此编译输出的类路径运行测试: classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs // 仅运行此编译输出的测试: testClassesDirs = output.classesDirs } } } } }
kotlin { jvm() { compilations.create('integrationTest') { defaultSourceSet { dependencies { def main = compilations.main // 依赖于 main 编译的编译类路径和输出进行编译: implementation(main.compileDependencyFiles + main.output.classesDirs) implementation kotlin('test-junit') /* ... */ } } // 创建一个测试任务来运行此编译产生的测试: tasks.register('jvmIntegrationTest', Test) { // 使用包含编译依赖项(包括 'main')、运行时依赖项和此编译输出的类路径运行测试: classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs // 仅运行此编译输出的测试: testClassesDirs = output.classesDirs } } } }

你还需要在其他情况下创建自定义编译,例如,如果你想将不同 JVM 版本的编译合并到最终构件中,或者你已经在 Gradle 中设置了源代码集并想迁移到跨平台项目。

在 JVM 编译中使用 Java 源代码

在使用 项目向导 创建项目时,Java 源代码会包含在 JVM 目标的编译中。

在构建脚本中,以下部分应用了 Gradle 的 java 插件,并配置了目标以配合它:

kotlin { jvm { withJava() } }

Java 源文件被放置在 Kotlin 源根目录的子目录中。例如,路径如下:

Java 源文件

公共源代码集不能包含 Java 源代码。

由于当前的限制,Kotlin 插件会替代 Java 插件配置的一些任务:

  • 目标的 JAR 任务,而不是 jar (例如, jvmJar)。

  • 目标的测试任务,而不是 test (例如, jvmTest)。

  • 资源由编译的等效任务处理,而不是 *ProcessResources 任务。

此目标的发布由 Kotlin 插件处理,不需要 Java 插件特有的步骤。

配置与本地语言的互操作性

Kotlin 提供了与本地语言的互操作性和用于特定编译的 DSL 配置。

本地语言

支持的平台

备注

C

所有平台,除了 WebAssembly

Objective-C

Apple 平台(macOS、iOS、watchOS、tvOS)

通过 Objective-C 的 Swift

Apple 平台(macOS、iOS、watchOS、tvOS)

Kotlin 只能使用带有 @objc 属性的 Swift 声明。

编译可以与多个本地库交互。通过在 定义文件 或构建文件的 cinterops 中配置互操作性:

kotlin { linuxX64 { // 替换为你需要的目标。 compilations.getByName("main") { val myInterop by cinterops.creating { // 描述本地 API 的 def 文件。 // 默认路径是 src/nativeInterop/cinterop/<interop-name>.def definitionFile.set(project.file("def-file.def")) // 放置生成的 Kotlin API 的包名。 packageName("org.sample") // 传递给编译器的选项,通过 cinterop 工具。 compilerOpts("-Ipath/to/headers") // 查找头文件的目录。 includeDirs.apply { // 头文件搜索目录(相当于 -I<path> 编译器选项)。 allHeaders("path1", "path2") // 额外的目录,搜索 'headerFilter' def 文件选项中列出的头文件。 // -headerFilterAdditionalSearchPrefix 命令行选项的等效项。 headerFilterOnly("path1", "path2") } // includeDirs.allHeaders 的快捷方式。 includeDirs("include/directory", "another/directory") } val anotherInterop by cinterops.creating { /* ... */ } } } }
kotlin { linuxX64 { // 替换为你需要的目标。 compilations.main { cinterops { myInterop { // 描述本地 API 的 def 文件。 // 默认路径是 src/nativeInterop/cinterop/<interop-name>.def definitionFile = project.file("def-file.def") // 放置生成的 Kotlin API 的包名。 packageName 'org.sample' // 传递给编译器的选项,通过 cinterop 工具。 compilerOpts '-Ipath/to/headers' // 查找头文件的目录(相当于 -I<path> 编译器选项)。 includeDirs.allHeaders("path1", "path2") // 额外的目录,搜索 'headerFilter' def 文件选项中列出的头文件。 // -headerFilterAdditionalSearchPrefix 命令行选项的等效项。 includeDirs.headerFilterOnly("path1", "path2") // includeDirs.allHeaders 的快捷方式。 includeDirs("include/directory", "another/directory") } anotherInterop { /* ... */ } } } } }

Android 编译

默认情况下,为 Android 目标创建的编译与 Android 构建变体 相关联: 每个构建变体下会创建一个相同名称的 Kotlin 编译。

然后,对于为每个变体编译的每个 Android 源代码集, 会创建一个以目标名称为前缀的 Kotlin 源代码集,例如 Android 源代码集 debug 的 Kotlin 源代码集 androidDebug 和名为 android 的 Kotlin 目标。 这些 Kotlin 源代码集会被相应地添加到变体的编译中。

默认源代码集 commonMain 会被添加到每个生产(应用程序或库)变体的编译中。 commonTest 源代码集同样被添加到单元测试和仪器测试变体的编译中。

kapt 注解处理也得到支持,但由于当前的限制,它要求在配置 kapt 依赖项之前先创建 Android 目标, 这需要在顶层的 dependencies {} 块中完成,而不是在 Kotlin 源代码集依赖项中完成。

kotlin { android { /* ... */ } } dependencies { kapt("com.my.annotation:processor:1.0.0") }

源代码集层级的编译

Kotlin 可以使用 dependsOn 关系构建一个 源代码集层级

源代码集层级

如果源代码集 jvmMain 依赖于源代码集 commonMain ,则:

  • 每当 jvmMain 为某个特定目标编译时, commonMain 也参与该编译,并且也被编译成相同目标的二进制形式,例如 JVM 类文件。

  • jvmMain 的源代码可以访问 commonMain 的声明,包括内部声明,还可以访问 commonMain依赖项 ,即使是指定为 implementation 依赖项的。

  • jvmMain 可以包含针对 commonMain预期声明 的平台特定实现。

  • commonMain 的资源总是会与 jvmMain 的资源一起处理和复制。

  • jvmMaincommonMain语言设置 应该保持一致。

语言设置的一致性检查方式包括:

  • jvmMainlanguageVersion 应该大于或等于 commonMainlanguageVersion

  • jvmMain 应该启用所有 commonMain 启用的非稳定语言特性(对于 bugfix 的特性没有这种要求)。

  • jvmMain 应该使用 commonMain 使用的所有实验性注解。

  • apiVersion 、bugfix 的语言特性和 progressiveMode 可以任意设置。

Last modified: 26 十一月 2024