如何将第三方 iOS pod 库添加到 kotlin 原生项目中?收到错误 "SharedCode:cinteropAFNetworkingIos failed"
How to add thirdparty iOS pod library into kotlin native project ? getting error "SharedCode:cinteropAFNetworkingIos failed"
我创建了 Kotlin 本机项目以在 iOS 和 android.I 之间共享代码,并为 cocoapods 进行了集成,以便使用 POD 文件在 iOS 项目中使用,项目成功 运行 在 iOS 和 Android 上,但是当我尝试在 Kotlin 本机项目中使用 iOS pod 库时,我开始出现以下错误。
我知道我必须先从 Xcode 运行 pod install 才能在 Kotlin 原生项目中编译库。
SO iOS pod 库应该通过 cinterop 转换,以便在 Kotlin Native 项目中使用。
我 运行 下面的命令只是为了检查框架编译是否成功。
./gradlew :SharedCode:packForXCode
收到这个错误
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':SharedCode:cinteropAFNetworkingIos'.
> Cannot perform cinterop processing for AFNetworking: cannot determine headers location.
Probably the build is executed from command line.
Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode.
请在下面找到 Gradle 文件。
build.Gradle.kts
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework("Shared") {
baseName = "SharedCode"
}
}
}
jvm("android")
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
version = "1.0.0"
cocoapods {
summary = "This is sample Summary"
homepage = "Home URL"
pod("AFNetworking", "~> 3.2.0")
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
//selecting the right configuration for the iOS framework depending on the Xcode environment variables
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets.getByName<KotlinNativeTarget>("ios").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew $@\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)```
我刚刚尝试了这些步骤,并设法使用 CocoaPods 插件扩展 this 示例与 AFNetworking 框架的工作互操作。这些是我的步骤:
- 克隆项目并签出
step-008
分支后,以这种方式编辑 build.gradle.kts:将 CocoaPods 插件作为 id("org.jetbrains.kotlin.native.cocoapods")
添加到 plugins
部分并删除整个 binaries
块来自 iOSTarget 规范块。应该这样做,因为 cocoaPods 插件会自行创建框架,我们应该避免重复(参见 discussion)。添加 cocoapods
规范而不是该块。脚本的这一部分应如下所示:
iOSTarget("ios") {}
version = "1.0.0"
cocoapods {
summary = "This is sample Summary"
homepage = "Home URL"
pod("AFNetworking", "~> 3.2.0")
}
- 然后,执行 Gradle 任务
podspec
为您的框架生成 podspec。这应该像上一个一样在 /SharedCode/
目录中完成。如果任务没有出现,说明没有正确应用CocoaPods插件。
- 当 podspec 准备就绪后,我们可以从 Xcode 项目中使用它。为此,打开
/native/KotlinIOS/
目录,并在那里创建 Podfile。我将这些内容用于:
use_frameworks!
platform :ios, '9.0'
target 'KotlinIOS' do
pod 'SharedCode', :path => '../../SharedCode'
end
这里重要的是名字对应我们的框架名,相对路径从第一步开始就指向包含build.gradle.kts
的地方。创建 Podfile 后,使用终端中的 pod install
在此处安装 pods(CocoaPods 应为 installed)。
- 现在打开生成的
KotlinIOS.xcworkspace
和 Xcode。在那里,还应该修复一件事。此时,KotlinIOS 项目设置为仅在 /SharedCode/build/Xcode-frameworks/
目录中搜索框架,但 CocoaPods 不会将任何内容放在那里。因此,select KotlinIOS 在左侧面板上,打开“构建设置”选项卡并找到“搜索路径”->“框架搜索路径”。按 + 并将 $(inherited) 添加到列表中,以使 CocoaPods 安装的框架可用。
- 现在,从 Xcode 执行构建。之后,在您的 Kotlin IDE 中,AFNetworking 包应该可用。要导入它,请使用
import cocoapods.AFNetworking.*
。第一次它可能需要使缓存无效并重新启动,以使其正确看到此包。
希望对您有所帮助。如果本说明中有不清楚的地方,请发表评论。
添加这个答案是因为一些用户想知道为什么 IDE 建议 在 [=34= 的情况下没有出现】 通用代码。原因是 IOS 代码的通用化还没有完成,这意味着 iosMain 将无法工作,它将编译但没有显示建议或导入。要使其正常工作,您必须指定特定的源集。
例如。
kotlin {
android()
iosX64()
cocoapods {
// Configure fields required by CocoaPods.
summary = "Kotlin Multiplatform Firebase login sample"
homepage = "https://github.com/worstkiller/firebaseloginkmm"
pod("FirebaseAuth")
frameworkName = "sharedFramework"
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.firebase:firebase-auth:${Versions.firebase_auth_android}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines}")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.viewmodel}")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:${Versions.junit}")
}
}
val iosX64Main by getting
val iosX64Test by getting
configure(listOf(iosX64Main)) {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.coroutines_native}")
}
}
}
}
在上面的代码块中,我添加了仅对 iosX64 源集的支持,这意味着它只能在机器上运行。您可以类似地添加对 iosArm64.
的支持
这是一个我已经提出的问题,如果可能的话,请投票使其有意义。
我创建了 Kotlin 本机项目以在 iOS 和 android.I 之间共享代码,并为 cocoapods 进行了集成,以便使用 POD 文件在 iOS 项目中使用,项目成功 运行 在 iOS 和 Android 上,但是当我尝试在 Kotlin 本机项目中使用 iOS pod 库时,我开始出现以下错误。
我知道我必须先从 Xcode 运行 pod install 才能在 Kotlin 原生项目中编译库。
SO iOS pod 库应该通过 cinterop 转换,以便在 Kotlin Native 项目中使用。
我 运行 下面的命令只是为了检查框架编译是否成功。
./gradlew :SharedCode:packForXCode
收到这个错误
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':SharedCode:cinteropAFNetworkingIos'.
> Cannot perform cinterop processing for AFNetworking: cannot determine headers location.
Probably the build is executed from command line.
Note that a Kotlin/Native module using CocoaPods dependencies can be built only from Xcode.
请在下面找到 Gradle 文件。
build.Gradle.kts
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
}
kotlin {
//select iOS target platform depending on the Xcode environment variables
val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iOSTarget("ios") {
binaries {
framework("Shared") {
baseName = "SharedCode"
}
}
}
jvm("android")
sourceSets["commonMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
}
sourceSets["androidMain"].dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
version = "1.0.0"
cocoapods {
summary = "This is sample Summary"
homepage = "Home URL"
pod("AFNetworking", "~> 3.2.0")
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
//selecting the right configuration for the iOS framework depending on the Xcode environment variables
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val framework = kotlin.targets.getByName<KotlinNativeTarget>("ios").binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
doLast {
val gradlew = File(targetDir, "gradlew")
gradlew.writeText("#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew $@\n")
gradlew.setExecutable(true)
}
}
tasks.getByName("build").dependsOn(packForXcode)```
我刚刚尝试了这些步骤,并设法使用 CocoaPods 插件扩展 this 示例与 AFNetworking 框架的工作互操作。这些是我的步骤:
- 克隆项目并签出
step-008
分支后,以这种方式编辑 build.gradle.kts:将 CocoaPods 插件作为id("org.jetbrains.kotlin.native.cocoapods")
添加到plugins
部分并删除整个binaries
块来自 iOSTarget 规范块。应该这样做,因为 cocoaPods 插件会自行创建框架,我们应该避免重复(参见 discussion)。添加cocoapods
规范而不是该块。脚本的这一部分应如下所示:
iOSTarget("ios") {}
version = "1.0.0"
cocoapods {
summary = "This is sample Summary"
homepage = "Home URL"
pod("AFNetworking", "~> 3.2.0")
}
- 然后,执行 Gradle 任务
podspec
为您的框架生成 podspec。这应该像上一个一样在/SharedCode/
目录中完成。如果任务没有出现,说明没有正确应用CocoaPods插件。 - 当 podspec 准备就绪后,我们可以从 Xcode 项目中使用它。为此,打开
/native/KotlinIOS/
目录,并在那里创建 Podfile。我将这些内容用于:
use_frameworks!
platform :ios, '9.0'
target 'KotlinIOS' do
pod 'SharedCode', :path => '../../SharedCode'
end
这里重要的是名字对应我们的框架名,相对路径从第一步开始就指向包含build.gradle.kts
的地方。创建 Podfile 后,使用终端中的 pod install
在此处安装 pods(CocoaPods 应为 installed)。
- 现在打开生成的
KotlinIOS.xcworkspace
和 Xcode。在那里,还应该修复一件事。此时,KotlinIOS 项目设置为仅在/SharedCode/build/Xcode-frameworks/
目录中搜索框架,但 CocoaPods 不会将任何内容放在那里。因此,select KotlinIOS 在左侧面板上,打开“构建设置”选项卡并找到“搜索路径”->“框架搜索路径”。按 + 并将 $(inherited) 添加到列表中,以使 CocoaPods 安装的框架可用。 - 现在,从 Xcode 执行构建。之后,在您的 Kotlin IDE 中,AFNetworking 包应该可用。要导入它,请使用
import cocoapods.AFNetworking.*
。第一次它可能需要使缓存无效并重新启动,以使其正确看到此包。
希望对您有所帮助。如果本说明中有不清楚的地方,请发表评论。
添加这个答案是因为一些用户想知道为什么 IDE 建议 在 [=34= 的情况下没有出现】 通用代码。原因是 IOS 代码的通用化还没有完成,这意味着 iosMain 将无法工作,它将编译但没有显示建议或导入。要使其正常工作,您必须指定特定的源集。
例如。
kotlin {
android()
iosX64()
cocoapods {
// Configure fields required by CocoaPods.
summary = "Kotlin Multiplatform Firebase login sample"
homepage = "https://github.com/worstkiller/firebaseloginkmm"
pod("FirebaseAuth")
frameworkName = "sharedFramework"
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutines}")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.firebase:firebase-auth:${Versions.firebase_auth_android}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines}")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.viewmodel}")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:${Versions.junit}")
}
}
val iosX64Main by getting
val iosX64Test by getting
configure(listOf(iosX64Main)) {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.coroutines_native}")
}
}
}
}
在上面的代码块中,我添加了仅对 iosX64 源集的支持,这意味着它只能在机器上运行。您可以类似地添加对 iosArm64.
的支持这是一个我已经提出的问题,如果可能的话,请投票使其有意义。