龙空技术网

了解.Net Native编译器

秋风技术 739

前言:

眼前姐妹们对“netnativecode”大约比较关切,兄弟们都需要分析一些“netnativecode”的相关内容。那么小编同时在网上收集了一些有关“netnativecode””的相关文章,希望同学们能喜欢,咱们一起来学习一下吧!

起因

在.Net6中 Native程序生成的过程 说到*.ilc.rsp这个文件,其实rsp格式文件很早都在.Net中使用了,最早知道这个格式文件是在<<CLR Via C#>>这本书,我觉得这是我看C#最认真的一本书了.继续说*.ilc.rsp文件这个是谁使用? 是ILCompiler(简写ilc)编译器使用,这个编译器将.Net (exe/dll)编译为obj目标文件.

ILCompiler源码地址: ,在Github上看到好像在.Net 7中要将ILCompiler合到.Net Runtime中.

准备工作

ILCompiler源码在runtimelab下,runtimelab是包含CoreCLR和BCL库.所以要执行根目录下的build.cmd/build.sh

//Windows下执行,这里和执行编译Runtime源码不太一样,增加了nativeaot.packages参数build.cmd nativeaot+libs+nativeaot.packages -rc Debug -lc Debug//Linux下执行build.sh nativeaot+libs+nativeaot.packages -rc Debug -lc Debug

编译前,还是需要一个.Net版本,这里就不说了,具体可以看 如何编译.Net 6 Runtime源码 ,编译完成后,是有ILCompiler的nupkg包,可以在源码根目录下,去这个路径artifacts/packages/Debug/Shipping/

ILCompiler的解决方案文件,在这个目录下src/coreclr/tools/aot/ilc.sln,打开解决方案后:

设置ILCompiler为启动项目设置工作目录 F:\GitCode\runtimelab-feature-NativeAOT\samples\HelloWorld设置命令行参数 以@开头. 如@obj/Debug/net6.0/win-x64/native/HelloWorld.ilc.rsp

然后启动ILCompiler项目,会将obj文件生成到 工作目录加命令行参数所在的目录.

生成Native程序

找到reproNative项目,在该项目属性中,找到链接器→输入: F:\GitCode\runtimelab-feature-NativeAOT\samples\HelloWorld\obj\Debug\net6.0\win-x64\native\HelloWorld.obj

链接obj目标文件,和cpp文件编译成原生程序

在reproNativew项目的cpp文件看到这一段代码比较有意思:

#if defined(_MSC_VER)#pragma section(".modules$A", read)#pragma section(".modules$Z", read)extern "C" __declspec(allocate(".modules$A")) void * __modules_a[];extern "C" __declspec(allocate(".modules$Z")) void * __modules_z[];__declspec(allocate(".modules$A")) void * __modules_a[] = { nullptr };__declspec(allocate(".modules$Z")) void * __modules_z[] = { nullptr };//// Each obj file compiled from managed code has a .modules$I section containing a pointer to its ReadyToRun// data (which points at eager class constructors, frozen strings, etc).//// The #pragma ... /merge directive folds the book-end sections and all .modules$I sections from all input// obj files into .rdata in alphabetical order.//#pragma comment(linker, "/merge:.modules=.rdata")//// Unboxing stubs need to be merged, folded and sorted. They are delimited by two special sections (.unbox$A// and .unbox$Z). All unboxing stubs are in .unbox$M sections.//#pragma comment(linker, "/merge:.unbox=.text")char _bookend_a;char _bookend_z;//// Generate bookends for the managed code section.// We give them unique bodies to prevent folding.//#pragma code_seg(".managedcode$A")void* __managedcode_a() { return &_bookend_a; }#pragma code_seg(".managedcode$Z")void* __managedcode_z() { return &_bookend_z; }#pragma code_seg()//// Generate bookends for the unboxing stub section.// We give them unique bodies to prevent folding.//#pragma code_seg(".unbox$A")void* __unbox_a() { return &_bookend_a; }#pragma code_seg(".unbox$Z")void* __unbox_z() { return &_bookend_z; }#pragma code_seg()

这一段代码,应该就是将obj的module放到节(这是可执行程序的知识,后面会在PE中说这个).

下面看main方法代码:

#if defined(_WIN32)int __cdecl wmain(int argc, wchar_t* argv[])#elseint main(int argc, char* argv[])#endif{#ifdef ENSURE_PRIMARY_STACK_SIZE    // TODO:     EnsureStackSize(1536 * 1024);#endif    int initval = InitializeRuntime();                 //初始化runtime    if (initval != 0)        return initval;    int retval = __managed__Main(argc, argv); //调用.net的main方法    RhpShutdown();      return retval;}

后面就可以看为什么没法在C程序调用.Net Native生成的静态库了.

个人能力有限,如果您发现有什么不对,请私信我

如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流

标签: #netnativecode