51. 附录C:常用Find模块列表与变量

引言:施工队长的”供应商名录”

在前面的章节中(特别是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 / GLU
  • FindVulkan — Vulkan图形API
  • FindGLUT — GLUT工具库
  • FindGLEW — OpenGL扩展加载库GLEW
  • FindSDL / FindSDL2 — Simple DirectMedia Layer
  • FindQt3 / 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++线性代数库Armadillo
  • FindEigen3 — 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 Interface
  • FindJava / FindAnt / FindMaven — Java构建工具链
  • FindSWIG — SWIG代码生成工具
  • FindBISON / FindFLEX — 词法/语法分析生成器
  • Gettext / FindIntl — GNU gettext国际化库

第二部分:典型模块输出变量速查

绝大多数Find模块都遵循CMake官方推荐的变量命名约定。一旦模块成功找到库,它会设置一组以库名大写为前缀的变量。了解这套”命名语法”,你就能在读完find_package后立刻知道该用什么变量。

通用变量命名规律

假设模块名为XXX(例如BoostOpenSSLZLIB),常见输出变量如下:

  • XXX_FOUND — 布尔值,表示是否成功找到该包。这是最可靠的判断依据。
  • XXX_INCLUDE_DIRSXXX_INCLUDES — 头文件搜索路径列表,通常直接用于target_include_directories
  • XXX_LIBRARIESXXX_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_FOUNDBoost_INCLUDE_DIRSBoost_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后,再来这里确认该模块吐出了哪些变量、命名是否符合标准规律。

记住两个黄金法则:

  1. 变量前缀 = 包名全大写。找Boost就是Boost_XXX,找OpenSSL就是OPENSSL_XXX(尽管OpenSSL的OPENSSL是全大写,但部分模块如SQLite3保留了数字和大小写混合,需要留意)。
  2. 优先用导入目标(Target),其次用变量。现代CMake模块(尤其是支持Config模式的库)通常提供XXX::XXXXXX::Component目标;传统的Module模式则以变量为主。如果你的CMake版本允许,永远优先使用目标,因为它能自动传播头文件路径、编译定义和链接依赖。

至此,我们的”施工队长”不仅有了一份完整的供应商名录,还学会了如何快速读懂每份合同的条款(输出变量)。下一本附录,我们将为他准备更专业的”翻译词典”——生成器表达式的完整参考手册。

请登录后发表评论

    没有回复内容

正在唤醒异次元光景……