android-studio - 如何从 Android Studio 加速 Kotlin Multiplatform 的 iOS 应用程序构建
问题描述
我有一个包含 iOS 应用、Android 应用和共享 KMP 模块的 KMP 项目。当我尝试从 Android Studio 构建 iOS 应用程序(以便能够对其进行调试)时,构建成功。☺️
问题是构建总是(当你更改代码时)大约需要 12 分钟⏰。当您调试并经常测试给定代码是否有效时,这会很长。90% 的构建时间用于运行这些任务:
> 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 模拟器上运行应用程序而不运行所有这些任务?
不知道为什么工作室需要链接RELEASE版本的框架。
我也不明白为什么它iOSArm64
在 X64 模拟器上运行时必须运行变体。
linkDebugFrameworkIosArm64
运行和linkKMPCoreDebugFrameworkIosArm64
不是重复有什么区别?
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")
解决方案
Android Studio 中的“默认配置”(例如,assemble
或build
gradle 任务)将构建所有“构建”任务,其中包括调试、发布以及 X64 和 Arm64 架构的 iOS 框架的链接。
注意到packForXcode
你在build.gradle.kts
文件中得到的那个任务了吗?当您想为您的 iOS 应用程序(至少在本地)构建 KMM 模块时,这就是您想要调用的内容。使用该任务将只构建您需要的架构和配置(例如X64
,DEBUG
在您的模拟器上),您很快就会发现它要快得多。它应该在运行脚本阶段作为Xcode 项目的构建步骤的一部分被调用。
如果您在 Android Studio 中创建新项目时使用 Kotlin Multiplatform 应用程序模板,我相信这应该已自动添加到您的 Xcode 项目中。
您可以在此处阅读更多相关信息:了解 KMM 项目结构 | Kotlin 多平台移动文档
推荐阅读
- html - 如何制作具有拉伸效果的 3D 元素?
- svg - 将 SVG 合并在一起
- linux - crontab 不能通过交叉编译工作
- php - 获取客户端用于请求数据的网站的 IP
- android - 如何禁用 Android Studio 3.6 多碎片
- css - 如何更改 Material-UI 似乎适用于其所有组件的默认填充
- npm - 安装私有 npm 包的问题
- python - python jarvis没有运行第2部分
- r - 看起来where子句中有一个错误
- amazon-web-services - 使用 AWS 托管区块链为 Hyperledger Fabric 网络实施 API 服务器时 DNS 解析失败?