在 .NET 运行时仓库中构建、运行与调试 Android 上的 CoreCLR:完整开发者工作流
【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址: https://gitcode.com/GitHub_Trending/runtime6/runtime
导读
本文基于 .NET 运行时仓库(dotnet/runtime)的官方开发者文档,系统讲解如何在 macOS、Linux 以及 Windows+WSL2 主机上为 Android 平台构建 CoreCLR 运行时、使用HelloAndroid示例在模拟器中部署运行应用、在模拟器上跑功能测试,并利用 Android Studio 对 CoreCLR 原生运行时进行断点调试。读完本文,你将掌握从环境准备、交叉编译到真机/模拟器验证、原生符号调试的完整闭环技能,可直接用于日常的 CoreCLR Android 移植与验证工作。
支持的构建主机与目标架构
根据 android.md 的说明,CoreCLR for Android 的构建支持情况如下:
| 主机系统 | 支持情况 |
|---|---|
| macOS | ✔ 支持 |
| Linux | ✔ 支持 |
| Windows | ❌ 不支持(仅能通过 WSL2 间接构建) |
| 目标架构 | 支持情况 |
|---|---|
| x86 | ❌ 不支持 |
| x64 | ✔ 支持 |
| arm | ❌ 不支持 |
| arm64 | ✔ 支持 |
注意:目前仅支持
x64与arm64两个目标架构。真机(尤其主流手机)通常是arm64,而模拟器按宿主机架构选择x64或arm64。
macOS / Linux 上的构建流程
环境前置条件(Prerequisites)
在 macOS 或 Linux 上构建 CoreCLR for Android,需要准备:
- OpenJDK 23:下载并安装(构建工具链依赖其完成 APK 打包等任务)。
- Android Studio:安装后通过 SDK Manager 获取以下组件:
- Android SDK,最低支持的 API level 为24;
- Android NDK r27c。
这些前置项也可以手动下载安装,两种替代方式:
- 自动化脚本:参考 Testing Libraries on Android 中描述的脚本,可一次性拉取 SDK/NDK;
- 手动下载归档:
- Android SDK:下载 command-line tools 后,用
sdkmanager安装 SDK 组件; - Android NDK:直接下载 NDK 归档。
- Android SDK:下载 command-line tools 后,用
安装完成后,设置以下环境变量(写入 shell 配置文件可避免每次重复导出):
export ANDROID_SDK_ROOT=<full-path-to-android-sdk> export ANDROID_NDK_ROOT=<full-path-to-android-ndk>构建运行时、类库与工具链
在仓库根目录(<repo-root>)执行以下命令,即可完成本地开发所需的 CoreCLR 运行时、JIT、CoreLib、原生 CoreLib、工具与类库的构建:
./build.sh clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.packages+libs -os android -arch <x64|arm64> -c <Debug|Release>如果需要进一步产出 CoreCLR 运行时NuGet 包,则在上述子集基础上追加host+packs:
./build.sh clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.packages+libs+host+packs -os android -arch <x64|arm64> -c <Debug|Release>两个要点:
- 生成的运行时 NuGet 包位于
<repo-root>/artifacts/packages/<configuration>/Shipping/; - 面向静态链接的静态 CoreCLR 运行时(
libcoreclr_static.a)目前只出现在内部构建产物中,尚未随 NuGet 包发布。
从源码看,clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.packages+libs这一串子集正是 src/mono/sample/Android/Makefile 中RUNTIME_FLAVOR=coreclr时runtimepack目标所复用的同一组构建子集,也就是说示例应用的make流程与文档给出的手工构建命令在运行时产物上完全一致。
Windows + WSL2 构建流程
Windows 上目前不能直接构建 CoreCLR for Android,但官方支持借助WSL2完成。
Windows 侧要求
- 下载并安装 Android Studio;
- 启用 Windows 的长路径支持,具体见 windows-requirements.md。
WSL 侧要求
- 先按 linux-requirements.md 完成 Linux 环境(工具链、依赖包)准备;
- 按上文 macOS/Linux 前置条件 安装 OpenJDK、Android SDK 与 Android NDK。可选方式:
- 使用官方提供的自动化脚本;
- 手动下载归档;
- 在 WSL 内安装 Android Studio(需要先保证 WSL 版本较新,且开启了 systemd):
# 在 Windows 主机侧执行,更新 WSL wsl --update # 在 WSL 发行版设置中启用 systemd 后,安装 Android Studio sudo snap install android-studio --classic
- 对于 Ubuntu,OpenJDK 21 已足够:
apt install openjdk-21-jdk - 设置环境变量:
export ANDROID_SDK_ROOT=<full-path-to-android-sdk> export ANDROID_NDK_ROOT=<full-path-to-android-ndk>
构建运行时、类库与工具链
在 WSL 的仓库根目录执行与 Linux 完全相同的命令:
./build.sh clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.packages+libs -os android -arch <x64|arm64> -c <Debug|Release>构建并运行 HelloAndroid 示例应用
为演示 CoreCLR Android 应用的构建与运行,文档使用 HelloAndroid 示例应用。运行它的前提是:CoreCLR 已经按目标 Android 平台成功构建。
示例的入口 Program.cs 非常简洁——向logcat输出Hello, Android!并返回退出码42:
using System; public static class Program { public static int Main(string[] args) { Console.WriteLine("Hello, Android!"); // logcat return 42; } }构建 HelloAndroid
在仓库根目录执行:
make BUILD_CONFIG=<Debug|Release> TARGET_ARCH=<x64|arm64> RUNTIME_FLAVOR=CoreCLR DEPLOY_AND_RUN=false run -C src/mono/sample/AndroidBUILD_CONFIG:Debug或Release;TARGET_ARCH:x64或arm64;RUNTIME_FLAVOR:指定为CoreCLR(Makefile默认值是mono,必须显式切换);DEPLOY_AND_RUN=false:只构建不部署运行。
成功构建后,APK 输出在:
<repo-root>/artifacts/bin/AndroidSampleApp/<x64|arm64>/<Debug|Release>/android-<x64|arm64>/Bundle/bin/HelloAndroid.apk从 Makefile 看,make run实际等价于执行dotnet publish,并携带了TargetOS=android、TargetArchitecture、DeployAndRun、RuntimeFlavor等参数;当DEPLOY_AND_RUN=true时,AndroidSampleApp.csproj 中的RunAppBundle目标会通过 xharness 调用android test,以--expected-exit-code=42校验示例应用成功运行(与Program.Main返回42呼应)。
在模拟器上运行 HelloAndroid
先在 Android Studio 的Device Manager中创建并启动一个 Android Virtual Device(AVD),随后执行:
make BUILD_CONFIG=<Debug|Release> TARGET_ARCH=<x64|arm64> RUNTIME_FLAVOR=CoreCLR DEPLOY_AND_RUN=true run -C src/mono/sample/Android模拟器也可以直接从终端启动:
$ANDROID_SDK_ROOT/emulator/emulator -avd <emulator-name>WSL2 下运行到 Windows 主机的模拟器
应用可以运行在Windows 主机侧的模拟器上,步骤如下:
- 在 Windows 主机安装 Android Studio(版本与前置条件一致);
- 在 Windows 中创建并启动模拟器;
- 在 WSL 中,将 WSL2 内 Android SDK 的
adb替换为 Windows 主机的adb:mv $ANDROID_SDK_ROOT/platform-tools/adb $ANDROID_SDK_ROOT/platform-tools/adb-orig ln -s /mnt/<path-to-sdk-on-host>/platform-tools/adb.exe $ANDROID_SDK_ROOT/platform-tools/adbWindows 主机上 SDK 的位置可以在 Android Studio 的 SDK Manager 中查看;
- 让 xharness 使用指向 Windows 主机 adb 的路径:
export ADB_EXE_PATH=$ANDROID_SDK_ROOT/platform-tools/adb - 在 WSL 中按上文命令执行
make。
在模拟器上构建并运行功能测试
文档以 Android.Device_Emulator.JIT.Test 测试项目为例,演示在 CoreCLR Android 上构建并运行测试:
./dotnet.sh build -c <Debug|Release> src/tests/FunctionalTests/Android/Device_Emulator/JIT/Android.Device_Emulator.JIT.Test.csproj /p:TargetOS=android /p:TargetArchitecture=<x64|arm64> /t:Test /p:RuntimeFlavor=coreclr/t:Test:触发测试执行目标;/p:RuntimeFlavor=coreclr:指定使用 CoreCLR 运行时;- 与
HelloAndroid一样,运行前需要先启动模拟器。
该测试项目的 csproj 声明了RunAOTCompilation=false(即纯 JIT 模式)与ExpectedExitCode=42,其 Program.cs 同样打印Hello, Android!并返回42,用于在设备/模拟器上验证 JIT 路径下的 CoreCLR 正常运行。
仓库 src/tests/FunctionalTests/Android/Device_Emulator 下还提供了大量同类测试变体,可用于覆盖不同运行时模式:Interpreter、AOT、AOT_LLVM、AOT_PROFILED、NativeAOT、PInvoke、RuntimeConfig、StartupHook、CrashChaining等,可在此基础上扩展验证面。
调试 CoreCLR 运行时与示例应用
目前托管代码调试尚不支持,但可以调试:
- 示例应用的Java 部分;
- CoreCLR host 与运行时本身的原生代码。
调试在 Android Studio 中通过Profile or Debug APK完成。
调试步骤
以
Debug配置、arm64目标架构构建运行时与HelloAndroid示例应用;将运行时库的调试符号文件
libcoreclr.so.dbg重命名为libcoreclr.so.so,该文件位于:<repo-root>/artifacts/bin/AndroidSampleApp/arm64/Debug/android-arm64/publish/libcoreclr.so.dbg打开 Android Studio,选择Profile or Debug APK项目;
选择目标 APK 文件,例如:
<repo-root>/artifacts/bin/AndroidSampleApp/arm64/Debug/android-arm64/Bundle/bin/HelloAndroid.apk在项目面板中展开
HelloAndroid -> cpp -> libcoreclr,双击libcoreclr.so:在右侧Debug Symbols面板点击Add;
定位到步骤 2 中重命名后的符号文件并选中(
<repo-root>/artifacts/bin/AndroidSampleApp/arm64/Debug/android-arm64/publish/libcoreclr.so.so);符号加载成功后,
HelloAndroid -> cpp -> libcoreclr下会列出全部源码文件;找到
exports.cpp,在coreclr_initialize函数上设置断点并启动调试会话:
提示:如果构建运行时没有把调试符号剥离到独立文件(即不存在
libcoreclr.so.dbg),则可省略第 5~8 步。构建时传入-keepnativesymbols选项即可保留符号:./build.sh clr.runtime+clr.alljits+clr.corelib+clr.nativecorelib+clr.tools+clr.packages+libs -os android -arch <x64|arm64> -c Debug -keepnativesymbols
-keepnativesymbols的实际效果在构建脚本 eng/native/build-commons.sh 中可以看到:它会把-DCLR_CMAKE_KEEP_NATIVE_SYMBOLS=true追加到 CMake 参数,从而阻止 native 构建剥离调试符号。
相关资源
- 使用 Mono 运行时调试 Android 应用的类似指南见 android-debugging.md。
常见问题(Troubleshooting)
Android 示例或功能测试构建失败
报错java.lang.NullPointerException: Cannot invoke String.length()
如果系统安装了多个 JDK,构建 Android 示例或功能测试时可能遇到如下错误(该错误来自 Android 构建目标,例如src/mono/msbuild/android/build/AndroidBuild.targets):
`src/mono/msbuild/android/build/AndroidBuild.targets(237,5): error MSB4018: java.lang.NullPointerException: Cannot invoke String.length() because <parameter1> is null解决办法:
- 移除旧的 JDK 版本;
- 安装 OpenJDK 23;
- 确保 OpenJDK 23 的可执行文件已加入 PATH。在 Unix 系统上可通过以下方式验证:
$> java -version openjdk version "23.0.1" 2024-10-15 OpenJDK Runtime Environment Homebrew (build 23.0.1) OpenJDK 64-Bit Server VM Homebrew (build 23.0.1, mixed mode, sharing)
说明:文档要求统一使用 OpenJDK 23(WSL/Ubuntu 场景下 OpenJDK 21 亦可满足构建),其根本原因是 Android 构建链会解析 JDK 路径与版本信息,多版本 JDK 并存时容易导致
String.length()空引用之类的解析失败。配置过程中注意把 JDK 版本纳入和ANDROID_SDK_ROOT、ANDROID_NDK_ROOT同等重要的环境变量管理范畴。
【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址: https://gitcode.com/GitHub_Trending/runtime6/runtime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考