+
+

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

+
+

1. LLVM 简介

+

LLVM 是一个开源的编译器基础架构,最初由 Chris Lattner 于 2000 年在伊利诺伊大学开发,后来成为一个广泛应用于编译器和程序分析的项目。

+

LLVM 的核心组件:

+
    +
  • +

    LLVM Core Libraries:提供用于编译器开发的核心工具集,包括代码生成、优化、目标机器描述等。

    +
  • +
  • +

    Clang:一个基于 LLVM 的 C、C++、Objective-C 编译器前端。

    +
  • +
  • +

    LLVM IR(Intermediate Representation):一种类似汇编的中间表示语言,是 LLVM 的核心抽象。代码在编译过程中先被转换为 LLVM IR,随后进行各种优化,再生成目标机器码。

    +
  • +
  • +

    LLVM Optimizer:对 LLVM IR 进行各种优化,如循环优化、内联展开等,以提升性能。

    +
  • +
  • +

    LLVM Code Generator:将优化后的 LLVM IR 转换为特定平台的机器码。

    +
  • +
  • +

    Linker:LLVM 也包含了一些链接器工具(如 LLD),用于将编译好的目标文件链接成可执行文件或库。

    +
  • +
+

LLVM 的优势:

+
    +
  • +

    模块化设计:可用于多种语言的编译器开发(如 Rust、Swift)。

    +
  • +
  • +

    跨平台支持:支持多种处理器架构(如 x86、ARM、RISC-V)。

    +
  • +
  • +

    高度优化:提供丰富的优化技术,帮助生成更高效的机器码。

    +
  • +
  • +

    动态编译支持:适用于 JIT(即时编译),如 WebAssembly 和 Swift 的 REPL 环境。

    +
  • +
+

LLVM 官网:https://llvm.org/

+

Getting Started with LLVM Core Libraries(中文版)

+

2. 下载 LLVM

+

在 Android NDK 中,LLVM/Clang 是默认的编译器。自 Android NDK r18 开始,Google 弃用了 GCC,全面转向使用 LLVM/Clang 作为 NDK 的编译工具链。

+

这意味着:

+
    +
  • +

    Clang 作为 C/C++ 的编译前端:替代了 GCC,负责将 C/C++ 代码编译为 LLVM IR。

    +
  • +
  • +

    LLVM IR 优化和代码生成:LLVM 对中间表示进行优化,并生成适合 Android 设备(如 ARM、ARM64、x86、x86_64)的机器码。

    +
  • +
  • +

    LLD 链接器:NDK 还默认使用了 LLD 作为链接器,提高了链接速度。

    +
  • +
+

NDK 中 LLVM 所在路径 +截图.png

+

查看 clang 版本,这里版本是 18.0.2

+
(base) PS D:\App\android\sdk\ndk\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\bin> ./clang --version
+
+Android (12285214, based on r522817b) clang version 18.0.2 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
+Target: x86_64-w64-windows-gnu
+Thread model: posix
+InstalledDir: D:/App/android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/windows-x86_64/bin
+

LLVM 下载:https://releases.llvm.org/ +image.png

+

通过下面命令,把 llvm 18.1.8 版本源码下载到本地

+
git clone --depth 1 --branch llvmorg-18.1.8 https://github.com/llvm/llvm-project.git
+

3. LLVM 项目介绍

