ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

使用 CoreRun 与 Core_Root 运行基于本地构建的 .NET 运行时

使用 CoreRun 与 Core_Root 运行基于本地构建的 .NET 运行时 语言运行时标准库JIT编译编译器【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址https://gitcode.com/GitHub_Trending/runtime6/runtime点击查看免费下载导读本文面向正在为 .NET 运行时仓库runtime repo贡献代码、需要快速验证 CoreCLR 修改效果的开发者系统讲解如何使用自己构建的 CoreCLR 产物来运行 .NET 应用程序包括以corerun作为宿主启动本地运行时、借助CORE_ROOT/CORE_LIBRARIES环境变量与命令行参数定位运行时与类库、以及通过测试构建脚本生成一整套Core_Root产物用于联调测试。读完本文你将掌握在不安装任何额外 SDK、不修改系统全局环境的前提下用最快的方式持续迭代测试自己编译出的 CoreCLR 与类库并理解corerun底层发现程序集、初始化运行时coreclr_initialize和传递运行时属性的完整原理。为什么需要 CoreRun运行本地运行时的三种方式要使用你自己构建的运行时来运行 .NET 应用除了托管应用程序本身之外还必须有一个能够加载运行时的*宿主host*程序并准备好应用依赖的全部 .NET 类库。在 runtime 仓库中官方文档归纳了三种主要方式使用机器上已安装的 .NET SDK并替换自包含应用中的必要二进制适合希望以接近真实发布形态验证的场景详见 使用已安装 SDK 运行你的构建。使用你的构建产出的开发版 Shipping 包Dev Shipping Packages这是最接近最终用户使用方式、但流程也最长的方案通过clrlibshostpacks子集构建出 NuGet 包与可分发运行时详见 使用构建的 Shipping 包。使用构建产物中生成的 CoreRun 宿主这也是本文的主角。corerun是一个平台无关的轻量级宿主工具专门用于快速测试本地构建的 .NET 运行时能够大幅加速运行时开发与测试失败问题的调查。当你处于频繁修改、持续测试调试的内循环中时官方推荐优先使用这种方式——因为它不需要打包、不需要安装每次重新构建后直接重新执行即可应用最新的改动。阅读本文之前请确保你已经至少完成了仓库的clr子集构建并且产物位于artifacts/bin/coreclr/OS.arch.configuration目录。如果尚未完成构建请先参考 CoreCLR 构建指南 完成环境准备与编译。认识 CoreRun 宿主它是什么、不知道什么corerun二进制是构建clr子集的产物之一位于仓库根目录/artifacts/bin/coreclr/OS.Arch.Configuration目录下Windows 上名为corerun.exe。从 CoreCLR 构建指南 的Build Results一节可以确认同一目录下还会产出coreclr运行时本体Windows 为coreclr.dllmacOS 为libcoreclr.dylibLinux 为libcoreclr.so以及System.Private.CoreLib.dll等核心托管库。关键设计点是corerun完全不理解 NuGet。它只需要两样东西平台对应的运行时动态库coreclr.dll/libcoreclr.dylib/libcoreclr.so应用运行所需的类库程序集例如System.Runtime.dll、System.IO.dll等。这一点在 corerun 源码 中体现得很直接平台抽象层pal针对不同平台分别定义了运行时库文件名常量——Windows 为coreclr.dllmacOS 为libcoreclr.dylibLinux 及其他类 Unix 系统为libcoreclr.so加载时统一拼成core_root/coreclr.dll或对应平台名称后调用try_load_coreclr动态加载。运行时与类库的发现启发式corerun通过以下顺序的启发式规则来定位运行时二进制源码中run()函数与帮助文本均明确记录了该顺序检查用户是否通过命令行传入了--clr-path参数检查CORE_ROOT环境变量是否已定义检查 .NET 运行时二进制是否与corerun二进制位于同一目录。无论通过哪种方式定位到运行时二进制其所在目录都会被同时用来查找全部基类库BCL程序集。此外你还可以通过定义CORE_LIBRARIES环境变量把额外的目录纳入类库程序集的搜索集合。从 corerun.cpp 的源码可以进一步确认环境变量的完整定义环境变量作用CORE_ROOT指向包含 CoreCLR 运行时二进制的目录CORE_LIBRARIES指向包含附加平台程序集的目录用于覆盖/补充框架程序集APP_ASSEMBLIES控制应用程序集如何提供给运行时PROPERTY默认通过TRUSTED_PLATFORM_ASSEMBLIES属性传入路径列表、EXTERNAL通过外部程序集探测回调提供、或直接给出一份平台分隔符分隔的路径列表MOCK_HOSTPOLICY测试用预加载一个 mock hostpolicy 动态库PLATFORM_NATIVE_R2R置为1时向运行时提供平台原生 R2RReadyToRun镜像的回调支持仅 Windows 与 macOSTPA 列表的构建细节CORE_LIBRARIES 如何覆盖框架程序集corerun最终通过TRUSTED_PLATFORM_ASSEMBLIESTPA属性把可信平台程序集清单交给运行时。源码中的build_tpa()函数见 corerun.cpp揭示了一个实用的细节它先按.dll、.exe两类扩展名遍历对每个扩展名依次遍历core_libraries来自CORE_LIBRARIES与core_root来自--clr-path/CORE_ROOT/corerun 所在目录这两个目录用一个std::set对简单程序集名去重同一个简单名称只保留第一个实例。源码注释明确指出由于 CoreCLR 并不总是优先采用 TPA 列表中的第一个实例例如 NI 原生镜像可能被优先于 IL 选择因此构建 TPA 时只保留每个简单程序集名的首个实例从而让用户可以通过把 dll 放进%CORE_LIBRARIES%目录来覆盖框架程序集。这正是用CORE_LIBRARIES指向系统共享类库目录即可复用已安装 .NET 的类库这一做法得以成立的底层机制。用 CoreRun 运行应用程序下面以经典的 Hello World 为例展示如何用你自己构建的运行时取代机器上安装的运行时来运行应用。使用系统级 .NET 安装中的共享类库首先创建并构建一个普通控制台应用mkdir HelloWorld cd HelloWorld dotnet new console dotnet build注意这里我们仍然用机器上的 SDK 完成编译编译只依赖 SDK 的编译能力关键区别在于运行时执行阶段交给corerun。接下来按以下步骤操作把corerun所在目录加入PATH环境变量以方便调用也可以跳过此步始终使用完整路径以下示例假设你以Debug配置、x64架构构建请根据你自己的构建参数调整路径。由于我们只构建了运行时clr 子集而没有构建类库需要通过CORE_LIBRARIES告诉corerun使用机器上 .NET 默认安装自带的类库以下示例假设你机器上默认 .NET 安装的版本名为7.0.0请替换为你实际安装的版本。最后执行corerun运行应用。Windows 命令提示符CMDset PATH%PATH%;repo_root\artifacts\bin\coreclr\windows.x64.Debug set CORE_LIBRARIES%ProgramFiles%\dotnet\shared\Microsoft.NETCore.App\7.0.0 corerun HelloWorld.dllmacOS 与 Linux# 如果你在 Linux 上把 osx 改为 linux。 export PATH$PATH:repo_root/artifacts/bin/coreclr/osx.x64.Debug export CORE_LIBRARIES/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.0 corerun HelloWorld.dllPowerShell# 注意这里用的是 因为我们要追加到已有的 PATH 变量。 # 另外在 Linux 或 macOS 上请把 ; 换成 :。 $Env:PATH ;repo_root\artifacts\bin\coreclr\windows.x64.Debug $Env:CORE_LIBRARIES %ProgramFiles%\dotnet\shared\Microsoft.NETCore.App\7.0.0 corerun HelloWorld.dll设置好PATH与CORE_LIBRARIES之后corerun HelloWorld.dll就知道去哪里获取它所需的程序集了。这套设置只需在同一个终端实例内做一次之后即使你重新构建并修改了运行时也可以直接再次执行corerun来运行应用——修改立即生效无需重复配置。这正是它适合改代码 → 重编译 → 立即测试内循环的原因。执行发布为自包含的应用程序当应用以自包含方式发布dotnet publish --self-contained时发布目录中已经包含应用运行所需的全部类库。因此只需要把上一节中CORE_LIBRARIES的值改为指向该发布目录corerun就会从你部署的应用中获取所有这些库的代码set CORE_LIBRARIESpath\to\publish\output corerun HelloWorld.dll这样你就用本地构建的 CoreCLR 运行了一个自包含布局的应用类库代码来自你的发布目录而非系统共享目录。认识 Core_Root类库 运行时的一站式测试目录什么是 Core_Root前文通过CORE_LIBRARIES借用系统类库的做法有一个局限你无法同时测试自己修改的类库。为了解决这个问题测试构建脚本会为你汇集一套完整的测试运行环境——Core_Root。Core_Root由测试构建脚本Windows 为src/tests/build.cmdmacOS/Linux 为src/tests/build.sh创建它会把你刚刚构建好的 CoreCLR 与测试所需的类库片段集中放置到一个目录中产出位置为artifacts/tests/coreclr/OS.Arch.Configuration/Tests/Core_Root从 CoreCLR 构建指南 可以看到完整的 Core_Root 不仅包含类库与 CLR还打包了Crossgen2、R2RDump、ILC 编译器以及corerun等工具是 CI 管道中运行 CLR 测试的方式也是最可靠的测试运行时改动与运行外部应用的途径之一。如何生成 Core_Root由于测试构建过程相当漫长官方建议只在需要时通过-generatelayoutonly标志生成 Core_Root 布局然后按需单独构建个别测试或测试树。重要前提要生成 Core_Root你必须先用-subset libs构建过类库。测试构建脚本默认以Release模式搜索类库无论你为运行时指定了什么配置。如果你用其他配置构建的类库必须传入/p:LibrariesConfigurationyour_config标志。更详细说明见 CoreCLR 测试文档。典型的生成命令假设 x64 机器的 Checked 配置 CLR 构建来自 CoreCLR 构建指南./src/tests/build.sh -arch x64 -checked -generatelayoutonly而在准备阶段构建指南推荐用如下命令同时构建 clr 与 libsclr 用 Debug、类库用 Release 是常见组合./build.sh -subset clrlibs -runtimeConfiguration Debug -librariesConfiguration Release使用 Core_Root 运行应用拿到 Core_Root 之后直接调用其中的corerun或者把 Core_Root 目录加入PATH即可用这套运行时 类库的组合运行应用Windows 命令提示符set PATH%PATH%;repo_root\artifacts\tests\coreclr\windows.x64.Debug\Tests\Core_Root corerun HelloWorld.dllmacOS 与 Linux# 如果你在 macOS 上把 linux 改为 osx。 export PATH$PATH:repo_root/artifacts/tests/coreclr/linux.x64.Debug/Tests/Core_Root corerun HelloWorld.dllPowerShell# 注意这里用的是 因为我们要追加到已有的 PATH 变量。 # 另外在 Linux 或 macOS 上请把 ; 换成 :。 $Env:PATH ;repo_root\artifacts\tests\coreclr\windows.x64.Debug\Tests\Core_Root corerun HelloWorld.dll相比仅使用 clr 构建产出的corerun生成 Core_Root 的优势在于你可以同时测试和调试类库与运行时——因为CORE_ROOT或--clr-path指向的 Core_Root 目录里既包含你构建的libcoreclr运行时也包含你构建的类库程序集二者是配套的同一套产物。CoreRun 的完整命令行选项corerun支持若干可选命令行参数执行corerun --help可查看完整帮助。以下选项在源码的display_usage()与parse_args()中均有对应实现见 corerun.cpp短选项与长选项等价选项说明示例-c, --clr-path PATH在命令行直接指定 Core_Root 位置。如果你的corerun就在 Core_Root 目录内或者已通过CORE_ROOT环境变量设置了路径则可以省略此参数corerun --clr-path /path/to/core_root HelloWorld.dll-p, --property PROPERTY在运行时初始化期间向其传递一个属性格式为keyvalue可多次指定属性值含空格时请为整个参数加引号corerun --property System.GC.Concurrenttrue HelloWorld.dll-l, --preload PATH在加载 CLR 之前先加载指定的共享库原生库corerun --preload /path/to/libfoo.so HelloWorld.dll-d, --debug在加载 .NET 运行时之前等待调试器附加corerun --debug HelloWorld.dll-e, --env PATH指定一个.env文件路径为本次测试运行设置环境变量格式兼容 python-dotenv 项目的 dotenv 规范仓库内实现见 dotenv.cppcorerun --env gcstress.env HelloWorld.dll-?, -h, --help显示帮助信息corerun --help-st源码内置执行 corerun 自检self-test验证参数解析与工具函数行为corerun -st帮助文本中还给出了一个综合示例同时演示了调试等待、传递两个运行时属性以及向托管程序集传参corerun -d -p System.GC.Concurrenttrue -p FancyProp/usr/first last/root HelloWorld.dll arg1源码视角这些选项底层做了什么从 corerun.cpp 的parse_args()与run()实现可以进一步理解各选项的语义--clr-path的优先级run()中先看config.clr_path命令行传入是否为空为空才回退到CORE_ROOT环境变量再为空则使用corerun可执行文件所在目录。这与文档描述的启发式顺序完全一致也与display_usage()中 The runtime binary is searched for in --clr-path, CORE_ROOT environment variable, then in the directory the corerun binary is located. 的说明一一对应。--property的传递链解析时按拆分键值运行时通过get_runtime_property回调host runtime contract把用户自定义属性提供给运行时初始化若属性格式缺少会直接报错。--debug的行为wait_for_debugger()会打印进程 PID 并提示 Waiting for the debugger to attach (PID: ...). Press any key to continue ...阻塞等待调试器附加附加成功后打印 Debugger is attached.。运行时初始化流程run()依次加载 CoreCLR 动态库、解析coreclr_initialize/coreclr_execute_assembly/coreclr_shutdown_2以及可选的coreclr_set_error_writer导出符号然后构造初始化属性其中除用户属性外还固定设置三项基础属性TRUSTED_PLATFORM_ASSEMBLIES全部受信程序集的完整路径清单即前文 TPA 列表APP_PATHS程序集加载器将探测的路径列表即入口程序集所在目录NATIVE_DLL_SEARCH_DIRECTORIESP/Invoke 调用原生 DLL 时探测的路径列表包含应用目录、CORE_LIBRARIES目录与 core root 目录。 随后调用coreclr_initialize创建运行时实例与应用域再调用coreclr_execute_assembly执行托管程序集最后通过coreclr_shutdown_2关闭运行时并取回退出码。--preload在加载 CLR 之前通过dlopen/LoadLibraryEx预加载指定共享库可用于注入原生依赖或 mock 库。--env的 dotenv 解析仓库内 dotenv.hpp 说明其实现了基于 python-dotenv 项目格式的.env文件解析并在load_into_current_process()中把键值写入当前进程环境供运行时与测试使用此外 corerun 自带的self_test()还会对 dotenv 解析逻辑做自检。常见问题与排查思路corerun找不到运行时请确认产物目录中确实存在coreclr.dll/libcoreclr.so/libcoreclr.dylib并检查--clr-path、CORE_ROOT是否指向该目录。源码中运行时加载失败会打印 Failed to load: 路径 与具体错误码可据此定位路径问题。类库版本不匹配使用CORE_LIBRARIES指向系统共享类库时务必确认其版本与你构建的运行时兼容如果需要同时测试类库改动请改用 Core_Root 方案。无法加载托管程序集或 P/Invoke 失败检查APP_PATHS是否包含入口程序集所在目录、NATIVE_DLL_SEARCH_DIRECTORIES是否包含原生依赖所在目录这些目录在run()中会自动汇集应用目录、CORE_LIBRARIES与 core root若自定义布局较特殊可通过--env注入辅助环境变量辅助排查。Core_Root 生成报类库配置错误回顾测试构建前提——必须先以-subset libs构建类库且默认按 Release 搜索若你的类库是其他配置请携带/p:LibrariesConfigurationyour_config。延伸阅读CoreCLR 构建指南了解 clr/lib 子集构建参数、产物布局与 Core_Root 生成命令的完整上下文。CoreCLR 测试文档测试构建脚本的详细用法、配置参数与测试运行方式。使用已安装 SDK 运行你的构建 与 使用构建的 Shipping 包另外两种测试自构建运行时的方案。源码参考corerun.cpp、corerun.hpp、dotenv.cpp。赞分享语言运行时标准库JIT编译编译器【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址https://gitcode.com/GitHub_Trending/runtime6/runtime点击查看免费下载相关推荐dotnet/runtime 如何用 corerun 与 Core_Root 运行自己构建的托管应用dotnet/runtime 如何用 corerun 与 Core_Root 运行自己构建的托管应用 你在 dotnet/runtime 仓库里改动了 Cor语言运行时标准库JIT编译编译器.NET Runtime CoreCLR 测试构建与运行完全指南从 src/tests 到 Core_Root.NET Runtime CoreCLR 测试构建与运行完全指南从 src/tests 到 Core_Root 本篇技术指南围绕 dotnet/runtime语言运行时标准库JIT编译编译器在 Cloudflare Worker 中运行 ECMAScript 模块基于 worker-javascript 示例构建 Workspace 运行时在 Cloudflare Worker 中运行 ECMAScript 模块基于 worker javascript 示例构建 Workspace 运行时 本文后端云原生存储上一篇BoardGame.io 开源项目教程下一篇深度解析开源法律大语言模型驱动企业智能法务转型的战略实施创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表