Makefile概述

来源:互联网 发布:淘宝网店女鞋图片 编辑:程序博客网 时间:2024/06/14 20:53

概述
make是UNIX®下的一个工具,用来自动创建程式并且进行优化. 当你研发的程式由许多组件或源文件组成时他特别有用.
一个叫makefile的描述符文件阐明了源文件之间的关系,并给出更新每一个文件的命令. 所有时候当源文件之一有所改动,make就调用 makefile自动重建这个程式. 因为仅重编译那些受改动影响的文件,因此节约了编译时间.同时也有助于降低用命令行建立这些条目时发生人为错误的可能性.
除了编译以外, make也是个可用于程式安装和更改系统设置的有效工具.
makefile介绍
为每一个工程创建一个名为makefile的设置文件. 每次修改源程式后, 用简单的命令make调用makefile来执行必要的重编译. make在当前工作目录中按以下的顺序查找这个描述文件:
makefile
Makefile
缺省条件下, 简单的make命令只创建文件中第一个目标. make命令的其他一般用法如下.
make prog1
建立目标 "prog1"
make -f mymakefile
用 "mymakefile" 作设置文件建立源文件中的第一个目标
make -f mymakefile prog1
用 "mymakefile" 作设置文件建立目标 "prog1"
makefile组成
makefile包含的五个主要部分是: 注释, 显式规则, 变量定义, 隐式规则及指示.
注释
Makefile中以字符“#”开始的行为注释行;在一行中字符“#”之后的内容也被看做为注释(和shell脚本一样)。注释行结尾如果使用反斜线 \,那么此行之下的一行(下一行)也被看做为注释行。在书写Makefile时推荐将注释作为一个独立的行,而不要和Makefile的有效内容放在同一行。当Makefile中需要使用字符“#”时,可使用反斜线加“#”(\#)来实现(对具有特殊含义字符“#”进行转义),其表示 “#”在这里是作为一字符而不是注释的开始标志。

详细出处参考:http://www.itqun.net/content-detail/289622.html显式规则
makefile由’规则’(rules)组成. 规则说明在何时和怎么重建某些文件,这些文件又可能是其他一些特定文件的目标. 规则由三部分组成: 一个或多个目标(target), 零个或多个先决条件(prerequisites), 零个或多个命令(command).
target ... : prerequisites  
         command
          ...
          ...
目标是make创建的域的通常叫法;例如可执行文件或目标文件. 目标也能是要执行的动作的名字, 例如, clean (见
伪目标
). 一旦所有先决条件变化将引起目标被创建. 如果目标存在且比他的先决条件新,则认为目标是"最新"的.
先决条件是个或多个文件,作为创建目标的输入. 先决条件的目的是定义某些目标对某些源文件的依赖属性.
命令是在有先决条件的规则之中. 他是当所有先决条件改动时make创建或更新目标采取的动作. 一条规则可包含多个命令. 每个在规则中执行的命令由shell解释执行. 缺省情况下, make用/bin/sh shell. 宏SHELL = bin/sh将覆盖缺省shell.
make的执行
make遵循"依赖规则"概念; make 读取当前目录下的makefile,从处理第一个目标开始. make查找每个目标的依赖(先决条件)以知道他们是否也作为目标列了出来 .
make沿依赖链遍历整个递归链直到发现一个没有先决条件的目标,或其先决条件没有规则. 一旦到达依赖链的末端, make便返回递归,在返回的过程执行每条目标规则中的命令. 对于遇见的所有有规则的先决条件, make采用同样的模式处理 .
一旦所有先决条件规则运行完了, make最后返回第一个目标 . 如果目标不存在, 或目标比他目前的先决条件生成的早, make运行命令来生成目标, 如以下是个makefile的例子 (例 1.0).
# Example 1.0
# Linking object files
prog1 : main.o file1.o \
       file2.o display.o
          cc -o prog1 main.o file1.o \
                  file2.o display.o
# Compiling source files
main.o : main.c mydefs.h
cc -c main.c
file1.o : file1.c mydefs.h
cc -c file1.c
file2.o : file2.c command.h
cc -c file2.c
display.o : display.c command.h
cc -c display.c
# Compiling source files
..PHONY : clean
clean :
         rm prog1 *.o