+
llvm-project/
+├── .clang-tidy                 # Clang-Tidy 配置文件,用于代码静态分析和代码质量检查
+├── .gitattributes              # Git 属性配置文件,控制文件的检查、合并和不同平台的换行符设置
+├── .git-blame-ignore-revs      # Git blame 忽略特定提交,用于排除格式化提交的影响
+├── .gitignore                  # Git 忽略文件配置,定义哪些文件和目录不应纳入版本控制
+├── .mailmap                    # Git 邮件映射文件,用于规范化提交者的邮箱地址
+├── CODE_OF_CONDUCT.md          # 社区行为规范,规定贡献者的行为守则
+├── CONTRIBUTING.md             # 贡献指南,介绍如何为项目做贡献
+├── LICENSE.TXT                 # 项目开源许可证,通常为 Apache License 2.0
+├── README.md                   # 项目简介和快速入门指南
+├── SECURITY.md                 # 安全报告流程,说明如何报告安全漏洞
+├── .ci                         # 持续集成相关配置文件
+├── .github                     # GitHub 特定文件(如 issue 模板、pull request 模板、CI 配置等)
+
+├── bolt                        # BOLT (Binary Optimization and Layout Tool),用于对二进制文件进行优化和布局调整
+├── clang                       # Clang 编译器前端,支持 C、C++、Objective-C 等语言
+├── clang-tools-extra           # Clang 相关的额外工具,如 clang-tidy、clangd、include-fixer 等
+├── cmake                       # CMake 模块和工具,辅助构建 LLVM 项目
+├── compiler-rt                 # 运行时库,包括 AddressSanitizer、ThreadSanitizer、UBSan 等
+├── cross-project-tests         # 跨项目测试,确保各个子项目在一起工作时的兼容性
+├── flang                       # Fortran 编译器前端,将 Fortran 代码编译为 LLVM IR
+├── libc                        # LLVM 实现的标准 C 库 (libc),专为高性能场景设计
+├── libclc                      # OpenCL C 标准库实现,主要用于 GPU 计算
+├── libcxx                      # LLVM 的 C++ 标准库实现(如 `<iostream>`、`<vector>`)
+├── libcxxabi                   # C++ ABI 支持库,用于异常处理和 RTTI(运行时类型识别)
+├── libunwind                   # 轻量级栈展开库,用于实现异常处理时的栈展开功能
+├── lld                         # LLVM 项目的高效链接器,替代 GNU ld
+├── lldb                        # LLVM 调试器,类似于 GDB,支持调试 C、C++、Swift 等语言
+├── llvm                        # LLVM 核心库,包括 IR 生成、优化和代码生成
+├── llvm-libgcc                 # 提供 GCC 兼容的库(如 `__builtin` 函数的实现)
+├── mlir                        # 多层次中间表示(MLIR),用于 DSL 和机器学习编译器开发
+├── openmp                      # OpenMP 运行时库,支持并行编程
+├── polly                       # LLVM 的循环优化器,用于自动并行化和矢量化
+├── pstl                        # 并行 STL(C++ 标准模板库)实现,提升算法性能
+├── runtimes                    # 各种运行时库的集合(如 libc、libc++、compiler-rt)
+├── third-party                 # 第三方依赖库,如 googletest(用于单元测试)
+├── utils                       # 辅助工具和脚本(如更新文档、构建脚本等)
+
+├── .arcconfig                  # Phabricator 配置文件,用于项目代码审查
+├── .arclint                    # Phabricator Lint 配置文件,用于代码风格检查
+├── .clang-format              # Clang-Format 配置文件,用于统一代码风格
+

4. 编译 LLVM

+

Getting Started with the LLVM System:https://llvm.org/docs/GettingStarted.html

+

下载并安装必需的软件 +image.png +比如,我这里是 Windows 11,先安装 Visual Studio

+

安装 Python 依赖项

+
pip install pygments pyyaml
+

搜索 “x64 Native Tools Command Prompt for VS”(这个工具默认配置 64 位环境) +截图.png

+

创建构建目录

+
cd D:\Projects\llvm-project
+
+mkdir build
+

进入 build 目录,并检测 cmake 和 ninja 是否能正常运行

+
**********************************************************************
+** Visual Studio 2022 Developer Command Prompt v17.12.0
+** Copyright (c) 2022 Microsoft Corporation
+**********************************************************************
+[vcvarsall.bat] Environment initialized for: 'x64'
+
+D:\App\VisualStudio\IDE>cd D:\Projects\llvm-project\build
+
+D:\Projects\llvm-project\build>cmake --version
+cmake version 3.29.5-msvc4
+
+CMake suite maintained and supported by Kitware (kitware.com/cmake).
+
+D:\Projects\llvm-project\build>ninja --version
+1.12.1
+

运行 CMake 配置

+
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="/utf-8" -DLLVM_ENABLE_PROJECTS="clang" ../llvm
+

可选的构建类型说明:

