This document explains how to use LeanCLR's AOT pipeline to translate managed DLL assemblies into C++ source files, integrate those files into your native build, and register generated AOT modules during runtime startup.
LeanAOT is a command-line tool that performs Ahead-of-Time (AOT) conversion from managed assemblies to C++ code.
- Input: one or more managed assemblies (for example
mscorlib.dll, app DLLs) - Output: generated C++ source files for method bodies, invokers, and module registration
- Typical use case: build native executable/runtime with pre-generated managed code metadata and stubs
Generated files usually include patterns such as:
*.method_body_partN.cpp*.module_registration.cpp*.module_registration.hmodules_registration.cpp
LeanAOT provides two editions targeting different production needs:
- Community Edition
- Commercial Edition
For current AOT feature coverage:
- Community Edition constraints
- Does not support AOT for generic methods
- Does not support AOT for methods that contain exception-handling regions (
try/catch/finally) - Does not support AOT for
externmethods
- Commercial Edition capability
- Supports AOT for generic methods
- Supports AOT for methods with exception handling
- Supports AOT for
externmethods
In addition to broader language/runtime coverage, the Commercial Edition includes more aggressive code generation and optimization passes, including:
- intrinsic function optimization
- generic sharing optimization
These optimizations typically improve runtime performance and reduce generated/native code size in medium to large codebases.
The Commercial Edition also supports HybridCLR's DHE (Differential Hybrid Execution) model, enabling differential hybrid execution workflows in projects that depend on DHE-based deployment/update pipelines.
From repository root:
src\leanaot\publish.batThis publishes a Release build of LeanAOT to:
src/tools/leanaot
LeanAOT currently requires all of the following options:
-d <path>- DLL search path
- can be specified multiple times
-a <assembly>or--assembly <assembly>- assembly name to AOT (without
.dllextension) - can be specified multiple times
- assembly name to AOT (without
-o <dir>- output directory for generated C++ code
Example:
LeanAOT ^
-d libraries\dotnetframework4.x ^
-d leanaot\Test\bin\Debug ^
-a mscorlib ^
-a Test ^
-o samples\simple-aot\cppLeanAOT can load one or more XML rule files to control which managed methods are included in AOT generation. These files are not related to Unity link.xml.
- AOT rule file user guide: aot-rule-file.md
- AOT rule file implementation design: aot-rule-file-design.md
After running LeanAOT, add the generated C++ files to your CMake target.
Recommended pattern (same idea as samples/simple-aot):
file(GLOB CPP_SOURCES "cpp/*.cpp")
add_executable(simple-aot main.cpp ${CPP_SOURCES})
target_link_libraries(simple-aot PRIVATE leanclr)Notes:
- Keep generated files in a dedicated folder (for example
cpp/) - Re-run
LeanAOTwhen managed DLLs change - Ensure
modules_registration.cppis included in the same target (it defines global module data used by runtime)
Before runtime startup, register generated AOT modules by wiring the exported global data into vm::Settings.
extern leanclr::metadata::RtAotModulesData g_aot_modules_data;leanclr::vm::Settings::set_aot_modules_data(&g_aot_modules_data);This call must happen before code paths that initialize or execute managed runtime logic.
Minimal startup sequence:
vm::Settings::set_file_loader(assembly_file_loader);
vm::Settings::set_aot_modules_data(&g_aot_modules_data);
// initialize runtime / execute managed entryFor a complete working flow, see:
src/samples/simple-aot/CMakeLists.txt(adds generatedcpp/*.cppinto target)src/samples/simple-aot/main.cpp(declares and registersg_aot_modules_data)