编译 LLVM 源码,使用 Clion 调试 clang

版权归作者所有,如有转发,请注明文章出处: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 所在路径

查看 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/

通过下面命令,把 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

下载并安装必需的软件

比如,我这里是 Windows 11,先安装 Visual Studio

安装 Python 依赖项

pip install pygments pyyaml

搜索 "x64 Native Tools Command Prompt for VS" (这个工具默认配置 64 位环境)

创建构建目录

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

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

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

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 支持

安装完成后,再次运行 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 位环境)

验证当前编译器配置,输出中应包含 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 命令再编译一遍试试。

接下来报错 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 报错同理。

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

7. 使用 CLion 调试 clang

7.1 导入项目

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

作为项目打开

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

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 字段中,添加禁用测试选项

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

7.4 配置调试信息

编辑 clang 调试配置

添加 Program arguments,比如

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

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

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

在设置窗口中,导航到 Build, Execution, Deployment > Toolchains。添加新的 toolchain,选择 Visual Studio,工具集选择 VisualStudio\IDE 目录,等待工具检测完毕点击应用。

参考:https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#MSVC

修改 Cmake 配置,工具链选择 Visual Studio

重新运行调试 clang

相关推荐
a00234500121 分钟前
判断矩阵是否为上三角矩阵
c语言
王老师青少年编程21 分钟前
gesp(二级)(12)洛谷:B3955:[GESP202403 二级] 小杨的日字矩阵
c++·算法·矩阵·gesp·csp·信奥赛
OTWOL1 小时前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法
QQ同步助手2 小时前
C++ 指针进阶:动态内存与复杂应用
开发语言·c++
qq_433554542 小时前
C++ 面向对象编程:递增重载
开发语言·c++·算法
易码智能2 小时前
【EtherCATBasics】- KRTS C++示例精讲(2)
开发语言·c++·kithara·windows 实时套件·krts
一只自律的鸡2 小时前
C语言项目 天天酷跑(上篇)
c语言·开发语言
ཌ斌赋ད2 小时前
FFTW基本概念与安装使用
c++
薄荷故人_3 小时前
从零开始的C++之旅——红黑树封装map_set
c++
悲伤小伞3 小时前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法