数据结构的学习(二)---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
                                          
相关推荐
czxyvX3 小时前
019-Linux-Socket编程-TCP
linux·tcp/ip
小付同学呀8 小时前
C语言学习(五)——输入/输出
c语言·开发语言·学习
A.A呐8 小时前
【Linux第六章】进程状态和优先级
linux
学编程的闹钟9 小时前
E语言计算器开发全攻略
学习
iambooo9 小时前
Shell在日志分析与故障排查中的实战应用
linux·服务器·网络
薛定e的猫咪9 小时前
Claude Code 完整学习手册:安装配置、CCR、MCP、插件与 Superpowers开发框架
学习
一路往蓝-Anbo9 小时前
第 9 章:Linux 设备树 (DTS) ——屏蔽与独占外设
linux·运维·服务器·人工智能·stm32·嵌入式硬件
钛态10 小时前
Flutter for OpenHarmony:dio_cookie_manager 让 Dio 发挥会话管理能力,像浏览器一样自动处理 Cookie 深度解析与鸿蒙适配指南
android·linux·运维·flutter·ui·华为·harmonyos
王码码203510 小时前
Flutter for OpenHarmony:Flutter 三方库 bluez 玩转 Linux 风格的蓝牙操作(蓝牙底层互操作)
linux·运维·服务器·前端·flutter·云原生·harmonyos
雾山大叔10 小时前
多会话浏览器串口调试助手
经验分享·笔记·学习