Поделиться через


Создание RID-специфических, автономных средств и средств AOT .NET

Эта статья применяется к: ✔️ SDK для .NET 10 и более поздним версиям

Упаковывайте средства .NET для конкретных платформ и архитектур, чтобы распространять нативные, быстрые и оптимизированные приложения. Эта возможность упрощает распространение оптимизированных приложений для инструментов командной строки, таких как серверы MCP или другие служебные программы для конкретной платформы.

Обзор

Начиная с пакета SDK для .NET 10, можно создать средства .NET, предназначенные для определенных сред операционной системы (представленных идентификаторами среды выполнения (RID)). Эти средства могут быть следующими:

  • Специфичный параметр RID: скомпилирован для определенных операционных систем и архитектур.
  • Автономно: Включает среду выполнения .NET и не требует отдельной установки .NET.
  • Собственный AOT: используйте компиляцию авансом для ускорения запуска и уменьшения использования памяти.

Пользователи не замечают разницу при установке средства. Интерфейс командной строки .NET автоматически выбирает и устанавливает лучший пакет для своей платформы.

Переход на специфическую для 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, SDK для .NET создает самодостаточные пакеты для каждого указанного RID. Однако вы теряете упаковку, зависящую от платформы по умолчанию, которая работает на любой платформе с установленной средой выполнения .NET.

Чтобы предоставить версии, зависящие от фреймворка, вместе с пакетами, зависящими от RID, добавьте any в список ToolPackageRuntimeIdentifiers.

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <ToolPackageRuntimeIdentifiers>win-x64;osx-arm64;linux-x64;any</ToolPackageRuntimeIdentifiers>
</PropertyGroup>

Эта конфигурация создает пять пакетов:

  • Один пакет указателя верхнего уровня, который перечисляет все доступные вложенные пакеты.
  • Три пакета, специфичные для RID (win-x64, osx-arm64, linux-x64), которые являются автономными и оптимизированными.
  • Один пакет, независимый от RID (any), который зависит от фреймворка и требует установки среды выполнения .NET.

Когда пользователи устанавливают средство:

  • В win-x64, osx-arm64или linux-x64 системах автономные, обрезанные пакеты загружаются и выполняются.
  • В любой другой операционной системе или архитектуре используется пакет, зависящий от any платформы.

Этот подход обеспечивает оптимизированные автономные двоичные файлы для общих платформ, при этом сохраняя совместимость с менее распространёнными платформами за счет платформенной зависимости.

Когда следует использовать RuntimeIdentifiers vs ToolPackageRuntimeIdentifiers

Как RuntimeIdentifiers, так и ToolPackageRuntimeIdentifiers подключают ваш инструмент к упаковке, зависящей от RID, но их цели немного различаются.

RuntimeIdentifiers следует использовать в следующих случаях:

  • Вы хотите, чтобы проект в общем создавал и публиковал приложения, относящиеся к RID, (а не как инструмент).
  • Вы в первую очередь ориентированы на CoreCLR (не AOT) или требуется стандартное поведение пакета SDK, в котором один dotnet pack создает несколько пакетов, относящихся к RID.
  • Вы можете условно задать PublishAot для подмножества RIDов, но вам все равно потребуется пакет на основе CoreCLR для каждого RID в RuntimeIdentifiers.

ToolPackageRuntimeIdentifiers следует использовать в следующих случаях:

  • Вы хотите определить поведение, зависяющее от RID, только для упаковки инструментов, не изменяя способ сборки проекта для других сценариев развертывания.
  • Вы используете Native AOT и планируете вручную создавать AOT бинарные файлы для каждого RID с dotnet pack -r <RID>.
  • Требуется гибридная модель, в которой некоторые RID получают родной AOT, а другие используют переносимую реализацию CoreCLR.

Notes:

  • Пакет указателя верхнего уровня указывает доступные пакеты, относящиеся к RID. Если задано ToolPackageRuntimeIdentifiers, оно определяет идентификаторы инструментов; иначе используется RuntimeIdentifiers.
  • ToolPackageRuntimeIdentifiers должно быть равно или являться подмножеством RIDs в RuntimeIdentifiers
  • Если PublishAot=trueпакеты, относящиеся к RID, создаются только при упаковке для конкретного RID (например, dotnet pack -r linux-x64).
  • Сборки Native 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. Пакет 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, на одном компьютере или одновременно. Перед публикацией пакета верхнего уровня необходимо просто создать и опубликовать их.

Упаковка средств Native AOT

Упакуйте пакет верхнего уровня один раз (на любой из платформ):

dotnet pack

Пакет для каждого конкретного RID на соответствующей платформе, например:

dotnet pack -r linux-x64

Необходимо выполнить каждую команду пакета, специфичную для RID, на платформе, где ОС соответствует ОС целевого RID. Дополнительные сведения о предварительных требованиях для компиляции Native AOT см. в разделе развертывание Native AOT.

Если задано значение PublishAottrue, поведение упаковки изменяется:

  • dotnet pack создает пакет указателя верхнего уровня (тип DotnetToolпакета).
  • Пакеты AOT, специфичные для RID, создаются только при явной передаче -r <RID>, например, dotnet pack -r linux-x64 или dotnet pack -r osx-arm64.

