Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1162133
  • 博文数量: 181
  • 博客积分: 4968
  • 博客等级: 上校
  • 技术积分: 1867
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-13 21:52
文章分类

全部博文(181)

文章存档

2015年(2)

2013年(6)

2012年(22)

2011年(41)

2010年(27)

2009年(51)

2008年(32)

我的朋友

分类: LINUX

2009-02-06 17:50:38

嵌入式开发学习总结——make 与 makefle

1、make和makefile是什么
2、为什么使用makefile
3、make的行为准则
4、make的工作方式
5、
makefile的变量和通配符
6、
makefile的例子
7、makefile高级

一、
make和makefile是什么

makefile是一个包括若干目标、依赖和规则的文本文件。根据规则对依赖的文件进行处理,可以产生目标。
一个工程中的源文件不计其数,按照类型、功能、模块分别存放在若干目录 中,makefile定义了一系列的规则来指定那些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至进行更复杂的功能操作。
make是一 个命令工具,能解释执行makefile中的指令。

二、为什么使用makefile

1、为了管理工程中哪些文件需要先编译,有哪些依赖。
2、为了尽可能只编译更新了的文件及其依赖。
2、为了使编译自动化,每次编译是需要输入make即可。
3、为了实现诸如条件编译,运行脚本等功能。

三、
make的行为准则

1、make把第一个目标作为其最终目标除非make调用时指定了目标。
2、如果规则的目标不存在或存在但比依赖中的某个旧,则执行规则中的命令。
3、如果工程的头文件被改变了,需要编译引用了这几个头文件的c文件,并链接目标程序。
4、在查看目标是否存在或查看依赖是否比目标新之前,先看看依赖中的每一项本身是不是某条规则的目标,如果是,需要先处理那条规则。

四、make的工作方式

1、make会在当前目录找文件makefile或Makefile,也可以用-f参数指定。
2、make找到文件中的第一个目标,然后处理它,如果它的依赖需要处理,就递归直到处理结束。

五、
makefile的变量和通配符

1、makefile中以#开头的文字都视为注释。
2、续行时键入'\'字符,然后紧跟回车。
3、可以定义变量或宏,并用$引用。
例如定义OBJS = main.o a.o b.o,$(OBJ)则表示main.o a.o b.o。
4、makefile中有一些内建变量:
$@ 当前规则的目标
$< 当前规则的第一个依赖
$^ 当前规则的所有依赖
$? 当前规则的所有比目标新的依赖
5、伪目标:每个makefile都应该写一个清空目标文件的规则,用于重新编译和保持文件的清洁。
为此,可以写一个clean的目标,它没有依赖,所以需要定义成伪目标,例如
.PHONY:clean
clean:
    -rm app $(OBJS)
rm前面的-表示即使在运行rm时出错,make将继续运行。

六、makefile的例子

一个计算器的例子,包括以下6个文件:
add_minus.c,add_minus.h
multiply_mod.c,multiply_mod.h
calculate.c,calculate.h
顾名思义,这是一个包括加减、乘和取模运算的简单计算器。
源代码如下:
/*
 * add_minus.h
 */
#ifndef __ADD_MINUS_H__
#define __ADD_MINUS_H__

int add(int, int);
int minus(int, int);
 
#endif

/*
 * add_minus.c
 */
int add(int x,int y)
{
  return (x + y);
}

int minus(int x,int y)
{
  return (x - y);
}

/*
 * multiply_mod.h
 */
#ifndef __MULTIPLY_MOD_H__
#define __MULTIPLY_MOD_H__

int multiply(int,int);
int mod(int,int);

#endif

/*
 * multiply_mod.c
 */
int multiply(int x,int y)
{
  return (x * y);
}

int mod(int x,int y)
{
  return (x % y);
}

/*
 * calculate.c
 */
#include
#include "add_minus.h"
#include "multiply_mod.h"

int main(void)
{
  int x = 5;
  int y = 3;

  printf("x + y = %3d\n",add(x,y));
  printf("x - y = %3d\n",minus(x,y));
  printf("x * y = %3d\n",multiply(x,y));
  printf("x %% y = %3d\n",mod(x,y));

  return 0;
}

假设最后需要产生的可执行文件为cal,其依赖关系如下:
cal:calculate.o add_minus.o multiply_mod.o
calculate.o:calculate.c
add_minus.c multiply_mod.c
add_minus.o:add_minus.c
multiply_mod.o:multiply_mod.c

根据以上依赖,可以编写一个简单的Makefile文件如下:
#
# This is a simple Makefile
#

cal:calculate.o add_minus.o multiply_mod.o
    gcc $^ -o $@

calculate.o:calculate.c add_minus.h multiply_mod.h
    gcc -c $< -o $@

add_minus.o:add_minus.c
    gcc -c $< -o $@

multiply_mod.o:multiply_mod.c
    gcc -c $< -o $@

.PHONY:clean

clean:
    -rm -fr cal *.o


七、makefile高级


1、通配符"*", "?"和"[...]"。

2、$(var:a=b)把变量var中所有以a字串结尾的a替换为b字串。

3、$(var:%.a=%.c)被替换字串中的有相同的模式,%可以在某个单词的中间。

4、wildcard, patsubst和addprefix函数。
$(wildcard *.c)产生一个该目录下所有以.c结尾的文件的列表。
$(patsubst %.c,%.o,$(SOURCES))处理所有在SOURCES字列中的字(一列文件名),如果它的结尾是.c,就用.o替换。
$(addprefix prefix,names...)增加前缀,如$(addprefix src/. foo bar)
的结果为:src/foo src/bar。

5、显示命令:利用@控制命令行的显示.
利用make的参数-n或者--just-print仅显示命令,可以用来调试makefile文件; -s或--slient表示禁止命令的显示。

6、执行命令:当在一个规则中包含多条命令时,如果多条命令位于不同的行,则各条命令在不同的shell中执行,每执行完一条命令就退回到原来的shell中;如果多条命令位于同一行,用分号隔开,则它们在同一shell中执行。

7、定义命令包。
命令包用于定义一组经常用到的命令序列,格式如下:
define myfun
...
...
undef
对于命令包的引用,同引用变量类似,$(myfun)可以当作一个规则执行。

8、追加变量值:可以用+=追加变量值

7、make -C subdir等价于 cd subdir && make

8、可以使用ifdef-else-endif进行条件判断,例如:
foo = OK
ifdef foo
   bozz = yes
else
   bozz = no
endif

9、让gcc帮助产生规则
使用gcc的时候,用-M开关,它会为每个.c文件输入一个规则,把.o当作目标,把.c和所有包含的.h作为依赖。
用-MM来代替-M传递给gcc, 那些用<>包围的header文件将不会被包括。
输出的规则不含命令:make会自动使用它对.o的内建命令。
例如:
SOURCES = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,%(SOURCES))

myprog:$(OBJS)
    gcc -o myprog $(OBJS)

depends:$(SOURCES)
    gcc -MM $(SOURCES) > depends

include depends
阅读(1912) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~