Swift 官方正式支持 Android - Apple银魂 - 科技改变生活 - 万事屋 | 生活·动漫·娱乐综合社区-银魂同好聚集地

Swift 官方正式支持 Android

近日,Swift 官方正式宣布成立 Android 的工作组,将 Android 列为官方支持的平台,该工作组的主要目标是为 Swift 语言添加并维护 Android 平台支持,让开发者能够使用 Swift 开发 Android 应用:

Swift 官方正式支持 Android

其实 Swift 语言跨平台支持也不是什么新鲜事,在之前我聊过的 Skip 用 Swift 写 Android App 的时候就聊过,只是不同的是 Skip 是将 Swift 翻译成 Kotlin,把 SwiftUI 翻译成 Compose 的形式来实现,这和 uni-app x 的跨平台实现殊途同归。

❝感兴趣的可以看 《2025 跨平台框架更新和发布对比》

但是 Swift 官方的方案则不同,它是通过 LLVM 进行适配的,我们之前聊过的 《为什么跨平台框架可以适配鸿蒙》 就聊过,LLVM 也是各大框架适配鸿蒙的重要基石,甚至一些方案适配鸿蒙是通过 Apple 的 LLVM 去先导出 IR 来完成前置工作。

而这次 Swift on Android 的实现,则是直接利用 Android 平台的构建工具:Android NDK 。

为什么这么说?因为  Swift  编译器从诞生之初就基于 LLVM ,而 Google 的 Android NDK 后来也使用基于 LLVM 的 Clang 作为其官方 C/C++ 编译器 :

❝说起 Clang 和苹果也是很有渊源,Clang 的设计初衷是提供一个可以替代 GCC 的前端编译器,因为 GCC 的发展不符合 Apple 的节奏和需要,同时受限于License,苹果公司无法使用 LLVM 在 GCC 基础上进一步提升代码生成质量,因此苹果公司决定从头编写 C、C++、Objective-C 语言的前端 Clang,以彻底替代GCC

而在编译上,比如 stdlib 里的 AddSwiftStdlib.cmake 可以看到, Swift 没有在 Android 上创造一套自己的 log 系统,它直接链接了 Android 的 Native 的日志 log 来实现,从而支持 Android Studio 的 Logcat :

Swift 官方正式支持 Android

所以基于 LLVM 的 Android NDK 是实现 Swift 跨平台编译的关键,它让 Swift 编译器能够被“重定向”,从而为 Android 支持的 CPU 架构(如 aarch64 armv7 x86_64 )生成相应的原生机器码 。

$ NDK_PATH=path/to/android-ndk-r27c
$ SWIFT_PATH=path/to/swift-DEVELOPMENT-SNAPSHOT-2024-11-09-a-ubuntu22.04/usr/bin
$ git checkout swift-DEVELOPMENT-SNAPSHOT-2024-11-09-a
$ utils/build-script 
    -R                                        # Build in ReleaseAssert mode.
    --android                                 # Build for Android.
    --android-ndk $NDK_PATH                   # Path to an Android NDK.
    --android-arch aarch64                    # Optionally specify Android architecture, alternately armv7 or x86_64
    --android-api-level 21                    # The Android API level to target. Swift only supports 21 or greater.
    --stdlib-deployment-targets=android-aarch64  # Only cross-compile the stdlib for Android, ie don't build the native stdlib for Linux
    --native-swift-tools-path=$SWIFT_PATH     # Path to your prebuilt Swift compiler
    --native-clang-tools-path=$SWIFT_PATH     # Path to a prebuilt clang compiler, one comes with the Swift toolchain
    --build-swift-tools=0                     # Don't build the Swift compiler and other host tools
    --build-llvm=0                            # Don't build the LLVM libraries, but generate some CMake files needed by the Swift stdlib build
    --skip-build-cmark                         # Don't build the CommonMark library that's only needed by the Swift compiler

❝简而言之,就是编译成 so 。

目前官方要求是在 Linux 环境下(官方推荐 Ubuntu 20.04/22.04)下,使用 Swift 官方提供的交叉编译工具链,将 .swift 源文件编译成原生可执行文件或共享库,之后将编译产物连同必需的 Swift 运行时库,通过 Android  adb 推送到 Android 设备或模拟器上,最终这些原生代码可以在 Android 的 shell 环境中直接运行,或被一个标准的 Android 应用加载并调用 :

Swift 官方正式支持 Android

首先需要运行以下命令复制复制对应的 so :

$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftCore.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftAndroid.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftSwiftOnoneSupport.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftRemoteMirror.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswift_Concurrency.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswift_RegexParser.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswift_StringProcessing.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libdispatch.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libBlocksRuntime.so /data/local/tmp

然后还需要复制 Android NDK 的 libc++ :

$ adb push /path/to/android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so /data/local/tmp

此外还需要复制在上一步中构建的 hello 可执行文件:

$ adb push hello /data/local/tmp

最终通过 adb shell 命令在 Android 设备上执行 hello 可执行文件:

$ adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/hello

而对于 Android 端来看,此时的 Swift 产物与 C/C++ 代码没什么区别 ,它必须作为一个标准的 .so 库被加载,并通过 JNI 规范暴露需要支持的能力。

目前 Swift 的核心标准库( stdlib )已经可以成功在 Android 平台进行编译  ,也就是目前 String Int Array Dictionary 等基础数据类型已经完成基本支持:

Swift 官方正式支持 Android

更高层次的核心库,比如 Foundation URLSession JSONEncoder )和 Dispatch (提供并发支持),也正在被移植到 Android 平台。

而对于 UI 部分,目前 Swift 官方暂未提供任何支持 Android 的 UI 框架 ,官方文档目前表示:“ You’d need some sort of framework to build a user interface for your application, which the Swift stdlib does not provide ” 。

Swift 官方正式支持 Android

所以, 从这个层面看,它更像是 KMP 的存在 ,而如果需要类似 CMP 的支持,那么大概率需要 SwfitUI 的官方适配,毕竟 Skip 其实只是一个翻译框架。

而在互操作上,其实过去就有 swift-java 这个图的互操作方向的尝试,当时的目标是实现 Swift 与 Java 之间的双向互操作性,即支持 Swift 调用 Java 库,也支持 Java 调用 Swift 库 :

Swift 官方正式支持 Android

但是从官方描述来看, Swift on Android 似乎并没有直接使用类似桥接绑定,也就是你需要自己实现这部分,如果你需要的话:

Swift 官方正式支持 Android

而对于 Swift on Android  来说,要让一个 Swift 函数能被外部的 C 代码(以及遵循 C 调用约定的 JNI)所发现和调用,一般也就是通过 @_cdecl 属性,这个属性可以将函数编译成一个简单的、符合 C 语言标准的符号(Symbol)并暴露出去。

❝虽然没找到对应的 demo 或者实现,但是理论上如果想要不暴露接口,大概率还是通过 @_cdecl

所以目前 Swift on Android 给人的感觉确实很毛坯 ,在交互和 UI 上都很欠缺,看起来只是开源了一种可能,具体能达到什么效果暂时还看不出来,但是多少算是官方起了个头,也算是有了希望,对于 iOS 来说,这个春天还需要再等等。

那么,你觉得 Swift on Android 的存在多久可以达到生产标准?

请登录后发表评论

    没有回复内容

万事屋新帖