经常在技术群里看到两类问题:一类人卡在Shell脚本的语法上,变量和符号搞不清楚;另一类人拿着CMakeLists.txt发懵,不知道那几行配置到底在干嘛。说实话,这两样东西放在一起学,效果反而最好。因为Shell是你和系统交互的“对话语言”,而CMake是很多C/C++项目实际使用的“构建大脑”,两者结合正好覆盖了从命令行操作到工程构建的完整链路。这篇文章我就把自己的使用经验整理出来,讲清楚Shell的基础语法、CMake的核心用法,再带大家写一个用Shell驱动CMake构建的完整脚本,适合刚接触Linux开发、或者从Windows转到嵌入式/C++方向的同学参考。
1. Shell语言基础:先把这些核心概念吃透
1.1 Shell到底是什么,值得花时间学吗
Shell直译过来是“壳”,它是用户和操作系统内核之间的一层解释器。你在终端里敲的每一条命令,都是经过Shell解释之后才交给内核去执行的。Linux和macOS上最常见的是Bash,Windows上如果你装了Git Bash或者WSL,同样能跑Shell脚本。
我个人的看法是:Shell是自动化一切重复劳动的起点。编译、打包、部署、批量处理文件,凡是你在终端里手动敲过的命令,都可以写成脚本让它自动执行。写十遍编译命令,不如写一次build.sh然后每次都敲一句./build.sh来得痛快。最早让我觉得Shell“真香”的场景是批量重命名日志文件,有一批文件叫log_20240101.txt、log_20240102.txt这种格式,想全部改成2024-01-01.log,手动改要改几十个,用Shell的for循环几行就搞定了。很多人第一次意识到Shell的威力,基本都是从这种批量操作的场景开始的。
1.2 变量、参数与特殊符号:${}和$()到底差在哪
这是Shell入门时最容易搞混的两个符号,技术群里隔三差五就有人问“linux shell ${}和$()区别是什么”,今天一次说清楚。
$()是命令替换,意思是在这个括号里先执行命令,把命令的输出结果当成一个值来用。比如:
bash复制today=$(date +%Y%m%d)
echo $today
这里先执行date命令拿到日期字符串,然后赋值给today变量。类似的需求还有获取当前目录、获取CPU核心数等等,核心思路都是“先把命令跑完,把结果拿来用”。
${}是变量扩展,告诉Shell“花括号里的名字是一个变量名”。简单场景下写$var和${var}没区别,但在变量名后面紧跟着其他字符时就必须用花括号了:
bash复制name="world"
echo "hello ${name}!"
echo "hello ${name}x"
第二行如果写成$namex,Shell会认为存在一个叫namex的变量,结果就是空字符串,而且不报错。把变量拼接到路径里时最容易踩这个坑,排查起来特别费劲。
再补充几个写脚本必须知道的位置参数:$0是脚本名,$1、$2是第一个、第二个参数,$#是参数个数,$@是所有参数。处理命令行输入时,这些都是基础中的基础。
1.3 shift命令:处理参数的隐藏利器
shift的作用是把位置参数往左移一位,原来的$2变成$1,$3变成$2。最常见的用法是配合while循环逐个解析命令行选项。
比如写一个安装脚本,支持-a表示安装所有组件、-p后面跟安装路径:
bash复制#!/bin/bash
install_all=false
install_path=""
while [ $# -gt 0 ]; do
case "$1" in
-a)
install
