一、makefile文件介绍
makefile关系到了一个工程的编译规则,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
makefile带来的最大好处就是——“自动化编译”,(一次写好,一直使用)一旦写好,只需要一个make命令,整个工程完全自动编译,极大地提高了编译效率,从而提高了软件开发的效率。make是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,VisualC++中的nmake,Linux下GNU的make,可见makefile成为了一种在工程方面的编译方法
文件名‘makefile’效果等同于‘Makefile’,但若文件名改为除二者之外的其他名字file,即使文件内容一模一样,执行make时,会出错,因为make命令只认makefile或Makefile,这时可用make -f file 指定。
下面以一个例子来说明,现有四个文件,add.c,max.c,txt.c,my.h,他们的内容如下:
二、makefile文件的编写以及make工作方式
1.源文件在同级目录下
现在我们来写一个makefile文件,规定它们的编译规则 :
vim makefile
通过make命令,可以自动编译多个文件,最终生产可执行文件
进入add.c,中将+号修改为-号,再次make,会发现只会重新编译add.c,其他没做修改的不会重新编译:
make如何知道哪一个被修改了呢?
答:根据.o文件的文件修改时间,一般情况下,.o文件是的生成比其对应的.c文件生成晚,如果一旦出现某一个.o文件的文件修改时间比.c文件的文件修改时间早,那就说明,该源文件已被修改,这时,make会重新编译这个源文件。
要回答上面这个问题最终还是要了解make的工作方式:
(1)make会在当前目录下找名字叫“Makefile” 或“makefile” 的文件。
(2)如果找到,它会找文件中的第一个目标文件, 在上面的例子中,他会找到“txt”这个文件,并把这个文件作为最终的目标文件。
(3)如果txt文件不存在,或是txt所依赖的后面的.o文件的文件修改时间要比txt这个文件新,那么,他就会执行后面所定义的命令来生成txt这个文件。
(4)如果txt所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
(5)当然,当通过一系列的依赖关系找到的.c和.h文件时,make会生成.o文件,然后再用.o文件生成make的终极任务,也就是可执行文件txt了。
make clean命令,清理*.o中间文件和已经生成的可执行文件:
makefile文件不是一次写完的,随着工程所需文件的增多,makefile文件是一点一点慢慢完成的,所以当我们工程新增了一个文件时,我们需要将其写进makefile文件中,虽然这样已经很大程度上的提高效率了,但在其写入makefile文件中我们觉得要在很多地方添加,有些麻烦,这时可通过变量来实现,
此时若添加一个文件,还要在makefile文件中添加两个部分,一个是val=右边,一个是下面指定.o文件的生成方式。由于makefile默认编译cc命令,系统自带默认编译命令cc(在/usr/bin目录下),这时,我们就可以省掉一些,如下,也可以生成可执行文件
GNU中的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,所以没必要在每个.o文件后面都写上它的的依赖文件.c,因为make会制动识别,比如add.o文件,make会自动识别出它的依赖文件add.c。
因此上述可以进一步省掉:
也可以生成可执行文件
第四行代码其实就是第一行代码定义的变量,将其替换为那个变量:
也可以正确生成可执行代码。
当工程中所需文件比较多时,定义val变量一行写不完时,换行需要转义符号‘\’,如下
现在,工程中若添加一个源文件,可以直接添加在第一行定义的变量后面,不用再修改makefile文件其他地方,就可以直接生成可执行文件。
2.源文件在不同目录下
将add.c,max.c和my.h放在与txt.c同级目录下的一个子目录里
makefile默认在当前目录下 搜索,可在第一行通过VPATH指定目录,可指定多个目录用分号隔开,若在./am目录里找不到就去'另一个路径里找':