.NET适配HarmonyOS进展

1. 前言

目前国产化系统浪潮下,适配鸿蒙是中国软件大势所趋,.NET作为最适合开发客户端语言之一,适配鸿蒙系统(HarmonyOS Next)是目前.NET开发者最关心的事情。我目前业余时间正在移植Avalonia到HarmonyOS,去年在.NET Config CN上分享过,目前又取得一点进展,所以本文把所有问题进行整合与大家进行分享。

2. 项目状态

目前**.NET可以成功在HarmonyOS Next上运行**。

Avalonia移植项目在部分大内存真机上初步可以运行,本文主要探讨.NET适配相关工作。

3. 运行时

自HarmonyOS 5.0.0(12)起,禁止匿名内存申请可执行权限,除系统内置的JavaScript引擎外,其他虚拟机不能使用Jit功能 ,所以无法将CoreCLR接入到鸿蒙系统中 ,而最新版的Mono虽然支持解释执行,但是由于性能问题也不会接入Mono到鸿蒙系统 ,最终只能选择接入NativeAOT运行时。

4. NativeAOT

支撑鸿蒙可以接入NativeAOT的原理是鸿蒙系统兼容libc是musl的Linux系统的动态库(.so)。而.NET的RID支持linux-musl-arm64/linux-musl-x64,所以理论上可以将.NET程序编译为原生的Linux动态库(.so),然后在鸿蒙的原生项目中,通过dlopen以及dlsym等函数调用C#中的入口函数。

而C#调用鸿蒙api则通过P/Invoke调用鸿蒙的NDK,而ArkUI的TypeScript api则通过NDK中的napi调用。

具体做法可以参考我正在做的Avalonia移植项目: https://github.com/CeSun/OpenHarmony.Avalonia

5. 已知问题

5.1 syscall限制 (已解决)

鸿蒙系统使用了seccomp限制危险的syscall调用。标准posix下,如果系统不支持某个syscall则返回错误码,而seccomp非常激进,如果调用了非法的sycall则直接杀掉进程。.NET的运行时初始化时,会调用__NR_get_mempolicy系统调用对numa支持进行检查,而这个系统调用不在鸿蒙的seccomp白名单中,所以导致直接宕机。

鸿蒙系统中seccomp的系统调用白名单如下:https://gitee.com/openharmony/startup_init/blob/master/services/modules/seccomp/seccomp_policy/app.seccomp.policy

其实安卓中也有类似的限制,.NET的NativeAOT之所以能在安卓平台下运行是因为.NET中对安卓进行了特殊处理,而在鸿蒙平台我们使用的是Linux平台的代码,所以没有对这些系统调用进行处理。

解决办法则是自行修改代码,将numa的函数全部修改为空函数

5.2 mmap申请虚拟内存过大(已解决)

解决上个问题后,.NET运行时初始化依然不能成功,导致程序崩溃,经过排查发现是GC初始化时会申请256G左右的虚拟内存,导致mmap返回Out Of Memory错误。

解决办法1:设置环境变量"DOTNET_GCHeapHardLimit",将虚拟内存申请控制在约180G以下即可。

解决办法2:修改源代码,将USE_REGIONS宏关掉。

5.3 ICU,OpenSSL等第三方库缺失(已解决)

解决方案1:从Alpine上偷包 ,因为Alpine的libc是musl,所以理论上Alpine的库在鸿蒙上大部分都能使用。

阿里云Alpine软件包镜像地址:

arm64架构:https://mirrors.aliyun.com/alpine/edge/main/aarch64/

amd64架构:https://mirrors.aliyun.com/alpine/edge/main/x86_64/

解决方案2 :如果该库有cmake项目,则可以通过鸿蒙的CMake工具链编译。

5.4 ICU初始化失败(已解决)

鸿蒙的ICU配置文件路径与默认路径不同,需要调用修改环境变量API,将ICU_DATA修改为/system/usr/ohos_icu

且鸿蒙平台上libICU的大版本是72,要使用这个版本的库。

5.5 NativeAOT如何跨平台编译 (Windows平台已解决)

NativeAOT众所周知不支持跨平台编译,而我的方案需要发布到linux-musl平台,所以无法在Windows上发布,影响开发效率。

解决方案 :在项目中引入项目https://github.com/CeSun/PublishAotCross

6. 如何修改NativeAOT代码

前文中提到部分问题的解决方案是修改源码,具体操作步骤如下:

修改完代码,执行以下命令进行编译(linux平台下,需要有编译环境):

shell 复制代码
./build.sh --subset mono+libs --configuration Release -arch arm64 --cross

编译成功后,打开目录 运行时/artifacts/bin/coreclr/linux.arm64.Release/aotsdk,将这里所有的替换到自己电脑nuget的缓存目录, 例如C:\Users\用户名\.nuget\packages\runtime.linux-musl-arm64.microsoft.dotnet.ilcompiler\dotnet版本\sdk

7.相关链接

https://github.com/dotnet/runtime/issues/110074
https://github.com/dotnet/runtime/issues/111649

相关推荐
宝桥南山12 小时前
.NET 11 - 尝试一下Minimal API中的异步验证新特性
microsoft·微软·c#·asp.net·.net·.netcore
无风听海13 小时前
深入理解.NET中的 Lazy<T>
服务器·php·.net
海盗123413 小时前
微软技术日报 2026-10-14:十月补丁 1411 个漏洞,.NET 11 交出 RC2
人工智能·microsoft·机器人·aigc·.net
学以智用14 小时前
.NET WinForms / WPF / Blazor 模板详解
.net
黄一一91124314 小时前
吾爱大佬开发,离线可用!PDF文件处理工具,本地网页版文件-浏览器里就能搞定,所有操作系统可用
windows·安全·阿里云·pdf·.net·开源软件
天府云创1 天前
Agentic开发时代到来——鸿蒙PC三大原生开发工具公测
华为·操作系统·harmonyos·鸿蒙系统·cli·deveco·agentic
慧都小妮子1 天前
MSG 附件太占内存?Aspose.Email for .NET 26.9 延迟加载
c#·.net·aspose·内存优化·延迟加载·aspose.email·附件内存
学以智用2 天前
ASP.NET Core 项目模板详解:Web应用 / Web API / MVC / Razor Pages
.net
IT规划师2 天前
MQTT实战 - 用了8年MQTT,我为什么还要重新系统啃一遍(一)
物联网·.net
邹肖桥2 天前
使用S7.net动态库对西门子Plc S7-1200进行通讯操作
.net