Chinaunix首页 | 论坛 | 博客
  • 博客访问: 501688
  • 博文数量: 174
  • 博客积分: 130
  • 博客等级: 入伍新兵
  • 技术积分: 587
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-12 19:39
文章分类

全部博文(174)

文章存档

2018年(2)

2016年(10)

2015年(6)

2014年(31)

2013年(92)

2012年(33)

我的朋友

分类: Python/Ruby

2013-07-28 00:42:52

原文地址:makefile 文件 作者:graylocus

makefile相当于一种脚本编程语言,可以使用变量、控制结构语句、函数,也可执行shell命令。
makefile是用来实现自动化编译,makefile区别于其他编程语言的最大特点就是,它的执行是由所编译文件的依赖关系驱动的。

1.makefile文件的组成
主要有五种部分:
(1)显式规则:什么是规则?
(2)隐式规则:由于make具有自动推导功能,所以隐晦的规则可以让人比较粗略的写makefile
(3)变量的定义:在makefile里,变量实际上就是字符串,makefile也可认为是做的是字符串处理工作。
(4)文件指示:1.引用另一个makefile文件,像include
               2.根据某些情况指定Makefile中的有效部分,就像C中的预处理#if
               3.定义一个多行的命令
(5)注释:用#注释,转义字符是\,如要输出#,可以\#。

2.makefile规则
make工具通过规则,确定所要编译文件之间的依赖关系,并进行编译。
(1)基本规则:
规则的两种形式:
   第一 targets : prerequistites
    command
   ....
   第二 targets : prerequitites ; command
    command
     ....
targets是目标,有两类目标,一是在执行过程中产生的文件名,如.o文件;二是某个动作,在执行过程中没有实际的文件与之对应。这种情况称为PHONY目标,只执行命令不产生文件。
command是命令,一般以tab键开头。如果和文件依赖规则在同一行,可以用“;”隔开
prerequisites表示生成目标文件所依赖的文件。如果其中某个文件比目标文件新,make工具会认为目标文件需要更新,make工具会生成新的目标文件。如果依赖过长,可以用“\”隔开
make工具对更新的定义:
第一 目标文件没有生成
第二 某个条件中的文件修改时间比目标文件晚
第三 某个条件中的文件需要更新

示例1:

点击(此处)折叠或打开

  1. app : main.o lib.o drv.o
  2. gcc -o app main.o \ # \用作换行
  3. lib.o drv.o
  4. main.o : main.c head.h
  5. gcc -c main.c
  6. lib.o : lib.c lib.h
  7. gcc -c lib.c
  8. drv.o : drv.c drv.h
  9. gcc -c drv.c
  10. clean:
  11. rm *.o app
(2)隐式规则的使用
由于make具有自动推导功能,所以隐晦的规则可以让人比较粗略的写makefile。比如,make工具会自动的使用gcc -c 命令,将一个后缀为.c的源文件编译得到一个同名的.o目标文件。使用这个隐式规则,我们可以将上面的示例1改写为如下形式:

示例2

点击(此处)折叠或打开

  1. app : main.o lib.o drv.o
  2.     gcc -o app main.o \     # \用作换行
  3.         lib.o drv.o

  4. main.o : head.h #得到main.o文件
  5.     
  6. lib.o : lib.h #lib.o
  7.     
  8. drv.o : drv.h
  9.     
  10. clean:
  11.     rm *.o app

(3)伪目标(目标,就是规则中的targets,有两种目标,前面已说明)
什么是伪目标?就是该目标不对应一个真正的目标文件,就像C语言中的标号,只执行命令,而不生成文件。make工具无法为不是具体文件的目标生成依赖关系,而且不能决定是否执行该目标。因此,需要人为的指明该目标,这里就是指明为clean,这叫做显式的指明。
为了避免与已存在的文件重名,有个方法,使用.PHONY 来显式的指明一个目标是伪目标,PHONY在英语里是虚假的,假冒的意思。
注意,是显式的。上面说的,当然就是隐式的。。
如:
.PHONY : clean 

使用了PHONY这个关键字,表示不管是否有clean文件存在,都要将clean声明为伪目标。

示例3:第一个目标是默认目标(默认目标,如make后什么也不加,默认目标为文件中第一个目标,将其声明为伪目标,则默认目标每次都会被执行。)

点击(此处)折叠或打开

  1. all : main.o lib.o drv.o
  2.     gcc -o app main.o \     # \用作换行
  3.         lib.o drv.o
  4. .PHONY all 
  5. main.o : main.c head.h
  6.     gcc -c main.c
  7. lib.o : lib.c lib.h
  8.     gcc -c lib.c
  9. drv.o : drv.c drv.h
  10.     gcc -c drv.c
  11. clean:
  12.     rm *.o app
makefile中的第一个目标会被认作默认目标。这里,把all声明为伪目标。由于伪目标依赖的文件总是不如伪目标新,所以伪目标all所依赖的命令总是执行。

(4)规则中的通配符
make工具支持三种:*, ? , []


3.规则中使用的命令
(1)回显命令:echo
make工具可以使用@字符,将make执行过程中需要打印的信息不在屏幕输出。
如:@echo "initializing..."

(2)使用shell环境下的命令,如,cd,ls,pwd。
在两条命令之间加上 “;”,可以将上一条命令的结果应用在下一条上。

4.变量的使用
makefile中 的变量分为两种:立即变量+延时变量

=?= 还有define用来定义延时变量,  其中?=只用在变量第一次被定义

:= 用来定义立即变量

对于 += 来说,右边的变量是延时变量,那么它就是延时变量。  右边是立即变量,它就是立即变量。

Makefile中,变量就是一个名字(像是C语言中的宏),代表一个文本字符串(变量的值)。在Makefile的目标、依赖、命令中引用一个变量的地方,变量会被它的值所取代(与C语言中宏引用的方式相同,因此其他版本的make也把变量称之为“宏”)。在Makefile中变量的特征有以下几点:

(1). Makefile中变量和函数的展开(除规则的命令行以外),是在make读取makefile文件时进行的,这里的变量包括了使用“=”定义和使用指示符“define”定义的。

(2). 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。

(3).  变量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。需要注意的是,尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的其它字符可能会在以后的make版本中被赋予特殊含义,并且这样命名的变量对于一些shell来说不能作为环境变量使用。

(4). 变量名是大小写敏感的。变量“foo”、“Foo”和“FOO”指的是三个不同的变量。Makefile传统做法是变量名是全采用大写的方式。推荐的做法是在对于内部定义定义的一般变量(例如:目标文件列表objects)使用小写方式,而对于一些参数列表(例如:编译选项CFLAGS)采用大写方式,这并不是要求的。但需要强调一点:对于一个工程,所有Makefile中的变量命名应保持一种风格,否则会显得你是一个蹩脚的程序员(就像代码的变量命名风格一样)。

(5).  另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自动化变量。像“$<”、“$@”、“$?”、“$*”等。

$@:规则中的目标文件

$<:依赖列表中的第一个依赖

$^:依赖列表中的所有依赖

$*:目标模式中“%”及其之前的部分

$?:所有比目标新的依赖的集合,以空格隔开



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