gradle 同步成功时,Kotlin 多平台无法解析引用

Posted

技术标签:

【中文标题】gradle 同步成功时,Kotlin 多平台无法解析引用【英文标题】:Kotlin multiplatform cannot resolved references while gradle sync succeeds 【发布时间】:2020-09-15 23:18:06 【问题描述】:

当我编译我的 kotlin 多平台项目时,我在公共模块中使用的东西上得到 Unresolved reference。但是 gradle 同步工作正常。你可以找到我的项目here

详细说明:

    我按照Jetbrain to build a mobile multiplatform project 的教程进行操作。一切正常。

    然后我在公共模块内部实现了一个ktor客户端来请求一个api(jsonplaceholder)。我添加了所有必需的依赖项,一切似乎都很好。所有引用都已解决,我没有错误。

    但是当我使用make Project 编译我的项目时,所有添加到获取ktor 等的依赖项都无法解析。

我想我的项目配置有问题,当我运行./gradlew androidDependencies 时,SharedCode 似乎有问题,因为它有时在命令输出中标记为\--- :SharedCode

该项目的build.gradle 是:

buildscript 
    ext.kotlin_version = '1.3.71'
    repositories 
        google()
        jcenter()

    
    dependencies 
        classpath 'com.android.tools.build:gradle:4.0.0-rc01'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
    


allprojects 
    repositories 
        google()
        jcenter()

    


task clean(type: Delete) 
    delete rootProject.buildDir

通用SharedCode 模块的build.gradle.kts 是:

import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins 
    kotlin("multiplatform")
    kotlin("plugin.serialization")


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 
                baseName = "SharedCode"
            
        
    

    jvm("android")

    val serializationVersion = "0.20.0"
    val ktorVersion = "1.3.2"

    sourceSets["commonMain"].dependencies 
        implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
        implementation("io.ktor:ktor-client-core:$ktorVersion")
        implementation("io.ktor:ktor-client-json:$ktorVersion")
        implementation("io.ktor:ktor-client-serialization:$ktorVersion")//Kotlinxserializer
    

    sourceSets["androidMain"].dependencies 
        implementation("org.jetbrains.kotlin:kotlin-stdlib")
    


val packForXcode by tasks.creating(Sync::class) 
    val targetDir = File(buildDir, "xcode-frameworks")

    /// selecting the right configuration for the iOS
    /// framework depending on the environment
    /// variables set by Xcode build
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets
            .getByName<KotlinNativeTarget>("ios")
            .binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)

    from( framework.outputDirectory )
    into(targetDir)

    /// generate a helpful ./gradlew wrapper with embedded Java path
    doLast 
        val gradlew = File(targetDir, "gradlew")
        gradlew.writeText("#!/bin/bash\n"
                + "export 'JAVA_HOME=$System.getProperty("java.home")'\n"
                + "cd '$rootProject.rootDir'\n"
                + "./gradlew \$@\n")
        gradlew.setExecutable(true)
    


tasks.getByName("build").dependsOn(packForXcode)

Android 应用的build.gradle 是:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android 
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig 
        applicationId "com.mpp.mpptest"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    

    buildTypes 
        release 
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        
    



dependencies 
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation project(':SharedCode')

你知道我做错了什么吗?

我阅读了Building Multiplatform Projects with Gradle,但没有帮助。

我发现的唯一工作项目来自KaMPKit。我已将我的build.gradle(.kts) 文件设置为它们在 KaMPKit 中的状态(请参阅分支 Set_build_gradle_as_KaMPKit),但“未解决的引用”问题仍然存在。

【问题讨论】:

你的项目链接给404 @vizsatiz,我已经修复了链接,抱歉 【参考方案1】:

我解决了我的问题。错误是因为我没有声明插件android.lybrary

即使没有必要修复问题,我还是决定将我的build.gradle 文件切换到kotlin DLS,我重写了所有build.gradle,并对共享模块进行了以下更改:

我创建了一个AndroidManifest.xml 我添加了com.android.library 插件 我添加了一个区块android

最后,共享模块的build.gradle.kts 如下所示:

import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins 
    kotlin("multiplatform")
    kotlin("plugin.serialization")
    id("kotlinx-serialization")
    id("com.android.library")


android 
    compileSdkVersion(29)
    defaultConfig 
        minSdkVersion(Versions.min_sdk)
        targetSdkVersion(Versions.target_sdk)
        versionCode = 1
        versionName = "1.0"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    


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 
                baseName = "SharedCode"
            
        
    

    jvm("android")

    sourceSets["commonMain"].dependencies 
        implementation(kotlin("stdlib-common", Versions.kotlin))
        implementation(Deps.Ktor.commonCore)
        implementation(Deps.Ktor.commonJson)
        implementation(Deps.Coroutines.common)
        implementation(Deps.Ktor.commonSerialization)
    

    sourceSets["androidMain"].dependencies 
        implementation(kotlin("stdlib", Versions.kotlin))
        implementation(Deps.Coroutines.jdk)
        implementation(Deps.Ktor.androidSerialization)
    

    sourceSets["iosMain"].dependencies 
        implementation(Deps.Ktor.iosSerialization)
    


val packForXcode by tasks.creating(Sync::class) 
    val targetDir = File(buildDir, "xcode-frameworks")

    /// selecting the right configuration for the iOS
    /// framework depending on the environment
    /// variables set by Xcode build
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val framework = kotlin.targets
            .getByName<KotlinNativeTarget>("ios")
            .binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)

    from( framework.outputDirectory )
    into(targetDir)

    /// generate a helpful ./gradlew wrapper with embedded Java path
    doLast 
        val gradlew = File(targetDir, "gradlew")
        gradlew.writeText("#!/bin/bash\n"
                + "export 'JAVA_HOME=$System.getProperty("java.home")'\n"
                + "cd '$rootProject.rootDir'\n"
                + "./gradlew \$@\n")
        gradlew.setExecutable(true)
    


tasks.getByName("build").dependsOn(packForXcode)

所有依赖版本号都来自Dependencies.kt 文件(参见KaMPKit)

所有依赖关系现在都已解决。

【讨论】:

以上是关于gradle 同步成功时,Kotlin 多平台无法解析引用的主要内容,如果未能解决你的问题,请参考以下文章

Gradle 同步 BUILD SUCCESSFUL 但使项目失败

在 Kotlin 1.3 多平台 gradle 项目中参考来自 kotlin-jvm 的 kotlin-js 资源

通过 gradle legacy 插件应用程序应用 Kotlin 多平台插件

如何使用单个build.gradle配置向kotlin多平台项目添加依赖项

从 kotlin 多平台项目创建 fat jar

Gradle kotlin Springboot多模块导致无法引用kotlin的类文件(BootJar)