数据结构的学习(二)---Makefile的使用

目录

一、Makefile介绍

[1.采用 Makefile 的好处](#1.采用 Makefile 的好处)

[2.make 主要解决两个题:](#2.make 主要解决两个题:)

[二、makefile 语法及其执行](#二、makefile 语法及其执行)

[1.makefile 语法规则](#1.makefile 语法规则)

2.Make是如何工作的?

三、makefile变量

1.自定义变量:​

2.预定义变量:


一、Makefile介绍

什么是make

make 是个命令,是个可执行程序
什么是 makefile?

makefile 是个文件,这个文件中描述了程序的编译规则

执行 make 命令的时候,make 命令会在当前目录下找 makefile 文件, 根据 makefile 文件里的规则,编译 的程序

1.采用 Makefile 的好处

1、简化编译程序的时候输入得命令,编译的时候只需要敲 make 命令就可以了

2、可以节省编译时间,提高编译效率

2.make 主要解决两个题:

1.大量代码的关系维护

大项目中源代码比较多,手工维护、编译时间长而且编译命令复杂,难以记忆及维护

把代码维护命令及编译命令写在 makefile 文件中,然后再用 make 工具解析此文件自动执行相应命令,可实现代码的合理编译

2.减少重复编译时间

在改动其中一个文件的时候,能判断哪些文件被修改过,可以只对该文件进行重新编译,然后重新链接所有的目标文件,节省编译时间

二、makefile 语法及其执行

1.makefile 语法规则

目标:依赖文件列表

<Tab>命令列表

1、目标:通常是要产生的文件名称,目标可以是可执行文件或其它 obj 文件,也可是一个动作的名称

2、依赖文件:是用来输入从而产生目标的文件,一个目标通常有几个依赖文件(可以没有)

3、命令:make 执行的动作,一个规则可以含几个命令(可以有) 有多个命令时,每个命令占一行

例子:

bash 复制代码
mycalc: main.o add.o sub.o mul.o div.o             
    gcc main.o add.o sub.o mul.o div.o -o mycalc

main.o: main.c
    gcc -c main.c -o main.o
add.o: add.c
    gcc -c add.c -o add.o
sub.o: sub.c
    gcc -c sub.c -o sub.o
div.o: div.c
    gcc -c div.c -o div.o
mul.o: mul.c
    gcc -c mul.c -o mul.o

clean:
    rm *.o
    rm mycalc

第一行执行命令时,找不到文件的话会往下面找生成该文件的命令

clean的使用,使用命令 make clean可以清除带.o的文件和mycalc程序

注意:如果makefile的名字不是默认名称(这里使用makefile1做例子)

则需要用 make -f makefile1 clean来执行

-f 可以指定以上名字以外的文件作为 makefile 输入文件

2.Make是如何工作的?

在默认的方式下,也就是我们只输入make命令。那么:

1、make会在当前目录下找名字叫"Makefile"或"makefile"的文件。

2、如果找到,它会找文件中的第一个目标文件(target),在下面的例子中,他会找到"mycalc"这个文件,并把这个文件作为最终的目标文件。

3、如果mycalc文件不存在,或是mycalc所依赖的后面的 .o 文件的文件修改时间要比mycalc这个文件新,那么,他就会执行后面所定义的命令来生成mycalc这个文件。

4、如果mycalc所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)

5、当然,你的C文件和H文件是存在的,于是make会生成 .o 文件,然后再用 .o 文件生成make的终极任务,也就是执行文件mycalc了。

这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

通过上述分析,我们知道,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令------"make clean",以此来清除所有的目标文件,以便重编译。

于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如add.c,那么根据我们的依赖性,我们的目标add.o会被重编译(也就是在这个依性关系后面所定义的命令),于是file.o的文件也是最新的啦,于是add.o的文件修改时间要比mycalc要新,所以 mycalc也会被重新链接了(详见mycalc目标文件后定义的命令)。

三、makefile变量

makefile 变量类似于 C 语言中的宏,当 makefile 被 make 工具解析时,其中的变量会被展开。

1.自定义变量:

定义变量:

变量名=变量值引用变量:

(变量名)或{变量名}

2.预定义变量:

makefile中有许多预定义变量,这些变量具有特殊的含义,可在 makefile 中直接使用。

$@ 目标名

$< 依赖文件列表中的第一个文件

$^ 依赖文件列表中除去重复文件的部分

SRC =依赖
TARGET =目标

AR 归档维护程序的程序名,默认值为 ar ARFLAGS 归档维护程序的选项

AS 汇编程序的名称,默认值为 as ASFLAGS 汇编程序的选项

CC C 编译器的名称,默认值为 cc CFLAGS C 编译器的选项

CPP C 预编译器的名称,默认值为$(CC) -E CPPFLAGS C 预编译的选项

CXX C++编译器的名称,默认值为 g++

CXXFLAGS C++编译器的选项

例如:将上面的代码替换成自定义变量与预定义变量

bash 复制代码
CC=gcc                                    
SRC =  main.o add.o sub.o mul.o div.o
TARGET =mycalc
CFLAGS= -g

$(TARGET):$(SRC)
    $(CC) $^ -o $(TARGET) $(CFLAGS)

main.o: main.c
    $(CC) -c $< -o $@
add.o: add.c
    $(CC) -c $< -o $@
sub.o: sub.c
    $(CC) -c $< -o $@
div.o: div.c
    $(CC) -c $< -o $@
mul.o: mul.c
    $(CC) -c $< -o $@

clean:
    rm *.o
    rm mycalc
                                          
相关推荐
电棍233几秒前
ubuntu网卡失效
linux
律宏阔4 分钟前
VMware 能识别 USB 设备,但无法连接(灰色)
linux
Rabitebla11 分钟前
【Linux系统编程】指令(三):创建、删除、复制、移动、看内容
linux·数据结构·c++·算法
AR-26710-27 分钟前
Linux Day9——复习第一部分(实操产出)
linux
PNP Robotics31 分钟前
【PNP具身解读】GPT6 Astra:具身智能新范式,大模型 + Franka机器人快速落地验证一、GPT6 Astra 背后的布局、数据与具身方向
人工智能·学习·机器学习·机器人
小李不想当小白1 小时前
PCB结构与组成(PCB设计入门学习笔记)
经验分享·笔记·单片机·嵌入式硬件·学习·pcb工艺·pcb
那年窗外下的雪.1 小时前
第 02 天:Linux 权限、inode、目录项与链接
学习·http
XGStudio20241 小时前
免费安全的 - 二维码转换工具
学习·ai
邵奈一1 小时前
【紧急处理ZCode事件】ZCode 工作区快照静默上传:检测方法与三层防护实践
人工智能·学习·大模型·国产
那年窗外下的雪.2 小时前
AIDC 学习日志|第 27 天|EVPN 多归属收敛时间线与 Leaf2 接管验证
网络协议·学习·http·tcpdump