)
#embed指令在 Clang 中的状态如下自Clang 19起可用。在C23标准中受支持。在旧模式中作为Clang 扩展提供。该指令有望被纳入C26标准目前作为 Clang 扩展提供。实现中仍有一些问题需要解决。开发者 Maria 已创建相关标签来跟踪这些问题。如果你希望跟进开发或参与贡献可以关注这些进展。总结本节课我们一起学习了 Clang 中的#embed指令。我们了解了它作为一种可移植数据嵌入方式的基本概念通过性能对比看到了其相对于传统“朴素”方法的巨大优势。我们深入探讨了其实现机制包括在unsigned char数组下的字符串字面量优化以及在通用情况下使用的EmbedExprAST 节点。最后我们回顾了该指令在 Clang 和 C/C 标准中的当前状态与未来展望。#embed指令为在代码中嵌入资源提供了一种高效、标准化的解决方案。https://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/d2edd3ff34534151022445c701563bbd_2.pnghttps://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/d2edd3ff34534151022445c701563bbd_2.pnghttps://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/d2edd3ff34534151022445c701563bbd_3.pnghttps://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/d2edd3ff34534151022445c701563bbd_3.png055理解LLVM_ENABLE_PROJECTS与LLVM_ENABLE_RUNTIMES️https://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/9ad5d6c7edc4e953486b0f7c60db432c_0.png在本节课中我们将要学习LLVM构建系统中两个核心配置选项的区别LLVM_ENABLE_PROJECTS和LLVM_ENABLE_RUNTIMES。理解它们的差异是正确构建编译器及其运行时库的基础。LLVM_ENABLE_PROJECTS的工作方式LLVM_ENABLE_PROJECTS使用CMake在配置阶段检测到的编译器。这个编译器通常是系统默认的GCC。它主要用于为主机架构构建编译器本身如Clang。理论上你也可以指定一个交叉编译器来构建编译器。公式-DLLVM_ENABLE_PROJECTSclang它的工作流程是标准的CMake递归构建会进入源码的子目录进行构建。LLVM_ENABLE_RUNTIMES的工作方式与LLVM_ENABLE_PROJECTS不同LLVM_ENABLE_RUNTIMES使用之前通过LLVM_ENABLE_PROJECTS构建好的Clang编译器来构建运行时库本身。这些运行时库是供编译出的代码例如由你构建的Clang编译的程序使用的目标平台可能与构建Clang的主机平台不同。公式-DLLVM_ENABLE_RUNTIMEScompiler-rt -DLLVM_ENABLE_PROJECTSclang它的实现机制更特殊CMake会创建一些“虚拟”目标并为每个目标调用LLVMExternalProject_Add。这会在你的构建目录通常是build/runtimes/runtimes-bins内部启动一个全新的CMake构建过程。这意味着运行时库的构建发生在CMake的“构建”步骤而非“配置”步骤并且会确保所有依赖如Clang、FileCheck等工具先被构建完成。上一节我们介绍了两个核心构建选项的基本概念本节中我们来看看在使用LLVM_ENABLE_RUNTIMES时的一些高级配置选项。运行时构建的配置选项有一些不太被宣传的选项可以传递给运行时库的构建过程。这通过-DCMAKE_C_FLAGS_FOR_RUNTIMES等变量实现。以下是几个关键选项传递编译器标志例如使用-DCMAKE_CXX_FLAGS_FOR_RUNTIMES-ferror-limit5。注意用于构建运行时的Clang可能不接受与构建编译器时完全相同的标志例如-fmax-errors对应-ferror-limit。指定交叉编译目标使用-DRUNTIMES_TARGETSaarch64-unknown-linux-gnu。你还可以通过-DCMAKE_C_FLAGS_TARGET等为特定目标指定优化选项。独立构建你可以进行独立构建此时可以使用任何编译器如GCC来编译运行时库。这需要你将源码顶层目录指定为runtimes并设置-DCMAKE_C_COMPILERgcc。理解了通用运行时构建机制后本节我们来看看Flang运行时flang-rt原有的构建方式及其存在的问题。Flang运行时的原有构建方式与挑战Flang运行时之前有两种构建方式“内联”构建进入源码子目录使用与构建Flang编译器相同的编译器进行构建。独立构建使用不同的顶层目录并指定已构建好的LLVM/Clang路径和所需的编译器。原有方式存在一个显著问题十进制库decimal library同时被Flang运行时和编译器本身共享使用。这导致如果运行时为了支持CUDA而用NVCC编译那么Flang编译器可执行文件也会依赖CUDA库。这是需要改变的一个原因以使Flang运行时与其他LLVM运行时保持一致。此外还有以下挑战多目标支持例如为AMD GPU编译时需要为每个主机架构x86 AArch64等分别构建运行时过程繁琐。共享代码的依赖共享的libdecimal代码带来了问题因为编译运行时和编译编译器本身可能对编译环境有不同要求例如LTO支持。环境依赖某些功能如128位浮点支持的测试依赖于构建Flang的主机平台环境而非最终运行代码的目标平台这可能导致可移植性问题。上一节我们分析了原有构建方式的问题本节中我们来看看如何将Flang运行时集成到统一的LLVM_ENABLE_RUNTIMES框架中。集成到LLVM_ENABLE_RUNTIMES的改动核心改动是让Flang运行时能够使用LLVM现有的运行时构建系统。主要构建方式使用-DLLVM_ENABLE_RUNTIMESflang-rt。这种方式会使用已构建的Clang来编译Flang运行时。代码示例cmake-DLLVM_ENABLE_PROJECTSclang;flang-DLLVM_ENABLE_RUNTIMESflang-rt...独立构建的支持独立构建仍然被支持。你需要将顶层目录设为runtimes并指定LLVM的路径。一个特殊之处在于由于此时还没有运行时库CMake检测编译器能力时会失败。因此我们需要像Clang自举构建一样告诉CMake忽略链接检查假设编译器可以工作。在集成过程中需要进行一系列重构来解决问题并保持一致性。本节我们将介绍这些具体的重构工作。重构与待解决的问题为了成功集成我们进行了以下关键重构库重命名遵循LLVM运行时库的命名约定如libclang_rt.component将Flang运行时库进行了重命名。十进制库libdecimal被集成到运行时中用户无需关心编译器与运行时的内部代码结构。源码与头文件分离我们清晰地分离了仅用于运行时的代码和仅用于编译器的代码特别是处理了那些混合两者的头文件。共享库支持使Flang运行时的共享库构建方式与其他LLVM运行时保持一致。尽管取得了进展仍有一些复杂问题待解决Fortran模块支持让Fortran模块也能使用运行时构建系统。多目标构建的复杂性同时为多个目标环境构建运行时非常复杂目前尚未实现。Windows支持Windows平台总有特殊之处需要处理。实验性CUDA支持使用NVCC编译运行时的实验性功能。https://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/9ad5d6c7edc4e953486b0f7c60db432c_2.pnghttps://github.com/OpenDocCN/cs-notes-pt1-zh/raw/master/docs/llvmcon-eu-2025/img/9ad5d6c7edc4e953486b0f7c60db432c_3.png本节课中我们一起学习了LLVM构建系统中LLVM_ENABLE_PROJECTS与LLVM_ENABLE_RUNTIMES的核心区别深入探讨了Flang运行时从原有特殊构建方式集成到统一运行时构建框架的过程、所做的重构以及面临的剩余挑战。掌握这些知识有助于你更灵活、正确地构建LLVM工具链及其组件。