Гибридный шаблон упаковки AOT + CoreCLR (пример)

Некоторые инструменты хотят лучшего из обоих миров:

  • Собственный AOT для подмножества высокоприоритетных платформ (в зависимости от инструмента).
  • Переносимая резервная точка CoreCLR, которая работает на платформах, не предназначенных для сборок Native AOT.

Вы можете достичь этой гибридной модели с помощью следующего шаблона:

  1. Настройте средство для собственных идентификаторов AOT и определенных средств.

    В файле проекта используйте ToolPackageRuntimeIdentifiers и включите PublishAot.

    Рассмотрим пример.

    <ToolPackageRuntimeIdentifiers>osx-arm64;linux-arm64;linux-x64;any</ToolPackageRuntimeIdentifiers>
    <PublishAot>true</PublishAot>
    
  2. Создайте пакет указателя.

    Запустите dotnet pack один раз (на любой платформе), чтобы создать пакет верхнего уровня, указывающий на пакеты, зависящие от RID.

    dotnet pack
    
  3. Соберите нативные пакеты AOT для выбранных RID.

    Для выполнения собственного AOT-компилирования требуется сборка на целевой платформе. Создайте каждый пакет RID с поддержкой AOT на соответствующей платформе с помощью dotnet pack -r <RID>.

Рассмотрим пример.

dotnet pack -r linux-x64
  1. Создайте резервный пакет CoreCLR.

    Чтобы обеспечить универсальный резервный вариант, упаковайте any RID без AOT:

    dotnet pack -r any -p:PublishAot=false
    

    Это создает переносимый пакет CoreCLR (например, yourtool.any.<version>.nupkg), который может выполняться на платформах, которые не имеют выделенной сборки AOT.

Замечание

Вы также можете использовать .NET SDK 10.0-noble-aot образы контейнеров для сборки и упаковки нативных AOT инструментов для Linux на любом хосте, поддерживающем контейнеры Linux. Рассмотрим пример.

  • mcr.microsoft.com/dotnet/sdk:10.0-noble-aot

Это полезно, если ваша машина для разработки не работает под управлением Linux нативно.

В этой гибридной настройке:

  • Пакетyourtool.<version>.nupkg указателя () ссылается на оба:
    • Пакеты AOT, специфичные для конкретных RID (например, yourtool.osx-arm64, yourtool.linux-x64).
    • Пакет any CoreCLR в качестве резервного пакета.
  • Интерфейс командной строки .NET автоматически выбирает наиболее подходящий пакет для платформы пользователя при запуске dotnet tool install или dnx.

Пример: dotnet10-hybrid-tool

Репозиторийdotnet10-hybrid-tool демонстрирует этот шаблон гибридной упаковки с пакетами Native AOT для osx-arm64, linux-arm64 и linux-x64, а также резервным пакетом CoreCLR для any RID, который используется, например, в Windows, если сборка AOT недоступна.

Вы можете установить и попробовать средство самостоятельно:

dotnet tool install -g dotnet10-hybrid-tool
dotnet10-hybrid-tool

Средство сообщает о своей платформе выполнения, идентификаторе среды выполнения (RID) и режиме компиляции (собственный AOT или CoreCLR).

Пример результатов на платформе с Native 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 использует номер версии пакета верхнего уровня, чтобы выбрать соответствующие пакеты, относящиеся к RID. Это означает:

  • Все пакеты, относящиеся к RID, должны иметь ту же версию, что и пакет верхнего уровня.
  • Все пакеты должны быть опубликованы в фид до того, как пакет верхнего уровня станет доступным.

Чтобы обеспечить гладкую публикацию, выполните следующее:

  1. Сначала опубликуйте все пакеты, относящиеся к 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
    
  2. Опубликуйте верхнеуровневый пакет последним.

    dotnet nuget push yourtool.1.0.0.nupkg
    

Публикация пакета самого верхнего уровня в последнюю очередь гарантирует, что все пакеты, специфичные для RID, доступны при установке средства пользователями. Если пользователь устанавливает средство до публикации всех пакетов RID, установка завершится ошибкой.

Установка и запуск средств

Упаковка с использованием RID является частью реализации, прозрачной для пользователей. Вы устанавливаете и запускаете инструменты так же, независимо от того, выбрал ли разработчик использование упаковки с учетом идентификатора среды выполнения (RID).

Чтобы установить средство глобально, выполните приведенные далее действия.

dotnet tool install -g mytool

После установки его можно вызвать напрямую:

mytool

Вы также можете использовать вспомогательный инструмент dnx, который в экосистеме Node.js ведет себя аналогично npx: он автоматически загружает и запускает ресурс, если он еще не установлен.

dnx mytool

Когда средство использует упаковку, специфичную для RID, .NET CLI автоматически выбирает правильный пакет для вашей платформы. Вам не нужно указывать RID, интерфейс командной строки определяет его на основании вашей системы и скачивает соответствующий RID-специфический пакет.

См. также