+
    +
  • +

    Release: 生成优化后的构建,无断言和调试信息。适合用于发布。

    +
  • +
  • +

    Debug: 生成未优化的构建,包含断言和调试信息。适合用于调试。

    +
  • +
  • +

    RelWithDebInfo: 生成优化后的构建,无断言,但包含调试信息。适合需要调试符号但仍然希望性能接近 Release 的情况。

    +
  • +
  • +

    MinSizeRel: 生成针对最小尺寸优化的构建,而非速度优化。适合用于空间受限的环境。

    +
  • +
+

编译项目

+
ninja
+

编译完成后大概 104GB +image.png

+

编译成功后,你可以验证 clang 或其他工具是否已正确生成

+
D:\Projects\llvm-project\build\bin\clang --version
+

image.png

+

5. 解决编译报错

+

5.1 编码警告 (warning C4819)

+
[94/3656] Building CXX object lib\Support\CMakeFiles\LLVMSupport.dir\Parallel.cpp.obj
+D:\Projects\llvm-project\llvm\lib\Support\Parallel.cpp(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[300/3656] Building CXX object lib\BinaryFormat\CMakeFiles\LLVMBinaryFormat.dir\ELF.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[306/3656] Building CXX object lib\BinaryFormat\CMakeFiles\LLVMBinaryFormat.dir\DXContainer.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm/BinaryFormat/DXContainer.h(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符 。请将该文件保存为 Unicode 格式以防止数据丢失
+[347/3656] Building CXX object lib\IR\CMakeFiles\LLVMCore.dir\DebugInfo.cpp.obj
+D:\Projects\llvm-project\llvm\lib\IR\DebugInfo.cpp(1504): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存 为 Unicode 格式以防止数据丢失
+[396/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\DXContainerPSVInfo.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm/BinaryFormat/DXContainer.h(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符 。请将该文件保存为 Unicode 格式以防止数据丢失
+[404/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCAsmBackend.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[411/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\ELFObjectWriter.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[415/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCAsmInfoELF.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[418/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCELFObjectTargetWriter.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[424/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCDXContainerWriter.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm/BinaryFormat/DXContainer.h(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符 。请将该文件保存为 Unicode 格式以防止数据丢失
+[427/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCContext.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[428/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCELFStreamer.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[445/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCSectionELF.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[447/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCObjectFileInfo.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[454/3656] Building CXX object lib\MC\CMakeFiles\LLVMMC.dir\MCSymbolELF.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[488/3656] Building CXX object lib\MC\MCParser\CMakeFiles\LLVMMCParser.dir\ELFAsmParser.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[519/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\Decompressor.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[522/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\DXContainer.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm/BinaryFormat/DXContainer.h(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符 。请将该文件保存为 Unicode 格式以防止数据丢失
+D:\Projects\llvm-project\llvm\lib\Object\DXContainer.cpp(344): warning C4018: “<”: 有符号/无符号不匹配
+[526/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\BuildID.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[533/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\ELF.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+D:\Projects\llvm-project\llvm\include\llvm/BinaryFormat/ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[535/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\ELFObjectFile.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[543/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\RelocationResolver.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[546/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\SymbolSize.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[548/3656] Building CXX object lib\Object\CMakeFiles\LLVMObject.dir\OffloadBinary.cpp.obj
+D:\Projects\llvm-project\llvm\include\llvm\BinaryFormat\ELFRelocs/LoongArch.def(1): warning C4819: 该文件包含不能在当前代码页(936)中 表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+[579/3656] Building CXX object lib\DebugInfo\PDB\CMakeFiles\LLVMDebugInfoPDB.dir\PDB.cpp.obj
+FAILED: lib/DebugInfo/PDB/CMakeFiles/LLVMDebugInfoPDB.dir/PDB.cpp.obj
+D:\App\VisualStudio\IDE\VC\Tools\MSVC\14.42.34433\bin\Hostx86\x86\cl.exe  /nologo /TP -DGTEST_HAS_RTTI=0 -DUNICODE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_FILE_OFFSET_BITS=64 -D_HAS_EXCEPTIONS=0 -D_LARGEFILE_SOURCE -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -ID:\Projects\llvm-project\build\lib\DebugInfo\PDB -ID:\Projects\llvm-project\llvm\lib\DebugInfo\PDB -ID:\Projects\llvm-project\build\include -ID:\Projects\llvm-project\llvm\include -external:I"D:\App\VisualStudio\IDE\DIA SDK\include" -external:W0 /Zc:inline /Zc:preprocessor /Zc:__cplusplus /Oi /bigobj /permissive- /W4 -wd4141 -wd4146 -wd4244 -wd4267 -wd4291 -wd4351 -wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4100 -wd4127 -wd4512 -wd4505 -wd4610 -wd4510 -wd4702 -wd4245 -wd4706 -wd4310 -wd4701 -wd4703 -wd4389 -wd4611 -wd4805 -wd4204 -wd4577 -wd4091 -wd4592 -wd4319 -wd4709 -wd5105 -wd4324 -w14062 -we4238 -std:c++17 -MDd  /EHs-c- /GR- /showIncludes /Folib\DebugInfo\PDB\CMakeFiles\LLVMDebugInfoPDB.dir\PDB.cpp.obj /Fdlib\DebugInfo\PDB\CMakeFiles\LLVMDebugInfoPDB.dir\LLVMDebugInfoPDB.pdb /FS -c D:\Projects\llvm-project\llvm\lib\DebugInfo\PDB\PDB.cpp
+

这些警告表明某些源文件包含在当前代码页(936,即简体中文 GBK 编码)中无法表示的字符。

+

可以通过设置编译器选项 -DCMAKE_CXX_FLAGS="/utf-8" 来避免这些编码问题。

+
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="/utf-8" ../llvm
+

这将告诉 MSVC 编译器以 UTF-8 编码处理所有源文件。

+

5. 2 缺少 atlbase.h 头文件 (fatal error C1083)

+
D:\Projects\llvm-project\llvm\include\llvm\DebugInfo\PDB\DIA\DIASupport.h(25): fatal error C1083: 无法打开包括文件: “atlbase.h”: No such file or directory
+[592/3656] Building CXX object lib\DebugInfo\DWARF\CMakeFiles\LLVMDebugInfoDWARF.dir\DWARFVerifier.cpp.obj
+D:\Projects\llvm-project\llvm\lib\DebugInfo\DWARF\DWARFVerifier.cpp(1513): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失
+ninja: build stopped: subcommand failed.
+

错误信息提示 atlbase.h 头文件无法找到,这通常是因为未安装 ATL/MFC 支持。这是 Visual Studio 的可选组件,默认情况下可能未安装。

+

解决方法:

+
    +
  • +

    打开 Visual Studio Installer

    +
  • +
  • +

    修改 Visual Studio 安装

    +
  • +
  • +

    添加 ATL/MFC 支持

    +
  • +
+

image.png

+

安装完成后,再次运行 ninja 重新编译

+

5.3 LLVM ERROR: out of memory

+
[1/281] Building RISCVGenDAGISel.inc...
+FAILED: lib/Target/RISCV/RISCVGenDAGISel.inc D:/Projects/llvm-project/build/lib/Target/RISCV/RISCVGenDAGISel.inc
+C:\Windows\system32\cmd.exe /C "cd /D D:\Projects\llvm-project\build && D:\Projects\llvm-project\build\bin\llvm-tblgen.exe -gen-dag-isel -I D:/Projects/llvm-project/llvm/lib/Target/RISCV -ID:/Projects/llvm-project/build/include -ID:/Projects/llvm-project/llvm/include -I D:/Projects/llvm-project/llvm/lib/Target --long-string-literals=0 D:/Projects/llvm-project/llvm/lib/Target/RISCV/RISCV.td --write-if-changed -o lib/Target/RISCV/RISCVGenDAGISel.inc -d lib/Target/RISCV/RISCVGenDAGISel.inc.d"
+LLVM ERROR: out of memory
+Allocation failed
+PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
+Stack dump:
+0\.      Program arguments: D:\\Projects\\llvm-project\\build\\bin\\llvm-tblgen.exe -gen-dag-isel -I D:/Projects/llvm-project/llvm/lib/Target/RISCV -ID:/Projects/llvm-project/build/include -ID:/Projects/llvm-project/llvm/include -I D:/Projects/llvm-project/llvm/lib/Target --long-string-literals=0 D:/Projects/llvm-project/llvm/lib/Target/RISCV/RISCV.td --write-if-changed -o lib/Target/RISCV/RISCVGenDAGISel.inc -d lib/Target/RISCV/RISCVGenDAGISel.inc.d
+Exception Code: 0x80000003
+ #0 0x0104f4e9 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x2af4e9)
+ #1 0x6a4528b4 (C:\Windows\SYSTEM32\ucrtbased.dll+0xc28b4)
+ #2 0x6a453ed2 (C:\Windows\SYSTEM32\ucrtbased.dll+0xc3ed2)
+ #3 0x010075ca (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x2675ca)
+ #4 0x01007e3f (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x267e3f)
+ #5 0x6a566608 (C:\Windows\SYSTEM32\MSVCP140D.dll+0x26608)
+ #6 0x6a43fb72 (C:\Windows\SYSTEM32\ucrtbased.dll+0xafb72)
+ #7 0x01112357 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x372357)
+ #8 0x00db004c (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1004c)
+ #9 0x00daa176 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0xa176)
+#10 0x00daa06f (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0xa06f)
+#11 0x00db0e69 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x10e69)
+#12 0x00daa0a1 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0xa0a1)
+#13 0x00daa135 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0xa135)
+#14 0x00dac0c7 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0xc0c7)
+#15 0x00db103b (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1103b)
+#16 0x0102c922 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x28c922)
+#17 0x01009a87 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x269a87)
+#18 0x01008d00 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x268d00)
+#19 0x00da66da (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x66da)
+#20 0x00da6694 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x6694)
+#21 0x00eba51f (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x11a51f)
+#22 0x00eb90b8 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1190b8)
+#23 0x00ebb1d4 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x11b1d4)
+#24 0x00eb90b8 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1190b8)
+#25 0x00eba414 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x11a414)
+#26 0x00eb90b8 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1190b8)
+#27 0x00ebb1d4 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x11b1d4)
+#28 0x00eb90b8 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1190b8)
+#29 0x00eb87ca (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1187ca)
+#30 0x00eb65a0 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x1165a0)
+#31 0x00eb6a07 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x116a07)
+#32 0x010e06a8 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x3406a8)
+#33 0x00fe7d1a (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x247d1a)
+#34 0x01113143 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x373143)
+#35 0x0111304a (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x37304a)
+#36 0x01112eed (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x372eed)
+#37 0x011131a8 (D:\Projects\llvm-project\build\bin\llvm-tblgen.exe+0x3731a8)
+#38 0x77507ba9 (C:\Windows\System32\KERNEL32.DLL+0x17ba9)
+#39 0x77dac0cb (C:\Windows\SYSTEM32\ntdll.dll+0x6c0cb)
+#40 0x77dac04f (C:\Windows\SYSTEM32\ntdll.dll+0x6c04f)
+ninja: build stopped: subcommand failed.
+

如果你使用的是 32 位编译环境(工具链或 llvm-tblgen.exe),它可能受到 2GB 内存使用限制。

+

通过下面命令验证是否生成 64 位可执行文件

+
D:\Projects\llvm-project\build>dumpbin /headers D:\Projects\llvm-project\build\bin\llvm-tblgen.exe | findstr machine
+             14C machine (x86)
+                   32 bit word machine
+

如果不是,搜索 “x64 Native Tools Command Prompt for VS”(这个工具默认配置 64 位环境) +image.png

+

验证当前编译器配置,输出中应包含 x64,表示 64 位环境已成功配置。

+
**********************************************************************
+** Visual Studio 2022 Developer Command Prompt v17.12.0
+** Copyright (c) 2022 Microsoft Corporation
+**********************************************************************
+[vcvarsall.bat] Environment initialized for: 'x64'
+
+D:\App\VisualStudio\IDE>cl
+用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.42.34433 版
+版权所有(C) Microsoft Corporation。保留所有权利。
+
+用法: cl [ 选项... ] 文件名... [ /link 链接选项... ]
+
+D:\Projects\llvm-project\build>where cl.exe
+D:\App\VisualStudio\IDE\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\cl.exe
+

清理之前的缓存,重新生成构建目录

+
rmdir /s /q build
+
+mkdir build
+
+cd build
+

最后,重新生成配置和编译。

+

5.4 LNK1104: 无法打开文件“tools\llvm-nm\CMakeFiles\llvm-nm.dir/intermediate.manifest”

+
[3117/3660] Linking CXX executable bin\llvm-nm.exe
+FAILED: bin/llvm-nm.exe
+C:\Windows\system32\cmd.exe /C "cd . && D:\App\VisualStudio\IDE\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe -E vs_link_exe --intdir=tools\llvm-nm\CMakeFiles\llvm-nm.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- D:\App\VisualStudio\IDE\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\llvm-nm.rsp  /out:bin\llvm-nm.exe /implib:lib\llvm-nm.lib /pdb:bin\llvm-nm.pdb /version:0.0 /machine:x64 /STACK:10000000 /debug /INCREMENTAL /subsystem:console && cd ."
+FINAL LINK: command "D:\App\VisualStudio\IDE\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\llvm-nm.rsp /out:bin\llvm-nm.exe /implib:lib\llvm-nm.lib /pdb:bin\llvm-nm.pdb /version:0.0 /machine:x64 /STACK:10000000 /debug /INCREMENTAL /subsystem:console /MANIFEST /MANIFESTFILE:tools\llvm-nm\CMakeFiles\llvm-nm.dir/intermediate.manifest tools\llvm-nm\CMakeFiles\llvm-nm.dir/manifest.res" failed (exit code 1104) with the following output:
+LINK : fatal error LNK1104: 无法打开文件“tools\llvm-nm\CMakeFiles\llvm-nm.dir/intermediate.manifest”
+[3130/3660] Building CXX object tools\llvm-exegesis\lib\CMakeFiles\LLVMExegesis.dir\UopsBenchmarkRunner.cpp.obj
+ninja: build stopped: subcommand failed.
+

查看 tools\llvm-nm\CMakeFiles\llvm-nm.dir/intermediate.manifest 文件是存在的而且也能正常打开,重新执行 ninja 命令再编译一遍试试。 +image.png

+

接下来报错 LNK1104: 无法打开文件“bin\llvm-rc.exe”

+
[297/531] Linking CXX executable bin\llvm-rc.exe
+FAILED: bin/llvm-rc.exe
+C:\Windows\system32\cmd.exe /C "cd . && D:\App\VisualStudio\IDE\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe -E vs_link_exe --intdir=tools\llvm-rc\CMakeFiles\llvm-rc.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100226~1.0\x64\mt.exe --manifests  -- D:\App\VisualStudio\IDE\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\link.exe /nologo tools\llvm-rc\CMakeFiles\llvm-rc.dir\llvm-rc.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceFileWriter.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptCppFilter.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptParser.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptStmt.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptToken.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\llvm-rc-driver.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\__\__\resources\windows_version_resource.rc.res  /out:bin\llvm-rc.exe /implib:lib\llvm-rc.lib /pdb:bin\llvm-rc.pdb /version:0.0 /machine:x64 /STACK:10000000 /debug /INCREMENTAL /subsystem:console  lib\LLVMObject.lib  lib\LLVMOption.lib  lib\LLVMSupport.lib  lib\LLVMTargetParser.lib  lib\LLVMIRReader.lib  lib\LLVMBitReader.lib  lib\LLVMAsmParser.lib  lib\LLVMCore.lib  lib\LLVMRemarks.lib  lib\LLVMBitstreamReader.lib  lib\LLVMMCParser.lib  lib\LLVMMC.lib  lib\LLVMDebugInfoCodeView.lib  lib\LLVMTextAPI.lib  lib\LLVMBinaryFormat.lib  lib\LLVMTargetParser.lib  lib\LLVMSupport.lib  psapi.lib  shell32.lib  ole32.lib  uuid.lib  advapi32.lib  ws2_32.lib  delayimp.lib  -delayload:shell32.dll  -delayload:ole32.dll  lib\LLVMDemangle.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
+FINAL LINK: command "D:\App\VisualStudio\IDE\VC\Tools\MSVC\14.42.34433\bin\Hostx64\x64\link.exe /nologo tools\llvm-rc\CMakeFiles\llvm-rc.dir\llvm-rc.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceFileWriter.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptCppFilter.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptParser.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptStmt.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\ResourceScriptToken.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\llvm-rc-driver.cpp.obj tools\llvm-rc\CMakeFiles\llvm-rc.dir\__\__\resources\windows_version_resource.rc.res /out:bin\llvm-rc.exe /implib:lib\llvm-rc.lib /pdb:bin\llvm-rc.pdb /version:0.0 /machine:x64 /STACK:10000000 /debug /INCREMENTAL /subsystem:console lib\LLVMObject.lib lib\LLVMOption.lib lib\LLVMSupport.lib lib\LLVMTargetParser.lib lib\LLVMIRReader.lib lib\LLVMBitReader.lib lib\LLVMAsmParser.lib lib\LLVMCore.lib lib\LLVMRemarks.lib lib\LLVMBitstreamReader.lib lib\LLVMMCParser.lib lib\LLVMMC.lib lib\LLVMDebugInfoCodeView.lib lib\LLVMTextAPI.lib lib\LLVMBinaryFormat.lib lib\LLVMTargetParser.lib lib\LLVMSupport.lib psapi.lib shell32.lib ole32.lib uuid.lib advapi32.lib ws2_32.lib delayimp.lib -delayload:shell32.dll -delayload:ole32.dll lib\LLVMDemangle.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:tools\llvm-rc\CMakeFiles\llvm-rc.dir/intermediate.manifest tools\llvm-rc\CMakeFiles\llvm-rc.dir/manifest.res" failed (exit code 1104) with the following output:
+LINK : fatal error LNK1104: 无法打开文件“bin\llvm-rc.exe”
+[310/531] Generating export list for LLVM-C
+ninja: build stopped: subcommand failed.
+

再次执行 ninja 命令编译,接下来的 LNK1104 报错同理。 +image.png

+

6. clang 编译 hello world

+

执行下面命令把 bin 目录配置到环境变量

+
set PATH=%PATH%;D:\Projects\llvm-project\build\bin
+

编写 hello.c 源码

+
#include <stdio.h>
+
+int main() {
+    printf("Hello, World!\n");
+    return 0;
+}
+

执行下面命令把 hello.c 编译成可执行程序

+
clang hello.c -o hello.exe
+

执行 hello.exe +image.png

+

7. 使用 CLion 调试 clang

+

7.1 导入项目

+

使用 CLion 打开 llvm-project\clang\CMakeLists.txt +image.png

+

作为项目打开 +image.png

+

7.2 设置 LLVM_DIR

+

执行 CMake 报错如下

+
CMake Error at CMakeLists.txt:31 (find_package):
+  Could not find a package configuration file provided by "LLVM" with any of
+  the following names:
+
+    LLVMConfig.cmake
+    llvm-config.cmake
+
+  Add the installation prefix of "LLVM" to CMAKE_PREFIX_PATH or set
+  "LLVM_DIR" to a directory containing one of the above files.  If "LLVM"
+  provides a separate development package or SDK, be sure it has been
+  installed.
+
+
+-- Configuring incomplete, errors occurred!
+

这因为 Clang 依赖于已构建的 LLVM 库。如果你之前已经成功构建了 LLVM,你需要告知 CMake 该文件的位置。

+

打开 CMake 设置,在 CMake Options 字段中,添加以下配置

+
-DLLVM_DIR="D:/Projects/llvm-project/build/lib/cmake/llvm"
+

或者

+
-DCMAKE_PREFIX_PATH="D:/Projects/llvm-project/build"
+

这会告知 CMake 在构建项目时去哪里寻找 LLVM 库。

+

点击应用,重新执行 cmake +image.png

+

7.3 禁用 llvm-gtest

+

接着报错如下

+
CMake Error at CMakeLists.txt:117 (message):
+  llvm-gtest not found.  Please install llvm-gtest or disable tests with
+  -DLLVM_INCLUDE_TESTS=OFF
+
+
+-- Configuring incomplete, errors occurred!
+

这个错误表明 CMake 在配置 LLVM 项目时找不到 llvm-gtest,因此无法继续。

+

不需要运行测试,可以通过设置 LLVM_INCLUDE_TESTS=OFF 来跳过测试模块。

+
-DLLVM_INCLUDE_TESTS=OFF
+

在 CMake Options 字段中,添加禁用测试选项 +image.png

+

cmake 执行成功后,可以看到 clang 项目所有的运行/调试配置 +image.png

+

7.4 配置调试信息

+

编辑 clang 调试配置 +image.png

+

添加 Program arguments,比如

+
"D:\Projects\llvm-project\build\hello.c" -o "D:\Projects\llvm-project\build\hello.exe"
+

找到 main 函数(clang/tools/driver/driver.cpp),并下断点 +截图.png

+

7.5 切换 Visual Studio 工具链

+

运行调试 clang,但是报错如下

+
D:/Projects/llvm-project/llvm/include/llvm/ADT/SmallVector.h:304: undefined reference to `llvm::SmallVectorBase<unsigned int>::size() const'
+
+D:/Projects/llvm-project/llvm/include/llvm/Support/CommandLine.h:783: undefined reference to `llvm::cl::generic_parser_base::printGenericOptionDiff(llvm::cl::Option const&, llvm::cl::GenericOptionValue const&, llvm::cl::GenericOptionValue const&, unsigned long long) const'
+
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl11OptionValueINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE[.refptr._ZTVN4llvm2cl11OptionValueINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE]+0x0): undefined reference to `vtable for llvm::cl::OptionValue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm23PrettyStackTraceProgramE[.refptr._ZTVN4llvm23PrettyStackTraceProgramE]+0x0): undefined reference to `vtable for llvm::PrettyStackTraceProgram'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl6parserINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE[.refptr._ZTVN4llvm2cl6parserINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE]+0x0): undefined reference to `vtable for llvm::cl::parser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl12basic_parserINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE[.refptr._ZTVN4llvm2cl12basic_parserINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEE]+0x0): undefined reference to `vtable for llvm::cl::basic_parser<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl17basic_parser_implE[.refptr._ZTVN4llvm2cl17basic_parser_implE]+0x0): undefined reference to `vtable for llvm::cl::basic_parser_impl'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl19generic_parser_baseE[.refptr._ZTVN4llvm2cl19generic_parser_baseE]+0x0): undefined reference to `vtable for llvm::cl::generic_parser_base'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl18GenericOptionValueE[.refptr._ZTVN4llvm2cl18GenericOptionValueE]+0x0): undefined reference to `vtable for llvm::cl::GenericOptionValue'
+D:\App\CLion 2024.2.3\bin\mingw\bin/ld.exe: utils/TableGen/CMakeFiles/clang-tblgen.dir/TableGen.cpp.obj:TableGen.cpp:(.rdata$.refptr._ZTVN4llvm2cl6OptionE[.refptr._ZTVN4llvm2cl6OptionE]+0x0): undefined reference to `vtable for llvm::cl::Option'
+collect2.exe: error: ld returned 1 exit status
+ninja: build stopped: subcommand failed.
+

这个错误信息表明在使用 MinGW 编译 LLVM 时,链接器找不到某些 LLVM 函数和虚表(vtable)的定义。

+

默认是使用 MinGW 编译器来编译 LLVM。LLVM 通常更适合使用 MSVC(Microsoft Visual C++)编译器在 Windows 上进行编译。

+

切换到 MSVC 编译器,应该能解决 undefined reference 的链接错误。

+

打开 Visual Studio Installer,确认已经安装 MSVC +image.png

+

在设置窗口中,导航到 Build, Execution, Deployment > Toolchains。添加新的 toolchain,选择 Visual Studio,工具集选择 VisualStudio\IDE 目录,等待工具检测完毕点击应用。 +截图.png +参考:https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#MSVC

+

修改 Cmake 配置,工具链选择 Visual Studio +截图.png

+

重新运行调试 clang +image.png

+ +