3、基础语法与变量:注释方式、变量定义与引用、set()与message()命令、变量作用域基础
各位同学,欢迎来到第三章。这一章我们开始真正动手写CMake代码了。
说实话,很多初学者觉得CMake语法很怪——既不像C++,也不像Python。我当年刚接触时也有同感。但别担心,这一章我会带你把这些基础语法掰开揉碎讲清楚。
3.1 注释方式:给代码加点说明
写代码不写注释,三个月后连自己都看不懂。CMake支持三种注释方式,我一个个说。
3.1.1 单行注释
用 # 开头,整行都会被忽略。这是最常用的方式。
# 这是一个单行注释
set(MY_VAR "hello") # 行尾也可以加注释
3.1.2 块注释(CMake 3.0+)
用 #[[ 和 ]] 包裹。适合临时屏蔽一大段代码。
#[[
这是一段块注释
可以跨多行
set(TEMP_VAR "不会被执行")
]]
3.1.3 文档注释(CMake 3.0+)
用 #! 开头,配合 cmake --help-command 使用。说实话,这个我很少用,了解一下就行。
3.2 变量定义与引用:CMake的"内存小盒子"
变量就是存数据的小盒子。CMake里所有变量本质上都是字符串,这一点要记住。
3.2.1 变量命名规则
- 大小写敏感:
MY_VAR和my_var是两个变量 - 只能包含字母、数字、下划线
- 不能以数字开头
- 建议全大写+下划线风格(我个人的偏好)
3.2.2 变量引用
用 ${变量名} 来取值。这是CMake最核心的语法之一。
set(NAME "CMake教程")
message("课程名称是:${NAME}")
你想想看,如果没有 ${},我们怎么知道哪个是变量名哪个是普通文本?
${NAM} 但实际定义的是 ${NAME},CMake不会提醒你,只会默默返回空值。排查这种bug特别费时间。
3.3 set() 命令:给变量赋值
set() 是CMake里最常用的命令之一。它的基本语法是:
set(变量名 值1 值2 ...)
3.3.1 普通变量
set(MY_NAME "张三")
set(MY_AGE 25) # 数字也是字符串
set(MY_LIST a b c) # 多个值会变成列表
3.3.2 缓存变量
加 CACHE 关键字,变量会持久化到CMakeCache.txt中。
set(MY_OPTION "ON" CACHE BOOL "是否启用某个功能")
这个在大型项目中特别有用。用户可以通过 cmake -DMY_OPTION=OFF 来覆盖默认值。
3.3.3 环境变量
用 $ENV{变量名} 读取系统环境变量。
message("PATH环境变量:$ENV{PATH}")
3.4 message() 命令:调试利器
message() 就是CMake的 printf。我写CMake时,每写几行就要加个message看看变量值对不对。
3.4.1 基本用法
message("你好,CMake") # 普通消息
message(STATUS "正在配置...") # 带状态前缀
message(WARNING "这可能有风险") # 警告
message(FATAL_ERROR "出错了") # 致命错误,会终止配置
3.4.2 调试技巧
我个人最常用的是 STATUS 级别,它会在输出前加 -- 前缀,看起来更清晰。
set(SRC_FILES main.cpp utils.cpp)
message(STATUS "源文件列表:${SRC_FILES}")
FATAL_ERROR 会立即终止CMake执行。我在项目中用它来做前置条件检查,比如检测到编译器版本太低就直接报错退出。
3.5 变量作用域基础:变量能活多久?
变量的作用域,说白了就是变量在哪些地方能被访问到。CMake的作用域规则其实很简单。
3.5.1 全局作用域
在顶层CMakeLists.txt中定义的变量,默认是全局的。所有子目录都能访问。
# 顶层 CMakeLists.txt
set(GLOBAL_VAR "我是全局的")
add_subdirectory(src)
3.5.2 局部作用域
在 function() 或 macro() 内部定义的变量,默认是局部的。函数退出后变量就没了。
function(my_func)
set(LOCAL_VAR "我是局部的")
message("内部:${LOCAL_VAR}") # 能访问
endfunction()
my_func()
message("外部:${LOCAL_VAR}") # 空字符串
3.5.3 子目录作用域
用 add_subdirectory() 进入子目录时,CMake会创建一个新的作用域。子目录可以访问父目录的变量,但反过来不行。
# 父目录
set(PARENT_VAR "来自父目录")
add_subdirectory(child)
# child/CMakeLists.txt
message("${PARENT_VAR}") # 能访问
set(CHILD_VAR "子目录的")
# 父目录看不到 CHILD_VAR
set(... PARENT_SCOPE) 来显式向上传递变量。
3.6 知识体系总览
下面这张图把本章的核心知识点串起来了。你可以把它当作一个快速参考地图。
3.7 本章小结
这一章我们学了CMake最基础的语法元素。说白了就是三件事:怎么加注释、怎么定义变量、怎么打印调试信息。再加上作用域的概念,你已经可以看懂大部分简单的CMakeLists.txt了。
嗯,这里要提醒一下:变量作用域是初学者最容易搞混的地方。我的建议是——先记住"子目录能看父目录,父目录看不到子目录"这条铁律。等后面学到函数和宏时,我们再深入展开。
- 注释用
#,块注释用#[[ ]] - 变量引用用
${},拼写错误不会报错 set()定义变量,message()打印信息- 作用域遵循"向下可见,向上不可见"原则