什么是makefile呢?makefile是用来指定编译的规则的一个文本,当你在开发一整个项目的时候,例如当你使用gcc main.c hello.c -o main.o 当使用这样的命令的时候,gcc编译器会自动去把main.c和hello.c一起进行编译,但是如果需要编译的文件越来越多,那么使用这种命令是非常不方便的,而makefile就解决了这种问题,当然后续我们还会学习更加现代的项目管理工具CMAKE。
MakeFile的安装
sudo apt install -y build-essential
MakeFile内容通常由以下3部分组成
<目标名称>:<前置依赖>
需要执行的命令
例如
main:hello main.o
gcc hello.o main.o -o main
下面,我们在基础的makefile文件上进行扩展
main:main.o hello.o
gcc main.o hello.o -o main
main.o:main.c hello.h
gcc -c main.c
hello.o:hello.c hello.h
gcc -c hello.c
clear:
rm main main.o hello.o
其中,由于main.o依赖main.c和hello.h文件,因此需要都加上,hello.o同理。gcc -c参数是用来生成.o文件的参数
clear是配置,当执行make clear命令的时候,可以一键清除main,main.o,hello.o文件。
当我们在makefile文件所在的目录的终端中执行命令make的时候,编译器就会自动执行make中的编译规则。
变量
在makefile 中我们也是有变量的,为什么要有变量呢?在上面我们的makefile示例中,可以看到我们在多处使用了main.o hello.o,因此,我们可以用一个变量等于这两个东西,然后在使用这两个文件的地方用变量名进行替换即可
object:=main.o hello.o
main:$(object)
gcc $(object) -o main
main.o:main.c hello.h
gcc -c main.c
hello.o:hello.c hello.h
gcc -c hello.c
clear:
rm main $(object)
可以看到,我们定义的时候是变量名:=值
的形式定义,使用的时候是$(变量名)
这种形式来使用
makefile中还有三个默认的变量,我们可以直接使用
$@:表示目标文件。
$^:表示所有的依赖文件。
$<:表示第一个依赖文件。
自动推导功能
在makefile中,是有自动推导功能的,这个功能是什么意思呢?就是说我们完全可以只写
object:=main.o hello.o
main:$(object)
gcc $(object) -o main
clear:
rm main $(object)
这一部分,而对于main.o和hello.o,makefile会想方设法的去给你编译出来,因此无需我们自己去设置规则,这样一来我们的makefile文件就大大简化了,但是这样会导致一个问题,当我们使用自动推导main.o和hello.o的时候,其实自动推导是不去管.h文件的,因此这样就会让makefile没法检测.h文件的变化,因此我们需要加上.h文件,整理后的makefile文件内容如下:
object:=main.o hello.o
main:$(object)
gcc $(object) -o main
main.o:hello.h
hello.o:hello.h
clear:
rm main $(object)
小tips:打开vscode中的终端快捷键是"ctrl+反引号"
伪目标
伪目标并不代表实际的文件名,它更多地是行为或者动作的标识符,伪目标并不生成具体文件。
例如我们在上面代码中的clear,这就是一个伪目标,因为我们并没有生成一个叫做clear的目标文件,而仅仅是当我们使用make clear的时候会执行特定的命令。
当我们在makefile中使用当前文件夹下没有的文件名称的时候,它默认就是一个伪目标,那么什么情况下我们会使用到伪目标呢?当我们文件夹下有一个叫做clear的文件,他的名字与clear产生了冲突,此时我们就需要显示的声明以下clear是一个伪目标。
声明伪目标的语法是:
.PHONY:<伪目标名称>
例如:
.PHONY:<clear>
假若我们没有这个显示声明,而且还有同名文件,他的执行情况就会如下图所示
禁止报错
当我们重复执行make clear的时候,会产生一些报错信息,那么,我们如果不想看到这些报错信息,就可以在rm main $(object)前面加一个-,因此完整的命令就是-rm main &(object)
问题
对于
main:main.o hello.o
gcc main.c hello.c -o main123
当我们gcc的生成文件名称叫做main123,而另一个目标文件叫做main的时候,会发生什么呢?我们会发现生成的文件名称叫做main123,那么我们可不可以这样做呢?这样做是不可以的,我们要时刻保证main与main123名称相同,这是因为main是我们makefile要监视的文件,而main123是生成的文件,这俩名称不匹配就会造成监视不到生成的文件,因此会造成重复编译。
以上就是makefile的全部内容,当然这只是基础的学习内容,但是对于我们学习嵌入式Linux应用开发已经足够了。