C++学习(十三)(构建系统,CMAKE)
构建系统是一组工具和实用程序,用于自动执行项目中的源代码文件的编译、链接和执行过程。构建系统的主要目标是管理编译过程的复杂性,并最终生成构建(可执行文件或二进制文件)。在 C++ (cpp) 中,一些常见的构建系统包括:
-
GNU Make:这是一个流行的构建系统,用于定义构建过程。它检查源文件的依赖关系和时间戳,以确定需要编译和链接哪些文件。
Makefile
代码示例:
# Makefile CXX = g++ CPPFLAGS = -Wall -std=c++11 TARGET = HelloWorld all: $(TARGET) $(TARGET): main.cpp $(CXX) $(CPPFLAGS)main.cpp -o $(TARGET) clean: rm $(TARGET)
-
CMake:它是一个跨平台的构建系统,专注于定义项目依赖关系和管理构建环境。CMake 为不同的平台生成构建文件(如 Makefiles),并允许开发人员编写一次源代码,然后针对不同的目标平台进行编译。
代码示例:
# CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(HelloWorld) set(CMAKE_CXX_STANDARD 11) add_executable(HelloWorld main.cpp)
-
Autotools:也称为 GNU 构建系统,由 GNU Autoconf、Automake 和 Libtool 工具组成,使开发人员能够跨不同的基于 Unix 的系统创建可移植软件。对于 C++ 项目,您需要创建具有特定规则的 , 文件,然后在终端中运行以下命令来构建项目:
configure.ac
Makefile.am
autoreconf --install ./configure make make install
-
SCons:此构建系统使用 Python 作为构建脚本,使其比 GNU Make 更具表现力。它还可以同时为多个平台和配置构建。
代码示例:
# SConstruct env = Environment() env.Program(target="HelloWorld", source=["main.cpp"])
-
Ninja:一个小型而专注的构建系统,它采用人类可读文本文件中指定的构建目标列表,并尽快构建它们。
代码示例:
# build.ninja rule cc command = g++ -c $in -o $out rule link command = g++ $in -o $out build main.o: cc main.cpp build HelloWorld: link main.o default HelloWorld
这些是 C++ 中一些流行的构建系统,每个系统都有自己的语法和功能。虽然 Make 被广泛使用,但 CMake 是一个跨平台的构建系统,可为 Make 或 Ninja 等其他构建系统生成构建文件。Autotools 适合创建便携式软件,SCons 利用 Python 作为其构建脚本,而 Ninja 专注于快速构建时间
我们可以用**“厨房自动化系统”**的比喻来理解构建系统的概念:
构建系统是什么?
想象你要做一道复杂大餐(比如佛跳墙),需要处理几十种食材、控制火候、按特定顺序烹饪。手动操作会累到崩溃,还容易出错。构建系统就像一套智能厨房机器人,它:
-
记住所有步骤(哪些食材要先处理,哪些要同时蒸煮)
-
自动检测变化(如果某个食材更新了,只重做相关步骤)
-
一键完成烹饪(不用手动盯着每个环节)
C++ 构建系统的作用
-
代替手动敲命令
不用每次修改代码都手动输入g++ -o main.cpp ...
(就像不用自己切菜生火)。 -
智能跳过重复工作
如果只改了一个文件,只重新编译这个文件,其他不变(类似只重切新到的葱,不重新炖汤)。 -
处理复杂依赖关系
自动解决“文件A依赖文件B,文件B又依赖文件C”的问题(类似知道要先煮高汤才能做酱汁)。 -
生成最终成品
把代码变成可执行文件(就像把食材变成菜品)。
以 GNU Make 为例
核心组成
-
Makefile
:相当于菜谱,用文本文件定义:-
要做哪些菜(编译目标)
-
每道菜的食材(源文件)和步骤(编译命令)
-
食材之间的依赖关系(比如主菜需要先做好酱汁)
-
示例 Makefile
# 最终菜品:佛跳墙(可执行程序)
佛跳墙: 高汤.o 鲍鱼.o 海参.o # 依赖的中间文件
厨师机链接 -o 佛跳墙 高汤.o 鲍鱼.o 海参.o
高汤.o: 高汤.cpp 调料.h # 高汤的食材和步骤
厨师机编译 -c 高汤.cpp
鲍鱼.o: 鲍鱼.cpp 调料.h
厨师机编译 -c 鲍鱼.cpp
clean: # 清理厨房(删除中间文件)
洗碗机 rm *.o 佛跳墙
执行过程
$ make # 机器人开始按菜谱做菜
$ make clean # 机器人清理厨房(删除临时文件)
为什么需要构建系统?
场景 | 手动操作问题 | 构建系统解决方案 |
---|---|---|
修改一个文件 | 要重新编译所有文件 → 费时 | 只编译改动文件 → 高效 |
多人协作 | 每个人的编译命令可能不同 → 结果不一致 | 统一流程 → 结果可靠 |
复杂项目(如Chrome) | 成千上万个文件 → 不可能手动管理 | 自动化依赖和编译 → 可控 |
其他常见构建系统
-
CMake:
像智能菜谱生成器,可以根据不同厨房(操作系统/编译器)自动生成对应的Makefile
。 -
Bazel:
谷歌开发的“工业级厨房机器人”,适合超大型项目(如自动驾驶系统)。 -
Ninja:
追求极速的“闪电厨师”,编译速度极快。
一句话总结
构建系统是程序员的厨房机器人——你只需写菜谱(Makefile),它帮你搞定复杂烹饪流程(编译链接),省时省力不翻车! 🤖🍲
这段 CMake 代码的作用是创建一个 C++ 项目的构建配置,让 CMake 生成合适的编译文件(如 Makefile 或 Visual Studio 解决方案)。下面用通俗易懂的方式一步步解释:
1. 指定 CMake 版本
cmake_minimum_required(VERSION 3.0)
- 这行代码的作用是确保 CMake 版本至少是 3.0,防止使用太旧的版本,避免不兼容问题。
2. 定义项目名称
project(MyProject)
- 这行代码定义了项目的名称,这里项目叫 "MyProject"。
3. 设置源码路径
set(SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/src") set(SOURCES "${SRC_DIR}/main.cpp" "${SRC_DIR}/file1.cpp" "${SRC_DIR}/file2.cpp")
SRC_DIR
变量指定源码目录,假设CMakeLists.txt
文件在root
目录下,它就表示root/src/
。SOURCES
变量列出了所有的源码文件(main.cpp
,file1.cpp
,file2.cpp
)。
4. 创建可执行文件
add_executable(${PROJECT_NAME} ${SOURCES})
add_executable()
这个命令告诉 CMake:- 生成一个 可执行文件(
MyProject
)。 - 使用 指定的源码文件 编译它。
- 生成一个 可执行文件(
5. 设置头文件路径
target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
- 这行代码告诉编译器,头文件(
.h
或.hpp
文件)存放在include
目录下。 PRIVATE
说明这个目录只对当前目标(MyProject)可见,不会影响其他目标(如果有的话)。
6. 设置 C++ 标准
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 14 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF )
这部分代码指定 C++ 版本,并设置相关编译选项:
CXX_STANDARD 14
→ 代码会使用 C++14 语法。CXX_STANDARD_REQUIRED ON
→ 必须使用 C++14,不允许降级到更低的标准。CXX_EXTENSIONS OFF
→ 禁用编译器特有的扩展(比如g++
的-std=gnu++14
),确保代码符合标准的 C++14。
总结
这段 CMake 代码的作用是:
- 创建一个名为 "MyProject" 的 C++ 项目。
- 设定源码目录
src/
,并包含main.cpp, file1.cpp, file2.cpp
作为源文件。 - 告诉 CMake 生成一个可执行文件 "MyProject"。
- 让编译器在
include/
目录中查找头文件。 - 确保使用 C++14 标准,并避免编译器特有扩展。
💡 最终效果: 当你运行 cmake .
并执行 make
(或在 IDE 里构建),CMake 会自动调用编译器,把 main.cpp
, file1.cpp
, file2.cpp
编译成可执行文件 MyProject
🎯。
📌 你可以试试运行这段 CMake
-
在一个空目录里创建以下结构:
/MyProject ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ ├── file1.cpp │ ├── file2.cpp ├── include/ │ ├── file1.h │ ├── file2.h
-
进入
MyProject
目录:cd MyProject mkdir build && cd build cmake .. make
-
运行生成的可执行文件:
./MyProject
这样你就能亲自体验这段 CMake 代码的作用啦!🚀