数据结构的学习(二)---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
                                          
相关推荐
jl48638212 小时前
打造医疗设备的“可靠视窗”:医用控温仪专用屏从抗菌设计到EMC兼容的全链路解析
大数据·运维·人工智能·物联网·人机交互
曾几何时`2 小时前
Docker容器化部署编译运行模块
运维·docker·容器
HalvmånEver2 小时前
Linux:线程 ID 与地址空间布局:深入理解线程内存分布(线程七)
linux·运维·服务器·操作系统·线程
呱呱巨基2 小时前
c语言 文件操作
c语言·开发语言·c++·笔记·学习
北京阿法龙科技有限公司2 小时前
工业场景下AR+AI图像识别:精准选型赋能运维与质检
运维·人工智能·ar
小oo呆2 小时前
【学习心得】CMD终端设置Proxy的几个要点
运维·服务器·网络
Forget_85502 小时前
RHEL——制作母盘
linux·运维·服务器
释怀不想释怀3 小时前
Linux命令--echo~反引号符~重定向符(>>)~tail命令
linux·运维·服务器
Max_uuc3 小时前
【C++ 硬核】给单片机装上“反射”:手写极简属性系统 (Property System) 自动化 CLI 开发
运维·自动化