Makefile 介绍
阅读数:171 评论数:0
跳转到新版页面分类
Linux
正文
一、概述
在Linux中使用make命令来编译程序,特别是大程序,而make命令所执行的动作依赖于Makefile文件。make命令根据文件更新的时间戳来决定哪些文件需要重新编译,这可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。
要想完整的了解Makefile的规则,请参考:GNU make手册
二、Makefile文件规则
一个简单的Makefile文件包含一系列的“规则”,基样式如下:
target...:prerequisites...
recipe
...
//即
目标: 依赖目标序列;生成命令
//或
目标: 依赖目标序列
tab字符 生成命令
...
tab字符 生成命令
一个target通常是指程序生成的文件的名字;targets可以是执行文件的名字或者object文件的名辽。target还可以是动作的名字,例如“clean”。
prerequisites是指用来生成target的一些文件,一个target通常依赖一些文件 。
recipe是指一个操作,该操作由make来执行。一个recipe可能含有多个命令,这些命令都在同一行,也可以各自独立一行。请注意:recipe的每一行都要有tab键!这是为了防止有人粗心大意。
通常,如果一个依赖发生了变化,就需要规则调用命令以更新或创建目标。但是并不是所有的目标都依赖,例如,目标“clean”的作用是清除文件,它没有依赖。
例子:
hello: hello.c
gcc -o hello hello.c
clean:
rm -f hello
对于上面的Makefile,执行make命令时,仅当hello.c文件比hello文件新,才会执行命令gcc -o hello hello.c生成可执行文件hello,如果还没有hello文件,这个命令也会执行。
运行make clean时,由于目标clean没有依赖,它的命令rm -rf hello将被强制执行。
三、Makefile文件里的赋值方法
变量的定义语法形式如下:
// 直接赋值,make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。
变量 = deferred
// 条件赋值,如果没有被赋值过就赋予等号后面的值
变量 ?= deferred
// 覆盖赋值,
变量 := immediate
// 追加赋值,添加等号后面值
变量 += deferred or immediate
define immediate
makefile文件中的变量无需声明类型,可以直接进行初始化。
宏变量 | 其命名方式一般是由大定字母组成的字符串。 |
环境变量 | 一部分是make命令内置的环境变量,另一部分是接收从make命令传递过来的参数而定义的变量。 |
自定义变量 | 其命令方式一般是由小写字母组成的字符串。 |
目标变量 | 其表示一类具有特定变量名以及特殊含义的变量。 |
自动化变量 | 自动化变量用于模式规则中,其中$@表示规则中的目标,$<表示规则中的第一个依赖目标名,$^表示规则中的依赖目标序列。 |
如果变量被export修饰,则它的取值会传递给子层makefile。如果unexport修饰则变量不会传递给子层makefile使用。如果变量被define修饰,则定义该变量以供后续使用。
四、Makefile常用内置函数
内置函数的调用是以$为开头进行标识, 函数调用的格式如下:
$(function arguments)
如果有多个参数,它们之间用逗号隔开。内核的Makefile中用到了大量的函数,现在介绍一些常用的。
在文本“text”中使用"to"替换每一处“from”。
比如
$(subst ee,EE,fee on the street)
结果为fEE on the stEEt.
2、$(patsubst pattern,replacement,text)
寻找text中符合格式pattern的字,用replacement替换它们。pattern和replacement中可以使用通配符。
比如:
$(patsubst %.c,%.o,x.c.c bar.c)
结果为:x.c.o bar.o
去掉前导和结尾空格,并将中间的多个空格压缩为单个空格
比如
$(strip a b c)
结果为: "a b c"
在字符串in中搜寻find,如果找到,则返回值是find,否则返回值为空。
$(findstring a,a b c)
$(findstring a,b c)
将分别产生值“a”和“ ”
返回text中由空格隔开且匹配格式"pattern..."的字,去除不符合格式“pattern...”的字。
比如
$(filter %.c %.s,foo.c bar.c baz.s ugh.h)
结果为“foo.c bar.c baz.s”。
6、$(filter-out pattern...,text)
返回在text中由空格隔开且不匹配pattern...的字,去除符合格式pattern...的字。它是filter的反函数。
$(filter-out %.c %.s,foo.c bar.c baz.s ugh.h)
结果为“ugh.h”
将list中的字按字母的顺序排序,并去掉重复的字。输出由单个空格隔开的字的列表。
比如:
$(sort foo bar lose)
结果为“bar foo lose”
-----------以上是字符串的操作
抽取name...中每一个文件名的路径部分,文件名的路径部分包括从文件名的首字符到最后一斜杠(含斜杠)之前的一切字符。
比如
$(dir src/foo.c hacks)
结果: “src/ ./”
抽取names...中每一个文件名中除路径部分外一切字符(真正的文件名)
例如
$(notdir src/foo.c hacks)
结果"foo.c hacks"
抽取names...中每一个文件名的后缀
例如
$(suffix src/foo.c src-1.0/bar.c hacks)
结果为“.c .c”
抽取names...中每一个文件名除后缀外一切字符。
例如
$(basename src/foo.c src-1.0/bar.c hacks)
结果为“src/foo src-1.0/bar hacks”。
12、$(addsuffix suffix,names...)
参数names...是一系列的文件名,文件名之间用空格隔开;suffix是一个后缀名。将suffix的值附加在每一个独立文件名的后面,完成后将文件名串联起来,它们之间用单个空格隔开。
$(addsuffix .c,foo bar)
结果为“foo.c bar.c”
13、$(addprefix prefix,names...)
prefix是一个前缀名,将prefix的值附加到每一个独立文件名的前面,完成后将文件名串联起来,它们之间用单个空格隔开。
$(addprefx src/, foo bar)
结果:“src/foo src/bar”。
参数pattern是一个文件名格式,包含有通配符(通配符和shell中的用法一样)。函数wildcard的结果是一行和格式匹配且真实存在文件的名称,文件之间用一个字格隔开。
例如
#比如当前目录下有文件 1.c 2.c 1.h 2.h,则
c_src :=$(wildcard *.c)
结果为“1.c 2.c”
-------------以上是文件的操作
对list中的变量循环处理,每个变量赋值到var上,对每个var执行text操作后,得到新的list
例如
dirs :=a b c d
files :=$(foreach dir,$(dirs),$(wildcard $(dir)/*))
结果为dirs中所有目录下的所有文件的列表。
16、$(if condition,then-part[,else-part])
如果condition为值,则执行then-part,否则执行else-part,else-part不存在时,返回空。
变量variable是一个查询变量的名称,不是对该变量的引用,所以,不能采用$和圆括号的格式书该变量,当然,如果坱要使用非常量的文件名,可以在文件名中使用变量引用。
结果是一个字符串,结果如下
undefined | 变量从来没有定义 |
default | 是默认定义 |
environment | 环境变量,选项-e没有打开 |
environment override | 环境变量,选项-e已打开 |
file | 在Makefile中定义 |
command line | 在命令行中定义 |
override | 在Makefile中用override指令定义 |
automatic | 自动变量 |
函数shell是make与外部环境的通信工具。函数shell的执行结果和在控制台上执行command arguments的结果相似。不过如果command arguments的结果含有换行符(和回车符),则在函数shell的返回结果中将它们处理为单个空格,若返回结果最后是换行符(和回车符)则被去掉。
比如当前目录下有文件1.c 2.c 1.h 2.h,则
c_src :=$(shell ls *.c)
结果为: 1.c 2.c
五、分支判断语句
makefile文件中的分支判断语句有四种:ifeq, ifneq, ifdef和ifndef。每个分支判断语句都与一个结束符 endif相匹配。
ifeq\ifneq (变量1,变量2)
分支判断语句可以嵌套使用,并且其中可以使用else。