本文適用於: ✔️.NET SDK 10 及更新版本
針對特定平台和架構打包 .NET 工具,這樣你就能分發原生、快速和修剪過的應用程式。 此功能使得更容易分發優化的應用程式給命令列工具,例如 MCP 伺服器或其他平台專用工具。
概觀
從 .NET SDK 10 開始,你可以建立針對特定作業系統環境(以執行時識別碼(RID)表示)的 .NET 工具。 這些工具可以包括:
- RID 專用:針對特定作業系統與架構編譯。
- 自成一體:包含 .NET 執行環境,且不需要另外安裝 .NET。
- 原生AOT:使用預先編譯以加快啟動速度並減少記憶體使用量。
使用者安裝時不會感覺到差異。 .NET CLI 會自動選擇並安裝最適合他們平台的套件。
選擇使用RID專屬包裝
要建立專門針對 RID 的工具,請用以下 MSBuild 屬性之一來設定你的專案:
RuntimeIdentifiers 屬性
請使用 RuntimeIdentifiers 來指定工具所支援的平台:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<PackAsTool>true</PackAsTool>
<ToolCommandName>mytool</ToolCommandName>
<RuntimeIdentifiers>win-x64;linux-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
</Project>
ToolPackageRuntimeIdentifiers 屬性
或者,使用 ToolPackageRuntimeIdentifiers 進行工具特定的 RID 配置:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<PackAsTool>true</PackAsTool>
<PublishAot>true</PublishAot>
<ToolCommandName>mytool</ToolCommandName>
<ToolPackageRuntimeIdentifiers>win-x64;linux-x64;osx-arm64</ToolPackageRuntimeIdentifiers>
</PropertyGroup>
</Project>
使用分號分隔的 RID 值清單。 有關執行時識別碼的清單,請參見 RID 目錄。
何時使用 RuntimeIdentifiers vs ToolPackageRuntimeIdentifiers
這兩者RuntimeIdentifiers和ToolPackageRuntimeIdentifiers 都將工具適配於特定的 RID 包裝,但它們的用途略有不同:
RuntimeIdentifiers 的使用時機:
- 你希望專案能建立 並發佈專門針對 RID 的應用程式 (而不只是當作工具)。
- 你主要目標是 CoreCLR (非 AOT),或者你想要標準的 SDK 行為,即一個
dotnet pack套件能產生多個專門的 RID 套件。 - 你可以將
PublishAot針對部分 RID 進行條件化,但你仍希望每個 RID 在RuntimeIdentifiers都有基於 CoreCLR 的套件。
ToolPackageRuntimeIdentifiers 的使用時機:
- 你只想為 工具封裝定義 RID 專屬行為,而不改變專案在其他部署情境下的建置方式。
- 你正在使用 Native AOT,並計劃依據每個 RID 手動建立
dotnet pack -r <RID>AOT 二進位檔。 - 你需要一個 混合模式 ,有些 RID 會使用 Native AOT,有些則回退到可攜式的 CoreCLR 實作。
Notes:
- 頂層指標套件指定可用的 RID 專用套件。 若指定
ToolPackageRuntimeIdentifiers,則決定工具的 RIDs;否則使用RuntimeIdentifiers。 -
ToolPackageRuntimeIdentifiers應等於RuntimeIdentifiers中的 RID 或是其子集 - 當
PublishAot=true時,僅在你為特定 RID 打包時才會產生專屬 RID 套件(例如dotnet pack -r linux-x64)。 - 原生 AOT 建置
PublishAot=true()僅在建置作業系統與目標作業系統相符時才被支援。
打包你的工具
打包流程會因你是否使用 AOT 編譯而有所不同。 要建立 NuGet 套件,或從專案中建立 .nupkg 檔案,請執行 dotnet pack 指令。
RID 專屬且獨立運作的工具
執行 dotnet pack 一次:
dotnet pack
此指令會建立多個 NuGet 套件:
- 每個RID一個包:
<packageName>.<RID>.<packageVersion>.nupkg- 範例:
mytool.win-x64.1.0.0.nupkg - 範例:
mytool.linux-x64.1.0.0.nupkg - 範例:
mytool.osx-arm64.1.0.0.nupkg
- 範例:
- 一個與 RID 無關的指標套件:
<packageName>.<packageVersion>.nupkg- 範例:
mytool.1.0.0.nupkg
- 範例:
AOT 工具
對於具有AOT編譯的工具(<PublishAot>true</PublishAot>),您必須為每個平台分別進行打包。
原生 AOT 的平台需求
原生 AOT 編譯要求 SDK RID 中的作業系統部分與目標 RID 的作業系統相符。 SDK 可跨架構(例如 x64 轉為 ARM64),但無法跨作業系統(例如 Windows 轉 Linux)。
這表示你有多種方式來建立原生 AOT 套件:
- 只為你的開發機器編譯:只支援你正在開發的作業系統上的原生 AOT。
-
Linux 建置時使用容器:如果你用的是 macOS 或 Windows,可以用容器來交叉編譯 Linux。 例如,使用
mcr.microsoft.com/dotnet/sdk:10.0-noble-aot容器圖片。 - 跨機器聯盟建置:使用 CI/CD 系統如 GitHub Actions 或 Azure DevOps Pipelines,在不同作業系統上建置。
你不需要在同一台機器或同時建立所有 RID 專屬套件。 你只需要先建置並發佈它們,再發佈頂層套件。
打包原生AOT工具
打包一次頂層套件(在任何平台):
dotnet pack
針對對應平台上的每個特定RID進行包裝,例如:
dotnet pack -r linux-x64
你必須在作業系統與目標 RID 作業系統相符的平台上執行每個 RID 專屬的 pack 指令。 欲了解更多關於 Native AOT 編譯的前置條件,請參見 Native AOT 部署。
當你設定 PublishAot 為 true時,打包行為會改變:
-
dotnet pack產生頂層指標封裝(封裝類型DotnetTool)。 - RID 專用的 AOT 套件僅在你明確傳遞
-r <RID>,例如 ,dotnet pack -r linux-x64或dotnet pack -r osx-arm64時才會產生。
混合 AOT + CoreCLR 封裝模式(範例)
有些工具想要兩者兼得:
- 原生AOT 用於部分高優先度平台(視工具而定)。
- 一個 可攜式的 CoreCLR 替代方案 ,適用於原生 AOT 構建不支援的平台。
你可以透過以下模式達成這種「混合」模式:
設定工具以支援Native AOT和特定工具RID。
在你的專案檔案中,使用
ToolPackageRuntimeIdentifiers並啟用PublishAot。例如:
<ToolPackageRuntimeIdentifiers>osx-arm64;linux-arm64;linux-x64;any</ToolPackageRuntimeIdentifiers> <PublishAot>true</PublishAot>建立指標套件。
執行
dotnet pack一次(在任何平台)即可建立指向 RID 專屬套件的頂層套件:dotnet pack為特定 RID 建置原生 AOT 套件。
原生的《進擊的巨人》編譯需要在目標平台上建構。 請在匹配的平台上使用
dotnet pack -r <RID>建立每個啟用 AOT 的 RID 套件。
例如:
dotnet pack -r linux-x64
建立一個 CoreCLR 備用套件。
為了提供通用後備方案,請在沒有提前編譯的情況下打包
anyRID:dotnet pack -r any -p:PublishAot=false這會產生一個可攜式的 CoreCLR 套件(例如
yourtool.any.<version>.nupkg),可以在沒有專用 AOT 建置的平台上執行。
備註
你也可以利用 .NET SDK 10.0-noble-aot 容器映像檔,從任何支援 Linux 容器的主機上建置並打包 Linux 原生 AOT 工具。 例如:
mcr.microsoft.com/dotnet/sdk:10.0-noble-aot
當你的開發機器不是原生運行 Linux 時,這很有用。
在這個混合配置中:
- 指標封包(
yourtool.<version>.nupkg)同時引用:- RID 專用的 Native AOT 套件(例如,
yourtool.osx-arm64,yourtool.linux-x64)。 - CoreCLR
any套件作為備用方案。
- RID 專用的 Native AOT 套件(例如,
- .NET CLI 會在使用者執行
dotnet tool install或dnx時,根據使用者的平台自動選擇最合適的套件。
範例:dotnet10-hybrid-tool
該 dotnet10-hybrid-tool 倉庫 展示了這種混合封裝模式,包含針對 osx-arm64、linux-arm64 和 linux-x64 的原生 AOT 套件,以及針對 any RID 的 CoreCLR 備援套件(例如在 Windows 上,當沒有 AOT 建置可用時使用)。
你可以安裝並自行試用這個工具:
dotnet tool install -g dotnet10-hybrid-tool
dotnet10-hybrid-tool
該工具會回報其執行時框架描述、執行時識別碼(RID)及編譯模式(Native AOT 或 CoreCLR)。
在原生 AOT 平台上的範例輸出:
Hi, I'm a 'DotNetCliTool v2' tool!
Yes, I'm quite fancy.
Version: .NET 10.0.2
RID: osx-arm64
Mode: Native AOT
使用 CoreCLR 備援的平台上的範例輸出:
Hi, I'm a 'DotNetCliTool v2' tool!
Yes, I'm quite fancy.
Version: .NET 10.0.2
RID: win-x64
Mode: CoreCLR
這使得它成為實驗 RID 專屬、AOT 編譯工具及 CoreCLR 備援行為的有用方式。
發佈你的工具
在發佈 RID 專屬工具套件時,.NET CLI 會使用頂層套件的版本號來選擇符合 RID 專屬的套件。 也就是說:
- 所有 RID 專用套件必須與頂層套件版本完全相同。
- 所有套件必須先發佈到你的動態消息,頂層套件才會開放。
為確保出版流程順利:
先發布所有 RID 專屬套件:
dotnet nuget push yourtool.win-x64.1.0.0.nupkg dotnet nuget push yourtool.linux-x64.1.0.0.nupkg dotnet nuget push yourtool.osx-arm64.1.0.0.nupkg dotnet nuget push yourtool.any.1.0.0.nupkg最後發佈頂層套件:
dotnet nuget push yourtool.1.0.0.nupkg
最後發布頂層套件,確保使用者安裝工具時,所有參考的 RID 專用套件皆可用。 如果使用者在所有 RID 套件發布前安裝了你的工具,安裝將會失敗。
安裝與執行工具
工具是否使用RID專屬封裝,是對使用者透明的實作細節。 安裝和執行工具的方式相同,不論工具開發者是否選擇採用 RID 專屬的包裝。
若要全域安裝工具,請依照下列步驟進行:
dotnet tool install -g mytool
安裝完成後,您可以直接呼叫:
mytool
你也可以使用 dnx 輔助工具,其運作方式類似 npx 於 Node.js 生態系:如果工具尚未存在,它會以單一手勢下載並啟動:
dnx mytool
當工具使用 RID 專屬封裝時,.NET CLI 會自動選擇適合你平台的封裝。 你不需要指定 RID——CLI 會從你的系統推斷出它,並下載相應的 RID 專屬套件。