# End of makefile  
注意: 参考
命令回显
.
在前面的例子中, 我们已给变量objs赋了值.
objs = main.o file1.o file2.o display.o
一旦变量定义好了, 他的值能用$(variable)或 ${variable}提取出来. 然而, 如果圆括号遗漏了, 那么只有变量名的第一个字符被用到. 因此:
?$(objs)得到变量objs的值.
?$objs 得到变量 o 的值(如果有变量o).
make能灵活的使用未定义的变量; 这种情况下值返回空串. 在设定一个变量前, make能用快捷符’?=’检查他是否已被设置. 下面的例子检查 foo是否已被设置:
foo ?= bar
如果没有, make 将分配给他一个值.
引用替换和计算变量名
更有两个引用变量的高级特性是引用替换和计算变量名.
?引用替换
引用替换用你指定的值替换变量的值. 他的格式象这样:’$(var:x=y)’, 意思是取得变量 var的值, 用y替换变量值中每个单词结尾处的x, 并取代结果字串. 下面的例子设定bar为a.c b.c c.c:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
?计算变量名
在变量名内部能引用另一个变量; 这称为计算变量名.
例:
a = b
b = c
x  :=   $($(a))
本例赋x值为’c’. $(a)展开为 ’b’, 所以$($(a))即$(b); 而 $(b)展开为’c’.
递归扩展和简单扩展变量
变量有两种方法获得值, 递归扩展变量和简单扩展变量.
递归扩展变量
简单扩展变量

行赋值用’=’ 或 用 "define" 指示
用行’:=’赋值
值的指定是逐字被装配的.
变量在定义时一次扫描获得其值
不论何时变量被替代都展开对其他变量的参考.
不包含对其他变量的参考; 包含他们被定义的值.
例:
       foo = $(bar)
       bar = $(yep)
       yep = hello
命令:
       all :;echo $(foo)
将显示’hello’.   $(foo)将展开为$(bar), $(bar)展开为$(yep)最终展开为’hello’.
例:
       a :=   foo          
       b :=   $(a) bar
       a :=   hello
等价于:
       b :=   foo bar         
       a :=   hello
执行是有目的的,却导致make运行速度非常慢, 因为每当变量扩展时在此定义中的引用都要执行一遍.
更容易预测复杂的makefile的编写.
给变量添加更多文本
我们常需要给一个已存在的变量添加更多的文本. 快捷操作符 ’+=’ 提供了这种灵活性. 在下面这个例子中, 先取得objs的值然后给这个值加上文本file3.o :
objs   +=   file3.o
这样我们就能够设定objs为main.o file1.o file2.o display.o file3.o:
objs =   main.o file1.o file2.o display.o
objs +=   file3.o
自动变量
基于规则的目标和先决条件,此类变量的值在每条已执行的规则中都各不相同. 在下一节
隐式规则
的例1.2中, ’$@’ 用于目标文件名, ’$+’ 用于源文件名.
通用的自动变量包括以下这些.
$@
规则目标的文件名
$%
目标成员名, 此时目标是个归档成员
$
第一个先决条件名
$?
所有比目标新的先决条件名
$^
全体用空格符分隔的先决条件名
$+
类似于’$^’, 不过重复的先决条件会以他们在 makefile中列出的次序多次列出。
特定目标和特定模式的变量值
?特定目标变量值
根据make所建目标的不同,这个功能能为相同的变量赋不同的值. 该值在目标的命令脚本的上下文中局部可用. 格式如下:
target ... : variable-assignment
下面的语句在prog1及他的先决条件的命令脚本中设置CFLAGS为-g :
prog1 : CFLAGS = -g
prog1 : main.o file1.o file2.o display.o
?特定模式变量值
此特征让你为所有匹配这种特别模式的目标定义一个变量. 模式表示为 ’%’. 接下来的例子中,对于所有匹配模式%.o的目标分配给CFLAGS值-o:
%.o : CFLAGS = -o
(更多信息请参考
附加参考
.)
隐式规则
隐式规则告诉make怎么采用惯例方法,这样就不必在每次用到时都要周详指定他们. 其中一条隐式规则是用cc -c命令更新文件’.o’,其源文件是相应的’.c’文件. 用隐式规则, 前一个例子中的makefile能写成下面的形式(例 1.2).

# Example 1.2
#1
# Defining the compiler
CC=gcc
#2
# Defining the object (objs)   variable
objs = main.o file1.o file2.o display.o
#3
# Linking object files
prog1 : $(objs)
       $(CC) -o $@ $+
       echo prog1 : make complete
#4
# Tell make how to build .o from .c files
%.o:%.c
      $(CC) -c $+
#5
# Compiling source files.
main.o : mydefs.h
file1.o : mydefs.h
file2.o : command.h
display.o : command.h
#6
# Removing the executable and object files
..PHONY : clean
clean :
      rm prog1 $(objs)
      echo clean : make complete
# End of makefile

注意:
1.编译器变量提供了对同一个makefile使用不同的编译器的灵活能力.
2.变量objs定义为全体目标文件.
3.’$@’自动变量意思是目标, ’$+’ 意思是全体以空格分隔的先决条件.
4.模式规则告诉 make怎么转换*.c 文件为 *.o 文件.
5.make有一个内建模式将*.h文件转换为依赖*.o文件.
6.make删除现有目录下的prog1和全部对象文件 (见
伪目标
).
以隐含规则建立的命令用到某些预定义的变量, 这些变量分成两类: 一类是程式名 (象 CC) 另一类是对应这些程式的特定变量 (如 CFLAGS).
如下是一些内建规则中用作程式名的变量.
AR
存档文件维护程式, 缺省是 ar
AS
做汇编的程式, 缺省是 as
CC
编译C程式的程式, 缺省是 cc
CXX
编译C++程式的程式 , 缺省是 g++
RM
删除文件命令, 缺省是 rm -f
下列一些变量他们的值是程式附加的参数.
ARFLAGS
给归档维护程式的标志; 缺省是 rv
ASFLAGS
给汇编器的额外标志
CFLAGS
给C编译器的额外标志
CXXFLAGS
给C++编译器的额外标志
指示
"Define" 指示

