如何从Android Studio加速KotlinMultiplatform的iOS应用构建

46qrfjad  于 2022-12-23  发布在  Android
关注(0)|答案(2)|浏览(88)

我有一个KMP项目,其中包含iOS应用程序,Android应用程序和共享KMP模块。当我尝试从Android Studio构建iOS应用程序(为了能够调试它)时,构建成功。️
The problem is that the build always (when you change a code) take around 12 minutes 😅⏰. Which is way to long when you are debugging and often testing if given code works. The 90% percent of time spent on build is used to run these tasks:

> Task :kmpcorelib:linkDebugFrameworkIosArm64
> Task :kmpcorelib:linkDebugFrameworkIosX64
> Task :kmpcorelib:linkKMPCoreDebugFrameworkIosArm64
> Task :kmpcorelib:linkKMPCoreDebugFrameworkIosX64
> Task :kmpcorelib:linkKMPCoreReleaseFrameworkIosArm64
> Task :kmpcorelib:linkKMPCoreReleaseFrameworkIosX64
> Task :kmpcorelib:linkReleaseFrameworkIosArm64
> Task :kmpcorelib:linkReleaseFrameworkIosX64
    • 我的问题是**:有没有办法在iOS模拟器上运行应用程序,而不运行所有这些任务?

我不知道为什么工作室需要链接框架的发布版本。
我也不明白为什么它在X64模拟器上运行时必须运行iOSArm64变体。
运行linkDebugFrameworkIosArm64linkKMPCoreDebugFrameworkIosArm64有什么区别,不是重复吗?
PS:我通过点击Android Studio中的默认配置来运行iOS Buld,而不是一些自定义Gradle脚本。

    • 这是KMP build. gradle的外观:**
plugins {
    id("com.android.library")
    kotlin("multiplatform")
    kotlin("native.cocoapods")
    kotlin("plugin.serialization") version "1.5.0"
    id("com.prof18.kmp.fatframework.cocoa") version "0.0.1"
    id("io.gitlab.arturbosch.detekt")
    id("maven-publish")
}
version = "1.3.11"
group = "com.betsys.kmpcorelib"
val podName = "KMPCore"
detekt {
    autoCorrect = true
    config = files("$rootDir/config/detekt.yml")
    baseline = file("$rootDir/config/baseline.xml")
    input = files("src/commonMain/kotlin")
    reports {
        html.enabled = true
        xml.enabled = true
        txt.enabled = true
    }
}

// If you want to build iOS app from Android Studio - you have to put this config to comment - it somehow breaks the iOS build
fatFrameworkCocoaConfig {
    fatFrameworkName = podName
    outputPath = "$rootDir/../cocoapods"
    versionName = "1.16.1"
}
val ktorVersion = "1.5.4"
val napierVersion = "1.4.1"
val koinVersion = "3.0.1"
val kotlinxVersion = "1.4.1"
val kotlinxDatetime = "0.1.1"
kotlin {
    // We cant use simple ios() target now, since it doesnt support Arm32 architecture
    // For that reason we have specify each target explicitly
    // Same for folders with iOS code. We havet to use duplicit iosX64Main etc. instead of one iosMain folder
    ios("ios") {
        binaries.framework(podName)
    }
    android {
        publishLibraryVariants("debug")
        publishLibraryVariantsGroupedByFlavor = true
    }
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-core:$ktorVersion")
                implementation("io.ktor:ktor-client-logging:$ktorVersion")
                implementation("io.ktor:ktor-client-mock:$ktorVersion")
                implementation("io.ktor:ktor-client-serialization:$ktorVersion")
                implementation("io.ktor:ktor-client-websockets:$ktorVersion")
                api("io.insert-koin:koin-core:$koinVersion")
                api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxVersion-native-mt")
                api("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDatetime")
                api("com.ionspin.kotlin:bignum:0.3.1-SNAPSHOT")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0")
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test-common"))
                implementation(kotlin("test-annotations-common"))
                implementation( "io.mockk:mockk-common:1.11.0")
                implementation("com.ionspin.kotlin:bignum:0.3.1-SNAPSHOT")
            }
        }
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-android:$ktorVersion")
                implementation("com.google.android.material:material:1.3.0")
                implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinxVersion")
                implementation("com.jakewharton.timber:timber:4.7.1")
            }
        }
        val androidTest by getting {
            dependencies {
                implementation(kotlin("test-junit"))
                implementation("junit:junit:4.13.2")
                implementation("io.mockk:mockk:1.11.0")
            }
        }
        val iosMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-ios:$ktorVersion")
            }
        }
        val iosTest by getting
    }
}
android {
    compileSdkVersion(30)
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdkVersion(19)
        targetSdkVersion(30)
        versionCode = 1
        versionName = "1.0"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
        }
    }
    packagingOptions {
        excludes.add("META-INF/*.kotlin_module")
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().all {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
}
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 sdkName: String? = System.getenv("SDK_NAME")
    val isiOSDevice = sdkName.orEmpty().startsWith("iphoneos")
    val framework = kotlin.targets
        .getByName<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>(
            if (isiOSDevice) {
                "iosArm64"
            } else {
                "iosX64"
            }
        )
        .binaries.getFramework(mode)
    inputs.property("mode", mode)
    dependsOn(framework.linkTask)
    from({ framework.outputDirectory })
    into(targetDir)
    println("Build Folder => $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.build.dependsOn("packForXCode")
wyyhbhjk

wyyhbhjk1#

Android Studio中的“默认配置”(例如assemblebuild gradle任务)将构建所有“构建”任务,其中包括用于调试、发布以及X64和Arm64架构的iOS框架链接。
注意build.gradle.kts文件中的packForXcode任务吗?当您要为iOS应用程序构建KMM模块时,需要调用该任务(至少在本地)。使用该任务将仅构建所需的体系结构和配置(例如,模拟器上的X64DEBUG),你很快就会发现它快了很多,它应该在Xcode项目的Run script阶段调用,作为Build steps的一部分。
如果您在Android Studio中创建新项目时使用KotlinMultiplatform应用程序模板,我认为这应该已自动添加到Xcode项目中。
您可以在这里阅读更多信息:Understand the KMM project structure | Kotlin Multiplatform Mobile Docs

jdzmm42g

jdzmm42g2#

我使用此任务为iOS构建更改:

./gradlew :shared:compileKotlinIosSimulatorArm64

工作相当快

相关问题