Makefile的作用: makefile关系到整个过程的编译规则,makefile制定了一系列规则来指定哪些文件先编译,哪些文件后编译,哪些编译需要重新编译,甚至进行更复杂的功能操作,makefile就像一个shell脚本一样,也可以执行操作系统的命令,也就是实现“自动化编译”,一旦写好,只需要一个make命令,整个工程就会完全自动编译,极大的提高了软件开发的效率。
首先了解程序的编译和链接。编译器需要的是语法正确,函数与变量的声明正确,只要语法正确,编译器就可以编译出中间文件。每个源文件都应该对应于一个中间目标文件。把源文件编译成中间代码文件(linux下是.o文件,Windows下是.obj文件)。链接主要是链接函数和全局变量。利用中间目标文件链接应用程序。
源文件首先会生成中间目标文件,再由中间目标文件生产执行文件。在编译时,编译器只检测程序语法,和函数是否被声明,如果没有被声明只会给出警告,仍然可以生产object file。在连接程序时,链接器会在所有的object file中寻找函数的实现,如果找不到会报链接错误。
写一个 makefile告诉make命令如何编译和链接所指的文件。规则是:
1.如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。
2.如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
3.如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。
makefile规则:
<target> : <prerequisites>
[tab] <commands>
target:目标文件,可以是中间目标文件也可以是执行文件,还可以是标签(Label)(依赖生产的)
prerequisites:源文件,要生成的目标文件所需要的文件或目标。(被依赖的)
command:make需要执行的命令。
这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。
每个*.o文件都对应一组依赖文件。而这些.o文件又是执行文件的依赖文件。
定义好依赖关系后,后续一行定义了如何生产目标文件的操作系统命令。注意要以Tab键作为开头。
make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新或者targets文件不存在,make会执行后续的命令。
clean不是一个文件,而是一个动作名字。
make在默认方式下如何执行:
1.make会在当前目录下找名字叫Makefile 或makefile的文件。
2.如果找到,它会找文件的第一个目标文件(tagart),并把文件作为最终的目标文件。
3.如果目标文件不存在,或者目标文件所依赖的.o文件修改时间要比目标文件新,那么会执行后续定义的命令语句生成目标文件。
4.如果目标所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件
5.如果C文件和H文件都存在,那么make会生成.o文件。然后.o文件声明make的终极任务,也就是执行目标文件了。
$(objects)的使用。
make自动推到——>隐晦规则
.PHONY:clean表示clean是一个伪目标
.PHONY : clean
clean :
-rm edit $(objects)
rm前面加一个”-” 表示某些文件出现问题。不用管,继续执行后面的命令。
makefile文件里主要包含五个东西:显示规则,隐晦规则,变量定义,文件指示和注释。
显示规则:又makefile书写者明显指出要生成的文件,以及文件要依赖的文件,生成的命令。
隐晦规则:主要是makefile有自动推导的功能。
变量的定义:变量一般是字符串,当makefile被执行时,其中的变量会被扩展到相应的引用位置上。
注释:makefile中只有注释行。用“#”字符。
最好用Makefile命名Makefile文件。
Makefile文件中可以引用其他的Makefile:
使用include关键字可以把别的Makefile包含进来,include语法是:
include
其中filename可以是当前操作系统shell的文件模式以为可以包含路径和通配符。
-include<filename>
表示无论include过程中出现什么错误,都不要报错而是继续执行。
环境变量MAKEFILE:
如果你的当前环境中定义了环境变量MAKEFILES,那么,make会把这个变量中的值做一个类似于include的动作。这个变量中的值是其它的Makefile,用空格分隔。只是,它和include不同的是,从这个环境变中引入的Makefile的“目标”不会起作用,如果环境变量中定义的文件发现错误,make也会不理。
建议不要使用这个环境变量,因为只要这个变量一被定义,那么当你使用make时,所有的Makefile都会受到它的影响。
make的工作方式:
一:第一个阶段
1. 读入所有的Makefile。
2. 读入被include的其它Makefile。
3. 初始化文件中的变量。
4. 推导隐晦规则,并分析所有规则。
5. 为所有的目标文件创建依赖关系链。
二:第二个阶段
6. 根据依赖关系,决定哪些目标要重新生成。
7. 执行生成命令。