.По умолчанию программа на C# компилируется в код на промежуточном языке MSIL. Для запуска подобной программы необходимо, чтобы на компьютере был установлен фреймворк .NET. Однако .NET SDK также позволяет компилировать проект на C# в нативное приложение, которое не использует JIT-компиляцию и может запускаться на компьютере без установленного .NET. Данная модель называется Native AOT и доступна, начиная с .NET 7 (для консольных проектов). Поддержка для ASP.NET Core и для MacOS добавлена в .NET 8.0.
Для использования Native AOT предварительно требуется установить некоторый дополнительный интрументарий. На Windows через установщик Visual Studio необходимо установить нагрузку Desktop development with C++ (Разработка классических приложений на C++).
На Ububtu надо установить пакеты clang и zlib1g-dev
sudo apt-get install clang zlib1g-devНа MacOS надо установить Command Line Tools for XCode.
Чтобы указать, что проект будет использовать модель публикации Native AOT, в файле проекта в элемент PropertyGroup необходимо добавить элемент <PublishAot>true</PublishAot>:
<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>
Для компиляции с помощью .NET CLI применяется следующая команда:
dotnet publish -r <RID>В частности, некоторые распространенные идентификаторы:
Для Windows:
win-x64
win-x86
win-arm64
Для Linux:
linux-x64
linux-arm64
Для MacOS:
osx-x64
osx-arm64
Полный список идентификаторов можно посмотреть на странице https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json
Например, для компиляции приложения для 64-битной Windows применяется команда:
dotnet publish -r win-x64 -c ReleaseА для компиляции для 64-битной Linux на архитектуре ARM (AArch64) используется команда
dotnet publish -r linux-arm64 -c ReleaseК примеру, возьмем простейший проект консольного приложения. Сначала в файл проекта csproj добавим параметр
<PublishAot>true</PublishAot>Перейдем в консоли к папке проекта. Допустим, нам надо скомпилировать приложение для 64-разрядной Windows. Для этого выполним команду:
dotnet publish -r win-x64 -c ReleaseВ результате получим примерно следующий вывод консоли:
C:\Users\eugen\source\repos\csharp\Native\HelloApp>dotnet publish -r win-x64 -c Release
MSBuild version 17.6.0-preview-23174-01+e7de13307 for .NET
Determining projects to restore...
Restored C:\Users\eugen\source\repos\csharp\Native\HelloApp\HelloApp\HelloApp.csproj (in 265 ms).
C:\Program Files\dotnet\sdk\8.0.100-preview.3.23178.7\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInf
erence.targets(287,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-
policy [C:\Users\eugen\source\repos\csharp\Native\HelloApp\HelloApp\HelloApp.csproj]
HelloApp -> C:\Users\eugen\source\repos\csharp\Native\HelloApp\HelloApp\bin\Release\net8.0\win-x64\HelloApp.dll
Generating native code
HelloApp -> C:\Users\eugen\source\repos\csharp\Native\HelloApp\HelloApp\bin\Release\net8.0\win-x64\publish\
C:\Users\eugen\source\repos\csharp\Native\HelloApp>
После этого в проекте в папке bin\Release\netX.X\win-x64\publish\ можно найти скомпилированное приложение.
В итоге скомпилированный файл exe можно запускать на 64-разрядных Windows даже там, где не установлен .NET.
Один из главных минусов компиляции в нативное приложение - это его размер, например, как видно на скриншоте при компиляции с .NET 8.0 Preview простое консольное приложение, которое выводит на консоль строку, занимает 1793 Кб. Но стоит отметить, что по сравнению с .NET 7.0 в .NET 8.0 размер нативного приложения значительно уменьшен, и команда разработчиков .NET продолжает работать над этим, поэтому в будущем размер приложения может ужаться значительно. Кроме того, можно применять различные оптимизации. Самая простейшая - использовать инвариантный режим для параметров глобализации, для чего надо добавить в файл проекта настройку
<InvariantGlobalization>true</InvariantGlobalization>Так, только эта настройка позволила в моем случае уменьшить размер приложения с 1793 КБ до 1567 КБ
В дополнение к большему размеру стоит отметить и некоторые другие недостатки подобной модели публикации. Прежде всего не для всех типов проектов, библиотек и сред данная модель может быть доступна. Так, поддержка консольных приложений добавлена с самого начала - в .NET 7.0. А вот для ASP.NET Core эта модель доступна только начиная с .NET 8.0. Кроме того, поддержка MacOS также добавлена только в .NET 8.0 (для Windows и Linux поддержка имеет уже в .NET 7)
Также для таких нативных приложений недоступна динамическая загрузка библиотек (например, с помощью метода Assembly.LoadFile).