楔子
上節了解AOT和CLR的區別,這節來稍微深入看下AOT的原理是什么?
原理
其實 AOT 的原理非常簡單,為啥呢?因為微軟又回歸了傳統,搞起來Obj目標文件和Link連接器。當年的VC++就是這么弄的。
AOT的編譯實際上是圍繞這兩個東西來的,編譯目標文件Obj用的是微軟的官方編譯器IlCompiler它的工具名是:ilc.exe。
而Link連接器,就是微軟的VC連接器鏈接Obj以生成靜態Exe。工具名是:Link.exe。
把ilc.exe生成的Obj,用Link.exe連接下,生成的結果就是你看到的那個幾兆的Exe文件。
原理的用法
注意這個地方不是平常那種AOT發布文件的用法,而是看下它里面是怎么弄的。
1.首先,在Nuget包下載一個ILCompiler AOT編譯器:runtime.win
x64.Microsoft.DotNet.ILCompiler
2.把下面路徑加到系統環境變量
Path下面。
C:\Users\Administrator.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\tools
3.打開powershell
4.輸入命令:
ilc.exe參數:
-r參數是引用了那些庫文件
-o是輸出目錄
-g是運行的時候需要用到的庫
-feature裁剪一些不需要的東西,減少exe體積
ilc.exe
//這行是你托管DLL的地址,也就是你需要編譯AOT程序的DLL
C:\Users\Administrator\Desktop\test\ConsoleApp1\obj\Debug\net7.0\win-x64\ConsoleApp1.dll
-o:C:\Users\Administrator\Desktop\test\test.obj
-r:C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\sdk\*.dll
-r:C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\framework\*.dll
-g
--initassembly:System.Private.CoreLib
--initassembly:System.Private.StackTraceMetadata
--initassembly:System.Private.TypeLoader
--initassembly:System.Private.Reflection.Execution
--directpinvoke:System.Globalization.Native
--directpinvoke:System.IO.Compression.Native
--stacktracedata
--scanreflection
--feature:System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization=false --feature:System.Diagnostics.Tracing.EventSource.IsSupported=false
--feature:System.Resources.ResourceManager.AllowCustomResourceTypes=false
--feature:System.Linq.Expressions.CanCompileToIL=false
--feature:System.Linq.Expressions.CanEmitObjectArrayDelegate=false
--feature:System.Linq.Expressions.CanCreateArbitraryDelegates=false
link.exe可以用vs2022命令行工具打開,注意最好選擇native x64版本。link.exe參數:LIBPATH需要庫文件
link.exe
//這個是上面ilc.exe生成的Obj文件,被連接器鏈接
C:\Users\Administrator\Desktop\test\test.obj
//這個最終生成的exe
/OUT:C:\Users\Administrator\Desktop\test\test.exe
/LIBPATH:"D:\Visual Studio\IDE\VC\Tools\MSVC\14.33.31629\ATLMFC\lib\x64" /LIBPATH:"D:\Visual Studio\IDE\VC\Tools\MSVC\14.33.31629\lib\x64"
/LIBPATH:"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64"
/LIBPATH:"D:\Windows Kits\10\lib\10.0.22621.0\ucrt\x64"
/LIBPATH:"D:\Windows Kits\10\\lib\10.0.22621.0\\um\x64"
"C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\sdk\bootstrapper.lib"
"C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\sdk\Runtime.WorkstationGC.lib"
"C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\sdk\System.Globalization.Native.Aot.lib"
"C:\Users\Administrator\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.0\sdk\System.IO.Compression.Native.Aot.lib" "advapi32.lib" "bcrypt.lib" "crypt32.lib" "iphlpapi.lib" "kernel32.lib" "mswsock.lib" "ncrypt.lib" "normaliz.lib" "ntdll.lib" "ole32.lib" "oleaut32.lib" "secur32.lib" "user32.lib" "version.lib" "ws2_32.lib"
/NOLOGO /MANIFEST:NO
/DEBUG /INCREMENTAL:NO
/SUBSYSTEM:CONSOLE
/ENTRY:wmainCRTStartup
/NATVIS:"C:\Program Files\dotnet\sdk\7.0.100\Sdks\Microsoft.DotNet.ILCompiler\build\NativeAOT.natvis"
/NODEFAULTLIB:libucrt.lib
/DEFAULTLIB:ucrt.lib
結果它生成的exe就是AOT發布的那個exe文件。
dotnet publish 實際上就是封裝了這兩個命令。
結尾:
實際上AOT感覺就是又重走了VC++的老路,