我们先来看一下make/Makefile在Linux中的简单使用(先看看猪跑,接着会解析规则):
第二步:创建一个Makefile文件,写入符合Makefile规则的内容
第三步:使用make命令,生成可执行程序,使用make clean删除可执行程序
Makefile是一个围绕依赖关系和依赖方法构建的一个自动化编译的工具。
1.依赖关系:在这个程序中,myfile可执行程序和myfile.c文件构成依赖关系,myfile.c的改变会影响myfile,所以myfile依赖于myfile.c。所以第一行就表示myfile可执行程序的生成依赖于myfile.c文件。
2.依赖方法:myfile可执行程序的生成依赖于myfile.c,而gcc myfile.c -o myfile
就是myfile文件依赖myfile.c的依赖方法。
(注意:完成一件事必须要有正确的依赖关系+正确的依赖方法。)
3.PHONY:被该关键字修饰的对象是一个伪目标,即该目标可以总是被执行(不需要进行时间新旧的比较),即如果我们希望多次生成一样的可执行程序,就可以用这个关键字修饰对象,不过我们一般不这样操作。大家肯定会有疑问:“啊?总是被执行是什么意思?”
我们接下来以这个Makefile文件为例,myfile.c文件的内容还是不变的。
make原理:这段代码,充分体现了依赖关系与依赖方法:make会在当前目录下找名字为“Makefile”或“makefile”的文件,然后找到第一个依赖关系,myfile的生成依赖于myfile.o,myfile.o的生成依赖于myfile.s,myfile.s的生成依赖于myfile.i,myfile.i的生成依赖于myfile.c,然后gcc的内容分别是它们的依赖方法。然后clean就是清理,当我们在命令行输入make clean,就会执行rm -f myfile myfile.i myfile.o myfile.s
这句指令,就可以直接删除这些文件了。这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
项目清理:工程是需要被清理的。像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。
这段代码第一次执行make,可以正常执行,然鹅,我们第二次在命令行输入make,就无法再次被执行了。然鹅,大家看上图make clean被执行一次生效之后,我们再执行一次,还是可以生效。那么这就是.PHONY的作用,也就是“总是被执行”的意思。如果大家希望make指令可以总是被执行,那么就在开头加上.PHONY。那么在不加.PHONY,gcc是怎么知道我们不需要再编译了呢?
方法:如果我们make之后,又对源文件进行修改,则我们还可以再执行make指令(即编译器会判断myfile.c的modify时间是否早于myfile可执行程序,如果晚于myfile,则说明myfile.c文件发生修改,make可以继续执行,生成新的程序,覆盖旧的程序)。
注意:make是一条命令,makefile是一个文件(在当前源代码的路径下),两个搭配使用,完成项目自动化构建。make指令默认执行Makefile文件中第一个依赖方法。如果你想运行指定的程序,就要显示定义,例如上述的make clean。
例如我们将Makefile文件改成如下代码并wq退出,在命令行输入make指令,就会先执行rm指令。
首先,我们可以直接使用gcc指令对多个源文件进行编译,进而生成可执行程序。注意用这种方式编译文件,不需要加上头文件,因为编译器通过源文件的内容可以直接知道所需头文件的名字。
但进行多文件编译的时候,一般不直接用gcc生成可执行程序,而是先用每个源文件生成各自的二进制文件,即.o文件,然后再将这些二进制文件通过链接生成可执行程序。但是随着源文件个数的增加,指令长度也会增长,所以我们就需要用到项目自动化构建工具make/Makefile,这样可以大大提高编译运行的效率。
原因:
步骤一: 在源文件所在目录下创建一个名为Makefile/makefile的文件。
步骤二: 编写Makefile文件。
执行结果:
补充:Makefile文件的快捷书写方式