Kotlin Multiplatform - 错误 ITMS-90171:无效的捆绑包结构

Posted

技术标签:

【中文标题】Kotlin Multiplatform - 错误 ITMS-90171:无效的捆绑包结构【英文标题】:Kotlin Multiplatform - ERROR ITMS-90171: Invalid Bundle Structure 【发布时间】:2021-05-20 11:08:55 【问题描述】:

我在 Apple App Store 上尝试使用 Kotlin Multiplatform 分发我的 ios 应用时遇到问题:

错误 ITMS-90171:“无效的捆绑结构 - 不允许使用二进制文件 'Smiledu_app.app/Frameworks/shared.framework/shared'。您的应用不能包含独立的可执行文件或库,除了有效的 CFBundleExecutable支持的捆绑包。有关 iOS 应用捆绑包结构的信息,请参阅https://developer.apple.com/go/?id=bundle-structure 的捆绑包编程指南。”

我检查了它在构建阶段中不存在 -> 复制捆绑资源

这是我的 build.gradle.kts

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

plugins 
    kotlin("multiplatform")
    kotlin("native.cocoapods")
    kotlin("plugin.serialization")
    id("com.android.library")
    id("kotlin-android-extensions")
    id("com.squareup.sqldelight")


repositories 
    gradlePluginPortal()
    google()
    jcenter()
    mavenCentral()
    maven 
        url = uri("https://dl.bintray.com/kotlin/kotlin-eap")
    


dependencies 
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.2.0")


configurations 
    create("compileClasspath")


android 
    compileSdkVersion(29)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig 
        minSdkVersion(24)
        targetSdkVersion(29)
        versionCode = 1
        versionName = "1.0"
    
    buildTypes 
        getByName("release") 
            isMinifyEnabled = false
        
    


val libName = "shared"

kotlin 
    android()
    ios 
        binaries.framework(libName)
    

    val coroutinesVersion = "1.4.1-native-mt"
    val serializationVersion = "1.0.0-RC"
    val ktorVersion = "1.4.0"
    val sqlDelightVersion = "1.4.3"
    val reactive_version = "1.1.18"

    sourceSets 
        val commonMain by getting 
            dependencies 
                implementation("org.jetbrains.kotlin:kotlin-stdlib-common")

                // Coroutines
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.2")

                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion")

                //  KTOR
                implementation("io.ktor:ktor-client-core:$ktorVersion")
                implementation("io.ktor:ktor-client-json:$ktorVersion")
                implementation("io.ktor:ktor-client-serialization:$ktorVersion")

                // SQLDELIGHT
                implementation("com.squareup.sqldelight:runtime:$sqlDelightVersion")

                // Reactive
                implementation("com.badoo.reaktive:reaktive:$reactive_version")
            
        
        val androidMain by getting 
            dependencies 
                implementation("org.jetbrains.kotlin:kotlin-stdlib")

                implementation("androidx.core:core-ktx:1.3.2")
                implementation("io.ktor:ktor-client-android:$ktorVersion")
                implementation("com.squareup.sqldelight:android-driver:$sqlDelightVersion")

                implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
            
        
        val iosMain by getting 
            dependencies 
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.2")

                // HTTP
                implementation("io.ktor:ktor-client-ios:$ktorVersion")
                implementation("com.squareup.sqldelight:native-driver:$sqlDelightVersion")
            
        

        all 
            languageSettings.apply 
                progressiveMode = true
                useExperimentalAnnotation("kotlin.RequiresOptIn")
                useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
            
        
    


val packForXcode by tasks.creating(Sync::class) 
    group = "build"
    val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
    val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
    val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
    val framework = kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    val targetDir = File(buildDir, "xcode-frameworks")
    from( framework.outputDirectory )
    into(targetDir)

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

sqldelight 
    database("SmileduDataBase") 
        packageName = "com.example.smiledu"
        schemaOutputDirectory = file("src/commonMain/db/databases")
    

【问题讨论】:

您好,请检查您的shared.framework 是否包含在`复制捆绑资源`步骤中:- your target app -> Build Phases -> Copy Bundle Resources 是的,它在 Copy Bundle Resources 中不存在。我已经更新了帖子 ***.com/questions/40558866/… 看看这个 你好,@SebastianPeredoMurga!在 kotlinlang Slack 上有一个类似的线程(获取邀请 here)。我在这里发布原始线程(link)的链接和引用: This issue for me was caused by including the framework in the bundle. Ie, I was copying the .framework file into the app bundle. This isn’t necessary as the framework is statically linked against the main app binary. Most likely, you have a folder containing the .framework that you copied into your project (like an “external” or “ThirdParty”). That folder should not have membership to any target. 【参考方案1】:

从“嵌入框架”部分中删除“shared.framework”可能会解决您的问题。确保在将构建推送到 TestFlight 之前在本地验证构建。

【讨论】:

以上是关于Kotlin Multiplatform - 错误 ITMS-90171:无效的捆绑包结构的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin MultiPlatform - 发布 Android 库失败

如何确定 kotlin-multiplatform 项目中的构建类型

Kotlin Multiplatform - 使用 Ktor 处理响应 http 代码和异常

Kotlin Multiplatform 中 iOS 应用程序的不同架构

如何在 Kotlin/Multiplatform 项目中使用 .klib 库

Kotlin-Multiplatform 中的 CPointer