pkg-config 是最可靠的路径查询方式,它能准确返回 LLVM 头文件(如 /usr/lib/llvm-17/include)和库路径(如 -L/usr/lib/llvm-17/lib -lLLVM-17),避免硬猜路径出错;且需注意头文件包含路径须完整(如 #include "llvm/IR/IRBuilder.h"),并确保 -I 与 -L 同时生效。

pkg-config 能查到的路径最可靠
很多发行版安装 llvm-dev(Ubuntu/Debian)或 llvm-devel(RHEL/Fedora)后,头文件和库不会直接落在 /usr/include 或 /usr/lib 下,而是按版本号隔离存放,比如 /usr/lib/llvm-17。硬猜路径容易出错,pkg-config 是官方推荐的查询方式。
运行以下命令可一次性拿到编译和链接所需的所有参数:
pkg-config --cflags llvm pkg-config --libs llvm
常见返回示例(以 LLVM 17 为例):
-
pkg-config --cflags llvm→-I/usr/lib/llvm-17/include -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -
pkg-config --libs llvm→-L/usr/lib/llvm-17/lib -lLLVM-17
注意:-lLLVM-17 中的版本号必须与实际安装一致;若系统装了多个 LLVM 版本,pkg-config 默认指向最新版,也可显式指定:PKG_CONFIG_PATH=/usr/lib/llvm-16/lib/pkgconfig pkg-config --cflags llvm。
include/llvm 目录结构不是 flat 的
头文件不是全扔在 /usr/lib/llvm-xx/include 根下——那是 CMake 生成的配置头(如 llvm/Config/llvm-config.h),真正要用的 API 头都在子目录里,比如:
-
llvm/IR/IRBuilder.h:构建 IR 的核心类 -
llvm/Pass.h:自定义 Pass 必须继承的基类 -
llvm/Support/raw_ostream.h:调试输出用的流封装
所以 -I/usr/lib/llvm-17/include 是必要但不充分的;你还得确保代码里 #include 路径写对,例如不能写成 #include "IRBuilder.h",而必须是 #include "llvm/IR/IRBuilder.h"。C++ 编译器不会自动补前缀。
lib 目录里有 .so 和 .a,但默认链接的是 .so
LLVM 安装后的 lib 目录下通常同时存在 libLLVM-xx.so(共享库)和 libLLVM-xx.a(静态库)。CMake 或 pkg-config --libs 默认给出的是动态链接选项,即 -lLLVM-17,它会找 .so 文件。
如果你需要静态链接(比如打包独立二进制),得手动加 -Wl,-Bstatic -lLLVM-17 -Wl,-Bdynamic,且要注意静态链接时依赖的其他库(如 z、pthread)也得显式列出来,否则链接失败。
另外,某些发行版(如 Ubuntu)把运行时依赖库(libtinfo.so.5、libxml2.so.2)拆到单独的包里,即使 llvm-dev 装好了,运行时仍可能报 cannot open shared object file —— 这时候要装对应的基础运行时包,而不是改 LD_LIBRARY_PATH。
CMakeLists.txt 里 find_package(LLVM) 的坑
用 CMake 构建自己的 LLVM 工具时,别直接写 find_package(LLVM REQUIRED) 就完事。这个命令默认只查找最低版本,不保证你用到的模块(比如 Analysis、Transforms)被启用。
正确做法是:
- 先通过
pkg-config --modversion llvm确认版本 - 在
find_package后立刻调用llvm_map_components_to_libnames显式列出所需组件:find_package(LLVM REQUIRED CONFIG) llvm_map_components_to_libnames(llvm_libs support core irreader)
- 然后
target_link_libraries(your_tool ${llvm_libs})
否则很可能编译通过、链接失败,报一堆 undefined reference,比如 llvm::raw_ostream::operator<< 找不到——那是因为 support 组件没被拉进来。
最容易被忽略的一点:LLVM 的头文件路径和库路径是解耦的,pkg-config 返回的 -I 和 -L 必须同时生效;少一个,要么编译不过,要么链接不过。别指望系统默认路径能兜底。

















