GNUmake 的主要工作是读一个描述文件,通过该文件描述的目标文件与源文件之间的依赖关系,从项目源代码中生成最终可执行文件和其他非源代码文件。
编写 makefile 文件就是描述这种关系,执行 make时,如果目标文件的日期至少比它的一个依赖文件日期早,make就会执行相应的命令,更新目标文件。
Make命令本身可带有四种参数:标志,宏定义,描述文件名和目标文件名。
其标准形式为 :
Make [flags] [macro definitions] [targets]
-f file :指定 file 文件为描述文件,如果没有这个参数,则系统默认当前目录名下为 makefile Makefile 的文件为描述文件。在 Linux 中, GNUmake 工具在当前工作目录中按照 GNUmakefile makfile Makefile 的顺序搜索描述文件。
一个 makefile 主要含有一系列的规则,如下:
       target ... : requisites ...
                    command
                    ...
                    ...
第一行称为规则,第二行是执行规则的命令,必须要以 TAB 键开始。
target是一个目标文件,可以是Object File,也可以是执行文件; requisites是生成这个target的所有依赖文件;command是完成这个操作的 shell命令。
target也可以当作伪目标,此时command为空,用于一个项目中要生成多个相互独立的目标文件。这些需要生成的独立的目标文件全部当作target伪目标的依赖文件,却没有实际生成它的命令,但make依然会试图更新所有依赖文件,这样就达到了预期的目的。
target还可以是一个标签,当其作为标签时,冒号后面不写依赖文件 。所以这时它不是一个文件,只不过是一个动作的名字,像C语言中的lable 一样,make不会自动去找文件的依赖性,也就不会自动执行其后所定义的命 令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。 利用这个特性,可以在一个makefile中定义不用的编译或是和编译无关的命 令,比如程序的打包,备份,删除中间文件等等,需要完成这些操作时,执 行一下“make (lable)”就可以了。

宏定义
宏定义的作用是为了简化makefile文件,也使得其更容易理解。定义一个宏,任起一行,格式:“宏名 = 设定宏的值”,引用时用 $(宏名) ${宏名} ,其作用与 C 语言的 define 是一样的,就是符号替换。几个常用的内部变量:
$@ :当前规则的目标文件
$< :当前规则依赖文件列表中的第一个依赖文件
$? :所有的修改日期比当前规则的目标文件的创建日期更晚的依赖文件,只有显式规则时才会被使用。
$* :当前规则中目标文件和依赖文件共享的文件名,不含扩展名。
$^ :整个依赖文件的列表。
如果一条语句过长,将符号"\"放在右边界,将下一行的内容作为这句的续 行;宏定义中符号"+="的意思是在原来的基础上添加新的内容。

隐含规则
隐含规则这个东西看了一段时间,比较费解。简单来说,就是makefile里没有写出生成目标的规则,make自己会去库中寻找生成它的规则。这些规则写在库中,一般为“后缀规则”,类似"filename.o是由filename.c生成的"。比如:
     main : main.o operate.o
             gcc –o main main.o operate.o
这个makefile中并没有写出如何生成main.o和operate.o这两个目标的规则和命令。系统会寻找main.c和operate.c按照规则生成这两个目标,如果找不到就会报错。(这里简化了隐含规则,当然还有其他生成.o文件的规则,例如.p生成.o)
还有其他比较深入的东西,暂时还没有遇到,所以不说了,从网上下载了《GNUmake中文手册》,感觉挺不错,留个记号,这个会是以后需要深入学习的地方。

用最简单的程序,小试牛刀一番,本来想试下流水灯的,无奈Linux下汇编不会,所以还是那个Hello World,把它拆成几个程序文件来写,用make来编译它。

/*operate.h*/
#ifndef _operate_h
#define _operate_h
void operate();
#endif

/* main.c */
#i nclude "operate.h"
int main()
{
operate();
return 0;
}

/*operate.c*/
#i nclude
void operate()
{
printf("Hello World!\n");
}

/* maikfile1 */
main : main.o operate.o
            gcc -o main main.o operate.o
main.o : main.c operate.h
            gcc -c main.c operate.h
operate.o : operate.c
            gcc -c operate.c
clean :
            rm main main.o operate.o

/* maikfile2*/
main : main.o operate.o
            gcc -o main main.o operate.o
clean :
            rm main main.o operate.o

用makefile1编译,屏幕依次显示上面的三条编译指令,然后生成可执行文件main,./main可以看到输出"Hello World!",执行make clean删除编译过程中生成的文件。
用makefile2编译,用到了隐含规则,同样可以达到相同的效果,屏幕显示
CC -c -o main.o main.c
CC -c -o operate.o operate.c                     <--可见隐含的命令是这样的

接下来,就练习编译一下uclinux的内核,makefile先接受这么多吧!
 
转载处 http://blog.21ic.com/user1/5930/archives/2008/62172.html