ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Hermes 内核中的 LLVH:LLVM 精简拷贝的本地化移植与补丁体系全解析

Hermes 内核中的 LLVH:LLVM 精简拷贝的本地化移植与补丁体系全解析 语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载LLVH 是 Hermes 仓库中内嵌的一份 LLVM 库与头文件的精简拷贝位于 external/llvh为 Hermes 的优化器、字节码生成与回归测试等基础设施提供 ADT、Support、IR、TableGen 等底层能力。本文以 external/llvh/README.md 为骨架结合仓库内补丁与源码完整讲解 LLVH 的来源版本、命名空间重命名策略、gtest/LIT 测试工具链的本地化修复以及 abi-breaking.h 等手写头文件的成因帮助读者理解 Hermes 如何在不依赖完整 LLVM 构建系统的前提下复用并改造 LLVM 代码。LLVH 是什么一份定点快照的 LLVM 拷贝LLVH 并非 Hermes 从零实现的库而是从 LLVM 官方仓库复制的库与头文件子集专门服务于 Hermes 的编译与测试流程。其来源信息记录在 external/llvh/README.md拷贝来源https://github.com/llvm-mirror/llvm.git固定提交哈希c179d7b006348005d2da228aed4c3c251590baa3采用定点快照pinned snapshot而非跟随上游的做法保证了 Hermes 构建的可复现性与稳定性——上游 LLVM 的任何变更都不会在未经审查的情况下影响 Hermes 的构建结果。从目录结构看LLVH 保留了 LLVM 的核心组织形态include/llvh/存放头文件ADT、Config、Demangle、IR、Support、TableGen 等子目录lib/存放库源码utils/存放 FileCheck、TableGen、count、lit、not、unittest 等工具链见 external/llvh。值得注意的一点是版本标注LLVH 的 CMakeLists.txt 将PACKAGE_VERSION声明为8.0.0svn但从后续导入的 LIT 版本LLVM v9.0.1看LLVH 实际整合了多个版本阶段的代码是一个跨版本精选后的混合体。重命名为 LLVH与主链路 LLVM 的隔离艺术LLVH 最重要的工程决策在于改名。上游 LLVM 的代码在 Hermes 中不能直接使用原因在于符号冲突如果 Hermes 链接了主链路的 LLVM例如调试器或其他依赖场景两套 LLVM 的命名空间与全局符号会互相冲突。为此LLVH 做了三层改名见 external/llvh/README.md 的 Rename to LLVH 一节C 命名空间llvm::手动重命名为llvh::include 目录llvm/头文件目录改名为llvh/即当前仓库中的 include/llvhC 公共符号LLVM*前缀的 C API 符号重命名为LLVH*例如LLVMGetErrorTypeId改为LLVHGetErrorTypeId、LLVMInstallFatalErrorHandler改为LLVHInstallFatalErrorHandler。第三层改名C 符号的完整 diff 记录在补丁 patches/rename-c-interface.patch 中。从补丁内容可以看到改名覆盖了llvh-c/Error.h、llvh-c/ErrorHandling.h等头文件与lib/Support/Error.cpp、lib/Support/CommandLine.cpp等实现文件函数声明与定义成对改名并删除了未被使用的LLVMParseCommandLineOptions等入口。同时README 明确说明未使用的llvh-c/下文件被移除最后对剩余全局符号做了手动重命名——这意味着 LLVH 只保留 Hermes 真正用到的 C API 面。此外仓库中还有一批针对特定编译器/平台行为的改造补丁例如 patches/llvm-changes-for-hermes.patch 记录了 2019 年为让 LLVM 在 Hermes 中编译而做的调整为 Android 静态库构建增加LLVM_STATIC_LIBS_FOR_ANDROID处理、在StringExtras.h中用#ifndef __ANDROID__屏蔽 Android 上不可用的strtold浮点转换、调整raw_ostream.h等。这些补丁共同体现了最小侵入、随用随改的移植策略。gtest 补丁四个针对 Windows/MSVC 的定向修复LLVH 内嵌了 googletest版本 1.8.0用于单元测试位于 external/llvh/utils/unittest/googletest。README 记录了四个必须打补丁才能解决的问题全部集中在 Windows clang/MSVC 工具链下1. GTEST_HAS_EXCEPTIONS 宏错误来自上游 googletest-1.10.0 的修复googletest-1.8.0 在 Windows 上用 clang 编译且禁用异常-fno-exceptions时存在一个 bugGTEST_HAS_EXCEPTIONS没有被定义为正确值。LLVH 从 googletest-1.10.0 的提交3498a1ac52deb83f30b8170c78bfba9dc6227198引入了修复只修改了 gtest-port.h 这一个文件。2. MSVC/Wine 下的 cxxabi.h 检测MSVC 本身没有cxxabi.h而__has_include在 Wine 环境下有 bug见 Wine bug 54130导致头文件检测可能得出错误结论。补丁 patches/gtest-port-msvc-cxxabi.patch 将检测条件改为#if !defined(_MSC_VER) defined(__has_include)即在 MSVC 下直接跳过cxxabi.h探测避免误判。3.std::nullptr_t的 UniversalTersePrinter 特化MSVC 下std::nullptr_t的operator存在歧义错误补丁 patches/gtest-printers-nullptr.patch 为其增加了UniversalTersePrinter特化使测试失败信息能正常打印空指针值。4.char16_t*的 UniversalTersePrinter 特化MSVC 在ostream中显式删除了char16_t*的operator直接打印会编译失败。补丁 patches/gtest-printers-char16.patch 提供了const char16_t*的特化实现并采用与 gtest 既有char*/wchar_t*打印一致的 C 风格转义规则同时引入iomanip头。附带-Wundef 警告抑制gtest.h与gmock.h内部对可能未定义的宏直接使用#if判断这在-Wundef编译选项下会输出大量无害但嘈杂的警告。LLVH 通过在两个头文件内容外层包裹#pragma GCC diagnostic push/ignored/pop来抑制涉及gtest.hgmock.hLIT 补丁Windows Python3 问题与 RUN 行替换增强LIT 是 LLVM 的回归测试驱动工具Hermes 用它驱动test/与unittests/下的测试可参考仓库根目录的 test/lit.cfg 与 unittests/lit.cfg。为修复 Windows 上的 python3 兼容问题LLVH 从 LLVM 拉入了 LIT 的更新版本基线为 LLVM release v9.0.1提交哈希c1a0a213378a458fbea1a5c77b315c7dce08fd052019-11-27。README 给出了当时同步 LIT 的完整操作流程git clone https://github.com/llvm/llvm-project.git cd llvm-project git checkout c1a0a213378a458fbea1a5c77b315c7dce08fd05 cp -r ./llvm/utils/lit/* /path/to/hermes/external/llvh/utils/lit注意LIT 的自测试self-tests与示例等未被使用的文件被有意省略以保持拷贝最小化。同步后的 LIT 工具链位于 external/llvh/utils/lit/lit包含TestRunner.py、run.py、discovery.py、formats/googletest.py等核心模块。在 v9.0.1 基线之上LLVH 又追加了两项本地化改进1. googletest.py 的 run_under 参数从 LLVM release v20.1.8提交87f0227cb60147a26a1eeb4fb06e3b505e9c7261拉入了run_under参数。从 formats/googletest.py 的实现看run_under允许为 gtest 测试指定前置运行包装命令如调试器或环境工具当它是列表时直接拼接在测试命令前是字符串时则用shlex.split解析后拼接兼容两种配置写法。2. 空 RUN 行替换与 UNSUPPORTED 标记这是对 TestRunner.py 的行为增强补丁为 patches/lit-skip-empty-run-lines.patch。其动机是当lit.cfg通过替换substitution把某个工具例如%shermes替换为一个标记、进而把整条 RUN 行替换成空字符串时原来空行仍会保留并导致测试行为异常。补丁在applySubstitutions之后加入两行逻辑# Drop empty RUN lines (e.g. from disabled substitutions). script [ln for ln in script if ln] if not script: return lit.Test.Result(Test.UNSUPPORTED, Test has no remaining run lines after substitution)即丢弃替换后为空的 RUN 行若所有 RUN 行都被丢弃则将该测试标记为UNSUPPORTED不支持而不是报错或误判为通过/失败。这一机制让lit.cfg可以安全地通过替换来按平台/工具可用性禁用整类测试。其他导入Support/JSON 与 ToolOutputFile除了 LIT 与 gtestLLVH 还从 LLVM v9.0.1 导入了两个 Support 模块Support/JSONLLVM 的 JSON 读写支持Hermes 的工具链如调试协议、测试基础设施可借此序列化/反序列化结构化数据Support/ToolOutputFile工具输出文件封装统一管理输出文件的创建、缓冲与错误处理。这两者都位于 external/llvh/lib/Support 的源码体系内与 ADT如llvh::SmallVector、llvh::StringRef等组件一起构成 Hermes 复用的准标准库。abi-breaking.h绕开 CMake 生成的手写配置头上游 LLVM 的abi-breaking.h是由 CMake 的configure_file()在构建期生成的用于定义两个关键宏LLVM_ENABLE_ABI_BREAKING_CHECKS控制 ABI 破坏性检查是否开启LLVM_ENABLE_REVERSE_ITERATION控制反向迭代行为。LLVH 不使用 LLVM 自身的构建系统它被挂载到 Hermes 的 CMake 体系中见 external/llvh/CMakeLists.txt 对configure_file(include/llvh/Config/config.h.cmake ...)的处理因此 include/llvh/Config/abi-breaking.h 是手写头文件将两个宏都硬编码为 0// Hermes does not use LLVMs ABI-breaking checks. #define LLVM_ENABLE_ABI_BREAKING_CHECKS 0 // Hermes does not use LLVMs reverse iteration. #define LLVM_ENABLE_REVERSE_ITERATION 0README 特别指出如果不定义这两个宏#if LLVM_ENABLE_ABI_BREAKING_CHECKS这类表达式在宏未定义时会静默按 0 求值行为恰好正确但会触发-Wundef警告。手写头文件的意义正在于以显式定义消除这类隐患——这与 gtest 头文件的-Wundef抑制是同一思路的两面一处显式定义、一处压制告警。构建集成LLVH 如何嵌入 Hermes 的 CMake 体系从 external/llvh/CMakeLists.txt 可以看到 LLVH 的构建集成要点通过set(HERMES_LLVM True)与add_definitions(-DHERMES_LLVM)标记自身身份供库源码内的条件编译使用设置LLVM_MAIN_SRC_DIR/LLVM_MAIN_BIN_DIR模拟 LLVM 的源码/构建目录布局将PACKAGE_NAME设为LLVH、版本标注为8.0.0svn通过configure_file将config.h.cmake、llvm-config.h.cmake生成到构建目录替代上游 LLVM 庞大的构建系统关闭 unity buildset(CMAKE_UNITY_BUILD OFF)因为部分源文件与 unity 构建不兼容依次挂载lib、utils/FileCheck、utils/TableGen、utils/not、utils/count、utils/unittest子目录定义check-llvh测试目标通过add_lit_testsuite运行test/下的回归测试并把FileCheck、llvh-tblgen作为 LIT 替换参数注入。这也是为什么 Hermes 的开发者可以零安装 LLVM直接构建所有需要的 LLVM 子集都以源码形式随仓库分发由 Hermes 自己的 CMake 流程统一编译。从补丁目录看完整维护史external/llvh/patches 目录汇集了 25 个补丁远超 README 中详述的几个它们是 LLVH 长期演进中各项本地化修复的档案例如CommandLined.patch、SourceMgr.patch、SourceMgr-msvc-warnings.patch命令行解析与 SourceMgr 的 MSVC 告警处理SmallVector.patch、StringSet-constructor.patch、ilist-*系列ADT 容器在特定编译器尤其是 MSVC 空基类优化下的修正emscripten-disable-threads.patchEmscripten 平台禁用线程支持对应 Hermes 的 WebAssembly 构建场景windows-rename-api-fix.patch、llvm-hosttriple-windows.patchWindows 平台的主机三元组与 API 修复gtest_has_exception_1_8_0.patch、lit-skip-empty-run-lines.patchREADME 中详述的测试工具链修复的落地补丁。结合 README 与补丁目录可以推断LLVH 的维护模式是以最小改动换取跨平台可构建性所有偏离上游的行为都以补丁文件形式显式记录既便于审计也便于未来与上游同步时逐项核对。小结LLVH 是 Hermes 工程化思路的一个缩影以定点快照锁定上游代码以llvh::命名空间与LLVH*符号重命名规避链接冲突以手写abi-breaking.h绕开 LLVM 构建系统再以一组精准的 gtest/LIT 补丁解决 Windows/MSVC/Wine/Emscripten 等环境的真实兼容问题。理解 LLVH也就理解了 Hermes 编译器与测试基础设施的底层依赖是如何被驯服的。相关源码可继续查阅 external/llvh/include/llvh/Config、external/llvh/utils/lit/lit/TestRunner.py 与 external/llvh/utils/unittest/googletest/patches。赞分享语言运行时编译器移动开发【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址https://gitcode.com/gh_mirrors/hermes/hermes点击查看免费下载相关推荐如何系统学云安全9本书与3条认证线的完整学习指南如何系统学云安全9本书与3条认证线的完整学习指南 GitHub_Trending/boo/books 是个开源电子书仓库按主题攒了数百份 PDF。这篇文章只教程SerenityOS 移植 ScummVMmalloc.h 缺失问题的补丁解析与移植实践SerenityOS 移植 ScummVMmalloc.h 缺失问题的补丁解析与移植实践 导读 本文围绕 SerenityOS 仓库中 ScummVM 移植所操作系统内核驱动Orleans 虚拟 Actor 框架解析分布式 .NET 应用的核心架构与实战指南Orleans 虚拟 Actor 框架解析分布式 .NET 应用的核心架构与实战指南 导读 本文基于 Microsoft Orleans 官方概述文档深入剖后端微服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表