当前位置: 首页 > news >正文

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
    构建类型(DebugReleaseRelWithDebInfoMinSizeRel),影响优化和调试选项。
  • CMAKE_C_COMPILER/CMAKE_CXX_COMPILER
    指定 C/C++ 编译器路径(如gccclang)。
  • 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++ 语言标准版本(如1117)。
  • 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_packageinclude
  • 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
    操作系统名称(如LinuxWindowsDarwin)。
  • CMAKE_SYSTEM_PROCESSOR
    处理器架构(如x86_64arm64aarch64)。
  • 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.编译器与工具链

环境变量名描述
CCC 编译器(如gccclang
CXXC++ 编译器(如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_PATHLinux 动态库搜索路径
DYLD_LIBRARY_PATHmacOS 动态库搜索路径
CPATHC/C++ 头文件搜索路径
LIBRARY_PATH静态库搜索路径

引用示例

# 从环境变量添加头文件搜索路径 include_directories($ENV{CPATH}) # 查找依赖库 find_library(FOO_LIB NAMES foo HINTS $ENV{LD_LIBRARY_PATH})

2.3.CMake 专用环境变量

环境变量名描述
CMAKE_PREFIX_PATHCMake 查找依赖的前缀路径(多个路径用;分隔)
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/usrC:\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\libB

2.环境变量(全局生效)

# 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.查看所有内部变量

  1. 在命令行中运行cmake -L列出所有变量(含内部变量)。
  2. 使用cmake-gui并勾选Advanced选项,查看完整变量列表。
  3. 在 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
http://www.jsqmd.com/news/860969/

相关文章:

  • Enumerize扩展模块:如何创建可重用的枚举定义
  • Octree-GS终极指南:如何用LOD结构化3D高斯实现实时大规模场景渲染
  • 10分钟掌握XGBoost:机器学习竞赛的终极梯度提升库
  • Midjourney纹理生成终极瓶颈曝光:GPU显存≠关键,真正卡点是CLIP文本嵌入层的纹理语义坍缩(附3种绕过方案)
  • 从elm-react-native学习React Native最佳实践:10个关键开发技巧
  • 不锈钢防火玻璃门——工程场景下安全与通透的平衡方案
  • Cookies.js 与其他Cookie库对比:终极优势分析与适用场景指南
  • OpenELB安全配置:RBAC、网络策略与证书管理最佳实践
  • 什么是换根DP及第一步操作说明
  • CANN/asc-devkit获取向量寄存器长度API
  • 案例11_2:液晶应用实例LCD1602(2)
  • SPlisHSPlasH部署与构建指南:Windows与Linux环境完整配置流程
  • Cookies.js 错误处理机制终极指南:编码异常与浏览器兼容性问题解决方案
  • Linux操作系统-逻辑卷管理(LVM)
  • No!! MeiryoUI终极指南:3步恢复Windows界面字体自定义功能
  • CANN/asc-devkit:获取核心内存带宽API
  • 深度防御架构:unblob的多层安全防护与权限隔离实践
  • 蓝晒法AI化转型关键突破,仅限前200名领取:含47个已验证蓝晒LUT预设+光照角度黄金比例表
  • 终极GTA5安全增强菜单:YimMenu完整使用指南与防护策略
  • 软工作业4
  • 基于PhasorDetect手持NIRS设备多光谱反射数据的组织氧饱和度实时监测研究附Matlab代码
  • SchemaCrawler:终极数据库模式发现与理解工具完全指南
  • Rufus终极指南:轻松创建Windows安装USB并绕过硬件限制
  • ElevenLabs希腊文语音本地化交付SOP,含欧盟GDPR语音数据脱敏协议模板与ASR对齐验证脚本
  • BiliTools终极指南:跨平台哔哩哔哩工具箱的完整使用教程
  • Faster RCNN PyTorch部署指南:从训练模型到生产环境
  • OmniSharp-vim与主流补全插件集成:asyncomplete、coc.nvim、deoplete配置详解
  • 第六届辽宁省大学生程序设计竞赛 B题思路分享(数论,构造,欧拉定理)
  • 3个真实开发场景:Continue如何让你的JetBrains IDE变成AI编程伙伴
  • 新手入门指南从注册Taotoken到发出第一个ChatCompletion请求