.Net 7的AOT原理简析

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.Net 7的AOT原理简析相关的知识,希望对你有一定的参考价值。

楔子

上节了解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++的老路,

以上是关于.Net 7的AOT原理简析的主要内容,如果未能解决你的问题,请参考以下文章

.Net 7 的Native AOT为啥不支持反射,你知道吗

.Net 7 的AOT的程序比托管代码更容易破解?

.Net 7 新编译器 ILC 简析

.Net 7 GC垃圾回收对象跨代简析

.Net 7 深入学习需要用到哪些工具?Visual Studio除外

.NET 7 AOT 的使用以及 .NET 与 Go 互相调用