跳转到内容
Skip
3.2k

升级指南

本页面包含 Skip 主要版本之间的升级指南。如果你正在启动一个新项目,这些指南不适用于你。请参阅入门指南

Skip 和 Swift Package Manager 都使用语义化版本。虽然语义化版本有许多优点,但这也意味着从 Skip 0.x 升级到 Skip 1.x 被视为潜在的“破坏性变更”,因此需要手动升级步骤。要将你的 Skip 0.x 库或应用迁移到 Skip 1.x,请执行以下操作:

  1. 在你的 Package.swift 文件中,将对以下 Skip 包的依赖从 from: 0.x.y 更新为 from: 1.0.0

    • skip
    • skip-unit
    • skip-lib
    • skip-foundation
    • skip-model
    • skip-ui

    例如,以下是我们的 HelloSkip 示例应用更新后的 Package.swift

    import PackageDescription
    ...
    let package = Package(
    name: "skipapp-hello",
    ...
    dependencies: [
    .package(url: "https://github.com/skiptools/skip.git", from: "1.0.0"),
    .package(url: "https://github.com/skiptools/skip-ui.git", from: "1.0.0")
    ],
    ...
    )
  2. 在 Xcode 中打开你的项目并运行 File → Packages → Update to Latest Package Versions

  3. 删除项目文件夹中的 .build/ 目录和 Package.resolved 文件。

如果遇到任何问题,请联系支持

Android/settings.gradle.kts 的必要更改

Section titled “Android/settings.gradle.kts 的必要更改”

Android/settings.gradle.kts 中的 commandLine 调用需要调用 xcrun swift build …,而不是之前的 swift build。完整示例可以参考 skip-hello 应用的构建文件:https://source.skip.dev/skipapp-hello/blob/main/Android/settings.gradle.kts

// 这个 gradle 项目是常规 Skip 应用项目的一部分。
// 它调用了共享的 build skip 插件逻辑,该逻辑作为 skip-unit buildSrc 的一部分包含
// 从 Android Studio 构建时,它使用 BUILT_PRODUCTS_DIR 文件夹与 Xcode 共享相同的构建输出,否则使用 SwiftPM 的 .build/ 文件夹
pluginManagement {
// BUILT_PRODUCTS_DIR 的本地覆盖
if (System.getenv("BUILT_PRODUCTS_DIR") == null) {
//System.setProperty("BUILT_PRODUCTS_DIR", "${System.getProperty("user.home")}/Library/Developer/Xcode/DerivedData/MySkipProject-aqywrhrzhkbvfseiqgxuufbdwdft/Build/Products/Debug-iphonesimulator")
}
// 插件源码作为 SkipUnit 转译的一部分链接
val skipOutput = System.getenv("BUILT_PRODUCTS_DIR") ?: System.getProperty("BUILT_PRODUCTS_DIR")
val outputExt = if (skipOutput != null) ".output" else "" // Xcode 将输出保存在 package-name.output 中;SPM 没有后缀
val skipOutputs: File = if (skipOutput != null) {
// BUILT_PRODUCTS_DIR 在从 Xcode 构建时设置,此时我们将使用 Xcode 的 DerivedData 插件输出
file(skipOutput).resolve("../../../SourcePackages/plugins/")
} else {
exec {
// 从 SwiftPM 模块生成转译的 Kotlin 并生成 Gradle 项目
commandLine("sh", "-c", "xcrun swift build --triple arm64-apple-ios --sdk $(xcrun --sdk iphoneos --show-sdk-path)")
workingDir = file("..")
}
// SPM 输出文件夹是父级 Package.swift 的同级目录
rootDir.resolve("../.build/plugins/outputs/")
}
// 加载 Skip 插件(skip-unit 项目的一部分),它负责配置 Android 项目
// 因为这个路径是一个符号链接,我们需要使用规范路径,否则 gradle 会将其误解为不同的构建源
var pluginSource = skipOutputs.resolve("skip-unit${outputExt}/SkipUnit/skipstone/buildSrc/").canonicalFile
if (!pluginSource.isDirectory) {
// 检查新 SwiftPM6 插件的 "destination" 文件夹以进行命令行构建
pluginSource = skipOutputs.resolve("skip-unit${outputExt}/SkipUnit/destination/skipstone/buildSrc/").canonicalFile
}
if (!pluginSource.isDirectory) {
throw GradleException("Missing expected Skip output folder: ${pluginSource}. Run `swift build` in the root folder to create, or specify Xcode environment BUILT_PRODUCTS_DIR.")
}
includeBuild(pluginSource.path) {
name = "skip-plugins"
}
}
plugins {
id("skip-plugin") apply true
}

Kotlin 2 引入了许多对 Kotlin 语言的改进,并将 Compose 编译器集成到了 Kotlin 编译器本身1。Skip 0.9.2 采用 Kotlin 2 作为目标语言,这涉及对 Skip 创建的 Gradle 项目的一些更改2。在内部,这涉及更改 Skip 添加到 Android Gradle 项目的一些依赖。

