Kotlin 中文文档 v2.0.10 Help

构建最终的原生二进制文件

默认情况下,Kotlin/Native 目标被编译为 *.klib 库构件,该构件可以被 Kotlin/Native 本身作为依赖使用,但不能作为可执行文件或原生库使用。

要声明最终的原生二进制文件,如可执行文件或共享库,请使用原生目标的 binaries 属性。 该属性表示为此目标构建的原生二进制文件集合,除了默认的 *.klib 构件之外,还提供了一组用于声明和配置它们的方法。

由 Kotlin/Native 编译器生成的二进制文件可能包含第三方代码、数据或衍生作品。 这意味着如果您分发 Kotlin/Native 编译的最终二进制文件, 您应始终在二进制分发中包含必要的许可证文件

声明二进制文件

使用以下工厂方法来声明 binaries 集合的元素。

工厂方法

二进制类型

可用目标

executable

产品可执行文件

所有原生目标

test

测试可执行文件

所有原生目标

sharedLib

共享原生库

所有原生目标,除了 WebAssembly

staticLib

静态原生库

所有原生目标,除了 WebAssembly

framework

Objective-C 框架

仅限 macOS、iOS、watchOS 和 tvOS 目标

最简单的版本不需要任何额外参数,并为每种构建类型创建一个二进制文件。 目前,有两种构建类型可用:

  • DEBUG – 生成包含调试信息的非优化二进制文件

  • RELEASE – 生成无调试信息的优化二进制文件

以下代码片段创建了两个可执行的二进制文件,分别是调试版和发布版:

