快捷搜索:  汽车  科技

net编译过程(了解.NetNative编译器)

net编译过程(了解.NetNative编译器)在reproNativew项目的cpp文件看到这一段代码比较有意思:链接obj目标文件 和cpp文件编译成原生程序ILCompiler的解决方案文件 在这个目录下src/coreclr/tools/aot/ilc.sln 打开解决方案后:然后启动ILCompiler项目 会将obj文件生成到 工作目录加命令行参数所在的目录.找到reproNative项目 在该项目属性中 找到链接器→输入: F:\GitCode\runtimelab-feature-NativeAOT\samples\HelloWorld\obj\Debug\net6.0\win-x64\native\HelloWorld.obj

起因

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

ILCompiler源码地址:https://github.com/dotnet/runtimelab.git 在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 打开解决方案后:

  1. 设置ILCompiler为启动项目
  2. 设置工作目录 F:\GitCode\runtimelab-feature-NativeAOT\samples\HelloWorld
  3. 设置命令行参数 以@开头. 如@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

net编译过程(了解.NetNative编译器)(1)

链接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[]) #else int main(int argc char* argv[]) #endif { #ifdef ENSURE_PRIMARY_STACK_SIZE // TODO: https://github.com/dotnet/runtimelab/issues/791 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生成的静态库了.

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

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

猜您喜欢: