ktor 依赖项未在多平台项目的 ios 模块中解析
ktor dependencies not resolved in ios module of multiplatform project
我有一个针对 iOS 和 Android 的 kotlin 多平台项目。
公共模块使用Ktor http客户端
Android 应用一切正常。
但是当使用 iOS lib 构建项目时,我收到以下异常:
> Task :app:compileKotlinIos FAILED
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:4:8: error: unresolved reference: io
import io.ktor.client.HttpClient
^
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:5:8: error: unresolved reference: io
import io.ktor.client.features.feature
...还有其他的,说 none 的 ktor 依赖关系已经解决。
这里是build.gradle:
plugins {
id 'kotlin-multiplatform' version '1.3.10'
}
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
ext {
support_lib_version = '28.0.0'
ktor_version = '1.0.0'
}
def keystorePropertiesFile = rootProject.file("./app/secret.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.ottamotta.mozoli"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [auth0Domain: "@string/com_auth0_domain", auth0Scheme: "https"]
}
buildTypes {
debug {
resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
}
release {
resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
minifyEnabled false
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.support:recyclerview-v7:${support_lib_version}"
implementation "com.android.support:appcompat-v7:${support_lib_version}"
implementation 'com.squareup.picasso:picasso:2.71828'
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1")
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
implementation "com.auth0.android:auth0:1.14.1"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
}
kotlin {
targets {
fromPreset(presets.android, 'android')
// This preset is for iPhone emulator
// Switch here to presets.iosArm64 (or iosArm32) to build library for iPhone device
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
implementation "io.ktor:ktor-client:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
implementation "io.ktor:ktor-client-jackson:$ktor_version"
}
}
commonTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-common'
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
}
}
androidMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
implementation "io.ktor:ktor-client-android:$ktor_version"
}
}
androidTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test'
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
}
iosMain {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktor_version")
}
}
iosTest {
}
}
}
task copyFramework {
def buildType = project.findProperty("kotlin.build.type") ?: "DEBUG"
def target = project.findProperty("kotlin.target") ?: "ios"
dependsOn "link${buildType.toLowerCase().capitalize()}Framework${target.capitalize()}"
doLast {
def srcFile = kotlin.targets."$target".compilations.main.getBinary("FRAMEWORK", buildType)
def targetDir = getProperty("configuration.build.dir")
copy {
from srcFile.parent
into targetDir
include 'app.framework/**'
include 'app.framework.dSYM'
}
}
}
这是生成错误的通用模块的文件代码:
package com.ottamotta.mozoli.api
import com.ottamotta.mozoli.*
import io.ktor.client.HttpClient
import io.ktor.client.features.feature
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.JsonSerializer
import io.ktor.client.features.json.defaultSerializer
import io.ktor.client.request.header
import io.ktor.client.request.request
import io.ktor.client.request.url
import io.ktor.http.HttpMethod
class MozoliApiKtor(
private val serverUrl: String,
private var jsonSerializer: JsonSerializer? = null,
private val tokenProvider: suspend () -> String?
) : MozoliApi {
private val client: HttpClient
private val AUTH_HEADER = "Authorization";
private val TOKEN_PREFIX = "Bearer "
init {
client = HttpClient {
install(JsonFeature) {
serializer = jsonSerializer ?: defaultSerializer()
}
}
jsonSerializer = client.feature(JsonFeature)?.serializer
}
override suspend fun getUserProfile(): User {
return client.request {
url("${serverUrl}/user/")
method = HttpMethod.Get
header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
}
}
override suspend infix fun getEventsByCity(cityId: String): List<Event> {
return client.request {
url("${serverUrl}/event/city/${cityId}")
method = HttpMethod.Get
header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
}
}
}
我遇到了和你一样的问题。为 Android 应用构建并完美运行,但 iOS 模块找不到任何 Ktor、协程或 kotlinx 序列化 class.
跟随 https://github.com/adrianbukros/github-multiplatform-example,并尝试复制他们的设置,我终于通过复制他们的一些 gradle 设置来完成 packForXCode
任务:
他们的公共模块build.gradle
,应该是这样的:
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
kotlin {
targets {
fromPreset(presets.jvm, "android")
fromPreset(presets.iosX64, "ios_x86_64")
fromPreset(presets.iosArm64, "ios_arm64")
configure([ios_x86_64, ios_arm64]) {
compilations.main.outputKinds("FRAMEWORK")
}
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-ios:$ktor_version"
}
configure([ios_x86_64Main, ios_arm64Main]) {
dependsOn iosMain
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String configuration = project.findProperty("CONFIGURATION")?.toUpperCase() ?: "DEBUG"
final String arch = project.findProperty("ARCHS") ?: "x86_64"
dependsOn kotlin.targets."ios_${arch}".compilations.main.linkTaskName("FRAMEWORK", configuration)
from { kotlin.targets."ios_${arch}".compilations.main.getBinary("FRAMEWORK", configuration).parentFile }
into frameworkDir
}
tasks.build.dependsOn packForXCode
他们的 settings.gradle
文件应如下所示:
enableFeaturePreview("GRADLE_METADATA") // IMPORTANT!
include 'commoncode'
include 'app'
如果仍然无法正常工作,请查看他们所有的 *.gradle
和 gradle.*
文件,看看您的文件有何不同。
这终于让我完成了任务,我可以在 XCode 中使用我的 Kotlin Ktor 代码。但是,现在 Android Studio 对共享 iOS 模块说 "Kotlin is not configured"。如果我弄清楚原因,我会回来报告,如果你找到了什么,请分享!
编辑
将公共模块 build.gradle
更改为如下所示,似乎一切正常!
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
kotlin {
targets {
fromPreset(presets.jvm, 'android')
// Change to `presets.iosArm64` to deploy the app to iPhone
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-ios:$ktor_version"
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
inputs.property "mode", mode
dependsOn kotlin.targets.ios.compilations.main.linkTaskName("FRAMEWORK", mode)
from { kotlin.targets.ios.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew $@\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
截至目前,iOS 的 kotlin 多平台在 windows 上没有 运行。这可以解释为什么只有 iosmain 代码中的依赖项无法解析。
我有一个针对 iOS 和 Android 的 kotlin 多平台项目。 公共模块使用Ktor http客户端
Android 应用一切正常。 但是当使用 iOS lib 构建项目时,我收到以下异常:
> Task :app:compileKotlinIos FAILED
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:4:8: error: unresolved reference: io
import io.ktor.client.HttpClient
^
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:5:8: error: unresolved reference: io
import io.ktor.client.features.feature
...还有其他的,说 none 的 ktor 依赖关系已经解决。
这里是build.gradle:
plugins {
id 'kotlin-multiplatform' version '1.3.10'
}
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
ext {
support_lib_version = '28.0.0'
ktor_version = '1.0.0'
}
def keystorePropertiesFile = rootProject.file("./app/secret.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.ottamotta.mozoli"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [auth0Domain: "@string/com_auth0_domain", auth0Scheme: "https"]
}
buildTypes {
debug {
resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
}
release {
resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
minifyEnabled false
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.support:recyclerview-v7:${support_lib_version}"
implementation "com.android.support:appcompat-v7:${support_lib_version}"
implementation 'com.squareup.picasso:picasso:2.71828'
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1")
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
implementation "com.auth0.android:auth0:1.14.1"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
}
kotlin {
targets {
fromPreset(presets.android, 'android')
// This preset is for iPhone emulator
// Switch here to presets.iosArm64 (or iosArm32) to build library for iPhone device
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
implementation "io.ktor:ktor-client:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
implementation "io.ktor:ktor-client-jackson:$ktor_version"
}
}
commonTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-common'
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
}
}
androidMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
implementation "io.ktor:ktor-client-android:$ktor_version"
}
}
androidTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test'
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
}
iosMain {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktor_version")
}
}
iosTest {
}
}
}
task copyFramework {
def buildType = project.findProperty("kotlin.build.type") ?: "DEBUG"
def target = project.findProperty("kotlin.target") ?: "ios"
dependsOn "link${buildType.toLowerCase().capitalize()}Framework${target.capitalize()}"
doLast {
def srcFile = kotlin.targets."$target".compilations.main.getBinary("FRAMEWORK", buildType)
def targetDir = getProperty("configuration.build.dir")
copy {
from srcFile.parent
into targetDir
include 'app.framework/**'
include 'app.framework.dSYM'
}
}
}
这是生成错误的通用模块的文件代码:
package com.ottamotta.mozoli.api
import com.ottamotta.mozoli.*
import io.ktor.client.HttpClient
import io.ktor.client.features.feature
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.JsonSerializer
import io.ktor.client.features.json.defaultSerializer
import io.ktor.client.request.header
import io.ktor.client.request.request
import io.ktor.client.request.url
import io.ktor.http.HttpMethod
class MozoliApiKtor(
private val serverUrl: String,
private var jsonSerializer: JsonSerializer? = null,
private val tokenProvider: suspend () -> String?
) : MozoliApi {
private val client: HttpClient
private val AUTH_HEADER = "Authorization";
private val TOKEN_PREFIX = "Bearer "
init {
client = HttpClient {
install(JsonFeature) {
serializer = jsonSerializer ?: defaultSerializer()
}
}
jsonSerializer = client.feature(JsonFeature)?.serializer
}
override suspend fun getUserProfile(): User {
return client.request {
url("${serverUrl}/user/")
method = HttpMethod.Get
header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
}
}
override suspend infix fun getEventsByCity(cityId: String): List<Event> {
return client.request {
url("${serverUrl}/event/city/${cityId}")
method = HttpMethod.Get
header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
}
}
}
我遇到了和你一样的问题。为 Android 应用构建并完美运行,但 iOS 模块找不到任何 Ktor、协程或 kotlinx 序列化 class.
跟随 https://github.com/adrianbukros/github-multiplatform-example,并尝试复制他们的设置,我终于通过复制他们的一些 gradle 设置来完成 packForXCode
任务:
他们的公共模块build.gradle
,应该是这样的:
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
kotlin {
targets {
fromPreset(presets.jvm, "android")
fromPreset(presets.iosX64, "ios_x86_64")
fromPreset(presets.iosArm64, "ios_arm64")
configure([ios_x86_64, ios_arm64]) {
compilations.main.outputKinds("FRAMEWORK")
}
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-ios:$ktor_version"
}
configure([ios_x86_64Main, ios_arm64Main]) {
dependsOn iosMain
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String configuration = project.findProperty("CONFIGURATION")?.toUpperCase() ?: "DEBUG"
final String arch = project.findProperty("ARCHS") ?: "x86_64"
dependsOn kotlin.targets."ios_${arch}".compilations.main.linkTaskName("FRAMEWORK", configuration)
from { kotlin.targets."ios_${arch}".compilations.main.getBinary("FRAMEWORK", configuration).parentFile }
into frameworkDir
}
tasks.build.dependsOn packForXCode
他们的 settings.gradle
文件应如下所示:
enableFeaturePreview("GRADLE_METADATA") // IMPORTANT!
include 'commoncode'
include 'app'
如果仍然无法正常工作,请查看他们所有的 *.gradle
和 gradle.*
文件,看看您的文件有何不同。
这终于让我完成了任务,我可以在 XCode 中使用我的 Kotlin Ktor 代码。但是,现在 Android Studio 对共享 iOS 模块说 "Kotlin is not configured"。如果我弄清楚原因,我会回来报告,如果你找到了什么,请分享!
编辑
将公共模块 build.gradle
更改为如下所示,似乎一切正常!
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
kotlin {
targets {
fromPreset(presets.jvm, 'android')
// Change to `presets.iosArm64` to deploy the app to iPhone
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-ios:$ktor_version"
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
inputs.property "mode", mode
dependsOn kotlin.targets.ios.compilations.main.linkTaskName("FRAMEWORK", mode)
from { kotlin.targets.ios.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew $@\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
截至目前,iOS 的 kotlin 多平台在 windows 上没有 运行。这可以解释为什么只有 iosmain 代码中的依赖项无法解析。