kotlin { linuxX64 { // 可根据需要定义目标。 binaries { executable { // 二进制文件配置。 } } } }

如果不需要额外配置 ,可以省略 lambda 表达式:

binaries { executable() }

您可以指定为哪些构建类型创建二进制文件。在以下示例中,仅创建了 debug 可执行文件:

binaries { executable(listOf(DEBUG)) { // 二进制文件配置。 } }
binaries { executable([DEBUG]) { // 二进制文件配置。 } }

您还可以声明具有自定义名称的二进制文件:

binaries { executable("foo", listOf(DEBUG)) { // 二进制文件配置。 } // 可以省略构建类型列表 // (在这种情况下,将使用所有可用的构建类型)。 executable("bar") { // 二进制文件配置。 } }
binaries { executable('foo', [DEBUG]) { // 二进制文件配置。 } // 可以省略构建类型列表 // (在这种情况下,将使用所有可用的构建类型)。 executable('bar') { // 二进制文件配置。 } }

第一个参数设置名称前缀,这是二进制文件的默认名称。例如,在 Windows 上,这段代码会生成文件 foo.exebar.exe 。您还可以使用名称前缀来在构建脚本中访问二进制文件

访问二进制文件

您可以访问二进制文件来配置它们或获取它们的属性(例如,输出文件的路径)。

您可以通过其唯一名称获取二进制文件。此名称基于名称前缀(如果指定)、构建类型 和 二进制类型,遵循以下模式: <可选名称前缀><构建类型><二进制类型> ,例如 releaseFrameworktestDebugExecutable

// 如果没有找到相应的二进制文件,将会失败。 binaries["fooDebugExecutable"] binaries.getByName("fooDebugExecutable") // 如果没有找到相应的二进制文件,返回 null。 binaries.findByName("fooDebugExecutable")
// 如果没有找到相应的二进制文件,将会失败。 binaries['fooDebugExecutable'] binaries.fooDebugExecutable binaries.getByName('fooDebugExecutable') // 如果没有找到相应的二进制文件,返回 null。 binaries.findByName('fooDebugExecutable')

或者,您可以使用类型化的 getter 方法通过名称前缀和构建类型来访问二进制文件。

// 如果没有找到相应的二进制文件,将会失败。 binaries.getExecutable("foo", DEBUG) binaries.getExecutable(DEBUG) // 如果未设置名称前缀,可省略第一个参数。 binaries.getExecutable("bar", "DEBUG") // 也可以使用字符串指定构建类型。 // 对于其他二进制类型,也有类似的 getter 方法: // getFramework, getStaticLib 和 getSharedLib。 // 如果没有找到相应的二进制文件,返回 null。 binaries.findExecutable("foo", DEBUG) // 对于其他二进制类型,也有类似的 getter 方法: // findFramework, findStaticLib 和 findSharedLib。
// 如果没有找到相应的二进制文件,将会失败。 binaries.getExecutable('foo', DEBUG) binaries.getExecutable(DEBUG) // 如果未设置名称前缀,可省略第一个参数。 binaries.getExecutable('bar', 'DEBUG') // 也可以使用字符串指定构建类型。 // 对于其他二进制类型,也有类似的 getter 方法: // getFramework, getStaticLib 和 getSharedLib。 // 如果没有找到相应的二进制文件,返回 null。 binaries.findExecutable('foo', DEBUG) // 对于其他二进制类型,也有类似的 getter 方法: // findFramework, findStaticLib 和 findSharedLib。

导出依赖项到二进制文件

在构建 Objective-C 框架或原生库(共享或静态)时,您可能需要打包的不仅是当前项目的类,还包括其依赖项的类。 使用 export 方法指定要导出的依赖项到二进制文件中。

kotlin { sourceSets { macosMain.dependencies { // 将会被导出。 api(project(":dependency")) api("org.example:exported-library:1.0") // 不会被导出。 api("org.example:not-exported-library:1.0") } } macosX64("macos").binaries { framework { export(project(":dependency")) export("org.example:exported-library:1.0") } sharedLib { // 可以将不同的依赖项集导出到不同的二进制文件。 export(project(':dependency')) } } }
kotlin { sourceSets { macosMain.dependencies { // 将会被导出。 api project(':dependency') api 'org.example:exported-library:1.0' // 不会被导出。 api 'org.example:not-exported-library:1.0' } } macosX64("macos").binaries { framework { export project(':dependency') export 'org.example:exported-library:1.0' } sharedLib { // 可以将不同的依赖项集导出到不同的二进制文件。 export project(':dependency') } } }

例如,您实现了多个 Kotlin 模块,并希望从 Swift 访问它们。 虽然在 Swift 应用程序中使用多个 Kotlin/Native 框架是有限的,但您可以创建一个总框架,并将所有这些模块导出到其中。

当您导出一个依赖项时,它会将该依赖项的所有 API 包含到框架的 API 中。 编译器会将这个依赖项的代码添加到框架中,即使您只使用了它的一小部分。 这会禁用对导出依赖项(以及它的依赖项在一定程度上)的死代码消除。

默认情况下,导出是非传递性的。这意味着,如果您导出库 foo 并且 foo 依赖于库 bar, 只有 foo 的方法会被添加到输出框架中。

您可以使用 transitiveExport 选项来改变这种行为。如果设置为 true ,库 bar 的声明也会被导出。

binaries { framework { export(project(":dependency")) // 传递导出。 transitiveExport = true } }
binaries { framework { export project(':dependency') // 传递导出。 transitiveExport = true } }

构建通用框架

默认情况下,由 Kotlin/Native 生成的 Objective-C 框架只支持一个平台。然而,您可以使用 lipo 工具 将这些框架合并成一个通用(fat)二进制文件。 这一操作特别适用于 32 位和 64 位 iOS 框架。在这种情况下,您可以在 32 位和 64 位设备上使用生成的通用框架。

import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask kotlin { // 创建并配置目标。 val watchos32 = watchosArm32("watchos32") val watchos64 = watchosArm64("watchos64") configure(listOf(watchos32, watchos64)) { binaries.framework { baseName = "my_framework" } } // 创建一个构建 fat 框架的任务。 tasks.register<FatFrameworkTask>("debugFatFramework") { // 通用框架必须与初始框架具有相同的基本名称。 baseName = "my_framework" // 默认的目标目录是 "<build directory>/fat-framework"。 destinationDir = buildDir.resolve("fat-framework/debug") // 指定要合并的框架。 from( watchos32.binaries.getFramework("DEBUG"), watchos64.binaries.getFramework("DEBUG") ) } }
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask kotlin { // 创建并配置目标。 targets { watchosArm32("watchos32") watchosArm64("watchos64") configure([watchos32, watchos64]) { binaries.framework { baseName = "my_framework" } } } // 创建一个构建 fat 框架的任务。 tasks.register("debugFatFramework", FatFrameworkTask) { // 通用框架必须与初始框架具有相同的基本名称。 baseName = "my_framework" // 默认的目标目录是 "<build directory>/fat-framework"。 destinationDir = file("$buildDir/fat-framework/debug") // 指定要合并的框架。 from( targets.watchos32.binaries.getFramework("DEBUG"), targets.watchos64.binaries.getFramework("DEBUG") ) } }

构建 XCFrameworks

所有 Kotlin 跨平台项目可以使用 XCFrameworks 作为输出,以将所有目标平台和架构的逻辑汇聚到一个单独的包中。 与 通用(fat)框架 不同,您不需要在将应用程序发布到 App Store 之前删除所有不必要的架构。

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework plugins { kotlin("multiplatform") } kotlin { val xcf = XCFramework() val iosTargets = listOf(iosX64(), iosArm64(), iosSimulatorArm64()) iosTargets.forEach { it.binaries.framework { baseName = "shared" xcf.add(this) } } }
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig plugins { id 'org.jetbrains.kotlin.multiplatform' } kotlin { def xcf = new XCFrameworkConfig(project) def iosTargets = [iosX64(), iosArm64(), iosSimulatorArm64()] iosTargets.forEach { it.binaries.framework { baseName = 'shared' xcf.add(it) } } }

当您声明 XCFrameworks 时,Kotlin Gradle 插件将注册三个 Gradle 任务:

  • assembleXCFramework

  • assembleDebugXCFramework (附加的调试构件,包含 dSYMs

  • assembleReleaseXCFramework

如果您在项目中使用 CocoaPods 集成 ,可以使用 Kotlin CocoaPods Gradle 插件构建 XCFrameworks。 该插件包括以下任务,这些任务可以用所有已注册的目标构建 XCFrameworks,并生成 podspec 文件:

  • podPublishReleaseXCFramework :生成一个 release 版本的 XCFramework 以及一个 podspec 文件。

  • podPublishDebugXCFramework :生成一个 debug 版本的 XCFramework 以及一个 podspec 文件。

  • podPublishXCFramework :同时生成 debug 和 release 版本的 XCFramework 以及 podspec 文件。

这将帮助您通过 CocoaPods 将项目的共享部分与移动应用程序分开分发。您还可以使用 XCFrameworks 发布到私有或公共的 podspec 仓库。

自定义 Info.plist 文件

在生成框架时,Kotlin/Native 编译器会生成信息属性列表文件 Info.plist。 你可以通过相应的二进制选项自定义其属性:

属性

二进制选项

CFBundleIdentifier

bundleId

CFBundleShortVersionString

bundleShortVersionString

CFBundleVersion

bundleVersion

要启用该功能,可以传递 -Xbinary=$option=$value 编译器标志,或者为特定框架设置 Gradle DSL 的 binaryOption("option", "value")

binaries { framework { binaryOption("bundleId", "com.example.app") binaryOption("bundleVersion", "2") } }
Last modified: 08 九月 2024