Якщо ви намагалися відправити програму .NET як окремі, природні виконувані файли, використовуючи Cival AOT, ви, ймовірно, спершу запустити обличчя у стіну SQLite. Ви налаштуєте все, завершення збирання успішно, а потім, moommaruntime аварійне аварійне завершення з таємничим механізмом DllNotFoundException помилки щодо e_sqlite3Дозвольте мені зберегти вам час розчарування, який я пройшов, і показати вам, як саме змусити SQLite працювати з корінним AOT через Windows, Linux (включаючи ARMS64 Raspberry Pi) і MacOS.
Давайте розпочнемо з абсолютної основи. Якщо ви коли- небудь створили програму.NET і бажаєте дізнатися, чому вам слід встановити ". NET Runtime " на серверах або чому ваша консольна програма потребує секунди, щоб запустити її під час першого запуску, AOT - це відповідь на ці проблеми.
Коли ви пишете код C# і будуєте вашу програму, компілятор не створює компіляторів, які ваш процесор може виконувати напряму. Замість цього, компілятор створює щось, що називається **Між once мова (IL)**І це як півшляху між кодом C # і інструкціями від машини.
Якщо ви запустите програму.NET, ось що станеться:
Це те саме, що мати перекладача, який читає ваш рецепт (IL) і словесно перекладає його на кухаря (CPU) в чергу під час приготування їжі.
Рідна AOT перевертає цю модель на голову. Замість перекладу вашого коду під час виконання, вона перекладає все під час збирання. Ви завершуєте з одним виконуваним файлом, який містить справжні коди машин, які можуть виконувати процесор безпосередньо, не чекаючи на запуск, ні перекладач, ні очікування.
Подумайте про це, як отримати професійно перекладені рецепти замість того, щоб брати живого перекладача. Робота виконується один раз, на передньому плані, і результат готовий до негайного використання.
Ось що тобі каже рідна АОТА:
1. Крихітні виконувані файли: 10- 30 Мб замість 150 Мб+
Ваш додаток і все, що йому потрібно, компілюються у один маленький бінарний файл. Не вистачає окремих файлів під час запуску.
2. Негайний запуск: 80% швидше починається холод
Мої тести: нормальний NET взяв на початок ~800мс, АOT взяв ~150 мс.
3. Нуль залежностей: Потрібний час запуску NET
Ви можете скопіювати ваш виконуваний файл на будь- який комп' ютер з відповідними операційними системами (Windows/Linux/Mac) і запустити програму. Без "встановлення. NET 9 Runtime " обов' язково.
4. Нижнє використання пам' яті: Близько 50% менше пам'яті
Немає компілятора JIT, що сидить у пам' яті. У моїй програмі для шлюзу . NET використовує 85MБ бездіяльності, AOT використовується 42MB.
5. Краще для обмеженого середовища: Працює, де JIT не може
У деяких середовищах (зі контейнерами Docker, iOS, вбудованими системами) не дозволяє створення коду під час виконання. OT працює всюди.
ААО - це не магія.
1. Без динамічного створення коду
Все, що генерує код під час виконання, не працюватиме:
System.Reflection.Emit (продуктивно розмножуються типи)Зазвичай код .NET в порядку, але деякі системи, які повністю залежать від відображення, потребують особливих налаштувань.
2. Специфічні для платформи збирання
Компіляція JIT створює IL, що працює на будь- якій платформі. AOT створює рідний код комп' ютера для одна конкретна платформа. Вам слід зібрати окремо для:
Ми помітимо автоматизацію з діями GitHub.
3. Час збирання довшого
Замість збирання до IL у секундах, AOT компілює весь шлях до комп' ютерного коду. Виділяє 2- 5 хвилин, замість 10 секунд. Це одноразова вартість для постійних вигод.
4. Деякі можливості потребують додаткового налаштування
JSON серіалізація, блокування сутностей, і все, що використовує важкі відбиття, може знадобитися для явного визначення типів компілятора, які слід зберегти. Ми покриємо це.
Рідна AOT ідеально підходить для:
Пропустити AOT для:
Для інструментів CLI, мікрослужби, контейнерів і пристроїв країв покращення - це зміна гри. Але коли ви додаєте бази даних, зокрема SQLite, є пастка.
Тепер, коли ви розумієте, що таке AOT, давайте поговоримо про один з найбільших болів: SQLite. Це стіна, на яку б'ють більшість людей, коли вони намагаються скористатися AOT за допомогою програм з резервною базою даних.
Ось типова подорож:
Microsoft.Data.Sqlite до вашого проектуPublishAot=true у вашій .csprojDllNotFoundException: Unable to load DLL 'e_sqlite3' or one of its dependencies
Ваш додаток аварійно завершує роботу перед тим, як зможе щось зробити.
Щоб зрозуміти проблему, треба знати про рідні бібліотеки.
SQLite не пишеться на C. Він скомпільований на специфічний для платформ рідний код:
e_sqlite3.dll на Windowslibe_sqlite3.so у Linuxlibe_sqlite3.dylib на macOSЯкщо ви використовуєте Microsoft.Data.Sqlite в нормі NET, це просто обгортка навколо цієї рідної бібліотеки SQLite. динамічне завантаження відповідний рідний файл для вашої платформи.
Це добре працює з нормальним. NET, тому що:
Рідна AOT має дві характеристики, які суперечать підходу SQLite:
1. Агресивне обрізання: AOT вилучає будь- який код, який, на його думку, ви не використовуєте. Якщо він не може статично довести, що вам щось потрібно, його буде вилучено. Динамічна бібліотека завантаження плутає символ cymer}it не може бачити з' єднання між вашим кодом і рідною SQLite DLLL.
2. Немає підтримки динамічного завантаження: AOT створює самовживаний виконуваний файл. Він очікує, що всі місцеві залежності буде явно пов' язано під час компіляції, а не динамічно завантажено під час виконання програми.
Результат: Microsoft.Data.Sqlite Очікується знайти рідну бібліотеку SQLite під час роботи під час роботи, але AOT або відрізав її, або не знає, як її скувати належним чином.
Ще гірше, якщо у вас є інші пакунки NuGet, які використовують SQLite (наприклад, деякі бібліотеки ORM або мій). mostlylucid.ephemeral.complete пакунок), який можна завершити за допомогою декілька несумісних постачальників SQLite у вашому дереві залежностей.
Кожен з постачальників послуг намагається працювати по- різному:
Компілятор AOT плутається з тим, який з них використовувати, і часто результат полягає в тому, що він не включає жодного з них, ще гірше, включає суперечні файли, які не можуть працювати разом.
Після кількох годин розстроєння, я знайшов розв'язання: SQLitePCLRaw.bundle_e_sqlite3Це особливий пакунок NOG, створений спеціально для роботи з AOT.
Додайте ці два пакунки до вашого проекту:
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
</ItemGroup>
The bundle_e_sqlite3 пакунок відрізняється від звичайних постачальників SQLite:
1. До неї включено попередньо зібрані рідні бібліотеки SQLite на кожній головній платформі:
2. Ці рідні бібліотеки упаковуються так, що компілятор AOT розуміє
Пучок явно позначає свої природні залежності, отже компілятор AOT знає, що має включити їх до кінцевого виконуваного файла. Без динамічного завантаження, без пошуку файлів під час виконання.
3. Він призначений для міжплатформних споруд.
Один пакунок працює на всі платформи, вам не потрібні специфічні для платформи пакунки або умовні посилання.
Пам'ятаєш дві проблеми, які ми визначили?
Проблема 1. Підстриження AOT вилучає бібліотеки, які не використовуються.
Проблема 2: AOT не підтримує динамічне завантаження
Результат: під час збирання Windows x64 вузол включає e_sqlite3.dll. Коли ви будуєте для Linux ARM64, він включає ARM64 libe_sqlite3.soВсе просто працює.
Ось частина, в якій 90% людей намагаються використовувати SQLite з АOT, включаючи мене при першій спробі.
З нормальним NET, вузол SQLite автоматично ініціює себе, коли ви вперше використовуєте SQLite. магія виникає за сценами, вам не потрібно нічого робити.
З корінним АОТом, автоматична ініціалізація не працює. Компілятор AOT не може бачити автоматичний код запуску (буде виглядати так, ніби невикористаний код і буде обрізано), отже, має бути ініціалізовано вручну вузол на самому початку вашої програми.
Ось вам чарівна лінія:
using SQLitePCL;
public class Program
{
public static void Main(string[] args)
{
// THIS IS CRITICAL: Initialize SQLite FIRST, before ANYTHING else
SQLitePCL.Batteries.Init();
// Now you can do normal application setup
var builder = WebApplication.CreateBuilder(args);
// This is now safe - SQLite is initialized
builder.Services.AddDbContext<MyDbContext>(options =>
options.UseSqlite("Data Source=app.db"));
var app = builder.Build();
app.Run();
}
}
Batteries.Init() Сделаешь?Цей метод повідомляє вузол SQLite:
Microsoft.Data.Sqlite і рідну бібліотекуЦе називається "Батестери," тому що це "проблеми, включені" тайфуни, які вам потрібні разом упаковки.
Вмістити Batteries.Init() асunit description in lists найперший рядок у вашій Main метод перед:
Думайте про це як під' єднання за допомогою пристрою перед тим, як його увімкнути. Якщо ви спробуєте скористатися SQLite перед викликом Init()♪ DllNotFoundException Незважаючи на те, що DL правильно вмонтований у вашу програму.
Якщо забудеш подзвонити Batteries.Init()Ваш додаток:
DllNotFoundException: Unable to load DLL 'e_sqlite3' or one of its dependencies
Це збиває з пантелику, тому що DLL є Я втратив дві години на цю помилку.
Тут повно грошей. .csproj налаштовано для багатоплатформової внутрішньої AOT у SQLite:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- Native AOT -->
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<InvariantGlobalization>true</InvariantGlobalization>
<!-- Single File -->
<PublishSingleFile>true</PublishSingleFile>
<StripSymbols>true</StripSymbols>
<!-- Optimization -->
<OptimizationPreference>Speed</OptimizationPreference>
<!-- Multi-platform targets -->
<RuntimeIdentifiers>
win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64
</RuntimeIdentifiers>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
</ItemGroup>
</Project>
Дозвольте мені розбити всі дії кожного з цих параметрів:
PublishAot=true
Це головний перемикач, за допомогою якого можна увімкнути компіляцію елементів AOT. Якщо цей пункт не буде позначено, ви зможете скористатися звичайною поведінкою. NET (зібрання JIT). За допомогою цього пункту ви зможете отримати початковий код у компіляції.
PublishTrimmed=true і TrimMode=full
Вони кажуть компілятору вилучити будь-який код, яким ти не користуєшся.
PublishTrimmed=true уможливлює обрізанняTrimMode=full означає "будь агресивний, убери все, що можеш."ПопередженняЦе може зламати код, який використовує важкі відбиття (на зразок деяких серіалізаторів JSON або ORM), оскільки інструмент обрізання не завжди може бачити те, що ви використовуєте у віддзеркаленні. Ми поговоримо про це пізніше.
InvariantGlobalization=true
За допомогою цього пункту можна вилучити всі дані, специфічні для культури, з форматів вашої програми app}, символів валюти, правил впорядкування тексту для різних мов.
Встановити лише це значення true якщо ваша програма:
Якщо ви будуєте інструмент CLI або шлюз API, який не має значення для локалізації, це вільні заощадження. Якщо ви створюєте щось, що потребує форматування дат для користувачів французької мови або впорядкування турецького тексту, пропустити цей параметр.
PublishSingleFile=true
Розбивати всі файли до одного виконуваного файла. Замість того, щоб мати:
myapp.exe
myapp.dll
System.Text.Json.dll
... 50 more files
Просто:
myapp.exe
Набагато простіше.
StripSymbols=true
Символи зневаджування допомагають зневаднику показувати змінні назви і номери рядків під час зневаджування. Вони корисні під час розробки, але додають декілька мегабайтів до вашого останнього виконуваного файла.
Цей параметр вилучає їх. Ваша програма запускає точно те саме, лише менше.
OptimizationPreference=Speed
За допомогою цього пункту можна наказати компілятору визначати пріоритет під час прийняття рішень:
Speed: Робіть це швидко (майже більші бінарні файли, але кращі результати)Size: Зробити його маленьким (майже повільнішим, але мінімальним бінарним розміром)Для більшості програм, Speed Різниця розмірів, зазвичай, лише 2-3МБ, але різниця швидкодії може бути помітною.
RuntimeIdentifiers
Це означає, які платформи ви хочете підтримувати. Він не будує їх всі' ї просто каже інструментing "це реальні цілі."
Наявні ідентифікатори:
win-x64: Windows 64- bit (Intel/AMD)win-arm64: Windows ARM64 (Surface Pro X тощо)linux-x64: Linux 64- bit (Ubuntu, Debian, RHEL тощо)linux-arm64: Linux ARM64 (Raspberry Pi 4/5, AWS Graviton)osx-x64: macOS Intel (старший Macs)osx-arm64: MacOS Apple Clicon (M1/ M2/ M3 Macs)Ви будуєте одну платформу за раз, використовуючи dotnet publish -r linux-x64, наприклад.
Пам' ятаєте, як я сказав, AOT потребує специфічної для платформи збирання? Вам слід зібрати окремо для Windows, Linux x64, Linux ARM64, macOS Intel і macOS Apple Clibon. Виконання цього завдання має бути достатньо іншим, ми можемо автоматично виконати його.
Якщо ви не знайомі, GitHub Дії - це безкоштовна служба CI/CD (Continentive Integration/ContentiveDoupment), вбудована у GitHub. За її допомогою ви можете виконувати автоматичні завдання кожного разу, коли ви натискаєте на код або створюєте теґ випуску.
Уявіть собі, що у вас є сервер збирання, який:
v1.0.0Все це працює на "PistHub" GitHub, вам не потрібно підтримувати будь-яку інфраструктуру для проектів з відкритим кодом і малих особистих проектів, це абсолютно безкоштовно.
Ось інтерфейс дій GitHub, який створюється автоматично для всіх основних платформ:
name: Build Native AOT Binaries
on:
push:
tags:
- 'v*'
jobs:
build-binaries:
name: Build ${{ matrix.runtime }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
runtime: linux-x64
artifact-name: myapp-linux-x64
- os: ubuntu-latest
runtime: linux-arm64
artifact-name: myapp-linux-arm64
- os: windows-latest
runtime: win-x64
artifact-name: myapp-win-x64
- os: macos-latest
runtime: osx-x64
artifact-name: myapp-osx-x64
- os: macos-latest
runtime: osx-arm64
artifact-name: myapp-osx-arm64
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install ARM64 tools (Linux ARM64 only)
if: matrix.runtime == 'linux-arm64'
run: |
sudo apt-get update
sudo apt-get install -y clang zlib1g-dev gcc-aarch64-linux-gnu
- name: Publish
shell: bash
run: |
# Set objcopy for ARM64 cross-compilation
if [ "${{ matrix.runtime }}" = "linux-arm64" ]; then
OBJCOPY_PARAM="-p:ObjCopyName=aarch64-linux-gnu-objcopy"
else
OBJCOPY_PARAM=""
fi
dotnet publish \
-c Release \
-r ${{ matrix.runtime }} \
--self-contained \
--output ./publish/${{ matrix.runtime }} \
-p:PublishAot=true \
-p:PublishTrimmed=true \
-p:StripSymbols=true \
$OBJCOPY_PARAM
- name: Create distribution package
shell: bash
run: |
mkdir -p ./dist
cd ./publish/${{ matrix.runtime }}
# Copy the main executable
cp myapp${{ matrix.file-ext }} ../../dist/
# CRITICAL: Copy native libraries (SQLite and any other native dependencies)
# PublishSingleFile bundles .NET code, but native DLLs remain separate
cp *.dll ../../dist/ 2>/dev/null || true
cp *.so ../../dist/ 2>/dev/null || true
cp *.dylib ../../dist/ 2>/dev/null || true
# Copy config files if needed
cp ../../appsettings.json ../../dist/ || true
cd ../../dist
# Create archive with all files
if [ "${{ runner.os }}" = "Windows" ]; then
7z a -tzip ../${{ matrix.artifact-name }}.zip *
else
tar czf ../${{ matrix.artifact-name }}.tar.gz *
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}
path: |
${{ matrix.artifact-name }}.zip
${{ matrix.artifact-name }}.tar.gz
retention-days: 7
if-no-files-found: ignore
Якщо YAML виглядає лякаючим, ось що він робить у звичайній англійській:
1. Тривога (on: push: tags)
Процес працює, коли ви натискаєте мітку Git, що починається з v (на зразок v1.0.0, v2.3.1). Це стандартний спосіб позначення версій випуску.
2. Стратегія матриці
Замість того, щоб писати п'ять різних робіт, ми визначаємо матриця збирання:
os (машина для запуску) і runtime (цільова платформа)То ж, коли ти штовхаєш v1.0.0, GitHub одночасно:
3. Кроки у кожному з збирання
Кожне збирання платформ виконує ті самі кроки:
dotnet publish з прапорцями AOT для цієї конкретної платформи4 Результат
Після завершення збирання у вас буде п' ять артефактів (binarys) готових для розповсюдження. Ви можете звантажити їх з запуску дій або скористатися другим завданням для створення випуску GitHub у автоматичному режимі (не показано у цьому фрагменті, але просто додати).
Ось дещо, що спантеличує мене годинами: PublishSingleFile=true Код лише в' язків. NETКорінні бібліотеки, такі як SQLite e_sqlite3.dll Залишайтеся окремо.
Ось чому крок " Створити пакунок дистрибутива " є таким важливим:
# Copy native libraries - these are NOT included in the main executable
cp *.dll ../../dist/ 2>/dev/null || true # Windows
cp *.so ../../dist/ 2>/dev/null || true # Linux
cp *.dylib ../../dist/ 2>/dev/null || true # macOS
The 2>/dev/null || true Частина означає, що якщо немає файлів, що відповідають цьому шаблону, то не знеохочуйтесь, просто продовжуйте." Це дозволяє однаковому сценарію працювати на всіх платформах.
Розподіл даних:
myapp.exe + e_sqlite3.dll (з'єднані в ZIP)myapp + libe_sqlite3.so (з'єднаний в брезенті. gz)myapp + libe_sqlite3.dylib (з'єднаний в брезенті. gz)Користувачі видобувають архів і запускають його. Природну бібліотеку SQLite розташовано поряд з виконуваним файлом, і вузол автоматично знаходить його під час виконання програми.
Зверніть увагу на workflow_dispatch Тригер згори:
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to publish'
required: true
За допомогою цього пункту ви можете увімкнути збирання вручну з веб- інтерфейсу GitHub без пересування теґу. Корисно для тестування процесу обробки або створення бета- збирання.
Для збирання ARM64 Linux потрібна особлива увага. Вам потрібні інструменти перерозподілу і вам слід вказати правильну objcopy Інструмент:
# Install tools
sudo apt-get install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
# Build with objcopy specified
dotnet publish \
-r linux-arm64 \
-p:PublishAot=true \
-p:ObjCopyName=aarch64-linux-gnu-objcopy
Без даних ObjCopyName Параметр, інструмент посилання не працює з таємними помилками щодо невідомих форматів файлів.
Ось те, чого я досяг з використанням мого виробника YARP, заснованого на bot- шлюзі виявлення з веденням журналу Midrentware і SQLite. Це реальний проект, який ви можете виконати. звантаження з GitHub.
Це ті, що фактичні розміри файлів з моїх випусків GitHub, а не теоретичних оцінень:
|----------|-----------|-------------------|-------------------| Д-р Цукер: "Воно x64] +1,7 вечора" 10. 9 Мб (ZIP) ♪
Порівняйте це з самозбереженням NET 9 в 130- 150 МБ на платформуМи говоримо про 10- 12x зменшення розміру.
Зрив:
Обидва файли повинні бути розподілені разом, але вони все ще значно менші, ніж традиційні.
Холодний початок (перший запит подався) на скромній версії Linux VPS:
Це дуже важливо для:
Бездіяльна пам' ять (запущений шлюз, без трафіку):
Під час завантаження (1000 запитів/ секунд):
Нижча пам' ять означає:
Batteries.Init()Це помилка # 1. Навіть якщо вузол правильно посилається, забуваючи про виклик SQLitePCL.Batteries.Init() на самому початку вашого Main метод призведе до аварійних завершень у режимі виконання.
Прилаштування:
public static void Main(string[] args)
{
SQLitePCL.Batteries.Init(); // FIRST LINE
// ... rest of your code
}
Це помилка No2, і я отримав два рази. PublishSingleFile=true НЕ містить до вашого виконуваного файла рідних SQLite DLL. Вам слід поширювати ці файли поряд з вашим виконуваним файлом.
Що станеться, якщо ви забудете:
DllNotFoundExceptionПрилаштування:
Під час пакування вашого випуску завжди включайте:
myapp.exe # Your main executable
e_sqlite3.dll # SQLite native library (Windows)
# or libe_sqlite3.so # SQLite native library (Linux)
# or libe_sqlite3.dylib # SQLite native library (macOS)
У ваших GitHub Дії або скрипти виконання:
# Copy ALL native libraries from the publish directory
cp *.dll ./dist/ 2>/dev/null || true
cp *.so ./dist/ 2>/dev/null || true
cp *.dylib ./dist/ 2>/dev/null || true
Користувачам слід видобути архів і запустити його. Природна бібліотека має знаходитися у тому ж каталозі.
winsqlite3 ПровайдерУ вас, можливо, будуть рекомендації на використання SQLitePCLRaw.provider.winsqlite3 у Windows для використання SQLite з підтримкою операційної системи. Не треба. Цей інструмент працює лише на Windows, потребує ініціалізації вручну, а також розбивання міжплатформових структур. Поставтеся з ним bundle_e_sqlite3.
Якщо ви використовуєте Core Framework Core за допомогою SQLite, ви отримаєте попередження щодо обрізання (IL2026, ILL3050). Зазвичай, такі попередження можна буде вимкнути для постачальника SQLite EF Core, але ретельно тестувати:
<PropertyGroup>
<NoWarn>$(NoWarn);IL2026;IL3050</NoWarn>
</PropertyGroup>
Ще краще, подумайте про використання Dapper або сирої ADO. NET з SQLite для програм AOT applications ♪ Що більш дружній до OT-дружності.
У Windows для Centific AOT потрібен пов' язувач Visual Studio MSVC. Якщо ви зберете програму за межами запрошення до команди розробника, ви побачите помилки щодо vswhere.exe. Дії GitHub працюють у автоматичному режимі, але для локальних збирання використовуйте:
Або започаткуйте середовище у вашому скрипті збирання:
& "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\Launch-VsDevShell.ps1" -Arch amd64
dotnet publish -c Release -r win-x64
Рідна AOT ідеально підходить для:
Уникайте AOT для:
Якщо ви прочитали весь цей допис і просто хочете, щоб було проведено контрольний список, ви можете обрати один з таких дописів:
1. Додайте пакунки:
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
2. Налаштуйте ваш комп'ютер .csproj для AOT:
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<InvariantGlobalization>true</InvariantGlobalization>
<PublishSingleFile>true</PublishSingleFile>
<StripSymbols>true</StripSymbols>
<OptimizationPreference>Speed</OptimizationPreference>
3. Ініціалізувати SQLite на початку вашої роботи Main метод:
SQLitePCL.Batteries.Init();
4. Зібрати для платформи призначення:
dotnet publish -c Release -r linux-x64 --self-contained
5 Тестіть свій двійковий код, він повинен просто запуститися без залежностей!
Те, що SQLite працює з корінним АОТО не є очевидним, але як тільки ви знаєте, що магія дрімаєSQLitePCLRaw.bundle_e_sqlite3 + Batteries.Init()Винагорода є істотною: крихітні контейнери, моментальний стартап і можливість піднятися на будь-яку платформу без залежностей під час виконання.
Для будь- кого, хто будує інструменти CLI, шлюзи або програми з країв за допомогою . NET, ATA OT з SQLite тепер є реалістичним параметром. GitHub Actions працює над потоком, який тут постачається, автоматично включає весь багатоплатформний процес збирання процесу * просто теґ, який буде випущено.
Якщо ви новий у AOT, почніть з малого: спочатку перетворити простий інструмент CLI або програму. Зручно скористайтеся процесом збирання, дізнайтеся, які попередження слід очікувати, і зрозумійте обмеження. Після того, як ви отримаєте базові можливості, ви зможете скористатися складнішими програмами.
Екосистема .NET все більше дружить з AOT. Більшість сучасних бібліотек або працюють з коробки, або мають чітку документацію про підтримку AOT. Майбутнє є рідним, і воно швидше, ніж ви думаєте.
Я відкрию свій зібраний AOT шлюз до:
Процес розгортання є однаковим всюди:
Ніякого кроку "встановити .NET Runtime" Без залежностей Немає конфліктів версій. Просто витягуйте і тікайте.
Для Докера, мой Dockerfile незручно просто:
FROM debian:bookworm-slim
# Copy just the two files we need
COPY minigw /app/minigw
COPY libe_sqlite3.so /app/libe_sqlite3.so
WORKDIR /app
RUN chmod +x minigw
EXPOSE 5000
ENTRYPOINT ["./minigw"]
Остаточне зображення: ~ 130МБ (здебільшого базове зображення Debian). Традиційний контейнер. NET буде 200- 250MB.
Все, що я тут показую, походить від реального, готового до виробництва проекту. Ви можете:
Проект - це мінімальний проксі- сервер з зворотним інтерфейсом YARP з виявленням bot середніх програм, які реєструють підписи на SQLite. Це демонструє:
Клонуйте його, вивчайте його, використовуйте як шаблон для ваших власних проектів AOT.
А теперь построи что-нибудь крошечное и быстрое.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.