当前位置: 首页 > article >正文

GCC, Makefile, make, CMake, CMakeLists.txt

使用CMake来编译源代码的流程 

GCC

GCC介绍

GCC 是一个开源的编译器套件,支持 C、C++、Fortran、Ada、Go 等多种编程语言的编译。负责将源代码转换为可执行文件。

当我们的程序只有一个源文件时,使用 gcc 命令编译非常简单。但是,如果程序包含多个源文件,我们就需要逐个用 gcc 命令编译所有源文件,并且还要在编译过程中手动管理各个文件之间的依赖关系,这样很容易造成混乱和繁琐的工作。

直接使用gcc编译很麻烦的例子

假设我们有一个 C++ 项目,包含三个源文件:

  • main.cpp
  • math_functions.cpp
  • utils.cpp

每个源文件包含不同的功能:

  • main.cpp 是程序的入口,包含 main() 函数。
  • math_functions.cpp 包含数学相关的函数,比如加法、减法等。
  • utils.cpp 包含一些工具函数,比如字符串处理和文件读取等。

我们希望将这三个源文件编译成一个可执行文件 program

如果手动使用 gcc 编译:

你需要依次执行以下命令:

gcc -c main.cpp -o main.o
gcc -c math_functions.cpp -o math_functions.o
gcc -c utils.cpp -o utils.o
gcc main.o math_functions.o utils.o -o program

这四条命令的目的是:

  1. 使用 -c 选项将每个源文件编译成目标文件(.o 文件)。
  2. 最后将所有的目标文件链接在一起,生成最终的可执行文件 program

注意:在最后链接库生成可执行文件的时候,.o文件的顺序有着严格的要求。被依赖的文件应该放在后面,而依赖其他文件的 .o 文件应该放在前面,比如这里main.o文件需要被放到命令的前面。

 综上看来,我们发现:如果有多个源文件的时候,直接使用gcc命令进行编译的时候会非常麻烦。

make和Makefile

make和Makefile介绍

Makefile 是一个文本文件,描述编译规则、文件依赖和构建过程。

make 是一个自动化构建工具,基于 Makefile 中的规则,自动化地编译源代码,生成目标文件或可执行文件。

下面我们将来举出一个makefile的例子:

# 变量定义
CC = g++                # 编译器
CFLAGS = -Wall -g       # 编译选项(警告、调试信息)
SRC = main.cpp math_functions.cpp utils.cpp  # 源文件列表
OBJ = $(SRC:.cpp=.o)    # 从源文件生成目标文件(.cpp -> .o)
TARGET = program        # 最终生成的可执行文件

# 默认目标(运行 `make` 时会默认执行的目标)
all: $(TARGET)

# 如何生成目标文件
$(TARGET): $(OBJ)
	$(CC) $(OBJ) -o $(TARGET)

# 生成 .o 文件规则:编译源文件为目标文件
%.o: %.cpp
	$(CC) $(CFLAGS) -c $< -o $@

# 清理中间文件和可执行文件
clean:
	rm -f $(OBJ) $(TARGET)

在这个例子中,我们可以看出来,这个makefile文件定义了编译生成可执行程序时的一系列规则和编译顺序,但是本质上还是调用g++编译器来编译各个程序。 

使用make和Makefile方式

1.进入到项目目录

2.在包含 Makefile 的目录中,运行命令:

make

优点:我们可以看到通过这种方式进行代码编译的时候,每次不需要输入一串很长的命令,只需要make命令非常简洁。

补充一点:

        make clean的作用是删除所有中间文件和生成的文件,这样子就是从头开始编译文件啦。但是我们一般更改了代码之后不会选择执行make clean,直接执行make就行

       make 会自动检查源文件的修改时间,并根据文件的依赖关系判断是否需要重新编译。如果源文件没有修改,make 会跳过不必要的步骤,只编译更改过的文件,因此不需要每次都执行 make clean。

什么时候需要使用make clean?

        解决潜在的编译问题:有时由于依赖关系问题或者中间文件未能正确更新,可能导致一些编译错误。此时,运行 make clean 可以清理掉旧的编译文件,确保一个干净的环境,但一般来说都不需要用到make clean。

缺点

  • 随着项目的扩展,源文件和目标文件的增多,手动更新 Makefile 会变得越来越复杂。需要显式地管理所有的依赖关系,确保文件顺序正确,特别是在大型项目中,手动编写和维护这些规则非常繁琐。
  • 链接顺序错误、依赖关系遗漏等问题很容易出错,而且调试起来相对麻烦。

有了make和makefile之后,虽然在编译源代码的时候,命令更加地简单,但是编写makefile文件很复杂,容易出错,在文件目录结构发生改变之后,我们需要对makefile进行手动维护。所以我们有更简单的方式来处理源代码的编译生成可执行文件问题。

1.使用IDE (集成开发环境) ,如 Visual Studio、CLion。通常都提供图形化的项目管理工具,可以自动生成和管理 Makefile,使得开发者不需要手动编写这些文件。

2.使用自动化构建工具Cmake。CMake 是一种现代的构建工具,它可以自动生成 Makefile 或其他构建系统所需的配置文件(比如 Ninja 构建文件、Visual Studio 项目文件等)。你只需要编写一个 CMakeLists.txt 文件,CMake 会根据你的需求自动生成适当的 Makefile

