CMake基础:常用内部变量和环境变量的引用
目录
1.常用 CMake 变量
1.1.编译与构建控制
1.2.路径与目录变量
1.3.项目信息变量
1.4.系统与平台变量
1.5.工具链与交叉编译
1.6.测试与安装变量
1.7.高级编译选项
2.常用环境变量
2.1.编译器与工具链
2.2.依赖库路径
2.3.CMake 专用环境变量
2.4.系统环境变量Path
3.变量与环境变量的区别
4.变量引用实践
5.常见问题排查
6.查看所有内部变量
相关链接
1.常用 CMake 变量
1.1.编译与构建控制
CMAKE_BUILD_TYPE
构建类型(Debug、Release、RelWithDebInfo、MinSizeRel),影响优化和调试选项。CMAKE_C_COMPILER/CMAKE_CXX_COMPILER
指定 C/C++ 编译器路径(如gcc、clang)。CMAKE_C_FLAGS/CMAKE_CXX_FLAGS
全局 C/C++ 编译选项(如-Wall、-std=c++17)。CMAKE_EXE_LINKER_FLAGS
可执行文件链接选项(如-lpthread)。CMAKE_C_STANDARD/CMAKE_CXX_STANDARD
指定 C/C++ 语言标准版本(如11、17)。CMAKE_C_STANDARD_REQUIRED
强制要求编译器支持指定的 C 标准(布尔值)。
引用示例:
# 根据构建类型设置编译选项 if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0") endif() # 指定 C++ 标准 set(CMAKE_CXX_STANDARD 20)1.2.路径与目录变量
CMAKE_SOURCE_DIR
项目源文件根目录的绝对路径。CMAKE_BINARY_DIR
构建输出目录的绝对路径(外建模式下为独立目录)。PROJECT_SOURCE_DIR
当前project()命令指定的源目录(多项目时区分子项目)。CMAKE_INSTALL_PREFIX
安装目标路径(默认/usr/local,可修改为./install等)。CMAKE_MODULE_PATH
CMake 模块(.cmake文件)的搜索路径,用于find_package或include。- CMAKE_CURRENT_SOURCE_DIR
当前处理的 CMakeLists.txt 所在的源目录。 - CMAKE_CURRENT_BINARY_DIR
前处理的 CMakeLists.txt 对应的构建目录。 - CMAKE_CURRENT_SOURCE_DIR(当前处理的CMakeLists.txt所在的源码绝对目录)
- CMAKE_CURRENT_LIST_DIR(当前执行的任意 CMake 脚本(.cmake 或 .txt)所在绝对目录)
引用示例:
# 添加源文件 add_executable(my_app ${CMAKE_SOURCE_DIR}/src/main.cpp) # 设置库输出目录 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)cmake_minimum_required(VERSION 3.20) project(cmake_var_demo LANGUAGES CXX) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # ===================== 第一步:未 include 外部脚本(二者等价)===================== message("=== 未加载外部脚本时 ===") message("主 CMake 中 LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}") # 指向 cmake_var_demo/ message("主 CMake 中 SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")# 指向 cmake_var_demo/ message("=== 分割线 ===\n") # ===================== 第二步:include 工具脚本(差异显现)===================== # 加载 cmake/utils.cmake 脚本(用 LIST_DIR 定位脚本路径) include(${CMAKE_CURRENT_LIST_DIR}/cmake/utils.cmake) # ===================== 第三步:使用自定义模块(测试 LIST_DIR 在模块中的用法)===================== message("=== 加载自定义模块 ===") # 指定自定义模块目录(用 LIST_DIR 定位 modules 目录) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake/modules) # 查找自定义模块(触发 FindTestLib.cmake 执行) find_package(TestLib REQUIRED) message("=== 分割线 ===\n") # ===================== 第四步:构建项目(实际业务逻辑)===================== # 添加可执行文件(用 SOURCE_DIR 定位源码目录,语义更清晰) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) # 设置头文件目录(两种写法均可,此处用 SOURCE_DIR 更贴合源码目录语义) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${TestLib_INCLUDE_DIRS} # 自定义模块返回的头文件目录 ) # 链接自定义模块(模拟) if(TestLib_FOUND) message("项目构建成功!将链接 TestLib(模拟)") endif()1.3.项目信息变量
PROJECT_NAME
项目名称(由project()命令定义,如project(MyProject))。PROJECT_VERSION
项目版本(由project()命令指定,如project(MyProject VERSION 1.2.3))。PROJECT_VERSION_MAJOR/MINOR/PATCH
自动拆分的主 / 次 / 补丁版本号(基于PROJECT_VERSION)。
引用示例:
# 设置可执行文件版本 set_target_properties(my_app PROPERTIES VERSION ${PROJECT_VERSION})1.4.系统与平台变量
CMAKE_SYSTEM_NAME
操作系统名称(如Linux、Windows、Darwin)。CMAKE_SYSTEM_PROCESSOR
处理器架构(如x86_64、arm64、aarch64)。WIN32/UNIX/APPLE
布尔变量,标识是否为 Windows 或 Unix 类系统(APPLE标识 macOS)。CMAKE_SIZEOF_VOID_P
指针大小(用于判断 32 位 / 64 位系统)。- CMAKE_CXX_PLATFORM_ID: CMake 内置只读变量,标识当前 C++ 编译器所在平台,用来区分系统平台。取值只读,不能 set 修改。常见值为:Windows、Linux、macOS、Android、FreeBSD
引用示例:
# 方式1:CXX架构ID if(CMAKE_CXX_ARCHITECTURE_ID STREQUAL "X64") message("当前CPU:x64") endif() # 方式2:跨平台通用写法 if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") set(CPU_ARCH "x64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") set(CPU_ARCH "arm64") else() set(CPU_ARCH "x86") endif() message("CPU架构: ${CPU_ARCH}") # 根据平台设置不同的链接库 if(WIN32) target_link_libraries(my_app PRIVATE ws2_32) # Windows 网络库 else() target_link_libraries(my_app PRIVATE pthread) # Unix 线程库 endif()1.5.工具链与交叉编译
CMAKE_TOOLCHAIN_FILE
工具链文件路径(用于交叉编译,如arm-linux-gnueabihf.toolchain.cmake)。CMAKE_C_COMPILER_FORCED/CMAKE_CXX_COMPILER_FORCED
强制指定编译器,忽略环境变量和默认搜索。CMAKE_CROSSCOMPILING
布尔变量,标识是否为交叉编译模式。
1.6.测试与安装变量
CMAKE_TEST_COMMAND
测试执行命令(默认ctest,可修改为其他测试工具)。CMAKE_INSTALL_COMMAND
安装命令(默认make install,对应不同生成器)。CMAKE_INSTALL_INCLUDEDIR/LIBDIR
安装时头文件 / 库文件的子目录(默认include/lib)。
1.7.高级编译选项
CMAKE_EXPORT_COMPILE_COMMANDS
布尔变量,生成compile_commands.json(用于 clangd 等工具)。CMAKE_POSITION_INDEPENDENT_CODE
布尔变量,强制生成位置无关代码(PIC,用于动态库)。CMAKE_CXX_VISIBILITY_PRESET
设置符号可见性(如hidden减少库暴露符号)。
2.常用环境变量
环境变量在 CMake 中通过$ENV{VAR_NAME}引用,常用于传递系统级配置。
2.1.编译器与工具链
| 环境变量名 | 描述 |
|---|---|
CC | C 编译器(如gcc、clang) |
CXX | C++ 编译器(如g++、clang++) |
PATH | 系统搜索路径,影响find_program等命令 |
引用示例:
# 使用环境变量指定的编译器 if(DEFINED ENV{CC}) set(CMAKE_C_COMPILER $ENV{CC}) endif() # 在 PATH 中查找工具 find_program(CLANG_FORMAT clang-format)2.2.依赖库路径
| 环境变量名 | 描述 |
|---|---|
LD_LIBRARY_PATH | Linux 动态库搜索路径 |
DYLD_LIBRARY_PATH | macOS 动态库搜索路径 |
CPATH | C/C++ 头文件搜索路径 |
LIBRARY_PATH | 静态库搜索路径 |
引用示例:
# 从环境变量添加头文件搜索路径 include_directories($ENV{CPATH}) # 查找依赖库 find_library(FOO_LIB NAMES foo HINTS $ENV{LD_LIBRARY_PATH})2.3.CMake 专用环境变量
| 环境变量名 | 描述 |
|---|---|
CMAKE_PREFIX_PATH | CMake 查找依赖的前缀路径(多个路径用;分隔) |
BUILD_TYPE | 自定义构建类型(可替代CMAKE_BUILD_TYPE) |
CMAKE_PREFIX_PATH是 CMake 中用于指定依赖包搜索路径的核心变量,为find_package()、find_program()、find_library()、find_file()和find_path()等命令提供根搜索目录,尤其适用于定位非标准安装路径的第三方库。
CMake 按以下顺序查找依赖包(优先级从高到低):
- 特定包的
XXX_DIR变量(如OpenCV_DIR)— 最高优先级,直接指定包配置文件路径 - CMAKE_PREFIX_PATH— 手动指定的搜索前缀
- CMAKE_SYSTEM_PREFIX_PATH— 系统默认前缀(如
/usr/local、/usr、C:\Program Files) - PATH 环境变量— 系统可执行文件路径
搜索机制:CMake 会在每个前缀目录下自动查找标准子目录,如:
bin:可执行文件lib/lib64:库文件include:头文件lib/cmake/XXX:包配置文件(Config 模式)
设置方法(5 种常用方式)
1.命令行参数(推荐,临时生效)
# Unix/Linux/macOS cmake .. -DCMAKE_PREFIX_PATH="/path/to/libA;/path/to/libB" # Windows (PowerShell) cmake .. -DCMAKE_PREFIX_PATH="C:/path/to/libA;C:/path/to/libB" # Windows (Command Prompt) cmake .. -DCMAKE_PREFIX_PATH=C:\path\to\libA;C:\path\to\libB2.环境变量(全局生效)
# Unix/Linux/macOS (临时) export CMAKE_PREFIX_PATH="/path/to/libA:/path/to/libB" # Unix/Linux/macOS (永久,添加到 ~/.bashrc 或 ~/.zshrc) echo 'export CMAKE_PREFIX_PATH="/path/to/libA:/path/to/libB"' >> ~/.bashrc source ~/.bashrc # Windows (PowerShell 临时) $env:CMAKE_PREFIX_PATH = "C:\path\to\libA;C:\path\to\libB" # Windows (永久,通过系统属性设置环境变量) setx CMAKE_PREFIX_PATH "C:\path\to\libA;C:\path\to\libB" ```{insert\_element\_4\_} #### 3. CMakeLists.txt 中设置(项目级) ```cmake # 覆盖原有值 set(CMAKE_PREFIX_PATH "/path/to/libA;/path/to/libB" CACHE PATH "My custom prefix path") # 追加路径(推荐,不影响原有设置) list(APPEND CMAKE_PREFIX_PATH "/path/to/new/lib")3.CMake 缓存编辑
运行 cmake-gui 或 ccmake 找到 CMAKE_PREFIX_PATH 变量进行编辑 保存并重新配置4.针对特定包的 ROOT 变量(3.12+)
# 替代 CMAKE_PREFIX_PATH 的特定包设置 cmake .. -DOpenCV_ROOT="/path/to/opencv" ```{insert\_element\_6\_} ### 四、最佳实践与注意事项 1. **路径顺序**:越重要的路径越靠前,CMake 按顺序搜索,找到第一个匹配项即停止 2. **跨平台兼容性**: - Unix 系统用冒号 `:` 分隔路径,CMake 内部会自动转换为分号 - Windows 系统用分号 `;` 分隔路径,避免使用反斜杠 `\`(或用双反斜杠 `\\`){insert\_element\_7\_} 3. **避免硬编码**:优先使用命令行或环境变量设置,保持 CMakeLists.txt 通用性 4. **结合 `find_package`**: ```cmake # 示例:查找非标准路径的 Qt set(CMAKE_PREFIX_PATH "/opt/Qt5.15.2/5.15.2/gcc_64" CACHE PATH "Qt installation path") find_package(Qt5 REQUIRED COMPONENTS Core Widgets)5.本地构建库:对于未安装的库,可指向其构建目录
cmake .. -DCMAKE_PREFIX_PATH="/path/to/my_lib/build"引用示例:
# 使用环境变量设置构建类型 if(DEFINED ENV{BUILD_TYPE}) set(CMAKE_BUILD_TYPE $ENV{BUILD_TYPE}) endif() # 从环境变量添加查找路径 list(APPEND CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})2.4.系统环境变量Path
# 将当前项目源码目录下的 dependencies 文件夹追加到系统环境变量 Path 的末尾 set(ENV{Path} "$ENV{Path};${CMAKE_CURRENT_SOURCE_DIR}/dependencies")| 代码片段 | 作用说明 |
|---|---|
set(ENV{Path} ...) | CMake 中修改系统环境变量Path的语法(ENV表示环境变量) |
$ENV{Path} | 保留系统原有的Path环境变量值(避免覆盖原有配置) |
; | Windows 系统下环境变量的路径分隔符(Linux 为:) |
${CMAKE_CURRENT_SOURCE_DIR} | CMake 内置变量,指代当前 CMakeLists.txt 所在的源码目录 |
/dependencies | 指向项目根目录下的dependencies文件夹(用于存放第三方依赖库 / 可执行文件) |
这段代码的目的是让 CMake 构建的项目,在运行时能自动加载dependencies文件夹中的第三方动态库(如.dll、.so)或可执行程序,无需手动将依赖路径添加到系统全局的Path中,保证项目环境的独立性。
我们可以把环境变量分为 3 个层级,权限和生命周期完全不同:
- 系统全局环境变量(你在电脑设置里查的)永久生效,所有程序都能用,修改需要手动配置 / 管理员权限,CMake无权、也不会修改它。
- 用户环境变量同样是永久配置,CMake 也不会碰。
- 进程临时环境变量(CMake 唯一能改的)当你运行 CMake 构建项目时,系统会单独启动一个 CMake 进程,这个进程会复制一份系统的
Path给自己用。set(ENV{Path})只是修改这个临时复制的副本,仅对:- 当前 CMake 构建过程
- CMake 启动的子进程(比如编译器、生成的程序)生效。
永久修改系统环境变量的正确方式:
- Windows:此电脑 → 属性 → 高级系统设置 → 环境变量 → 编辑
Path - Linux/macOS:修改
~/.bashrc/~/.zshrc配置文件
3.变量与环境变量的区别
| 特性 | CMake 变量 | 环境变量 |
|---|---|---|
| 定义方式 | set(VAR value) | 系统命令(如export VAR=value) |
| 作用域 | 局部或全局(取决于设置方式) | 全局(整个 shell 会话) |
| 引用方式 | ${VAR} | $ENV{VAR} |
| 典型用途 | 项目内部配置、路径拼接 | 系统级配置、跨项目共享设置 |
4.变量引用实践
1.避免硬编码路径:
# 不推荐 include_directories("/usr/local/include") # 推荐 include_directories(${CMAKE_INSTALL_PREFIX}/include)2.环境变量默认值:
# 使用环境变量或默认值 set(MY_LIB_PATH $ENV{MY_LIB_PATH} CACHE PATH "自定义库路径") if(NOT MY_LIB_PATH) set(MY_LIB_PATH "/usr/local") endif()3.条件编译与平台适配:
if(WIN32) set(PLATFORM_LIBS ws2_32) elseif(APPLE) set(PLATFORM_LIBS "-framework CoreFoundation") else() set(PLATFORM_LIBS pthread) endif() target_link_libraries(my_app PRIVATE ${PLATFORM_LIBS})5.常见问题排查
1.变量未定义错误
- 使用
message(STATUS "VAR = ${VAR}")打印变量值 - 通过
if(DEFINED VAR)检查变量是否存在
2.环境变量不生效
- 确保环境变量在运行 CMake 前已设置
- 使用
message(STATUS "ENV_VAR = $ENV{VAR}")验证环境变量值
3.跨平台差异
- Windows 环境变量区分大小写,Linux/macOS 通常不区分
- 路径分隔符:Windows 使用
\,Unix 使用/(CMake 中统一用/)
6.查看所有内部变量
- 在命令行中运行
cmake -L列出所有变量(含内部变量)。 - 使用
cmake-gui并勾选Advanced选项,查看完整变量列表。 - 在 CMake 脚本中通过
message(STATUS ${VARIABLE_NAME})打印变量值。
这些内部变量覆盖了编译、平台适配、路径管理等核心功能,合理使用可大幅提升 CMake 脚本的灵活性和可移植性。更多细节可查阅 CMake 官方变量文档。
相关链接
- CMake 官网 CMake - Upgrade Your Software Build System
- CMake 官方文档:CMake Tutorial — CMake 4.0.3 Documentation
- CMake 源码:https://github.com/Kitware/CMake
- CMake 源码:CMake · GitLab
- 中文版基础介绍: CMake 入门实战 | HaHack
- wiki: Home · Wiki · CMake / Community · GitLab
- Modern CMake 简体中文版: Introduction · Modern CMake
