本文仍處於修訂中
寫在開始前
我們的主要業務基於 dotnet core 2.x 與 3.1 完成,目前 dotnet core 3.1 支援的 CPU 架構列表中還不包含龍芯,且在 gitlab issue 中表示官方當前沒有對 MIPS 的支援計劃。
更具體作業系統與 CPU 架構列表見 [Download .NET Core 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1
6月下旬,龍芯團隊宣佈在 dotnet/coreclr 基礎上完成了MIPS64 的移植工作 Open-sourcing CoreCLR MIPS64 Port #38069,計劃實現 3.x 版本並貢獻到上游 dotnet/runtime。
按照相關 issue 裡的指引,這裡對編譯了移值工作,進行了一些測試。
具體的進度
作為下游開發者,想知道距離生產環境使用還有多遠,必須先提及 dotnet core 應用程式的釋出/部署方式
1. dotnet core 支援兩種方式的釋出/部署
- 獨立應用(self-contained)
- 依賴於執行時(runtime-dependent)
前者包含可執行檔案(exe),無法跨平臺;後者生成了跨平臺的二進位制檔案(dll),需要執行環境預先安裝好執行時。關於部署策略的詳細資訊,可以參考.NET Core application publishing overview。
釋出獨立應用需要針對特定作業系統及 CPU 架構編譯幷包含相應執行時,實際開發中我們以依賴於執行時的方式交付,配合預先準備的包含執行時(runtime)的 docker 映象完成部署。
微軟官方 aspnet core 示例中的 Dockerfile
# ...
FROM mcr.microsoft.com/dotnet/core/runtime:3.1
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet","dotnetapp.dll"]
2. dotnet core 的組成部分
作為編譯型語言,和 Java 原始碼被 javac 編譯為位元組碼再交由 JVM 執行一樣,csharp/vb.net 等原始碼被編譯為內容主要是 IL(中間語言,平臺無關)的 Windows PE 檔案(可用於所有作業系統),然後交由 CLR 執行。
dotnet core 由以下若干部分組成:
- 執行時與框架庫,包含 .NET Core Runtime 與 ASP.NET Core Runtime,平臺特定
- SDK 和編譯器:開發相關
- dotnet 命令:啟動 dotnet 應用及作為互動式工具鏈
mono,unity3d 都是執行時實現,在此略提及
由前文的 Dockerfile 可以看到,依賴於執行時的 dotnet core 應用通過 dotnet xxxx.dll
執行,這裡有若干層意義:
- dotnet 提供了 Host(宿主/主機)能力,因為依賴於執行時(runtime-dependent)的 dotnet core 應用並不是可執行檔案,需要類似 JVM 的機制執行起來
- dotnet 以互動式命令將 runtime 與 sdk 集合在一起,成為完整的工具鏈
而 dotnet/coreclr 編譯結果並不包含可執行的 dotnet 命令,執行/測試已釋出的 dotnet core 應用有以下選擇
- 編寫本機/原生程式碼,參考 Write a custom .NET Core host to control the .NET runtime from your native code。
- 使用編譯得到的 corerun,參考 Using CoreRun To Run .NET Core Application。
當前的交付/部署體驗都是通過 dotnet 命令進行的,獲取該命令需要更多的工作,接下來是龍芯團隊的移值工作的說明。
龍芯團隊的工作
龍芯團隊的工作在 19 年 7 月份開始,當時的 dotnet core原始碼結構、功能與現在的變更如下表。
原倉庫 | 移值倉庫 | 功能 | 釋出 | 變更 |
---|---|---|---|---|
dotnet/coreclr | gsvm/coreclr | 執行時原始碼 | 合併入 dotnet/runtime | |
dotnet/corefx | gsvm/corefx | 標準庫原始碼 | 2020/7/7 | 合併入 dotnet/runtime |
dotnet/core-setup | gsvm/core-setup | 編譯倉庫 | 2020/7/7 | 合併入 dotnet/runtime |
dotnet/cli | 命令列工具鏈原始碼 | 合併入 dotnet/sdk |
dotnet/core-setup 比較特殊,它是用來用來編譯 runtime,類庫和宿主程式的倉庫,注意直到這一步 dotnet 命令才終於可用。
本地編譯 gsvm/coreclr
龍芯團隊首份釋出的原始碼是 dotnet/coreclr。按照社群的溝通記錄,由於依賴複雜,建議基於 docker 進行編譯
git clone https://github.com/gsvm/coreclr.git
cd coreclr
docker run --rm -v $(pwd):/coreclr -w /coreclr aoqi/dotnet-buildtools:loongson3a-loongnix-1.0-llvm8ld ./build.sh -skiptests -ignorewarnings release
注意使用docker manifest inspect
可知,映象 aoqi/dotnet-buildtools:loongson3a-loongnix-1.0-llvm8ld
僅適用於龍芯作業系統,更多內容請參考 龍芯3A4000 開發機編譯CoreCLR 環境 #6
作者使用的伺服器使用 uname -p
輸出的是 mips64 而不是 mips,前者會導致 gsvm/coreclr 中相關指令碼對 CPU 架構的斷言失敗,被相關人士認為違反了分發版本的命名規則,所以後續使用了交叉編譯。
交叉編譯 gsvm/coreclr
如果手邊已經有 x64 伺服器,基於 docker 進行交叉編譯也是不錯的選擇,我們可以將編譯結果 scp/rsync 到龍芯伺服器。
docker run --rm -v $(pwd):/coreclr -w /coreclr -e ROOTFS_DIR=/crossrootfs/mips64el aoqi/dotnet-buildtools:x86_64-ubuntu-16.04-c103199-20180628134544-upstream-cross-mips64el ./build.sh release ignorewarnings mips64 cross skipcrossgen
編譯耗時不多,但連結步驟需要使用大量的記憶體,作者最初使用了一臺騰迅雲低配主機都在進度 87% 時失敗,更換使用一臺更高配置伺服器後編譯成功,相關討論可見於 cross compile failed ...
交叉編譯 gsvm/corefx
7月7日龍芯團隊釋出了 dotnet/corefx 和 dotnet/core-setup 倉庫,編譯方法如下,參考 cross-building.md。
git clone https://github.com/gsvm/corefx.git
cd corefx
docker run --rm -v $(pwd):/corefx -w /corefx -e ROOTFS_DIR=/crossrootfs/mips64el aoqi/dotnet-buildtools:x86_64-ubuntu-16.04-c103199-20180628134544-upstream-cross-mips64el-corefx ./src/Native/build-native.sh mips64 debug cross ignorewarnings cmakeargs -DOBJCOPY=/usr/lib/llvm-6.0/bin/llvm-objcopy
本地編譯
docker run --rm -v $(pwd):/corefx -w /corefx -e ROOTFS_DIR=/crossrootfs/mips64el_loongnix aoqi/dotnet-buildtools:x86_64-ubuntu-16.04-c103199-20180628134544-upstream-cross-mips64el-corefx ./src/Native/build-native.sh mips64 debug cross ignorewarnings cmakeargs -DOBJCOPY=/usr/lib/llvm-6.0/bin/llvm-objcopy
leoninew 原創,轉載請註明來自部落格園