一、make实用程序
1、make命令一个强大的地方就是他具有理解一个工程依赖关系的能力。对于依赖关系的理解允许make命令只重新构建整个工程中由于源文件的修改而需要更新的部分。make 实用程序使用开发者创建的输入文件来描述要构建工程。GNU make使用Makefile 作为他的输入文件默认文件名。所以,当输入make命令时,他会在当前目录下查找名为 Makefile的文件,根据Makefile文件的安排构建工程。
Makefile关系到了整个工程的编译规则。一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为Makefile就像一个shell脚本一样,其中也可以执行操作系统的命令。
Makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释Makefile中命令的工具。
所有的Makefile文件结构都遵循下面的格式:
最终目标:依赖(目标1目标2 ……) #规则0
命令
目标1:依赖(目标11目标12 ……) #规则1
命令1
目标2:依赖(目标21目标22 ……) #规则2
命令2 …… 目
注意:命令之前必须应有一个Tab。
2、Makefile规则
(1)显式规则
(2)隐含规则
(3)后缀规则
(4)模式规则
在模式规则中,目标名中需要包含有一个模式字符“%”,包含有模式字符的目标被用来匹配一个文件名。一个模式规则的格式为:
%.o:%.c:指定了如何由文件“N.c”来创建文件“N.o”,文件“N.c”必须是已经存在或者可被创建的;
(5)清空目标文件的规则
每个makefile文件都应有一个“清空目标文件”的规则:
.PHONY表示clean是一个伪目标
减号“-”的作用是一旦出现问题,可以继续执行后面的操作
clean不能放在文件头,习惯上放在文件尾
3、Makefile文件的几种目标
(1)指定目标——根据依赖生成指定目标文件
(2)伪目标
它不代表一个真正的文件名,在执行make时可以指定这个目标来执行其所在规则定义的命令,有时我们也可以将一个伪目标称为标签。特点:没有规则。“伪目标”的取名不能和文件名重名。
(3)多目标
Makefile的规则中的目标可以不止一个,其支持多目标,有可能我们的多个目标同时依赖于一个文件,并且其生成的命令大体类似。于是我们就能把其合并起来。
(4)标准目标
Makefile标准目标是一些约定俗成的目标,它们代表一个确定的含义,包含:
all:编译整个软件包,但不重建任何文档。一般此目标作为默认的终极目标。此目标一般对所有源程序的编译和连接使用"-g"选项,以使最终的可执行程序中包含调试信息。
clean:删除所有被make创建的文件;
install: 完成程序的编译并将最终的可执行程序、库文件等拷贝到指定的目录。此种安装一般不对可执行程序进行 strip 操作。
print:列出改变过的源文件;
tar:打包备份源程序;
dist:创建一个压缩文件;
TAGS:更新所有的目标;
(5)5特殊目标
GNU make所支持的特殊目标有:
PHONY:它的所有依赖被视为伪目标。伪目标所在规则定义的命令会被无条件执行。
PRECIOUS:它的所有依赖文件在make过程中会被特殊处理。
DELETE_ON_ERROR:规则的命令执行错误,它将删除已经被修改的目标文件。
SILENT:指定命令行没有意义,这是旧版中的用法。当前用法是使用make命令行参数“-s”或者“--silent” ……
4、Makefile中可以使用变量
变量类似于C语言的宏,但值可修改
变量名大小写敏感
变量名不应该包含:#=或空格
变量使用时用$(var)形式
(1)递归展开变量:
使用“=”表示,可先使用,后定义。
(2)直接展开变量:
使用“:=”表示,须先定义再使用。
(3)变量值的替换:
可以替换变量的共有部分,格式为“$(var:a=b)”,可以把变量var中所有以a 字串结尾的a替换为b字串
(4)变量取值 变量的定义值在长度上没有限制;
当引用一个没有定义的变量时,make默认它的值为空;
一些特殊的变量在make中内嵌有固定的值,不过这些变量允许在Makefile中显式的重新赋值。
自动化变量不能在Makefile中显式修改;
如果希望实现这样一个操作,仅对一个之前没有定义过的变量赋值,可以使用“?=”代替“=”或者“:=”来实现。
可以使用+=给变量追加值
(5)“?=”操作符的使用——条件赋值
只有定义变量在当前操作之前没有赋值的情况下才会对这个变量进行赋值。
(6)自动化变量
$ 依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$< 目标文件所对应依赖文件的第一个依赖文件的名称。如果依赖目标是以模式(即"%")定义的,那么"$将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$* 不包含扩展名的目标文件名称。(如果目标为a.b.c,则$*表示a.b)
$+ 所有的依赖文件,以空格分开,可包含重复的依赖文件。
$^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。
$? 所有的依赖文件,以空格分开。
$@ 当前规则的目标文件的完整名称。
$% 如果目标是一个静态库(归档文件)时,则该变量表示静态库的成员名称。
5、预定义变量
AR 静态库维护(打包)程序的名称,默认值为 ar。
ARFLAGS 静态库维护程序的选项。
AS 汇编程序的名称,默认值为 as。
ASFLAGS 汇编程序的选项。
CC C 编译器的名称,默认值为 cc。
CFLAGS C 编译器的选项(编译参数)。
CPPFLAGS C 预编译的选项。
CPP C 预编译器的名称,默认值为 $(CC) -E。
CXX C++ 编译器的选项,默认值为 g++。
CXXFLAGS C++ 编译器的选项。
EXEC 表示编译后生成的执行文件名称
OBJS 目标文件列表
LDFLAGS 连接参数
RM 删除文件的命令;缺省为:rm -f。
VPATH 路径变量。定义搜索文件的目录,用“:”分开。
CURDIR 执行make命令时的目录(当前目录)
6、Makefile的命令行选项
直接在 make 命令的后面键入目标名可建立指定的目标,如果直接运行 make,则建立第一个目标。还可以用 make -f mymakefile 这样的命令指定 make 使用特定的 Makefile,而不是默认的 GNUmakefile、makefile 或 Makefile。
GNU make 命令还有一些其他选项,下面是 GNU make 命令的常用命令行选项命令行选项含义:
-C dir 在指定目录 dir在读取 Makefile文件并执行。
-f file 以指定的 file 文件作为 Makefile。
-h 显示所有的 make 选项。
-i 忽略所有的命令执行错误。
-I dir 当包含其他 Makefile 文件时,可利用该选项指定搜索目录。
-n 只打印要执行的命令,但不执行这些命令。
-p 显示 make 变量数据库和隐含规则。
-s 在执行命令时不显示命令。
-w 在处理 Makefile 之前和之后,显示工作目录。
-W file 假定文件 file 已经被修改。
7、make执行过程
执行make命令,make读取当前目录下的Makefile文件,并将Makefile文件中的第一个目标作为其执行的“默认目标”,开始处理默认目标所在的规则。第一个规则就是目标“all”所在的规则,而all又依赖于dm6446,dm6446依赖于dm6446_al,dm6446_al依赖于$(TARGET),$(TARGET)依赖于$(OBJFILES) $(XDC_LFILE),$(OBJFILES)即所有的.o文件,对这些.o文件为目标的规则处理有以下三中情况。
1) 目标.o文件不存在,使用其描述规则创建它。
2) 目标.o文件存在,目标.o文件所依赖的.c源文件、.h文件中的任何一个比目标.o文件“更新”(在上次make之后被修改)。则根据规则重新编译生成它。
3) 目标.o文件存在,目标.o文件比它的任何一个依赖文件(.c源文件、.h文件中)“更新”,这表明它的依赖文件在上一次make之后没有被修改,则什么也不做。
这些.o文件所在的规则之所以被执行,是因为这些.o文件出现在“默认目标”的依赖列表中。一个规则的目标如果不是“默认目标”所依赖的,或者“默认目标”的依赖文件所依赖的,那么这个规则将不会被执行,除非通过make的命令行明确指定此目标,例如“make clean”。
在完成了对.o文件的创建或更新之后,make将处理默认目标“encode”所在的规则,分为以下3种情况。
1) 目标文件“encode”不存在,则执行规则一创建目标“encode”
2) 目标文件“encode”存在,其依赖文件中有一个或者多个文件比它更新,则根据规则重新链接生成“encode”
3) 目标文件“encode”存在,并且比它的任何一个依赖文件都更新,则什么也不做。