define指示给变量赋值. define指示和跟着的变量名在同一行. 变量值在下一行. 最后一行的endef表示define结束. define作用类似于’=’, 举例如下:
define two-lines
echo foo
echo $(bar)
endef
普通变量赋值和define指示的差别在于普通赋值不能含换行符, 而在define的值里分割行的换行符成为变量值的一部分.
以上例子功能等同于:
two-lines = echo foo; echo $(bar)
以分号分开的两条命令作用非常象两条分别的shell命令. 然而, 注意到分在两行make将调用两次shell, 对每一行运行一次独立的子shell.
"Include" 指示
指示include告诉make暂停读取当前makefile转而读取每一个列出的文件. 读完以后, make 在指示中出现的地方重新读取makefile. 格式如下:
include filenames...
filenames能含shell文件名模式.
举个例子, 如果你有三个 ’.mk’ 文件, ’x.mk’, ’y.mk’, 及 ’z.mk’, 并且$(bar)是展开为 bish bash, 那么下列表达式:
include foo *.mk $(bar)
等价于:
include foo x.mk y.mk z.mk bish bash
include指示的一个用法是分配一个公共变量定义集给被各自"makefile"文件处理的程式 .
"Override" 指示
override 指示能设置makefile中已用命令参数设置过的变量. 格式如下:
override variable = value
给在命令行中定义的变量添加文本, 用:
override variable += more text
此指示被发明来做更改或增加用户在命令行中指定的值. 举例来说, 假定你总是希望C编译器用-g开关, 不过你又不想让用户象通常相同用命令参数指定其他开关. 你能用override指示:
override CFLAGS += -g
命令回显
make在一行被执行前先显示他, 叫做回显. 以’@’起始的命令则不回显 . echo也能用来指示makefile的进度. 如下所示:
echo prog1 : make complete
加上-n标志, make只回显命令但不真正执行他们. 只有这种情况, 即使命令以 ’@’ 开头亦会显示. 为防止一切回显, 能用-s标志. 输出就如同每条命令都以’@’开头.
伪目标
伪目标不是个文件名而是由一个显式请求引起的动作. 在伪目标中的命令不创建所有目标, 但每次目标发生重建时命令都要执行. 举例如下:
clean :
         rm prog1 *.o
当命令象下面这样显式的调用时,将删除 prog1及所有目标文件:
make clean
因为rm不是创建一个名为 clean的文件, 可能这个文件根本不曾存在. 但如果某人确实在这个目录下建了名为clean的文件, 伪目标将停止工作. 文件clean在没有先决条件时将不可避免的被认为是最近更新的, 他的命令也不会执行.
为避免这个问题, 目标被定义为 .PHONY. 在下面的例子中, make clean 将运行命令而不论是否真有名clean 的文件:
.PHONY   :   clean
clean   :
          rm   prog1   *.o
在文件名中用通配符
单个文件名用通配符可指代多个文件. make在目标先决条件, 命令和变量中用到通配符 ’*’, ’?’, 及’[...]’. 通配符能用在规则命令中, 这些命令被shell展开. 例如, 这是删除所有目标文件的规则:
clean:
       rm *.o
当你定义变量时通配符是不会展开的. 即, 如果你这样写:
objects = *.o
那么变量对象的值是真实的字符串 ’*.o’.
命令中的错误
命令执行完以后, make 检查退出状态以验证其已成功完成, 同时发送下一条命令到新shell. 如果返回错误, make 放弃当前规则,非常可能放弃所有规则. 要忽略命令行中的错误, 在行开头加上’-’号 (在初始的tab后). ’-’号在命令传递给shell执行前丢弃. 下面的例子即使rm不能删除文件他也继续运行, :
clean:
       -rm   -f   *.o
类似的特性也能通过在make后加-i参数实现; 全体规则中的全部命令的错误都被忽略.
并行执行
缺省情况下, make一次只运行一条命令, 在执行下一条命令前等待上一条命令执行结束. make用’-j’选项能同时执行多条命令. ’-j’选项后缀的整数指定一次能运行作业的数量.
用make更新归档文件
被叫做成员的归档文件通常用作链接的子程式库. 他们由程式ar维护. 格式如下:
archive(member)
make中独立的文件成员能作为目标或先决条件. 在下面的例子中, 是要通过复制文件foo.o在归档sublib中创建成员foo.o :
sublib(foo.o)   :   foo.o
          ar   cr   sublib foo.o


原创粉丝点击