Chinaunix首页 | 论坛 | 博客
  • 博客访问: 135527
  • 博文数量: 30
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 550
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-08 20:28
个人简介

永远不要放弃学习,放弃学习就是放弃了勇敢生活下去的动力!

文章分类

全部博文(30)

文章存档

2014年(30)

我的朋友

分类: 嵌入式

2014-03-09 14:59:28

首先我们学习操作系统的时候就学习了Makefile是什么,其实make工具就是通过Makefile的文件来完成并自动维护编译工作,make工具的工作流程如下所示:

查找当前目录下的Makefile文件。

初始化文件中的变量。

分析Makefile中的所有规则。

为所有的目标文件创建依赖关系。

根据依赖关系,决定哪些目标文件要重新生成。

执行生成命令。
Makefile规则:

#注释
    目标文件:依赖文件列表
《Tab》命令列表

下面我通过一个简单的例子来写一个最简单的makefile文件吧
该例子程序有:maketest.c,hello1.h,hello2.h,hello1.c,hello2.c
maketest.c文件

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include "hello1.h"
  3. #include "hello2.h"
  4. int main(int argc,char **argv)
  5. {
  6.     char *pstr="hello in main";
  7.     int arr[]={1,2,3,4,5};
  8.     printf("%s\n",pstr);
  9.     print_hello1("hello 1");
  10.     print_hello2("hello 2");
  11. }

hello1.h文件

点击(此处)折叠或打开

  1. #ifndef _HELLO_1_H
  2. #define _HELLO_1_H
  3. void print_hello1(char *p_str);
  4. #endif

hello2.h文件

点击(此处)折叠或打开

  1. #ifndef _HELLO_2_H
  2. #define _HELLO_2_H
  3. void print_hello2(char *p_str);
  4. #endif

hello1.c文件

点击(此处)折叠或打开

  1. void print_hello1(char *p_str)
  2. {
  3.     printf("%s\n",p_str);
  4. }


hello2.c文件

点击(此处)折叠或打开

  1. void print_hello2(char *p_str)
  2. {
  3.     printf("%s\n",p_str);
  4. }


Makefile文件

点击(此处)折叠或打开

  1. maketest: maketest.o hello1.o hello2.o
  2.     gcc -o maketest maketest.o hello1.o hello2.o
  3. maketest.o: maketest.c hello1.h hello2.h
  4.     gcc -c maketest.c
  5. hello1.o:hello1.c hello1.h
  6.     gcc -c hello1.c
  7. hello2.o:hello2.c hello2.h
  8.     gcc -c hello2.c


大家应该看都会看明白了,
目标文件:可以生成目标文件的文件
gcc -o 目标程序 依赖的文件
gcc -c 需要编译的.c文件

下面介绍复杂一点的makefile规则

clean目标是一个约定俗成的名字,在所有软件项目的Makefile中都表示清除编译生成的文件,类似这样的约定俗成的目标名字有:
all,执行主要的编译工作,通常用作缺省目标。

install,执行编译后的安装工作,把可执行文件、配置文件、文档等分别拷到不同的安装目录。

clean,删除编译生成的二进制文件。

distclean,不仅删除编译生成的二进制文件,也删除其它生成的文件,例如配置文件和格式转换后的文档,执行make distclean之后应该清除所有这些文件,只留下源文件。

$@,表示规则中的目标。

$<,表示规则中的第一个条件。

$?,表示规则中所有比目标新的条件,组成一个列表,以空格分隔。

$^,表示规则中的所有条件,组成一个列表,以空格分隔。

例如前面写过的这条规则:
main: main.o stack.o maze.o
    gcc main.o stack.o maze.o -o main
可以改写成:
main: main.o stack.o maze.o
    gcc $^ -o $@
    这样即使以后又往条件里添加了新的目标文件,编译命令也不需要修改,减少了出错的可能
比如上一个例子我想编译makefile文件,我可以通过gcc来找出彼此之间的依赖关系,然后再写makefile文件


点击(此处)折叠或打开

  1. [root@localhost s]# ls
  2. hello1.c hello1.h hello2.c hello2.h makefile maketest.c
  3. [root@localhost s]# gcc -M maketest.c        //利用gcc -M命令来寻找你main函数所有的依赖关系,包含库函数的
  4. maketest.o: maketest.c /usr/include/stdio.h /usr/include/features.h \
  5.  /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
  6.  /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
  7.  /usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h \
  8.  /usr/include/bits/types.h /usr/include/bits/typesizes.h \
  9.  /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
  10.  /usr/lib/gcc/i686-redhat-linux/4.4.4/include/stdarg.h \
  11.  /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h hello1.h \
  12.  hello2.h
  13. [root@localhost s]# gcc -MM *.c    //除掉头文件的依赖,这就是你源程序之间的依赖
  14. hello1.o: hello1.c
  15. hello2.o: hello2.c
  16. maketest.o: maketest.c hello1.h hello2.h
  17. [root@localhost s]#

下面看看makefile怎样写的

点击(此处)折叠或打开

  1. all: maketest
  2. maketest:maketest.o hello1.o hello2.o
  3.     gcc $^ -o $@
  4. maketest.o: maketest.c hello1.h hello2.h
  5. hello1.o:hello1.c
  6. hello2.o:hello2.c

  7. clean:
  8.     -rm maketest *.o
  9. .PHONY:clean


这样就写好了makefile文件,其中clean规则就是利用make clean来执行用的。

如果再往下面学习makefile规则,那么就参照GNU make的官方手册的规则来写,

点击(此处)折叠或打开

  1. all:maketest
  2. maketest:maketest.o hello1.o hello2.o
  3.     gcc $^ -o $@
  4. clean:
  5.     -rm maketest *.o
  6. .PHONY:clean

  7. sources=maketest.c hello1.c hello2.c
  8. include $(sources:.c=.d)

  9. %.d:%.c
  10.     sed -e; rm -f $@; \
  11.     $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
  12.     sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
  13.     rm -f $@.$$$$

sources变量包含我们要编译的所有.c文件,$(sources:.c=.d)是一个变量替换语法,把sources变量中每一项的.c替换成.d,所以include这一句相当于:include maketest.d hello1.d hello2.d
set -e命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则立刻终止,不再执行后续命令

make -n命令只打印要执行的命令,而不去执行,这有助于我们调试makefile文件,
make -c 目录 可以指定目录下的makefile文件
make工具盒makefile大概也就学习这么多了,我想我们拥有gcc编译的能力,拥有编写普通makefile文件能力后,那么就可以慢慢去学习较深的能力,其实较深的就是普通的积累与函数的运用,就像shell变成一样,我们学会了基本的东西,那么加上函数之后我们就可以编写复杂的脚本程序来处理我们


阅读(2890) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~