使用 pkg-config 实用程序修复 CMake 构建问题
引言
最近,CMake 3.30.0 发布,修复了使用 SQLite3 库构建的问题。修复方式引起了我的兴趣。他们只添加了一个使用 `pkg-config` 的小脚本。我对该实用程序的潜力产生了好奇。我将研究它的用法。
背景
三周前,当我在我的 CMake 脚本中运行 `find_package( SQLite3 REQUIRED )` 时,它失败了并输出了一个错误。`find_package` 总是对解决依赖关系和编写可移植构建脚本有很大帮助,这要归功于抽象和自动化配置和版本控制的贡献者。虽然熟悉这种情况,但我一直有点懒,并且对在实用程序失败时需要编写手动配置感到恼火。
在寻找解决这个使用 SQLite3 的 find_package 问题的方案时,我在互联网上找到了许多人建议的不同方法,但其中大多数对我来说都不起作用。然后,我对这种困惑的根源产生了兴趣。
当我到达 GitHub 存储库 `Kitware/CMake` 下的脚本 `FindSQLite3.cmake` 时,我注意到它看起来与我在我的环境中看到的不同,我使用的是 CMake 3.29.6。幸运或不幸的是,它自 2024 年 3 月就已经修复了,但仍在等待下一个版本。现在,3.30.0 上周发布了此修复程序。让我们升级 CMake 并享受使用 SQLite3 构建 C++ 代码的便利。
CMake 脚本中的 pkg-config
脚本中的修复非常简单:使用 `PkgConfig` 包中的 `pkg_check_modules` 命令。它调用 `pkg-config` 工具来获取编译器所需的信息,并在 CMake 脚本的变量中提供这些信息。在此处CMake 文档中查看您可以使用它获取哪些变量。
即使您现在无法升级 CMake,但拥有或可以安装 pkg-config,也可以通过在您的 CMake 构建脚本中包含以下小脚本来解决 SQLite3 的问题。这个解决方案是我暂时使用的。
find_package(PkgConfig) pkg_check_modules(PC_SQLite3 sqlite3) set( SQLite3_ROOT "${PC_SQLite3_PREFIX}" )
带有 `_PREFIX` 后缀的变量是 `pkg_check_modules` 提供的变量之一,并且上面的脚本将其设置为 `SQLite3_ROOT`。 默认情况下,`find_path` 和 `find_library` 命令从带有后缀 `_ROOT` 的变量中搜索路径,因此拥有 `SQLite3_ROOT` 允许旧的 `FindSQLite3.cmake` 脚本找到所需的文件。
命令行中的 pkg-config
由于 `pkg-config` 是一个命令行工具,我开始对它如何改变命令行上的 C++ 代码编译感兴趣。 所以,我用来自我的上一篇文章的代码试了一下。
# install pkg-config apt-get install pkg-config # install sqlite3 libraries apt-get install libsqlite3-dev # compile the code setting up compile options by pkg-config g++ --std=c++14 -I./include ./main-2.cpp ./src/SmartDbConnFactory.cpp $(pkg-config --libs --cflags sqlite3)
编译成功,生成的可执行文件可以运行!
但是,执行 `pkg-config --libs --cflags sqlite3`,我只得到 `-lsqlite3`。 我无法从中感受到这个工具的力量。
所以,我也用 `opencv` 试了一下。 这一次,该命令返回了一个很长的命令。 这会很有趣。
pkg-config --libs --cflags opencv-I/usr/include/opencv4 -lopencv_stitching -lopencv_alphamat -lopencv_aruco -lopencv_barcode -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_cvv -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hdf -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_mcc -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_shape -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_highgui -lopencv_datasets -lopencv_text -lopencv_plot -lopencv_ml -lopencv_videostab -lopencv_videoio -lopencv_viz -lopencv_wechat_qrcode -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core
让我们用 OpenCV 写一个简单的代码。 这个程序将把一个图像文件转换成灰度图像。
// main.cpp #include <iostream> #include <opencv2/opencv.hpp> int main() { cv::Mat image = cv::imread("example.jpg"); cv::Mat grayImage; cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY); cv::imwrite("example_gray.jpg", grayImage); return 0; }
现在,使用 pkg-config 实用程序编译它。
# install OpenCV libraries and dependencies apt-get install libopencv-dev # compile the code setting up compile options by pkg-config g++ --std=c++14 main.cpp $(pkg-config --libs --cflags opencv4)
编译成功,图像文件转换工作正常! 我对这个结果感到兴奋。 这将使我的编码生活更轻松。