一、make
make管理器
GNU Make是在linux环境下用来构建和管理工程的命令工具,是存放在/usr/bin目录下的一个可执行文件。
Make是通过比较对应文件(规则的目标和依赖)的最后修改时间,来决定哪些文件需要更新,哪些文件不需要更新。对需要更新的文件,make就执行Makefile中记录的相应命令,告诉make工具需要怎么样去编译和链接程序。
make 的下载:
#sudo apt-get install make
二、Makefile
1、Makefile文件
Makefile,是make工作时的配置文件,是make正常工作的基础。Make是根据Makefile文件描述的编译规则及编译选项等来进行对工程编译和管理工程。
Makefile带来的好处是,可以自动化编译,减少手动编译效率低的问题。
2、Makefile执行
不带目标执行
默认解析当前目录下的Makefile文件,并执行第一个文件,执行完第一个Makefile文件后退出文件,并且不会再去执行下一个Makefile文件。
带目标执行
#make all
默认解析当前目录下的Makefile文件,并且从目标all开始执行,在执行第一个目标后退出
执行指定Makefile文件
#make -f mkfile
#make --file mkfile
#make --makefile mkfile
执行指定路径的Makefile
#make -C dir
3、简单用例
以上面的例子说明make工作过程:
当在 shell 提示符下输入“make”命令以后。make 读取当前目录下的 Makefile 文件,并将 Makefile 文件中的第一个目标作为其执行的“终极目标”,开始处理第一个规则(终极目标所在的规则)。在例子中,第一个规则就是目标“edit”所在的规则。规则描述了“edit”的依赖关系,并定义了链接.o 文件生成目标“edit”的命令; make 在执行这个规则所定义的命令之前,首先处理目标“edit”的所有的依赖文件(例子中的那些.o 文件)的更新规则(以这些.o 文件为目标的规则。对这些.o 文件为目标的规则处理有下列三种情况:
- 目标.o 文件不存在,使用其描述规则创建它;
- 目标.o 文件存在,目标.o 文件所依赖的.c 源文件、.h 文件中的任何一个比目标.o文件“更新”(在上一次 make 之后被修改)。则根据规则重新编译生成它;
- 目标.o 文件存在,目标.o 文件比它的任何一个依赖文件(的.c 源文件、.h 文件)
完成了对.o 文件的创建(第一次编译)或者更新之后,make 程序将处理终极目标 “edit”所在的规则,分为以下三种情况:
- 目标文件“edit”不存在,则执行规则以创建目标“edit”。
- 目标文件“edit”存在,其依赖文件中有一个或者多个文件比它“更新”,则根 据规则重新链接生成“edit”。
- 目标文件“edit”存在,它比它的任何一个依赖文件都“更新”,则什么也不做。
上例中,如果更改了源文件“insert.c”后执行 make,“insert.o”将被更新,之后 终极目标“edit”将会被重生成;如果我们修改了头文件“command.h”之后运行“make”,那么“kbd.o”、“command.o”和“files.o”将会被重新编译,之后同样终极目标“edit”也将被重新生成
4、Makefile的常用语法
(1)变量使用
一般格式:
变量名经 = 变量值
= : 表示将右边变量赋值给左边
:= :表示在make时将右边的变量值的变量展开并赋予左边变量
+= :表示将内容追加到变量值后面
变量通过美元符号与圆括号实现调用:
$(变量)
(2)常用自动变量
变量 | 说明 |
---|---|
$@ | 表示规则的目标文件名。如果目标是一个文档文件(Linux中,一般称.a文件为文档文件,也称为静态库文件),那么它代表这个文档的文件名。在多目标模式规则中,它代表的是哪个触发规则被执行的目标文件名。 |
$% | 当规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则 的目标是“foo.a(bar.o)”,那么,“ %”的值就为“bar.o”,“ @”的值为“foo.a”。如果目标不是静态库文件,其值为空。 |
$< | 规则的第一个依赖文件名。如果是一个目标文件使用隐含规则来重建,则它代表由隐含规则加入的第一个依赖文件。 |
$? | 所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代表的是库成员(.o文件)。 |
$^ | 规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有库成员(.o文件)名。一个文件可重复的出现在目标的依赖中,变量 “ ” 只 记 录 它 的 一 次 引 用 情 况 。 就 是 说 变 量 “ ^”只记录它的一次引用情况。就是说变量“ ”只记录它的一次引用情况。就是说变量“^”会去掉重复的依赖文件。 |
$+ | 类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。 |
$* | 在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的 部分(当文件名中存在目录时,“茎”也包含目录(斜杠之前)部分。例如:文件“dir/a.foo.b”,当目标的模式为“a.%.b”时,“$*”的值为“dir/a.foo”。“茎”对于构造相关文件名非常有用。 |
(3)常用函数
1)函数名称:模式替换函数—patsubst。
$(patsubst PATTERN,REPLACEMENT,TEXT)
函数功能:搜索“TEXT”中以空格分开的单词,将否符合模式“TATTERN”替换 为“REPLACEMENT”。
示例:
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”中以.c 结尾的单词替换成以.o 结尾的字符。函数的返回结果 是“x.c.o bar.o”。
2)函数名称:取字串函数—wordlist。
$(wordlist S,E,TEXT)
函数功能:从字串“TEXT”中取出从“S”开始到“E”的单词串。“S”和“E”
表示单词在字串中位置的数字。
返回值:字串“TEXT”中从第“S”到“E”(包括“E”)的单词字串。
3)函数名称:取首单词函数—firstword
$(firstword NAMES…)
函数功能:取字串“NAMES…”中的第一个单词。
返回值:字串“NAMES…”的第一个单词。
4)函数名称:单词连接函数——join。
$(join LIST1,LIST2)
函数功能:将字串“LIST1”和字串“LIST2”各单词进行对应连接。就是将“LIST2”
中的第一个单词追加“LIST1”第一个单词字后合并为一个单词;将
“LIST2”中的第二个单词追加到“LIST1”的第一个单词之后并合并为
一个单词,……依次列推。
返回值:单空格分割的合并后的字(文件名)序列。
示例 1:
$(join a b , .c .o)
返回值为:“a.c b.o”。
示例 2:
$(join a b c , .c .o)
返回值为:“a.c b.o c”。
5)函数名称:获取匹配模式文件名函数—wildcard
$(wildcard PATTERN)
函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。
返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。
$(wildcard *.c)
返回值为当前目录下所有.c 源文件列表。
6)foreach 函数
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
表达式第一次执行时将展开 为“ ( w i l d c a r d a / ∗ ) ” ; 第 二 次 执 行 时 将 展 开 为 “ (wildcard a/*)”;第二次执行时将展开为“ (wildcarda/∗)”;第二次执行时将展开为“(wildcard b/)”;第三次展开为“$(wildcard c/)”;….;
7)shell函数
make可以使用它来和外部 通信
contents := $(shell cat foo)
将变量“contents”赋值为文件“foo”的内容,文件中的换行符在变量中使用空格代
替