从源码构建 sharp 时,为何找不到已存在的 glib-object.h?
结论:先检查 libvips 版本和实际构建路径
glib-object.h 存在,说明文件已经安装。即使 pkg-config 能输出它的目录,也不能确定 sharp 构建时使用了这些参数。
sharp 0.34.5 要求 libvips >=8.17.3,而你提供的 vips -v 输出为 8.14.1。如果 pkg-config 检测到的也是 8.14.1,sharp 默认不会选择这套系统 libvips。最低版本要求可以在 sharp 0.34.5 的 package.json 中确认。
当前日志还不足以说明版本问题是否是这次头文件错误的完整原因,需要确认构建实际选择了哪套依赖。
为什么 pkg-config 能找到,编译器却找不到?
sharp 0.34.5 有两条构建路径:选择系统 libvips 时,通过 pkg-config 获取头文件和链接参数;否则,从 node_modules 中相应的 libvips 包获取目录。因此,在终端单独执行 pkg-config --cflags vips-cpp 成功,并不代表当前构建使用了系统 libvips。参见 binding.gyp。
日志表明,编译器已经读到了 /usr/include/vips/vips8,但处理其中的 #include <glib-object.h> 时找不到对应文件。结合版本信息,需要验证一种可能:构建没有采用系统 libvips 的完整参数,却通过默认搜索路径读到了系统的 vips 头文件。
1. 确认 sharp 实际检测到的依赖
在项目目录执行:
vips -v
pkg-config --modversion vips-cpp
pkg-config --cflags vips-cpp
pkg-config --libs vips-cpp
比较 vips -v 和 pkg-config --modversion vips-cpp 的结果。系统安装了多套 libvips 时,两者可能对应不同位置;sharp 的检测逻辑使用后者。
还可以查看当前安装的 sharp 0.34.5 的内部检测结果:
npm explore sharp -- node -e "const v = require('./lib/libvips'); console.log({minimum: v.minimumLibvipsVersion, detected: v.globalLibvipsVersion(), useGlobal: v.useGlobalLibvips()});"
这个命令使用该版本的内部模块,仅适合诊断。minimum 表示最低要求,detected 表示检测到的系统版本,useGlobal 表示是否选择系统 libvips。判断结果还受 SHARP_IGNORE_GLOBAL_LIBVIPS 和 SHARP_FORCE_GLOBAL_LIBVIPS 影响,见 libvips 检测代码。
2. 需要链接系统 libvips 时,先升级配套依赖
如果必须使用系统安装的 libvips,应安装满足 >=8.17.3 要求的版本,并配齐该版本的开发头文件、库和 .pc 文件。安装方式取决于发行版及软件源,不能仅凭当前内核版本确定包管理命令。
如果 libvips 安装在自定义目录,需要将其 .pc 文件所在目录加入 PKG_CONFIG_PATH。然后重新检查版本和编译参数,确认它们指向同一套安装,再执行:
npm explore sharp -- npm run build
不要通过设置 SHARP_FORCE_GLOBAL_LIBVIPS 强行绕过 8.14.1 的版本限制。强制选择旧库不会让它具备新版本所需的接口;也不要只补上一个 -I/usr/include/glib-2.0 就认定依赖已经兼容。
3. 版本正确后,检查真正执行的编译命令
如果仍报同样的错误,检查失败的 C++ 编译命令是否包含 pkg-config 输出的头文件目录。
在 Linux 上,如果前一次 node-gyp 构建已经生成 src/build/Makefile,可以显示完整命令:
npm explore sharp -- sh -c 'cd src/build && make V=1'
如果编译命令缺少相关 -I 参数,继续检查构建选择和环境变量;如果参数已经存在,再确认构建是否发生在另一容器、sysroot 或文件系统环境中。GLib 还可能需要架构相关的头文件目录,因此应核对完整的 pkg-config 输出。
是否必须从源码构建?
Node.js 已更新,并不意味着当前系统必须从源码构建。是否需要源码构建,取决于目标平台是否有可用的预编译包,以及是否需要自定义 libvips。现有材料没有给出必须源码构建的具体限制。如果确实需要源码构建,先让依赖版本和构建路径保持一致,再处理后续编译错误。
备注:内容仅供参考。
