如何查看云端系统内核版本
lsb_release -a
shiyanlou:~/ $ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.6 LTS
Release: 20.04
Codename: focal

如何查看cmake版本
cmake --version
shiyanlou:~/ $ cmake --version
cmake version 3.16.3
CMake suite maintained and supported by Kitware (kitware.com/cmake).

错误升级cmake
sudo pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple cmake
shiyanlou:~/ $ sudo pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple cmake
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting cmake
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/28/19/b54ff2e03946beeef785e6407d965a9493d26c50dd1aa09ffc7b53fbf9a5/cmake-4.2.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (28.9 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 28.9/28.9 MB 10.6 MB/s eta 0:00:00
Installing collected packages: cmake
Successfully installed cmake-4.2.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
notice A new release of pip is available: 24.0 -> 25.0.1
notice To update, run: pip3.8 install --upgrade pip

查询更新效果cmake
失败了吧^_^

合理的方式
bash
# 1. 创建并激活 Python3.8 虚拟环境
python3.8 -m venv myenv
source myenv/bin/activate
# 2. 在虚拟环境中安装/升级 cmake(无需 sudo)
pip3.8 install -i https://pypi.tuna.tsinghua.edu.cn/simple cmake==3.25.0 --upgrade
# 3. 验证版本
cmake --version
# 4. 退出虚拟环境(如需)
deactivate
可以指定版本,不指定版本升级到最新版。
pip3.8 install -i https://pypi.tuna.tsinghua.edu.cn/simple cmake --upgrade

- 避免使用
sudo pip,优先通过虚拟环境 或系统包管理器(apt) 安装软件包; - 若需指定 cmake 版本,可在虚拟环境中用
pip install cmake==xxx精准安装。
基础入门-AI
你已经成功在虚拟环境中确认了 cmake 4.2.1 版本,接下来我会给你一个极简且完整的 CMake 入门实例,包含基础的 C/C++ 源码、CMakeLists.txt 编写、编译和运行全流程,让你快速掌握 CMake 的核心用法。
一、实例场景
我们用 CMake 编译一个简单的 C 语言程序(计算两数之和),涵盖 CMake 最基础的指令:指定版本、项目名称、添加可执行文件。
二、完整操作步骤
1. 创建项目目录和源码文件
先创建一个专属目录,避免文件混乱:
bash
运行
# 创建项目目录并进入
mkdir cmake_demo && cd cmake_demo
# 创建 C 语言源码文件 main.c
touch main.c
编辑 main.c(可以用 vim 或 nano,新手推荐 nano):
bash
运行
nano main.c
粘贴以下代码(实现两数相加功能):
c
运行
#include <stdio.h>
int main() {
int a = 10, b = 20;
printf("Hello CMake!\n");
printf("a + b = %d\n", a + b);
return 0;
}
按 Ctrl+O 保存,Ctrl+X 退出 nano。
2. 编写核心文件 CMakeLists.txt
CMake 的核心是 CMakeLists.txt(文件名大小写敏感,必须这么写),创建并编辑:
bash
运行
touch CMakeLists.txt
nano CMakeLists.txt
粘贴以下内容(每行都有注释,新手易理解):
cmake
# 1. 指定 CMake 最低版本要求(匹配你的 4.2.1,也可写 3.0 以上)
cmake_minimum_required(VERSION 3.0)
# 2. 定义项目名称(自定义,比如 cmake_demo)
project(cmake_demo)
# 3. 添加可执行文件:格式为 可执行文件名 源码文件
# 这里生成的可执行文件叫 demo,源码是 main.c
add_executable(demo main.c)
同样按 Ctrl+O 保存,Ctrl+X 退出。
3. 用 CMake 构建编译文件并编译
CMake 推荐Out-of-Source Build(外部构建,源码和编译产物分离),步骤如下:
bash
运行
# 1. 创建编译目录并进入(存放临时文件和可执行文件)
mkdir build && cd build
# 2. 运行 cmake 生成 Makefile(指定上级目录的 CMakeLists.txt)
cmake ..
# 3. 编译(等同于 make,-j 后加数字表示多核编译,更快)
cmake --build . -j2
4. 运行生成的可执行文件
编译完成后,build 目录下会生成 demo 可执行文件,运行即可:
bash
运行
./demo
三、预期输出
运行后会看到:
plaintext
Hello CMake!
a + b = 30
四、核心指令解释
| 指令 | 作用 |
|---|---|
cmake_minimum_required(VERSION 3.0) |
指定 CMake 最低版本,避免兼容性问题 |
project(cmake_demo) |
定义项目名称,会影响生成的文件命名、编译环境等 |
add_executable(demo main.c) |
告诉 CMake:要生成一个名为 demo 的可执行文件,源码是 main.c |
cmake .. |
从 build 目录向上找 CMakeLists.txt,生成 Makefile |
cmake --build . |
执行编译,等价于在 build 目录运行 make |
五、进阶小扩展(可选)
如果你的源码有多个文件(比如 main.c + calc.c),只需修改 CMakeLists.txt:
cmake
cmake_minimum_required(VERSION 3.0)
project(cmake_demo)
# 多个源码文件用空格分隔
add_executable(demo main.c calc.c)
总结
- CMake 核心是编写
CMakeLists.txt,最基础的三行指令:指定版本、项目名、添加可执行文件; - 推荐使用「外部构建」(创建 build 目录),避免编译产物污染源码;
- 核心流程:
编写源码 → 编写 CMakeLists.txt → 创建 build 目录 → cmake .. → cmake --build . → 运行可执行文件。
这个实例覆盖了 CMake 入门的核心用法,你可以基于此修改源码(比如写 C++ 程序,只需把 .c 改成 .cpp),快速熟悉 CMake 的使用逻辑。
更进一步-AI
你已经掌握了 CMake 的基础用法,接下来我为你提供一个进阶版 CMake 实战案例 ,这个案例模拟真实项目场景:包含多源文件、多目录结构、静态库编译、头文件路径配置、编译选项控制、版本号定义等核心进阶特性,能帮你理解 CMake 在实际项目中的应用方式。
一、进阶案例场景
我们构建一个「简易计算器」项目,结构如下(分目录管理源码和头文件,将核心计算逻辑编译为静态库,主程序链接库文件运行):
plaintext
calc_project/ # 项目根目录
├── CMakeLists.txt # 根目录CMake配置
├── include/ # 头文件目录
│ └── calc.h # 计算器函数声明
├── src/ # 源码目录
│ ├── CMakeLists.txt # 子目录CMake配置
│ ├── calc.c # 计算器函数实现
│ └── main.c # 主程序(调用库函数)
└── build/ # 编译目录(外部构建)
二、完整实现步骤
1. 创建项目目录结构
先按上述结构创建所有目录和文件:
bash
运行
# 创建根目录并进入
mkdir -p calc_project/{include,src,build} && cd calc_project
# 创建头文件
touch include/calc.h
# 创建子目录源码和CMake文件
touch src/calc.c src/main.c src/CMakeLists.txt
# 创建根目录CMake文件
touch CMakeLists.txt
2. 编写头文件(include/calc.h)
声明计算器核心函数,同时定义版本宏(后续由 CMake 注入):
c
运行
#ifndef CALC_H
#define CALC_H
// 版本号(由CMake定义)
#define CALC_VERSION_MAJOR @CALC_VERSION_MAJOR@
#define CALC_VERSION_MINOR @CALC_VERSION_MINOR@
// 计算器核心函数声明
int add(int a, int b); // 加法
int subtract(int a, int b); // 减法
int multiply(int a, int b); // 乘法
double divide(int a, int b); // 除法(处理除零)
#endif // CALC_H
3. 编写核心实现文件(src/calc.c)
实现计算器函数,包含异常处理(除零判断):
c
运行
#include "calc.h"
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int multiply(int a, int b) {
return a * b;
}
double divide(int a, int b) {
if (b == 0) {
printf("Error: 除数不能为0!\n");
return 0.0;
}
return (double)a / b;
}
4. 编写主程序(src/main.c)
调用静态库函数,打印版本号和计算结果:
c
运行
#include "calc.h"
#include <stdio.h>
int main() {
// 打印版本号
printf("=== 简易计算器 v%d.%d ===\n", CALC_VERSION_MAJOR, CALC_VERSION_MINOR);
// 测试计算
int a = 20, b = 5;
printf("%d + %d = %d\n", a, b, add(a, b));
printf("%d - %d = %d\n", a, b, subtract(a, b));
printf("%d × %d = %d\n", a, b, multiply(a, b));
printf("%d ÷ %d = %.2f\n", a, b, divide(a, b));
// 测试除零
printf("%d ÷ %d = %.2f\n", a, 0, divide(a, 0));
return 0;
}
5. 编写子目录 CMake 配置(src/CMakeLists.txt)
将 calc.c 编译为静态库,并指定头文件路径:
cmake
# 1. 收集源码文件(也可直接写 calc.c,file 指令更灵活)
file(GLOB CALC_SOURCES "calc.c")
# 2. 编译静态库:库名 calc_lib,源码为 CALC_SOURCES
add_library(calc_lib STATIC ${CALC_SOURCES})
# 3. 指定头文件搜索路径(让编译器找到 include 目录的 calc.h)
# INTERFACE 表示:链接该库的目标(如 main)会继承这个头文件路径
target_include_directories(calc_lib
INTERFACE ${CMAKE_SOURCE_DIR}/include
PRIVATE ${CMAKE_SOURCE_DIR}/include
)
# 4. 添加可执行文件:主程序 main.c,生成可执行文件 calc_app
add_executable(calc_app main.c)
# 5. 链接静态库:让 calc_app 链接 calc_lib
target_link_libraries(calc_app PRIVATE calc_lib)
# 6. 设置编译选项(开启警告、C99标准)
target_compile_options(calc_app PRIVATE -Wall -std=c99)
target_compile_options(calc_lib PRIVATE -Wall -std=c99)
6. 编写根目录 CMake 配置(CMakeLists.txt)
配置项目版本、全局编译选项、包含子目录:
cmake
# 1. 指定CMake最低版本
cmake_minimum_required(VERSION 3.0)
# 2. 项目名称、版本号、语言(C语言)
project(CalcProject
VERSION 1.0 # 版本号 1.0(MAJOR=1,MINOR=0)
LANGUAGES C # 指定编译语言为C(默认C/C++)
)
# 3. 配置头文件:将 @CALC_VERSION_MAJOR@ 替换为实际版本号
# 生成 calc_config.h 文件到 include 目录
configure_file(
${CMAKE_SOURCE_DIR}/include/calc.h
${CMAKE_SOURCE_DIR}/include/calc.h
@ONLY
)
# 4. 包含子目录(执行 src/CMakeLists.txt)
add_subdirectory(src)
# 5. 设置全局编译选项(可选,也可在子目录单独设置)
if(CMAKE_COMPILER_IS_GNUCC)
add_compile_options(-Wall -Wextra -O2) # 开启警告、优化
endif()
三、编译并运行项目
进入 build 目录执行外部构建:
bash
运行
# 进入编译目录
cd build
# 1. 生成Makefile(基于根目录CMakeLists.txt)
cmake ..
# 2. 编译(-j2 多核编译,更快)
cmake --build . -j2
# 3. 运行可执行文件(在 build/src 目录下)
./src/calc_app
四、预期输出
plaintext
=== 简易计算器 v1.0 ===
20 + 5 = 25
20 - 5 = 15
20 × 5 = 100
20 ÷ 5 = 4.00
Error: 除数不能为0!
20 ÷ 0 = 0.00
五、核心进阶特性解释
| 特性 / 指令 | 作用 |
|---|---|
add_library(calc_lib STATIC ${CALC_SOURCES}) |
编译静态库(STATIC),区别于基础案例的直接编译可执行文件,适合代码复用 |
target_include_directories |
精准指定头文件路径,INTERFACE/PRIVATE 控制作用域,避免头文件找不到的问题 |
target_link_libraries |
将可执行文件链接到静态库,是多文件 / 多目录项目的核心 |
project(VERSION 1.0) + configure_file |
动态注入版本号到代码中,无需手动修改头文件,适合版本管理 |
target_compile_options |
为特定目标(可执行文件 / 库)设置编译选项(如警告、C 标准),更灵活 |
add_subdirectory(src) |
包含子目录的 CMakeLists.txt,实现分目录管理配置,适合大型项目 |
总结
- 进阶 CMake 核心是分目录管理 +库编译:将核心逻辑封装为静态库,主程序链接库文件,提高代码复用性;
target_*系列指令(target_include_directories/target_link_libraries)是现代 CMake 的核心,精准控制目标的依赖和编译属性;configure_file实现「代码与配置解耦」,比如版本号、编译开关等可由 CMake 统一管理,无需修改源码。
这个案例覆盖了实际项目中 80% 的 CMake 常用进阶用法,你可以在此基础上扩展(比如添加动态库、条件编译、安装规则等),进一步加深理解。
旧版:
https://blog.csdn.net/ZhangRelay/article/details/148171780
一、CMake 是什么?
CMake 不是编译器 ,也不是构建工具 (如 make/ninja),而是一个跨平台的构建系统生成器(Build System Generator)。
- 通俗理解:你用 CMake 写一份「平台无关」的配置文件(
CMakeLists.txt),CMake 会根据你的系统(Linux/macOS/Windows)和编译器(GCC/Clang/MSVC),自动生成对应的构建文件(比如 Linux 下的Makefile、Windows 下的 Visual Studio 工程文件、跨平台的 Ninja 配置)。 - 核心定位:桥梁------ 连接开发者的「通用配置」和不同平台的「底层构建工具」。
二、CMake 解决的核心问题
在 CMake 出现前,跨平台 C/C++ 开发有两大痛点:
- 构建文件不通用 :Linux 写
Makefile,Windows 写 VS 工程,macOS 写 Xcode 工程,维护多套配置成本极高; - Makefile 编写复杂:手动写复杂的 Makefile 容易出错,尤其是多目录、多库的大型项目;
- 依赖管理繁琐:手动处理头文件路径、库链接、编译选项,容易出现「在 A 机器能编译,B 机器编译失败」的问题。
CMake 正是为解决这些问题而生:一份 CMakeLists.txt,适配所有主流平台和构建工具。
三、CMake 的核心优势
- 跨平台性:支持 Linux/macOS/Windows/Android/iOS 等几乎所有主流平台,无需为不同平台写不同配置;
- 易用性 :相比手写 Makefile,CMake 指令更简洁、语义更清晰(比如
target_link_libraries直接链接库,无需手动写链接参数); - 扩展性:支持静态库 / 动态库编译、条件编译、版本管理、自定义编译规则、第三方库集成(如 FindBoost.cmake);
- 生态完善:几乎所有主流 C/C++ 项目(如 OpenCV、Qt、TensorFlow)都用 CMake 作为构建系统,学习成本有高回报;
- 现代特性 :「目标(Target)」为核心的设计(
target_*系列指令),精准控制编译属性,避免全局污染。
四、CMake 的工作流程
CMake 执行分为两个核心阶段,这也是你之前实操中「cmake .. + cmake --build .」的底层逻辑:
预览
查看代码
编写 CMakeLists.txt
运行 cmake 命令
生成平台专属构建文件
(如 Makefile/Ninja/VS工程)
运行构建命令
(cmake --build . 或 make/ninja)
编译器编译源码
生成可执行文件/库
graph TD
A[编写 CMakeLists.txt] --> B[运行 cmake 命令]
B --> C[生成平台专属构建文件<br/>(如 Makefile/Ninja/VS工程)]
C --> D[运行构建命令<br/>(cmake --build . 或 make/ninja)]
D --> E[编译器编译源码<br/>生成可执行文件/库]
编写 CMakeLists.txt
运行 cmake 命令
生成平台专属构建文件
(如 Makefile/Ninja/VS工程)
运行构建命令
(cmake --build . 或 make/ninja)
编译器编译源码
生成可执行文件/库

- 配置阶段(Configure) :执行
cmake ..,CMake 解析CMakeLists.txt,检查系统环境(编译器、库依赖),生成构建文件; - 构建阶段(Build) :执行
cmake --build .,调用底层构建工具(如 make),根据构建文件编译源码。
五、CMake 的核心思想
-
基于「目标(Target)」 现代 CMake(3.0+)的核心是「目标」------ 可执行文件(
add_executable)、库(add_library)都是「目标」。所有编译属性(头文件路径、编译选项、库链接)都绑定到具体目标(如target_include_directories),而非全局设置,避免冲突。 -
Out-of-Source Build(外部构建) 推荐将编译产物(临时文件、可执行文件)放在单独的
build目录,与源码分离:- 优点:源码目录干净,删除
build即可清空所有编译产物,支持多套编译配置(如 debug/release)。
- 优点:源码目录干净,删除
-
声明式配置 你只需要告诉 CMake「要做什么」(比如「编译一个叫 calc_app 的可执行文件,链接 calc_lib 库」),无需关心「怎么做」(比如链接库需要加
-l参数、头文件路径需要加-I参数),CMake 会自动处理底层细节。
六、CMake 的适用场景
- 小项目:替代手写 Makefile,简化编译流程;
- 中大型项目:分目录管理、库编译、依赖管理、跨平台发布;
- 开源项目:适配不同用户的系统和编译环境,降低使用者的接入成本;
- 工程化开发:集成测试、安装规则(
make install)、打包(CPack)等。
总结
- CMake 是「构建系统生成器」,核心价值是跨平台、简化构建配置,而非直接编译代码;
- 现代 CMake 以「目标(Target)」为核心,通过
target_*系列指令精准控制编译属性; - 核心工作流程是「配置阶段(生成构建文件)+ 构建阶段(编译源码)」,外部构建(build 目录)是最佳实践。
理解这些核心概念后,你之前写的基础案例、进阶案例就不再是「记指令」,而是能明白每个指令背后的设计逻辑,后续学习更复杂的 CMake 用法(如集成第三方库、条件编译、安装规则)也会更轻松。