|
前面我们编译内核时,那么多.c文件最终生成一个zImage镜像。其实是make工具通过解析Makefile文件进行一系列编译操作,最终生成我们想要的镜像文件。Makefile文件中描述了个工程所有文件的编译顺序、编译规则以及依赖关系,决定了工程中文件是否需要编译,以及这些文件的编译顺序。Make工具还可以通过比较文件最后修改时间,来决定哪些文件需要更新哪些不需要更新,更改了某个文件之后,只对依赖此文件的目标文件进行重新编译更新,这就大大减少了编译时间。 打开源码目录可以看到,Makefile文件不仅存在于源码根目录下,在其他的子目录下也基本都有Makefile文件。在执行编译时,Make工具会解析根目录下Makefile 文件进行编译,而根目录的Makefile会调用子目录下的Makefile,子目录下又有子目录,层层调用。 Makefile需要按照一定的格式语法规则进行书写。如果你是做Linux应用开发的人员,那么写Makefile就是必备技能,就需要深谙Makefile语法规则。对于我们Linux平台初级开发人员,很少需要我们去写一个复杂的Makefile文件,只是在做平台移植的时候可能需要去简单修改或者阅读Makefile文件,所以呢,下面我们就简单了解一下Makefile基本格式规则。 目标和依赖 目标就是我们需要生成的文件,依赖就是生成目标文件所需要的其他文件,称为依赖文件。基本语法规则如下:
- targets … :dependent_files …
- (tap)command
- …
复制代码
举例一
我们先创建一个简单的app.c文件:
- elf@ubuntu:~/work/tmp$ touch app.c
复制代码
在文件中输入如下代码:
- #include
- int main(void)
- {
- printf("my first app !!! \r\n");
- return 0;
- }
复制代码
按照基本规则建立一个简单的Makefile文件,app为我们需要的目标文件,app.c为所要生成的app的依赖文件,gcc –o app app.c就是生成目标app需要执行的命令。
建立一个Makefile文件:
- elf@ubuntu:~/work/tmp$ touch makefile
复制代码
文件中输入如下内容:
注意:复制粘贴过程中可能会出现格式问题
- app:app.c
- gcc -o app app.c
复制代码
使用make命令,可以看到执行了命令gcc -o app app.c,ls命令查看文件,发现在该目录下生成了app目标文件:
- elf@ubuntu:~/work/tmp$ make
- gcc -o app app.c
- elf@ubuntu:~/work/tmp$ ls
- app app.c makefile
复制代码
执行app,即可看到app.c中我们写的打印信息:
- elf@ubuntu:~/work/tmp$ ./app
- my first app !!!
复制代码
然后我们再执行make命令,会发现出现如下信息,‘app’ is up to date,说明app已经是最新的,没必要再重新生成:
- elf@ubuntu:~/work/tmp$ make
- make: ‘app’ is up to date.
复制代码
我们做一下稍微的改动,修改app.c文件中的内容或者使用touch命令更改一下app.c的时间属性,然后再进行make看看:
- elf@ubuntu:~/work/tmp$ touch app.c
- elf@ubuntu:~/work/tmp$ make
- gcc -o app app.c
复制代码
可以看到又重新执行了gcc -o app app.c命令,重新生成了app。也就是说,make工具会判断依赖文件的时间戳是否比目标文件时间戳更新,来决定是否重新生成目标文件。
举例二 假如我们有多个文件需要编译,比如我们创建多个文件fun1.c,fun1.h,fun2.c,fun2.h,app.c。 fun1.c:
- #include
- #include "fun1.h"
- void fun1(char *s)
- {
- printf("%s\r\n",s);
- }
复制代码
fun1.h:
- #ifndef _FUN1_H
- #define _FUN1_H
- void fun1(char *s);
- #endif
复制代码
fun2.c:
- #include "fun2.h"
- int fun2(int x,int y)
- {
- return x+y;
- }
复制代码
fun2.h:
- #ifndef _FUN2_H
- #define _FUN2_H
- int fun2(int x,int y);
- #endif
复制代码
创建app.c文件,该文件引用fun1.c和fun2.c中定义的函数:
- #include
- #include "fun1.h"
- #include "fun2.h"
- int main(void)
- {
- fun1("I am fun1 !");
- printf("fun2 return value=%d \n",fun2(1,2));
- return 0;
- }
复制代码
最后创建makefile文件,其中app是我们的最终目标文件,app的依赖文件为app.o,fun1.o,fun2.o,这几个.o文件称为中间目标文件,它们又有各自所依赖的.c和.h文件,最后的clean也是一个目标文件,但是这个目标没有任何依赖,也不会生成真正文件,只是执行一条命令,我们称之为伪目标。我们可以看到clean执行的是删除.o和app的命令。
|