这些更改对于 Skip 框架项目来说大部分是透明的。但在 Skip 0.9.2 之前创建的 Skip 应用项目需要进行一些更改才能与新的 Compose 编译器配合使用。

要升级 Skip 应用项目,在任何文本编辑器(如 Xcode、Android Studio 或 TextEdit)中打开 Android/app/build.gradle.kts 文件,并进行以下更改:

  1. plugins { } 块中添加 alias(libs.plugins.kotlin.compose)
  2. composeOptions { } 块中移除 kotlinCompilerExtensionVersion = libs.versions.kotlin.compose.compiler.extension.get()

skip-build-plugin 包含在所有使用 skip init 创建的 Skip 应用项目中,如果检测到你的项目需要更新,它会提供有用的错误消息:

需要升级的 Skip 项目的 Xcode 错误消息{: style=“width: 100%;”} {: style=“text-align: center; margin: auto;“}

Android/app/build.gradle.kts 的必要更改

Section titled “Android/app/build.gradle.kts 的必要更改”

以下是对 Android/app/build.gradle.kts 所需更改的简要对比。完整示例可以参考 skip-hello 应用的构建文件:https://source.skip.dev/skipapp-hello/blob/main/Android/app/build.gradle.kts

更改前:

plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.android.application)
id("skip-build-plugin")
}
android {
namespace = group as String
compileSdk = libs.versions.android.sdk.compile.get().toInt()
compileOptions {
sourceCompatibility = JavaVersion.toVersion(libs.versions.jvm.get())
targetCompatibility = JavaVersion.toVersion(libs.versions.jvm.get())
}
defaultConfig {
minSdk = libs.versions.android.sdk.min.get().toInt()
targetSdk = libs.versions.android.sdk.compile.get().toInt()
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.kotlin.compose.compiler.extension.get()
}
}

更改后:

plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose) // 添加此行
alias(libs.plugins.android.application)
id("skip-build-plugin")
}
android {
namespace = group as String
compileSdk = libs.versions.android.sdk.compile.get().toInt()
compileOptions {
sourceCompatibility = JavaVersion.toVersion(libs.versions.jvm.get())
targetCompatibility = JavaVersion.toVersion(libs.versions.jvm.get())
}
kotlinOptions {
jvmTarget = libs.versions.jvm.get().toString() // 添加此行
}
defaultConfig {
minSdk = libs.versions.android.sdk.min.get().toInt()
targetSdk = libs.versions.android.sdk.compile.get().toInt()
}
composeOptions {
// kotlinCompilerExtensionVersion = libs.versions.kotlin.compose.compiler.extension.get() // 移除此行
}
}

错误:检测到任务 ‘compileDebugJavaWithJavac’ (17) 和 ‘compileDebugKotlin’ (22) 的 JVM 目标兼容性不一致。

Section titled “错误:检测到任务 ‘compileDebugJavaWithJavac’ (17) 和 ‘compileDebugKotlin’ (22) 的 JVM 目标兼容性不一致。”

整个 Gradle 项目必须使用相同的 JVM 目标,包括你自己的应用以及所有 Skip 依赖。之前这是通过 compileOptions 块的 sourceCompatibilitytargetCompatibility 属性自动完成的,但现在还需要使用 jvmTarget 属性将其添加到 kotlinOptions 块中。按如下方式编辑你的 build.gradle.kts 文件:

android {
compileOptions {
sourceCompatibility = JavaVersion.toVersion(libs.versions.jvm.get())
targetCompatibility = JavaVersion.toVersion(libs.versions.jvm.get())
}
kotlinOptions {
jvmTarget = libs.versions.jvm.get().toString() // 添加此行
}
}

当 Compose 编译器插件未添加到应用的 Android/app/build.gradle.kts 文件时,会出现此错误。确保你已按照本迁移指南中的说明修复此错误。

此错误的简要表示如下:

e: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
> Task :app:compileDebugKotlin FAILED
File being compiled: /opt/src/github/skiptools/skipapp-hello/Android/app/src/main/kotlin/hello/skip/Main.kt
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:50)
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:253)
at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236)
at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:65)
Caused by: java.lang.RuntimeException: Exception while generating code for:
FUN LOCAL_FUNCTION_FOR_LAMBDA name:PresentationRootView$lambda$1 visibility:private modality:FINAL <> (ctx:skip.ui.ComposeContext) returnType:kotlin.Unit?
VALUE_PARAMETER name:ctx index:0 type:skip.ui.ComposeContext
BLOCK_BODY
VAR name:contentContext type:skip.ui.ComposeContext [val]
  1. Jetpack Compose 编译器迁移到 Kotlin 仓库:https://android-developers.googleblog.com/2024/04/jetpack-compose-compiler-moving-to-kotlin-repository.html

  2. 迁移 Jetpack Compose 项目:https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-compiler.html#migrating-a-jetpack-compose-project