makefile 中 edit

来源:互联网 发布:知乎的海贼 王路飞 编辑:程序博客网 时间:2024/06/05 20:59

makefile 说白了是一种方便编程的脚本,可用vim makefile 命令建立.随便一种文本的方式建立他,然后放在你代码的目录下.

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

假设我们有下面这样的一个程序,源代码如下: 

/* main.c */ 
#include "mytool1.h" 
#include "mytool2.h" 

int main(int argc,char **argv) 

mytool1_print("hello"); 
mytool2_print("hello"); 


/* mytool1.h */ 
#ifndef _MYTOOL_1_H 
#define _MYTOOL_1_H 

void mytool1_print(char *print_str); 

#endif 

/* mytool1.c */ 
#include "mytool1.h" 
void mytool1_print(char *print_str) 

   printf("This is mytool1 print %s\n",print_str); 


/* mytool2.h */ 
#ifndef _MYTOOL_2_H 
#define _MYTOOL_2_H 

void mytool2_print(char *print_str); 

#endif 
   
/* mytool2.c */ 
#include "mytool2.h" 
void mytool2_print(char *print_str) 

   printf("This is mytool2 print %s\n",print_str); 



当然由于这个程序是很短的我们可以这样来编译 
gcc -c main.c 
gcc -c mytool1.c 
gcc -c mytool2.c 
gcc -o main main.o mytool1.o mytool2.o 
这样的话我们也可以产生main程序,而且也不时很麻烦.但是如果我们考虑一下如果有一天我们修改了其中的一个文件(比如说mytool1.c)那么我们难道还要重新输入上面的命令?也许你会说,这个很容易解决啊,我写一个SHELL脚本,让她帮我去完成不就可以了.是的对于这个程序来说,是可以起到作用的.但是当我们把事情想的更复杂一点,如果我们的程序有几百个源程序的时候,难道也要编译器重新一个一个的去编译? 
为此,聪明的程序员们想出了一个很好的工具来做这件事情,这就是make.我们只要执行以下make,就可以把上面的问题解决掉.在我们执行make之前,我们要先编写一个非常重要的文件.--Makefile.对于上面的那个程序来说,可能的一个Makefile的文件是: 
#   这是上面那个程序的Makefile文件

$ vim makefile

输入:(以下括号为提示:)


main:main.o mytool1.o mytool2.o (main是你最终程序的名字,后面是他的附属关系,)
(Tab键)gcc -o main main.o mytool1.o mytool2.o (输入之前一定要先按TAB键,链接!)
main.o:main.c mytool1.h mytool2.h (又一个附属关系)
(Tab键)gcc -c main.c (编译)
mytool1.o:mytool1.c mytool1.h 
(Tab键)gcc -c mytool1.c (编译)
mytool2.o:mytool2.c mytool2.h 
(Tab键)gcc -c mytool2.c(编译)

保存退出,然后执行make命令就OK啦!

以下是补充内容,可更深入应用:

三、make 是如何工作的
在默认的方式下,也就是我们只输入make 命令。那么,
1、make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最
终的目标文件。
3、如果edit 文件不存在,或是edit 所依赖的后面的 .o 文件的文件修改时间要比edit 这个文件新,那么,他就会执行后面所定
义的命令来生成edit 这个文件。
4、如果edit 所依赖的.o 文件也存在,那么make 会在当前文件中找目标为.o 文件的依赖性,如果找到则再根据那一个规则生成.o
文件。(这有点像一个堆栈的过程)
5、当然,你的C 文件和H 文件是存在的啦,于是make 会生成.o 文件,然后再用 .o 文件生命make 的终极任务,也就是执
行文件edit 了。
这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,
如果出现错误,比如最后被依赖的文件找不到,那么make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不
成功,make 根本不理。make 只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,
我就不工作啦。
通过上述分析,我们知道,像clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,
不过,我们可以显示要make 执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如file.c,那么根据我们的依赖性,我们的
目标file.o 会被重编译(也就是在这个依性关系后面所定义的命令),于是file.o 的文件也是最新的啦,于是file.o 的文件修改
时间要比edit 要新,所以edit 也会被重新链接了(详见edit 目标文件后定义的命令)。
而如果我们改变了“command.h”,那么,kdb.o 、command.o 和files.o 都会被重编译,并且,edit 会被重链接。
四、makefile 中使用变量
在上面的例子中,先让我们看看edit 的规则:
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文件,那么我们需要在两个地方加(应该
是三个地方,还有一个地方在clean 中)。当然,我们的makefile 并不复杂,所以在两个地方加也不累,但如果makefile 变得
复杂,那么我们就有可能会忘掉一个需要加入的地方,而导致编译失败。所以,为了makefile 的易维护,在makefile 中我们可
以使用变量。makefile 的变量也就是一个字符串,理解成C 语言中的宏可能会更好。
比如,我们声明一个变量,叫objects, OBJECTS, objs, OBJS, obj, 或是OBJ,反正不管什么啦,只要能够表示obj 文件就行了。
我们在makefile 一开始就这样定义:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
于是,我们就可以很方便地在我们的makefile 中以“$(objects)”的方式来使用这个变量了,于是我们的改良版makefile 就变成
下面这个样子:
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
于是如果有新的 .o 文件加入,我们只需简单地修改一下 objects 变量就可以了。