Linux——make/makefile

一、基本概念

二、makefile写法与理解

2.1 makefile基础写法

2.2 伪目标

 三、推导过程

四、定义变量

五、多文件下的makefile 

六、makefile整体代码


一、基本概念

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一

系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至 于进行更复杂的功能操作。

makefile带来的好处就是自动化编译,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是Linux系统内置的一个命令,makefile是需要自己建立的一个文件,要注意文件名只能是全部小写makefile,或者只有M大写Makefile,否则执行make命令时就会找不到当前路径下与之对应的makefile文件。

二、makefile写法与理解

2.1 makefile基础写法

例如我们有一个code.c文件,要让它形成一个名为code的可执行程序

第二行的开头必须是tab键,同理第六行的开头也是tab键。根据上述写法,我们来反向推导理论,code依赖于code.c,所以 code:code.c 这一行叫做依赖关系, gcc -o code code.c 这一行叫做依赖方法,依赖关系+依赖方法,才能达到我们要编译程序的目的。而在依赖关系中,出现在:之前的,叫目标文件,出现在:之后的,叫依赖文件列表。clean:       是依赖关系,rm -f code是依赖方法,目标文件是clean,依赖文件列表为空。


现在我们要编译程序,就直接输入make命令即可,而要清除文件,输入make clean即可清理。

通过上面大家会发现,为什么编译就只make就行,而清理需要在make带上clean才可以?这是因为,当我们输入make命令以后,系统会在当前路径下查找名为makefile/Makefile文件,make默认执行的是从上往下遇到的第一个目标,如果要执行其他的目标,就需要在make后面带上目标文件,才可以执行。


2.2 伪目标

.PHONY修饰的目标是一个伪目标,伪目标总是被执行的,那总是被执行和总是不被执行又是什么意思呢?

我们连续make,发现并不是每次都执行,提示了一个code已经是最新的,这叫总是不被执行,而连续make clean发现每一次都执行了清理,这叫总是被执行。在大型项目中代码量非常多,这个时候如果就改了两个文件,所有文件都要重新编译,那太浪费时间了,就只编译改的那两个文件就可以,所以在实际中,编译成可执行程序,不需要修饰成伪目标,但是清理要修饰成伪目标,要把工程清理干净,那么makefile就可以提高我们编译工作的效率。


那系统怎么知道要不要重新编译呢?在这里介绍一个命令,stat,stat后面跟文件可以查看文件属性以及ACM时间,其中modify时间代表对文件内容的最近修改时间,change时间代表对文件属性的最近修改时间。            

系统就通过对比源文件和可执行目标文件的modify时间,来决定要不要重新编译,最开始没有可执行程序,make之后,形成了可执行程序code,这个时候code的modify时间肯定是比code.c的modify时间晚的,就不重新编译,如果对code.c的代码进行了修改,那现在code.c的modify时间就比code的modify时间要晚,就需要编译。

 第一次编译后的modify时间,不会再编译

 对源文件修改之后的modify时间,会再编译


 三、推导过程

我们把编译的过程写全,预处理编译汇编链接每一步都生成对应的文件

code依赖于code.o,当前没有code.o,但是有一组code.o的依赖关系,code.o依赖于code.s,当前没有code.s,但是有一组code.s的依赖关系,code.s依赖于code.i,当前没有code.i,但是有一组code.i的依赖关系,code.i依赖于code.c,当前有code.c,用code.c生成code.i,code.i生成code.s,code.s生成code.o,code.o生成code

这个过程中用了栈结构,在向下找存在的依赖关系时把依赖方法依次入栈,当找到code.c存在时,再依次取栈顶元素完成编译


四、定义变量

但是通常为了让我们的makefile更通用,以及在多文件时提高效率,我们会采用定义变量的方式

可以做到更加灵活的控制,生成的可执行程序,编译器,改这里就全部改了,类似于C/C++中的#define

如果想要打印变量对应的内容,可以采用$(变量)来获取变量对应的内容

可以看到变量对应的内容全部打印出来了,但makefile依赖方法语句会回显,怎么才能关闭这个回显,只打印语句输出的内容呢,在依赖方法前加上@就可以

既然这种方式可以打印变量的内容,那我们的编译和清理语句也可以换掉,而在编译时一般习惯生成.o文件,所以我们要先用code.c生成code.o,再用code.o生成code


在第一组依赖关系中$(BIN),$(OBJ)以及第二组依赖关系的$(SRC)都写了两次,其实可以不用这么麻烦,$@表示目标文件,$^表示依赖文件列表


五、多文件下的makefile 

那如果现在有100个文件怎么办呢?难道把BIN,SRC,OBJ都要定义100个吗?显然不是的,这样的话就跟直接写没有区别了,我们可以采用这种写法

SRC=$(wildcard *.c)就是获取当前路径下所有后缀为.c的文件,OBJ=$(SRC:.c=.o)就是把所有同名.c 替换 成为.o 形成目标文件列表,然后创建100个文件,code1~code100,后缀为.c,我们验证SRC和OBJ是否可以获取当前路径下的.c文件以及把.c替换成.o


那怎么编译呢?怎么让每一个.o和.c对应起来呢?

%是通配符,展开所有的.c文件和.o文件,而且是一一对应的,$<是将展开的每一个.c文件都交给gcc。


六、makefile整体代码

当多文件的时候可以这么写,自动化构建非常方便,如果只有一个文件的话,就按照最初的那种最基础的写法写就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值