弄懂CMake是什么,看完这篇就够了!
目录
1. 我们是如何手动编译C++文件的
1.1. 如何编译单个代码文件
想象一下,你正在厨房里做一道简单的煎蛋。你只需要一个鸡蛋、一个平底锅和一点油。这个过程非常简单,你只需要把鸡蛋打入锅中,煎一会儿,然后翻面再煎一会儿,最后就可以享用美味的煎蛋了。
在编程中,如果你只有一个源代码文件,比如 main.cpp,你可以直接使用 g++ 编译器来编译它。就像煎蛋一样,这个过程非常简单:
g++ -o myprogram main.cpp
这行命令会把 main.cpp 文件编译成一个可执行文件 myprogram。这里的 -o myprogram 是告诉 g++ 把生成的可执行文件命名为 myprogram。
1.2. 编译多个文件时变得很麻烦
现在,假设你要做一道更复杂的菜,比如巧克力蛋糕。你需要准备鸡蛋、面粉、巧克力、糖、牛奶等多种材料,并且需要按照一定的顺序和比例混合它们。如果你每次都要手动混合这些材料,不仅会很麻烦,还很容易出错。
在编程中,如果你有多个源代码文件,比如 main.cpp、player.cpp 和 player.h,直接使用 g++ 编译会变得非常复杂。你需要手动编写一个很长的命令来编译所有文件:
g++ -o myprogram main.cpp player.cpp
这行命令会编译 main.cpp 和 player.cpp 文件,并生成一个名为 myprogram 的可执行文件。
这看起来还不算太复杂,但如果项目更大,有几十个甚至上百个文件,手动编写这样的命令就变得非常困难。而且,如果文件之间的依赖关系复杂,比如 main.cpp 依赖于 player.h,你还需要手动管理这些依赖关系,这很容易出错。
1.3. CMake为此而诞生
CMake 就像是一个智能的厨房助手,它可以帮助你自动管理这些复杂的步骤。你只需要告诉它你需要哪些材料(源代码文件)和一些基本的指令,它就会自动生成一个详细的“烹饪计划”(构建文件),比如先加入多少克的蛋清,再加入多少克的糖……然后你可以按照这个计划来完成整个编译过程。
CMake 并不直接编译代码,而是为正式编译做整理和准备。它会生成一个 Makefile(在 Linux 和 macOS 上)或者 Visual Studio 项目文件(在 Windows 上),然后你可以使用 make 或 Visual Studio 来执行实际的编译工作。
2. CMake、Make、g++之间的关系
2.1. CMake和Make不是同一个东西!
CMake 和 make 是两个不同的工具,但它们通常一起使用。CMake 生成 Makefile 文件,然后 make 使用这个 Makefile 文件来构建项目。简单来说,CMake 是一个“生成器”,而 make 是一个“执行器”。
CMake 是一个跨平台的构建系统生成器。它的主要任务是读取 CMakeLists.txt 文件,根据文件中的指令生成适合特定构建系统的文件。例如,它可以在 Linux 上生成 Makefile,在 Windows 上生成 Visual Studio 解决方案文件等。
make 是一个构建工具,它通过读取 Makefile 文件来执行构建任务。Makefile 文件包含了如何编译和链接源代码文件的规则。make 会根据这些规则来生成可执行文件或库。
2.2. Make和g++的关系
g++ 是一个 C++ 编译器,它可以直接编译和链接 C++ 源代码文件,生成可执行文件或库。例如:
g++ -o myprogram main.cpp
这行命令会编译 main.cpp 文件,并生成一个名为 myprogram 的可执行文件。
而 make 是一个构建工具,它可以根据 Makefile 文件中的规则调用 g++(或其他编译器)来编译源代码。Makefile 文件定义了如何使用 g++ 来编译和链接源代码文件。例如,一个简单的 Makefile 可能看起来像这样:
all: main.cpp
g++ -o myprogram main.cpp
在这个 Makefile 中,make 会调用 g++ 来编译 main.cpp 文件。
2.3. CMake + Make 如何编译多文件
假设你有一个多文件项目,包含 main.cpp、player.cpp 和 player.h。直接使用 g++ 编译这些文件会变得很复杂,尤其是当项目规模变大时。CMake 可以帮助你简化这个过程。
2.3.1. 编写 CMakeLists.txt 文件
首先,你需要创建一个 CMakeLists.txt 文件,这是 CMake 的配置文件。它告诉 CMake 你的项目需要哪些源代码文件,以及如何生成可执行文件。
假设你的项目结构如下:
MyProject/
├── CMakeLists.txt
├── main.cpp
├── player.cpp
└── player.h
CMakeLists.txt 文件的内容如下:
# 指定 CMake 的最小版本
cmake_minimum_required(VERSION 3.10)
# 设置项目名称
project(MyProgram)
# 添加可执行文件
add_executable(MyProgram main.cpp player.cpp)
2.3.2. 生成构建文件
在项目根目录下(即包含 CMakeLists.txt 文件的目录),运行以下命令来生成构建文件:
cmake -B build
这会在当前目录下创建一个名为 build 的目录,并在其中生成构建文件(如 Makefile)。
2.3.3. 使用 Make 编译项目
进入 build 目录:
cd build
然后运行:
make
make 会根据生成的 Makefile 文件中的规则调用 g++ 来编译 main.cpp 和 player.cpp 文件,并生成可执行文件 MyProgram。
详细解释:
cmake -B build:
-
cmake是 CMake 的命令行工具。-B build指定生成的构建文件放在build目录中。这个目录会自动创建,你不需要手动创建它。- CMake 会读取
CMakeLists.txt文件,根据文件中的指令生成适合当前系统的构建文件(如 Makefile)。
make:
-
make是一个构建工具,它会读取 Makefile 文件中的规则。- Makefile 文件是由 CMake 生成的,它包含了如何使用
g++编译源代码文件的详细步骤。 make会自动处理文件之间的依赖关系,确保在编译main.cpp之前,player.h已经准备好。
3. 如何使用CMake
3.1. 在Windows使用CMake
1. 第一种方法:生成 Makefile
在 Windows 系统中,你可以使用 CMake 生成 Makefile 文件,然后使用 make 来编译项目。步骤和上面一样:
cmake -B build
cd build
make
2. 第二种方法:生成 Visual Studio 项目
如果你更喜欢使用 Visual Studio,你可以让 CMake 生成一个 Visual Studio 项目文件。运行以下命令:
cmake -B build -G "Visual Studio 16 2019"
这会生成一个适合 Visual Studio 2019 的项目文件。然后你可以用 Visual Studio 打开 build 目录中的项目文件,并直接在 Visual Studio 中编译和运行项目。
详细解释:
cmake -B build -G "Visual Studio 16 2019":
-
-G参数指定生成器的类型。这里指定生成 Visual Studio 2019 的项目文件。- CMake 会生成一个
.sln文件(Visual Studio 解决方案文件)和相关的.vcxproj文件(项目文件)。 - 你可以用 Visual Studio 打开这个解决方案文件,然后直接编译和运行项目。
- 使用 Visual Studio 编译项目:
-
- 打开 Visual Studio。
- 选择“打开” -> “项目/解决方案”,然后选择
build目录中的.sln文件。 - 在 Visual Studio 中,你可以直接点击“生成”按钮来编译项目。
- Visual Studio 会自动处理文件之间的依赖关系,并生成可执行文件。
3.2. 在Linux或macOS上使用CMake
在 Linux 或 macOS 平台上使用 CMake 来辅助编译项目,步骤和在 Windows 上生成 Makefile 的步骤一样:
cmake -B build
cd build
make
详细解释:
cmake -B build:
-
- 在 Linux 或 macOS 上,CMake 默认生成 Makefile 文件。
- 这个命令会在当前目录下创建一个
build目录,并在其中生成 Makefile 文件。
make:
-
- 进入
build目录后,运行make命令。 make会读取 Makefile 文件中的规则,调用g++来编译源代码文件。make会自动处理文件之间的依赖关系,确保在编译main.cpp之前,player.h已经准备好。
- 进入
4. 对于Linux开发,编译项目流程
在 Linux 中,你可以直接使用 g++ 来编译单文件项目,或者使用 CMake 来编译多文件项目。对于多文件项目,推荐使用 CMake,因为它可以自动管理文件之间的依赖关系,让你的编译过程更加简单和高效。
1. 单文件编译
如果你只有一个源代码文件,比如 main.cpp,你可以直接使用 g++ 编译器来编译它:
g++ -o myprogram main.cpp
这行命令会把 main.cpp 文件编译成一个可执行文件 myprogram。
2. 多文件编译
如果你有多个源代码文件,比如 main.cpp、player.cpp 和 player.h,你可以使用 CMake 来简化编译过程。
编写 CMakeLists.txt 文件
创建一个 CMakeLists.txt 文件,内容如下:
cmake_minimum_required(VERSION 3.10)
project(MyProgram)
add_executable(MyProgram main.cpp player.cpp)
生成构建文件
在项目根目录下运行以下命令:
cmake -B build
使用 Make 编译项目
进入 build 目录:
cd build
然后运行:
make
详细解释:
cmake -B build:
-
- 在 Linux 上,CMake 默认生成 Makefile 文件。
- 这个命令会在当前目录下创建一个
build目录,并在其中生成 Makefile 文件。 - 如果不单独创建build目录的话,一些中间文件和依赖链接文件就会散落在当前目录,如果项目比较庞大,编译所需的中间文件太多的话,就会让当前目录变得杂乱不堪,所以一般都会将 CMake 生成的,用来指导编译的中间文件(包含 Makefile 文件)统一放到 build 目录中,build 就是“编译”的意思,表示其中存放的都是用于指导编译的过程文件。
make:
-
- 进入
build目录后,运行make命令。 make会读取 Makefile 文件中的规则,调用g++来编译源代码文件。make会自动处理文件之间的依赖关系,确保在编译main.cpp之前,player.h已经准备好。
- 进入
5. 现代化机器人开发的首选
5.1. ROS 和 ROS2
ROS(Robot Operating System)是一个用于机器人开发的中间件,它提供了一系列工具和库,方便开发者编写和管理机器人程序。
ROS2 是 ROS 的下一代版本,它在编译方式上与 ROS1 类似,但在内部功能实现上发生了很大的改变。
详细的 ROS 与 ROS2 介绍,可以参考:ROS和ROS2是什么 - 图书资源
5.2. ROS
在 ROS 中,编译过程主要依赖于 catkin 构建系统。
5.2.1. 工作空间的创建
在 ROS 中,工作空间是一个包含所有源代码和编译输出的目录。通常,工作空间包含以下几个子目录:
src:存放源代码和包。build:存放编译过程中生成的中间文件。devel:存放编译生成的可执行文件和库文件。
创建一个工作空间的命令如下:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
5.2.2. 编译过程
在 ROS 中,使用 catkin_make 命令来编译工作空间中的包。catkin_make 会依次调用 cmake 和 make 来配置和编译项目。
编译命令如下:
cd ~/catkin_ws
catkin_make
编译完成后,需要将编译生成的环境变量添加到当前终端环境中,以便能够运行编译生成的程序:
source devel/setup.bash
5.2.3. ROS 编译的特点
- 依赖管理:ROS 使用
rosdep工具来管理依赖项。在编译之前,可以使用以下命令安装所有依赖项:
rosdep install --from-paths src --ignore-src -r -y
- 模块化:ROS 的编译过程是模块化的,每个包都可以独立编译。
- 灵活性:虽然
catkin_make是最常用的编译工具,但也可以使用其他工具,如catkin build。
5.3. ROS2编译
ROS2 是 ROS 的下一代版本,它在编译方式上与 ROS1 类似,但在内部功能实现上发生了很大的改变。ROS2 使用 colcon 作为构建工具,替代了 ROS1 中的 catkin_make。
5.3.1. 工作空间的创建
在 ROS2 中,工作空间的创建过程与 ROS1 类似,但有一些不同之处。创建一个工作空间的命令如下:
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
5.3.2. 编译过程
在 ROS2 中,使用 colcon build 命令来编译工作空间中的包。colcon 是一个更灵活的构建工具,它支持多种构建选项。
编译命令如下:
cd ~/ros2_ws
colcon build
编译完成后,同样需要将编译生成的环境变量添加到当前终端环境中:
source install/setup.bash
5.3.3. ROS2 编译的特点
- 依赖管理:和 ROS 一样,ROS2 也使用
rosdep工具来管理依赖项。在编译之前,可以使用以下命令安装所有依赖项:
rosdep install --from-paths src --ignore-src -r -y
- 模块化:和 ROS 一样,ROS2 的编译过程也是模块化的,每个包都可以独立编译。
- 灵活性:
colcon提供了更多的构建选项,例如可以只编译特定的包:
colcon build --packages-select package_name
- 跨平台支持:ROS2 支持多种操作系统,包括 Linux、Windows 和 macOS。
5.4. ROS 和 ROS2 编译的区别
- 构建工具:ROS 使用
catkin_make,而 ROS2 使用colcon。 - CMake 配置:ROS2 的 CMake 配置更加简化,使用了基于 CMake 封装的
ament_cmake。 - 依赖管理:虽然两者都使用
rosdep,但 ROS2 的依赖管理更加灵活。 - 跨平台支持:ROS2 提供了更好的跨平台支持,而 ROS 主要支持 Linux。
6. 总结
CMake 是一个强大的工具,它可以帮助你简化代码的编译过程,无论你的项目是单文件还是多文件,无论你在哪个平台上开发。通过 CMake,你可以自动生成构建文件,自动管理文件之间的依赖关系,让你的编译过程更加简单和高效。
- 单文件编译:可以直接使用
g++,但手动管理多文件项目会很复杂。 - CMake:通过生成构建文件(如 Makefile 或 Visual Studio 项目文件),自动管理文件之间的依赖关系。
- Make:根据 Makefile 文件中的规则调用
g++来编译源代码。 - ROS 和 ROS2:集成了 CMake,通过
catkin_make和colcon工具来编译项目。
希望这篇文章能帮助你更好地理解 CMake 和它的强大功能。无论是简单的煎蛋还是复杂的巧克力蛋糕,CMake 都能成为你的好帮手!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)