CMake和CMakeLists.txt 

CMake和CMakeLists.txt 介绍

CMakeLists.txt 是 CMake 配置文件,用于描述项目的构建需求。它包含了项目名称、所需的库、源文件、编译选项等信息,CMake 会根据这些信息生成相应的构建系统文件(如 Makefile)。

CMake 是一个跨平台的构建系统生成工具,根据 CMakeLists.txt 文件中的指令,生成适合当前系统和编译器的构建系统文件(如 Makefile)

CMakeLists.txt是谁来编写呢?

当然是我们自己啦,嘻嘻,我们现在的逻辑就是使用CMake工具+CMakeList.txt来生成出Makefile文件,然后用make工具+makefile来编译源文件。

你别慌,相对于自己编写Makefile文件来说,手动编写CmakeLists.txt要简单的多了,下面请听我娓娓道来!!!

CMakeLists.txt 详细分析

下面这是一个CMakeLists.txt的示例

# 设置使用的 CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(MyProject)

# 设置 C++ 编译标准
set(CMAKE_CXX_STANDARD 17)

# 设置源文件列表,这些文件将被 CMake 用来编译最终的可执行文件
set(SOURCE_FILES
    main.cpp
    math_functions.cpp
)

# 用前面指定的源文件编译生成一个可执行文件(名为 MyProject)
add_executable(MyProject ${SOURCE_FILES})

CMakeLists.txt示例的详细解释:

project(MyProject) :(在 CMake 配置和管理过程中使用这个名称,这个名称和最后生成的可执行文件名称没有关系)这里这个名称平时用的比较少,这里不详细阐述。

add_executable(MyProject ${SOURCE_FILES}),这里设置的名称MyProject为最终生成的可执行文件的名称。

通常情况下,我们会让 project()add_executable() 使用相同的名称,这样做是为了保持一致性和简洁性,易于理解和管理。

对比一下Makefile的内容,显而易见可知,CMakeLists.txt编写的内容:

1.非常简洁,不容易出错

2.不需要我们来考虑源文件的依赖顺序问题

3.在项目结构发生改变的时候也比较好维护

Cmake和CmakeLists.txt详细使用示例

项目目录结构:

/my_project
    /src
        main.cpp
    CMakeLists.txt
1.编写源代码和 CMakeLists.txt文件

编写完源代码并且在项目根目录下创建并编写好 CMakeLists.txt 文件

为了保持源代码和构建文件分离,通常我们会在项目根目录下创建一个单独的 build 目录。这样做的好处是,所有的构建文件临时文件生成的可执行文件都存放在这个目录下,保持项目根目录干净

2.创建构建目录并运行CMake 配置:

在项目根目录下执行以下命令:

mkdir build
cd build

进入 build 目录后,运行 cmake 命令来配置项目。我们需要指定 CMakeLists.txt 文件所在的目录(通常是项目的根目录)。cmake 会检查源代码,并生成适用于当前系统的构建文件(比如 Makefile、Visual Studio 项目文件等)。

cmake ..

.. 表示当前目录的上一级,即项目根目录,一般来说CMakeLists.txt 文件所在的目录就是根目录,正好是..

3.构建项目

运行 CMake 命令后,会在构建目录build下生成适用于当前系统的构建文件比如Makefile。此时我们执行命令:

make

执行 make 后,就会根据Makefile文件中的规则来编译源代码并生成对应可执行文件

4.运行程序

构建完成后,我们可以直接运行生成的可执行文件。假设项目名是 MyProject,我们可以通过以下命令运行它:

./MyProject

亲身实践之后,我发现:使用CMake方式的时候确实是应该构建一个build目录,以此来保持源代码和构建文件分离。

参考文章:CMake 和makefile_makefile cmake-CSDN博客


http://www.kler.cn/a/527457.html

相关文章:

  • Java内存模型 volatile 线程安全
  • python 使用Whisper模型进行语音翻译
  • 安卓(android)订餐菜单【Android移动开发基础案例教程(第2版)黑马程序员】
  • AI常见的算法和例子
  • hive:基本数据类型,关于表和列语法
  • ResNet 残差网络
  • 分布式微服务系统架构第89集:kafka消费者
  • 吴恩达深度学习——有效运作神经网络
  • 【LLM】Ollama框架入门指北
  • jEasyUI 创建 CRUD 应用
  • 安卓安全访问配置说明network-security-config —未来之窗跨平台操作
  • 【搞定offer】远程医疗:健康科技领域,搞定医疗offer
  • 2501,编写dll
  • 大语言模型(LLM)模拟金融市场参与者行为
  • 离线大模型-通义千问
  • 栈和队列特别篇:栈和队列的经典算法问题
  • ### 2024 江西省赛题解(A,C,D,G,H,J,K,L) BEFI待补
  • qt-Quick3D笔记之官方例程Runtimeloader Example运行笔记
  • 合并2个排序的链表
  • DeepSeek是什么,最近到底经历了什么?它能干什么?
  • 注册谷歌账号
  • Linux:多线程[2] 线程控制
  • 10.5 LangChain Model I/O 深度解析:如何用标准化接口打通大模型开发的“任督二脉”?
  • 2 MapReduce
  • 【思维导图】并发编程
  • 答疑解惑:如何监控EMC unity存储系统磁盘重构rebuild进度