目录
1.3.添加全局查找路径(CMAKE_PREFIX_PATH,多库通用)
1.4.设置模块查找路径(CMAKE_MODULE_PATH,老库兜底)
[1.5.直接设置头文件 / 库文件目录(INCLUDE_DIRECTORIES/LINK_DIRECTORIES,不推荐现代 CMake)](#1.5.直接设置头文件 / 库文件目录(INCLUDE_DIRECTORIES/LINK_DIRECTORIES,不推荐现代 CMake))
1.6.find_package自带的HINTS和PATHS
[2.已设置库目录后,让 find_package 找到的方法](#2.已设置库目录后,让 find_package 找到的方法)
[3.找到库后,CMake 自动设置的变量(核心 + 扩展)](#3.找到库后,CMake 自动设置的变量(核心 + 扩展))
[3.2.分配置变量(Debug/Release 分离时)](#3.2.分配置变量(Debug/Release 分离时))
1.cmake设置库目录的方法
1.1.设置库根目录(XXX_ROOT,最常用)
现代库(Qt、Boost、MySQL)都会自带 XXXConfig.cmake 或 xxx-config.cmake(配置文件),直接指定库的安装根目录,后续 find_package 会自动在根目录下搜索 lib/cmake、include 等子目录,适配绝大多数现代库(Qt、Boost、MySQL 等)。CMake 会自动在以下子目录中搜索配置文件: 库根目录/lib/cmake → 库根目录/cmake → 库根目录/share/cmake
- 语法:
set(<库名>_ROOT "库的根目录")(库名大写,如Qt6_ROOT、BOOST_ROOT) - 示例(Windows 下 Boost):
cpp
# 绝对路径(推荐,避免歧义)
set(BOOST_ROOT "D:/boost_1_83_0")
# 跨平台相对路径(适合项目内嵌库,如 libs/boost 放在项目根目录)
set(BOOST_ROOT ${CMAKE_CURRENT_LIST_DIR}/libs/boost)
- 示例(Linux 下 MySQL):
cpp
set(MySQL_ROOT "/usr/local/mysql-8.0.36") # 自定义安装目录
# 系统默认目录可省略,find_package 会自动搜索,但指定后更高效
- 适用场景:单个库配置、现代库(带
XXXConfig.cmake)、跨平台项目。
1.2.指定库配置文件目录(XXX_DIR,最精准)
直接指向库的 XXXConfig.cmake 或 xxx-config.cmake 所在目录,跳过自动搜索,确保 find_package 精准定位,适合路径复杂的库。
- 语法:
set(<库名>_DIR "库的 cmake 配置目录") - 示例(Qt6):
cpp
# Windows:Qt 配置文件在 lib/cmake/Qt6 下
set(Qt6_DIR "D:/Qt6.5.1/6.5.1/msvc2019_64/lib/cmake/Qt6")
# Linux:Qt 配置文件在 lib/cmake/Qt6 下
set(Qt6_DIR "/opt/Qt6.5.1/6.5.1/gcc_64/lib/cmake/Qt6")
- 示例(MySQL):
cpp
set(MySQL_DIR "D:/mysql-8.0.36-winx64/lib/cmake/MySQL")
- 适用场景:库路径特殊、需精准控制查找结果、避免多个库版本冲突。
1.3.添加全局查找路径(CMAKE_PREFIX_PATH,多库通用)
将多个库的根目录添加到 CMake 全局查找路径,后续所有 find_package 都会自动在这些目录中搜索,适合项目依赖多个库的场景。
- 语法:
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "库根目录1" "库根目录2") - 示例(同时配置 Boost、Qt6、MySQL):
cpp
# 跨平台写法(Windows/Linux 通用,路径用斜杠 / 或双反斜杠 \\)
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
"D:/boost_1_83_0"
"D:/Qt6.5.1/6.5.1/msvc2019_64"
"D:/mysql-8.0.36-winx64"
"/usr/local/mysql" # Linux 目录可并行添加
)
- 适用场景:多库依赖、不想单独设置每个库的
ROOT变量。
1.4.设置模块查找路径(CMAKE_MODULE_PATH,老库兜底)
针对无 XXXConfig.cmake 的老库(仅提供 FindXXX.cmake 模块文件),指定模块文件所在目录,让 CMake 能找到模块并通过模块定位库目录。
- 语法:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "FindXXX.cmake 所在目录") - 示例(老库 OldLib,无配置文件):
cpp
# 1. 指定模块文件目录(如项目根目录下的 cmake/modules 文件夹)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake/modules)
# 2. 设置老库根目录(模块文件 FindOldLib.cmake 会读取该变量)
set(OldLib_ROOT "D:/OldLib-1.0")
# 3. 查找库(模块会根据 OldLib_ROOT 定位头文件和库文件)
find_package(OldLib REQUIRED)
- 适用场景:老版本开源库、无配置文件的自定义库。
1.5.直接设置头文件 / 库文件目录(INCLUDE_DIRECTORIES/LINK_DIRECTORIES,不推荐现代 CMake)
直接指定库的头文件目录和库文件目录,跳过 find_package,直接用于编译链接。现代 CMake 不推荐(缺乏版本检查和依赖管理),但适合简单场景或无模块 / 配置文件的库。
cpp
# 设置头文件目录(对应库的 include 文件夹)
include_directories("库目录/include")
# 设置库文件目录(对应库的 lib 或 lib64 文件夹)
link_directories("库目录/lib")
示例:
cpp
include_directories("D:/boost_1_83_0/include")
link_directories("D:/boost_1_83_0/lib64-msvc-14.3") # 区分编译器和架构
# 后续直接链接库名
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE boost_system boost_asio)
- 适用场景:简单项目、无模块 / 配置文件的库、快速验证原型。
1.6.find_package自带的HINTS和PATHS
2.已设置库目录后,让 find_package 找到的方法
假设你已通过 set(XXX_ROOT "库根目录") 或 set(库目录相关变量) 指定路径,CMake 会按以下优先级查找:
- 直接指定配置文件路径 :
set(XXX_DIR "库目录/cmake")(XXXConfig.cmake 所在目录,最精准); - 设置根目录 :
set(XXX_ROOT "库根目录")(CMake 会自动在库根目录/lib/cmake、库根目录/cmake等子目录中找配置文件); - 添加到全局查找路径 :
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "库根目录")(全局生效,适合多个库); - 模块模式兜底 :若库无配置文件,需确保
FindXXX.cmake模块能通过CMAKE_MODULE_PATH找到,且模块中会读取你设置的XXX_ROOT变量定位库目录。
总结查找顺序:
XXX_DIR→XXX_ROOT/lib/cmake→CMAKE_PREFIX_PATH中的目录 → 系统默认路径(/usr/lib/cmake 等)
3.找到库后,CMake 自动设置的变量(核心 + 扩展)
3.1.通用核心变量(所有库统一,必用)
| 变量名 | 作用 |
|---|---|
<XXX>_FOUND |
布尔值,TRUE= 找到库(用于 if(XXX_FOUND) 条件判断,避免编译报错) |
<XXX>_INCLUDE_DIRS |
头文件目录列表(直接传给 target_include_directories) |
<XXX>_LIBRARIES |
需链接的库文件列表(自动区分 Debug/Release,传给 target_link_libraries) |
<XXX>_VERSION_STRING |
库版本(如 6.5.1),细分 _MAJOR/_MINOR/_PATCH(如 Qt6_VERSION_MAJOR=6) |
<XXX>_COMPILE_DEFINITIONS |
库要求的编译宏(如 QT_NO_KEYWORDS),传给 target_compile_definitions |
<XXX>_COMPILE_OPTIONS |
库要求的编译选项(如 -std=c++17),传给 target_compile_options |
3.2.分配置变量(Debug/Release 分离时)
若库提供不同编译模式的版本,会生成以下变量,支持手动指定:
库提供不同编译模式的版本,会生成以下变量,支持手动指定:
| 变量名 | 作用 |
|---|---|
<XXX>_LIBRARIES_DEBUG |
Debug 版库文件(如 Qt6Widgetsd.lib、boost_system-d.lib) |
<XXX>_LIBRARIES_RELEASE |
Release 版库文件(如 Qt6Widgets.lib、boost_system.lib) |
<XXX>_INCLUDE_DIRS_DEBUG/RELEASE |
分模式头文件目录(极少用,通常与通用目录一致) |
3.3.库特定变量(常用库示例,补充通用变量未覆盖的功能)
- Qt :
Qt6::<Module>(目标名,如Qt6::Widgets,推荐直接链接目标而非变量)、Qt6_QMAKE_EXECUTABLE(qmake 路径); - Boost :
Boost_<COMPONENT>_LIBRARY(单个组件库,如Boost_ASIO_LIBRARY)、Boost_INCLUDE_DIR(单数,与_INCLUDE_DIRS等价); - MySQL :
MySQL_INCLUDE_DIR(单数头文件目录)、MySQL_LIBRARY(核心库文件)、MySQL_CLIENT_LIBS(客户端完整依赖库)。
4.实操示例
(以 Boost 为例,已设置库目录)
假设已设置 Boost 目录 set(BOOST_ROOT "D:/boost_1_83_0"),完整流程:
cpp
# 1. 引导 find_package 找到 Boost(已设置 BOOST_ROOT,无需额外路径)
find_package(Boost REQUIRED COMPONENTS asio system) # 要求 asio、system 组件
# 2. 验证查找结果(可选,调试用)
if(Boost_FOUND)
message("Boost 找到:版本=${Boost_VERSION_STRING}")
message("头文件目录:${Boost_INCLUDE_DIRS}")
message("链接库:${Boost_LIBRARIES}")
else()
message(FATAL_ERROR "Boost 未找到,请检查 BOOST_ROOT 路径")
endif()
# 3. 应用变量到项目
add_executable(my_app main.cpp)
target_include_directories(my_app PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(my_app PRIVATE ${Boost_LIBRARIES}) # 自动链接对应模式库
target_compile_features(my_app PRIVATE cxx_std_17) # 满足 Boost.Asio 编译要求
5.总结
1.路径规范
- 跨平台优先用斜杠
/或双反斜杠\\(避免单反斜杠转义问题); - 相对路径优先用
CMAKE_CURRENT_LIST_DIR(当前 CMakeLists.txt 所在目录)拼接,避免硬编码绝对路径。
2.现代 CMake 推荐 :优先使用方法一(XXX_ROOT)、方法二(XXX_DIR)、方法三(CMAKE_PREFIX_PATH),配合 find_package + 目标链接(target_link_libraries),自动处理依赖和分配置(Debug/Release)。
3.64/32 位适配 :库目录需匹配编译架构(如 lib64 对应 64 位,lib 对应 32 位),可通过 CMAKE_SIZEOF_VOID_P 判断(8 为 64 位,4 为 32 位)。