引言:施工队长的”供应商名录”
在前面的章节中(特别是5.1和5.2),我们的CMake”施工队长”已经学会了如何通过find_package命令从外部采购标准化建材(第三方库)。但在实际工作中,队长不可能每次都去翻箱倒柜找供应商联系方式——他需要一本常备的供应商名录,以及一份材料规格速查表,知道每家店能提供什么、包装长什么样。
这本附录就是那位队长的”口袋手册”。我们会列出CMake内置的标准Find模块清单,并说明它们最常见的输出变量命名规律。当你在新的项目中需要集成某个库时,翻开这一页,就能快速知道该打哪个电话(用哪个模块)、对方会送来几样东西(产生哪些变量)。
第一部分:标准Find模块清单
CMake的官方发行版自带了上百个FindXXX.cmake模块,位于CMake安装目录的Modules文件夹下。你随时可以通过以下命令查看本机支持的所有内置模块:
cmake --help-module-list | grep ^Find
下面我们将常用模块按功能分类整理,方便你在实际项目中速查。
压缩与归档库
FindZLIB— zlib压缩库FindBZip2— bzip2压缩库FindLibArchive— libarchive多格式归档库FindXZ— XZ Utils / liblzma压缩库
数据库与存储
FindPostgreSQL— PostgreSQL客户端库FindMySQL/FindMariaDB— MySQL/MariaDB客户端FindSQLite3— SQLite3嵌入式数据库FindMongoDB— MongoDB C++驱动(部分版本)FindODBC— ODBC数据库连接接口FindOracle— Oracle OCI客户端(部分旧版CMake)
图形、GUI与窗口系统
FindOpenGL— OpenGL / OpenGL ES / GLUFindVulkan— Vulkan图形APIFindGLUT— GLUT工具库FindGLEW— OpenGL扩展加载库GLEWFindSDL/FindSDL2— Simple DirectMedia LayerFindQt3/FindQt4/FindQt5/FindQt6— Qt各版本(注意:Qt5/Qt6更推荐使用Config模式)FindGTK2/FindGTK3— GTK+图形界面库FindwxWidgets— wxWidgets跨平台GUI库FindX11— X11窗口系统客户端库FindMotif— Motif/LessTif工具库
数学与科学计算
FindBLAS— BLAS基础线性代数子程序FindLAPACK— LAPACK线性代数包FindFFT/FindFFTW— 快速傅里叶变换库FindGSL— GNU科学计算库FindArmadillo— C++线性代数库ArmadilloFindEigen3— Eigen3头文件线性代数库FindMatlab— MATLAB引擎和MAT文件库FindHDF5— HDF5层次化数据格式库
多媒体与图像
FindPNG— libpng图像库FindJPEG— libjpeg图像库FindTIFF— libtiff图像库FindGIF— giflib图像库FindFreetype— FreeType字体渲染库FindFontconfig— Fontconfig字体配置库FindOpenAL— OpenAL音频库FindALSA— ALSA Linux音频架构FindPulseAudio— PulseAudio音频服务器FindGStreamer— GStreamer多媒体框架FindFFmpeg— FFmpeg音视频处理(部分第三方或较新CMake版本)
网络与通信
FindCURL— libcurl网络传输库FindOpenSSL/FindLibSSL— OpenSSL加密与SSL/TLS库FindLibSSH/FindLibSSH2— SSH客户端库FindBoost— Boost库集合(含Boost.Asio等网络组件)FindProtobuf— Protocol Buffers序列化库FindgRPC— gRPC远程过程调用(较新版本)FindXMLRPC— XML-RPC协议库FindEXPAT— Expat XML解析库FindLibXml2— libxml2 XML解析库FindLibXslt— libxslt XSLT处理库
测试与分析工具
FindGTest/FindGoogleTest— GoogleTest测试框架FindCxxTest— CxxTest测试框架FindCppUnit— CppUnit测试框架FindDoxygen— Doxygen文档生成工具FindSphinx— Sphinx文档生成工具FindLATEX— LaTeX排版系统FindClangTidy— clang-tidy静态分析工具FindIWYU— include-what-you-use头文件分析工具
线程与并发
FindThreads— 系统线程库(POSIX pthreads或Windows threads)FindOpenMP— OpenMP并行编程支持FindTBB— Intel oneAPI Threading Building Blocks
开发工具与辅助库
FindPkgConfig— pkg-config工具集成FindPythonInterp/FindPython— Python解释器(CMake 3.12+推荐使用FindPython)FindPythonLibs/FindPython2/FindPython3— Python开发头文件和库FindLua/FindLua50/FindLua51— Lua脚本语言库FindRuby— Ruby解释器和库FindJNI— Java Native InterfaceFindJava/FindAnt/FindMaven— Java构建工具链FindSWIG— SWIG代码生成工具FindBISON/FindFLEX— 词法/语法分析生成器Gettext/FindIntl— GNU gettext国际化库
第二部分:典型模块输出变量速查
绝大多数Find模块都遵循CMake官方推荐的变量命名约定。一旦模块成功找到库,它会设置一组以库名大写为前缀的变量。了解这套”命名语法”,你就能在读完find_package后立刻知道该用什么变量。
通用变量命名规律
假设模块名为XXX(例如Boost、OpenSSL、ZLIB),常见输出变量如下:
XXX_FOUND— 布尔值,表示是否成功找到该包。这是最可靠的判断依据。XXX_INCLUDE_DIRS或XXX_INCLUDES— 头文件搜索路径列表,通常直接用于target_include_directories。XXX_LIBRARIES或XXX_LIBS— 需要链接的库文件列表,通常直接用于target_link_libraries。XXX_LIBRARY_DIRS— 库文件所在的目录路径,较少直接使用(现代CMake推荐直接链接库路径)。XXX_DEFINITIONS— 使用该库所需的编译定义(宏),可用于target_compile_definitions。XXX_VERSION/XXX_VERSION_STRING— 找到的版本号字符串。XXX_MAJOR_VERSION/XXX_MINOR_VERSION/XXX_PATCH_VERSION— 版本号的数字分量。XXX_EXECUTABLE— 某些工具类包会提供可执行文件路径(如Doxygen、Protobuf编译器)。
FindBoost — Boost库的”分层账单”
Boost由于组件众多,其变量体系比其他模块更复杂。除了标准的Boost_FOUND、Boost_INCLUDE_DIRS、Boost_LIBRARIES外,还有按组件细分的变量:
find_package(Boost 1.74 REQUIRED COMPONENTS system filesystem thread)
# 常用变量:
# Boost_FOUND — 整体是否找到
# Boost_INCLUDE_DIRS — 头文件路径
# Boost_LIBRARY_DIRS — 库文件目录
# Boost_LIBRARIES — 所有请求组件的库文件列表
# Boost_VERSION_STRING — 版本号,如 "1.74.0"
# 按组件细分的变量(仅在请求了该组件时生成):
# Boost_SYSTEM_FOUND
# Boost_FILESYSTEM_FOUND
# Boost_THREAD_FOUND
# Boost_SYSTEM_LIBRARY — 具体某个组件的库路径
# Boost_FILESYSTEM_LIBRARY
# Boost_THREAD_LIBRARY
注意:在CMake 3.30+中,官方更推荐使用Boost提供的BoostConfig.cmake(Config模式),但 legacy 项目中仍大量使用Module模式下的FindBoost。
FindOpenSSL — 加密库的”双证输出”
OpenSSL通常分为Crypto(加密)和SSL(安全通信)两个核心库,因此其变量也成对出现:
find_package(OpenSSL REQUIRED)
# 常用变量:
# OPENSSL_FOUND — 整体找到标志
# OPENSSL_INCLUDE_DIR — 头文件目录(注意是单数 DIR)
# OPENSSL_LIBRARIES — 两个核心库的合集
# OPENSSL_VERSION — 版本号,如 "3.0.8"
# 细分库变量:
# OPENSSL_SSL_LIBRARY — libssl 的路径
# OPENSSL_CRYPTO_LIBRARY — libcrypto 的路径
# OPENSSL_SSL_LIBRARIES — ssl 及其依赖
# OPENSSL_CRYPTO_LIBRARIES — crypto 及其依赖
FindZLIB / FindPNG / FindJPEG — 图像压缩库的”标准三件套”
这类底层C库通常输出非常规整,记住一套就能举一反三:
find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
find_package(JPEG REQUIRED)
# ZLIB: ZLIB_FOUND, ZLIB_INCLUDE_DIRS, ZLIB_LIBRARIES
# PNG: PNG_FOUND, PNG_INCLUDE_DIRS, PNG_LIBRARIES, PNG_DEFINITIONS
# JPEG: JPEG_FOUND, JPEG_INCLUDE_DIRS, JPEG_LIBRARIES
特别留意FindPNG会额外定义PNG_DEFINITIONS(例如PNG_ARM_NEON_OPT=0之类的宏),这是因为libpng的头文件有时需要特定的编译定义才能正确工作。
FindCURL — 网络传输库的”多协议账单”
find_package(CURL REQUIRED)
# CURL_FOUND — 找到标志
# CURL_INCLUDE_DIRS — 头文件路径
# CURL_LIBRARIES — 库文件路径
# CURL_VERSION_STRING — 版本号
CURL比较友好,变量命名完全符合标准约定。但注意前缀是CURL_而不是CURL_(实际上确实是CURL_,无需纠结大小写特例)。
FindSQLite3 — 嵌入式数据库的”精简发票”
find_package(SQLite3 REQUIRED)
# SQLite3_FOUND
# SQLite3_INCLUDE_DIRS
# SQLite3_LIBRARIES
# SQLite3_VERSION — 版本号字符串
FindThreads — 系统线程的”自动识别”
这个模块比较特殊,它找到的”库”在不同平台上表现不同(Linux下通常是-lpthread,Windows下可能是空或系统库)。因此它的变量名略有差异:
find_package(Threads REQUIRED)
# CMAKE_THREAD_LIBS_INIT — 需要链接的线程库标志
# CMAKE_USE_PTHREADS_INIT — 如果使用了POSIX pthreads,为真
# CMAKE_USE_WIN32_THREADS_INIT — 如果使用了Windows threads,为真
# Threads::Threads — 现代CMake推荐使用的导入目标(IMPORTED target)
强烈建议:对于FindThreads,优先使用目标Threads::Threads而不是变量${CMAKE_THREAD_LIBS_INIT}。这是少数几个内置模块中,Modern CMake目标用法明显优于传统变量用法的典型案例。
FindPkgConfig — 调用”外援采购员”
严格来说,这不是找某个特定库,而是找pkg-config这个工具本身,并通过它间接查询其他库:
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBXML2 REQUIRED libxml-2.0)
# 随后会产生以模块名(此处为 LIBXML2)为前缀的变量:
# LIBXML2_FOUND
# LIBXML2_INCLUDE_DIRS
# LIBXML2_LIBRARIES
# LIBXML2_LINK_LIBRARIES — 适合用于 target_link_libraries 的完整标志
# LIBXML2_CFLAGS_OTHER — 额外的编译标志
# LIBXML2_LDFLAGS_OTHER — 额外的链接标志
# LIBXML2_VERSION — 通过 pkg-config 获取的版本
如何快速查阅某个模块的全部变量?
如果你想知道某个Find模块到底设置了哪些变量,最直接的方法是阅读它的源码,或者使用CMake内置帮助命令:
# 查看 Find.cmake 文件位置
cmake --help-module FindBoost | head -n 50
# 或者在 CMakeLists.txt 中临时输出所有以 XXX_ 开头的变量
get_cmake_property(_vars VARIABLES)
foreach(_var ${_vars})
if(_var MATCHES "^Boost_")
message(STATUS "${_var} = ${${_var}}")
endif()
endforeach()
总结:把速查表放进队长的口袋
这本附录的价值在于快速定位:当你知道项目需要某个第三方库时,先来这里看看CMake有没有内置对应的Find模块;当你调通了find_package后,再来这里确认该模块吐出了哪些变量、命名是否符合标准规律。
记住两个黄金法则:
- 变量前缀 = 包名全大写。找Boost就是
Boost_XXX,找OpenSSL就是OPENSSL_XXX(尽管OpenSSL的OPENSSL是全大写,但部分模块如SQLite3保留了数字和大小写混合,需要留意)。 - 优先用导入目标(Target),其次用变量。现代CMake模块(尤其是支持Config模式的库)通常提供
XXX::XXX或XXX::Component目标;传统的Module模式则以变量为主。如果你的CMake版本允许,永远优先使用目标,因为它能自动传播头文件路径、编译定义和链接依赖。
至此,我们的”施工队长”不仅有了一份完整的供应商名录,还学会了如何快速读懂每份合同的条款(输出变量)。下一本附录,我们将为他准备更专业的”翻译词典”——生成器表达式的完整参考手册。


没有回复内容