ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenEuler源码编译liblz4报错解决:lz4-devel开发包是关键

OpenEuler源码编译liblz4报错解决:lz4-devel开发包是关键 OpenEuler 上做源码编译最烦的往往不是机器卡顿而是 configure 阶段突然被人当头一棒。解压好源码包、信心满满敲下./configure结果没跑几行就报出checking for liblz4... no然后紧跟一行configure: error: Package requirements (liblz4) were not met整个构建直接中止。这种问题在 OpenEuler 服务器上非常典型尤其在编译 QEMU、libvirt、kmod 这类跟虚拟化、存储相关的组件时几乎是绕不开的一道小坎。这个报错看着吓人根子却很简单系统里缺了 liblz4 的开发包。注意是“开发包”不是 lz4 命令本身。很多人第一反应是dnf install lz4装完发现还是同样的报错那是因为装错了包。这篇文章按我自己的实战顺序把这个问题的“为什么”“怎么查”“怎么解”全部拆开讲顺便把 ARM 架构 OpenEuler、虚拟化场景相关的坑也一起说清楚适合正在 OpenEuler 上做源码编译的运维、开发以及被 Package requirements 类报错卡住的新手参考。1. 第一次遇到这个报错configure 在半路上“撂挑子”1.1 先还原一下现场绝大多数见到这个报错的场景都是这样的你从源码构建某个软件进入源码目录后执行./configure屏幕滚动一会儿然后卡住输出大概长这样checking for liblz4... no configure: error: Package requirements (liblz4) were not met: No package liblz4 found Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables LIBLZ4_CFLAGS and LIBLZ4_LIBS to avoid the need to call pkg-config.这一屏信息透露了两点第一configure 在探测名为liblz4的库时没有找到第二它提示你可以调PKG_CONFIG_PATH,也可以强行设LIBLZ4_CFLAGS和LIBLZ4_LIBS绕过检测。可很多新手看到后面两行反而更懵这两个环境变量从哪来设成什么值别急后面逐条说。这个报错本质上不是编译器坏了也不是源码包坏了而是 configure 的依赖探测机制用了 pkg-config而 pkg-config 在系统里找不到liblz4的元数据文件。这时候 configure 宁可停下也不敢带着残缺依赖继续编译。这种“宁可报错也不硬编”的风格是 autotools 生态的默认策略保的是构建过程的稳定和后续运行期的安全。1.2 liblz4 到底是什么“拦路虎”liblz4 是 lz4 压缩算法的 C 语言库接口。lz4 是一个以极快压缩解压速度著称的压缩算法很多底层项目会在可选项里默认带上它。说几个常见场景QEMU 的某些块设备格式、压缩相关特性会依赖 liblz4libvirt 的日志、快照、内存转储功能经常需要 liblz4systemd 的 journal 日志压缩在较新版本里默认倾向用 lz4部分存储中间件、数据库、分布式文件系统客户端也会把 lz4 列为编译依赖。所以你在 OpenEuler 上源码编译这些项目时configure 阶段就多了一道类似开关的检查如果 liblz4 存在就开启相关支持如果不存在还没到“降级编译”这一步很多项目干脆直接报错中止。尤其当你是在构建虚拟化相关组件时这个依赖几乎是必经之路。2. 先搞清楚包的关系lz4 和 lz4-devel 不是一回事2.1 运行库与开发库的分工在 RPM 系 Linux 发行版里一个开源库通常被拆成多个包lz4命令行工具lz4 命令和运行时动态库liblz4.so.1。日常跑程序、用命令压缩文件有这个就够了。lz4-devel编译期需要的头文件例如/usr/include/lz4.h、/usr/include/lz4frame.h以及最关键的文件/usr/lib64/pkgconfig/liblz4.pc。lz4-static静态库liblz4.a一般只有在需要静态链接时才用。configure 检查liblz4时依赖的正是那个.pc文件。它相当于图书馆里的索引卡片记录了这个库的头文件路径、库文件路径、链接参数、版本号。pkg-config 通过读这张卡片才知道编译命令该怎么写。你只装lz4就好比书在书架上但检索目录里没有登记编译器自然认为“没有这本书”。这就是为什么dnf install lz4不能解决问题。2.2 用 dnf 反向定位开发包在 OpenEuler 上正确做法是装lz4-devel。但为了让你以后遇到其他类似报错也能举一反三我建议先学会“反向查包”。先搜一下仓库里有哪些 lz4 相关包dnf search lz4通常输出会包括lz4.x86_64lz4-devel.x86_64lz4-static.x86_64如果你不确定哪个包包含了liblz4.pc可以用 dnf 的provides功能按文件反查dnf provides */liblz4.pc这个命令会搜索仓库所有已收录包的文件清单凡是包含该文件名的包都会列出来。在 OpenEuler 20.03、22.03 这类版本上返回结果基本就是lz4-devel。这个方法价值很大*/通配符会忽略路径前缀不管.pc文件是在/usr/lib64/pkgconfig还是/usr/share/pkgconfig都能一把抓出来。2.3 安装并验证确认包名后直接安装dnf install -y lz4-devel安装完成后先验证一下 pkg-config 是否已经能识别这个库pkg-config --modversion liblz4如果输出类似1.9.3说明 pkg-config 已经找到了这张“索引卡片”。此时再回头看/usr/lib64/pkgconfig/liblz4.pc这个文件就是关键它存在且内容正确configure 就不会再报no。提示pkg-config --modversion liblz4输出的版本号可以帮你判断当前能用的 lz4 版本。如果项目对版本有硬性要求比如需要 1.9 以上这一步就能提前发现矛盾。3. 实操演示从报错到完整编译通过3.1 环境准备与安装命令我这里以一台 OpenEuler 20.03 x86_64 服务器为例现场模拟一遍完整过程。假设你要构建的是某个依赖 liblz4 的组件最开始系统状态是“缺 lz4-devel”。执行顺序如下dnf update -y dnf install -y gcc gcc-c make pkg-config autoconf automake第一组命令是常规编译环境必须有 pkg-config否则任何基于 pkg-config 检测的软件都会直接报错。然后安装 lz4-develdnf install -y lz4-devel装完以后不用急着重跑 configure先做三件小事pkg-config --exists liblz4 echo exists pkg-config --cflags liblz4 pkg-config --libs liblz4正常情况下--cflags输出-I/usr/include或空值--libs输出类似-llz4。这说明编译参数已经被正确解析出来configure 再调用同一个接口时就不会迷路了。3.2 清理残留缓存再重跑 configure这里有一个很容易踩的坑如果 configure 之前已经失败过有些项目会在源码目录里生成config.cache或config.log并把失败结果记进去。第二次重跑时configure 可能直接读缓存跳过部分检测这会导致明明装好了包日志里仍显示旧的状态。稳妥做法是执行make distclean 2/dev/null || true rm -f config.cache rm -rf autom4te.cache然后重新执行./configure --prefix/usr/local这次观察输出你会发现checking for liblz4... yes看到yes那一刻悬着的心基本可以放下了。后续就是常规操作make -j$(nproc) make install3.3 一个临时绕过方案LIBLZ4_CFLAGS 和 LIBLZ4_LIBS还有一个场景需要提一下。如果你所在的网络环境短时间内装不了 lz4-devel但又急着把 configure 跑完可以利用报错信息里给出的第二个引导方式手动指定库位置。假设你已经从别的机器拷入了liblz4.so和lz4.h放在/opt/lz4下可以这样临时设置export LIBLZ4_CFLAGS-I/opt/lz4/include export LIBLZ4_LIBS-L/opt/lz4/lib -llz4 ./configureconfigure 会跳过 pkg-config 检测直接采用你给的两个变量。这属于“手动绕行”方案能解一时燃眉之急但长期维护不推荐因为它绕过了 pkg-config 的版本检验如果版本不对问题会延迟到链接期甚至运行期才暴露。4. ARM 架构 OpenEuler 上的编译故事4.1 ARM 架构下的库路径差异最近几年 ARM 架构的 OpenEuler 服务器越来越多有些朋友在鲲鹏这类机器上做虚拟化部署自己从源码编译 libvirt-daemon-kvm 相关组件结果同样被liblz4卡住。ARM 架构下有个和 x86 不太一样的细节系统的库目录同样是/usr/lib64但软件仓库的包名会标注aarch64。在 ARM 机器上执行uname -m输出是aarch64。此时用 dnf 安装 lz4-devel 时dnf 会自动选择架构正确的包。但如果你是从源码自行编译 lz4再让目标项目去依赖它就需要特别留意 pkg-config 的搜索路径。自行编译安装到/usr/local时.pc文件通常落在/usr/local/lib64/pkgconfig而这个路径不一定在默认搜索范围内。验证当前搜索范围可以这样看pkg-config --variable pc_path pkg-config如果输出里没有/usr/local/lib64/pkgconfig就要手动把路径追加到环境变量export PKG_CONFIG_PATH/usr/local/lib64/pkgconfig:$PKG_CONFIG_PATH这个知识点在 ARM 交叉编译时尤为重要。如果你在 x86 主机上交叉编译 ARM 版本软件必须把交叉工具链里那份 pkg-config 路径配好否则即便宿主机的 liblz4 装得再全目标 ARM 环境依然会被判定为“找不到”。4.2 虚拟化场景中的连环依赖很多人在 ARM 架构 OpenEuler 上源码构建 libvirt-daemon-kvm 栈时会发现liblz4 只是第一关后面还连着yajl、libpciaccess、numactl等一系列依赖。这种“连环依赖”在编译虚拟化组件时特别常见我习惯的做法是提前一次性把基础依赖装齐dnf install -y lz4-devel yajl-devel libpciaccess-devel numactl-devel \ libattr-devel libcap-ng-devel device-mapper-devel虽然每个项目报错时都可以单独反查但虚拟化组件之间共享依赖很多先装齐一批后面配置会顺畅得多。注意源码树里如果有多个组件比如 libvirt 和 QEMU 分开构建每个组件都建议单独跑一遍pkg-config --exists liblz4做验证避免前一个组件编译通过就默认所有依赖都到位。5. 疑难杂症避坑手册为什么装了包仍然报 no5.1 自定义安装路径导致 PKG_CONFIG_PATH 失效最常见的“装了包还报 no”发生在从源码自行编译 lz4 的场景。默认包管理器安装的 lz4-devel.pc文件放在标准路径pkg-config 一定能找到但如果你为了给某个老项目适配特定版本手动编译安装了一份 lz4.pc文件大概率落在/usr/local/lib/pkgconfig或/opt/lz4/lib/pkgconfig这类非标准路径里。此时 pkg-config 不认识这个地方自然报 no。解决办法很简单把路径加进环境变量export PKG_CONFIG_PATH/opt/lz4/lib/pkgconfig:$PKG_CONFIG_PATH ./configure经验是优先使用--define或直接把.pc文件软链到标准目录实在图省事再用环境变量。但环境变量的缺点很明显换一个终端窗口就丢了所以写进~/.bashrc前要想清楚避免影响后续其他项目。5.2 多版本 lz4 与 configure 缓存残留另一种“灵异事件”是明明 pkg-config 能查到 liblz4configure 里还是报 no。原因往往出在 configure 的缓存上。某些源码包即使不加config.cache参数也会在autom4te.cache或config.log里记录探测结果。切换分支、更换依赖版本后旧记录还在configure 比较“懒”直接用了旧结论。处理方式rm -rf autom4te.cache config.cache config.log ./configure另外还有一种情况是 pkg-config 查到的版本和项目要求的版本不一致。比如项目需要liblz4 1.9.0系统里是 1.8.2configure 会把失败信息写得更详细一般会带上版本冲突的提示。此时要么升级系统包仓库要么从更高版本源码自编译 lz4 并放到自定义路径。5.3 32 位与 64 位架构混装在多架构支持场景下如果你在 64 位 OpenEuler 上编译 32 位程序会遇到一个非常隐蔽的问题系统里装的是lz4-devel.x86_64它提供/usr/lib64/pkgconfig/liblz4.pc而 32 位编译需要的是/usr/lib/pkgconfig/liblz4.pc或至少库文件是 32 位版本。此时 pkg-config 仍然能查到 liblz4但链接时会对不上位。排查方式file /usr/lib64/liblz4.so file /usr/lib/liblz4.so如果目标是 32 位安装对应架构的开发包dnf install -y lz4-devel.i686这个“位数不匹配”的问题在容器镜像里更容易被掩盖因为镜像里可能同时存在多个架构的 pkg-config 路径环境变量一叠加搜索顺序就可能出错。建议在 configure 之前用pkg-config --variablelibdir liblz4确认实际库路径再判断是否符合当前构建目标。5.4 常见问题速查表现象直接原因快速排查命令解决办法configure 报 liblz4 no缺少 lz4-develpkg-config --modversion liblz4dnf install -y lz4-develpkg-config 找不到 .pc.pc 在非标准路径pkg-config --variable pc_path pkg-config设置 PKG_CONFIG_PATH装了包仍报 noconfigure 缓存残留ls config.cache删除缓存重新 configure链接时找不到 liblz4.so只装了 dev 头文件ldconfig -p | grep lz4安装 lz4 运行时库32/64 位数不匹配架构混装file /usr/lib64/liblz4.so安装对应架构的 devel 包版本过低仓库版本旧dnf list lz4-devel更新仓库或自编译新版本这张表可以打印出来贴在工位旁边遇到类似问题先对照一遍多半不用看日志就能定位。6. 事后复盘给新手的速查清单和个人体会6.1 一条通用排查套路liblz4 这个 case 解决之后其实你掌握的是一个更通用的技能。以后再遇到任何Package requirements (xxx) were not met报错都可以按下面这三步走用dnf provides */xxx.pc反查提供该.pc文件的 RPM 包名安装对应的-devel包验证pkg-config --modversion xxx能输出版本号删除config.cache和autom4te.cache再重跑./configure。这三步能覆盖九成以上的类似问题。剩下那一成基本是自定义安装路径和架构混装用前面表格里的方法也能快速定位。6.2 我踩过几次坑之后的一些体会说实在的liblz4 这个报错在编译依赖里算是最温和的一类因为你只要反查包名、装上-devel就能解决。真正恶心的是“包装对了但路径没找对”的隐性问题比如你自己编译了一份 lz4 到自定义目录后面所有依赖它的项目都要求你配置 PKG_CONFIG_PATH一旦忘了报错又会回到最初那行checking for liblz4... no。我个人现在编译任何依赖较多的项目时都会先刻意做两件事第一把dnf provides反查结果归档到项目 README 里防止同事或未来的自己重新踩坑第二在 configure 之前先看一眼pkg-config --modversion和pkg-config --libs的输出确认依赖版本符合预期再继续。这样看似多花半分钟省下的却是链接阶段排查问题的几小时。如果你正在被这个报错困扰按上面第 2 节和第 3 节的操作顺序走一遍基本十分钟内能解决。以后再遇到类似的Package requirements报错别忘了你已经掌握了一套通用排查方法别再被这些“刚刚好差一个开发包”的报错唬住了。
返回列表