接續前一篇用 .NET Native AOT 編譯程式庫給 Python 呼叫的實驗。

下一步我打算搬到 Linux 執行,過程有些小波折,編譯原生二進位檔案有優點,但領教過比較複雜繁瑣的編譯程序,倒也襯托出 .NET Runtime 的好處。

參考官方文件 Native AOT deployment,先簡單整理重點。

  1. .NET 8 對 Native AOT 的支援比較完整,反正 Native AOT 不涉及目標主機安裝的 .NET Runtime 版本,建議用 .NET 8。
  2. 在 .csproj 加入 <PublishAot>true</PublishAot>dotnet publish 將改編譯成 Native AOT,並會啟動編輯及編譯階段動態程式碼使用分析 (Dynamic Code-Usage Analysis)。
  3. 原生二進位檔對平台版本的依賴很深,如果你用 Ubuntu 20.04 編譯的 Native AOT 檔案,只能在 Ubuntu 20.04 以後的作業系統執行,無法在 Ubuntu 18.04 用。
  4. .csproj 加入 <IsAotCompatible>true</IsAotCompatible> 可標示程式庫相容 Native AOT (等同啟用以下設定:IsTrimmable、EnableTrimAnalyzer、EnableSingleFileAnalyzer、EnableAotAnalyzer)
  5. Native AOT 編譯後會產生偵錯檔 .dbg(Linux)/.pdb(Windows)/.dSYM(macOS) 可協助 Crash Dump 偵錯,在非 Windows 平台,設定 <StripSymbols>false</StripSymbols> 可將其併入原生二進位檔。
  6. .NET Native AOT 支援以下平台
  7. 作業系統必須安裝 C++ 編譯工具才能編譯 Native AOT,Winows 要安裝 VS2022 Desktop Development with C++,Ubuntu 要 sudo apt-get install clang zlib1g-dev、macOS 要安裝 Command Line Tools for XCode。參考

要編譯 Linux 用的 Native AOT 原生程式庫需要用 Linux 平台上編譯(編譯平台與目標平台需相同),嘗試在 Windows 平台執行 dotnet publish -r linux-x64 會得到 error : Cross-OS native compilation is not supported.

我是將專案原始檔複製到 Debian,一開始忘了裝安裝 gcc 或 clang,dotnet publish /p:NativeLib=Shared --use-current-runtime 會發生 collect2 : error : ld returned 1 exit status 錯誤 參考),安裝 clang、zlib1g-dev 後成功編譯出 .so 檔:

在 Linux 平台跑 test.py,有三處要修改:1) Windows 載入 .dll,Linux 要載入 .so 2) .NET 端用 Marshal.StringToHGlobalAnsi(result) 傳回字串,在 Windows 是 BIG5 編碼,在 Linux 則是 UTF-8 3) Python 呼叫 .NET Marshal.FreeHGlobal() 釋放 Unmanaged 記憶體配置的做法在 Linux 會出錯,出現 munmap_chunk(): invalid pointer in linux (這部分超出我的知識範圍,期待具相關經驗的前輩指點解惑)

以上就是本次的 Native AOT 登陸 Linux 經驗分享。
(串接 Managed 及 Unmanaged 世界這塊水頗深,我目前還在新手村打史萊姆... )

Tips of how to publish Native AOT library on Linux.


Comments

Be the first to post a comment

Post a comment