apt安装与自编译LLVM的llvm-config输出差异及库结构咨询
LLVM相关问题解答
1. llvm-config输出差异的原因
你观察到的差异并非单纯由静态/动态库类型直接导致,核心是两个编译选项的配置不同:
- apt源分发的LLVM包默认开启了
LLVM_BUILD_LLVM_DYLIB=ON编译选项,会把所有LLVM功能组件统一打包为一个全量集成库,因此llvm-config --libs all只会输出这一个库的链接参数-lLLVM-13。 - 你自编译的版本未开启单库打包,且开启了
BUILD_SHARED_LIBS=ON,每个LLVM组件都会生成独立的共享库,所以输出会展开所有组件对应的独立库名。如果自编译时开启LLVM_BUILD_LLVM_DYLIB=ON,也可以得到和apt版本一致的输出。
2. LLVM整体库结构
LLVM采用分层组件化的库设计,从底层到上层大致分为以下层级:
- 基础支撑层:最底层的通用工具库,包含
LLVMSupport(系统适配、字符串处理、内存管理等基础工具)、LLVMDemangle(符号解析)、LLVMBitstreamReader/LLVMBitWriter(bitcode格式读写)等通用依赖组件。 - IR核心层:以
LLVMCore为核心,包含LLVM IR的定义、创建、遍历、修改接口,是整个LLVM架构的核心基础。 - 分析转换层:包含各类IR分析与优化组件,比如
LLVMAnalysis(各类IR分析接口,包括别名分析、数据流分析等)、LLVMTransformUtils(IR转换通用工具)、LLVMInstCombine/LLVMScalarOpts/LLVMVectorize等不同方向的优化pass库,以及上层的LLVMPasses/LLVMipo等全程序优化组件。 - 通用代码生成层:包含跨架构的通用代码生成框架,比如
LLVMCodeGen(通用代码生成逻辑)、LLVMSelectionDAG(DAG指令选择框架)、LLVMGlobalISel(全局指令选择框架)、LLVMAsmPrinter(汇编输出)等组件。 - 目标架构层:每个支持的硬件架构都有独立的库组,命名规则统一,比如X86架构对应
LLVMX86Info(架构基础信息)、LLVMX86Desc(架构描述)、LLVMX86CodeGen(X86代码生成实现)、LLVMX86Disassembler(反汇编实现),其他架构的库命名逻辑完全一致。 - 上层功能层:包含面向特定场景的功能组件,比如JIT相关的
LLVMExecutionEngine/LLVMOrcJIT、调试信息相关的LLVMDebugInfoDWARF、链接相关的LLVMLinker/LLVMLTO等。
3. add_llvm_executable宏的实现逻辑
这个CMake宏是LLVM封装的编译辅助工具,核心做了三件事:
- 自动引入LLVM预定义的编译选项、头文件搜索路径,避免手动配置出错
- 自动处理指定LLVM组件之间的依赖关系,按正确的依赖顺序生成链接参数,不需要开发者手动梳理所有依赖库的顺序
- 自动适配当前LLVM的编译配置,不管底层是单一大库还是拆分的组件库,都可以生成正确的链接指令,不需要开发者关心底层库的打包方式
4. 参考资料
- LLVM官方文档的架构板块有完整的组件分层说明,每个库的接口定义和作用都可以在官方Doxygen文档中查询到详细说明
- 官方LLVM开发教程中有专门讲解LLVM编译系统和库结构的章节,配套的示例代码可以辅助理解
- 如果需要研究CMake宏的具体实现,可以直接查看LLVM源码目录下
cmake/modules/路径中的LLVM-Config.cmake和AddLLVM.cmake文件,里面包含所有LLVM CMake宏的完整定义,注释非常详尽
内容的提问来源于stack exchange,提问作者LGG
相关产品推荐
相关产品推荐

