ROS云课三分钟-cmake默认版本和升级-260120

如何查看云端系统内核版本

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)

总结

  1. CMake 核心是编写 CMakeLists.txt,最基础的三行指令:指定版本、项目名、添加可执行文件;
  2. 推荐使用「外部构建」(创建 build 目录),避免编译产物污染源码;
  3. 核心流程:编写源码 → 编写 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,实现分目录管理配置,适合大型项目

总结

  1. 进阶 CMake 核心是分目录管理 +库编译:将核心逻辑封装为静态库,主程序链接库文件,提高代码复用性;
  2. target_* 系列指令(target_include_directories/target_link_libraries)是现代 CMake 的核心,精准控制目标的依赖和编译属性;
  3. 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++ 开发有两大痛点:

  1. 构建文件不通用 :Linux 写 Makefile,Windows 写 VS 工程,macOS 写 Xcode 工程,维护多套配置成本极高;
  2. Makefile 编写复杂:手动写复杂的 Makefile 容易出错,尤其是多目录、多库的大型项目;
  3. 依赖管理繁琐:手动处理头文件路径、库链接、编译选项,容易出现「在 A 机器能编译,B 机器编译失败」的问题。

CMake 正是为解决这些问题而生:一份 CMakeLists.txt,适配所有主流平台和构建工具

三、CMake 的核心优势

  1. 跨平台性:支持 Linux/macOS/Windows/Android/iOS 等几乎所有主流平台,无需为不同平台写不同配置;
  2. 易用性 :相比手写 Makefile,CMake 指令更简洁、语义更清晰(比如 target_link_libraries 直接链接库,无需手动写链接参数);
  3. 扩展性:支持静态库 / 动态库编译、条件编译、版本管理、自定义编译规则、第三方库集成(如 FindBoost.cmake);
  4. 生态完善:几乎所有主流 C/C++ 项目(如 OpenCV、Qt、TensorFlow)都用 CMake 作为构建系统,学习成本有高回报;
  5. 现代特性 :「目标(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 的核心思想

  1. 基于「目标(Target)」 现代 CMake(3.0+)的核心是「目标」------ 可执行文件(add_executable)、库(add_library)都是「目标」。所有编译属性(头文件路径、编译选项、库链接)都绑定到具体目标(如 target_include_directories),而非全局设置,避免冲突。

  2. Out-of-Source Build(外部构建) 推荐将编译产物(临时文件、可执行文件)放在单独的 build 目录,与源码分离:

    • 优点:源码目录干净,删除 build 即可清空所有编译产物,支持多套编译配置(如 debug/release)。
  3. 声明式配置 你只需要告诉 CMake「要做什么」(比如「编译一个叫 calc_app 的可执行文件,链接 calc_lib 库」),无需关心「怎么做」(比如链接库需要加 -l 参数、头文件路径需要加 -I 参数),CMake 会自动处理底层细节。

六、CMake 的适用场景

  • 小项目:替代手写 Makefile,简化编译流程;
  • 中大型项目:分目录管理、库编译、依赖管理、跨平台发布;
  • 开源项目:适配不同用户的系统和编译环境,降低使用者的接入成本;
  • 工程化开发:集成测试、安装规则(make install)、打包(CPack)等。

总结

  1. CMake 是「构建系统生成器」,核心价值是跨平台、简化构建配置,而非直接编译代码;
  2. 现代 CMake 以「目标(Target)」为核心,通过 target_* 系列指令精准控制编译属性;
  3. 核心工作流程是「配置阶段(生成构建文件)+ 构建阶段(编译源码)」,外部构建(build 目录)是最佳实践。

理解这些核心概念后,你之前写的基础案例、进阶案例就不再是「记指令」,而是能明白每个指令背后的设计逻辑,后续学习更复杂的 CMake 用法(如集成第三方库、条件编译、安装规则)也会更轻松。

相关推荐
通信小呆呆3 天前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
H__Rick3 天前
自动对焦学习-3
人工智能·学习·计算机视觉
Daisy Lee3 天前
量化学习-第1章-什么是量化金融
学习·金融·datawhale
Alsn863 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
YM52e3 天前
买菜计算器小应用 - HarmonyOS ArkUI 开发实战-PC版本
学习·华为·harmonyos·鸿蒙·鸿蒙系统
小雨下雨的雨3 天前
HarmonyOS ArkUI训练营入门-组件掌握系列-Animation 动画效果实现-PC版本
学习·华为·harmonyos·鸿蒙
闪闪发亮的小星星3 天前
高斯光以及高斯光公式解释
笔记
cqbzcsq3 天前
CellFlow虚拟细胞论文阅读
论文阅读·人工智能·笔记·学习·生物信息
YangYang9YangYan3 天前
2026初入职场学习数据分析的价值
学习·数据挖掘·数据分析
阿米亚波3 天前
【Windows】QEMU 启动 openEuler aarch64/arm64 架构系统 + 离线软件源
linux·windows·经验分享·笔记·架构·arm