Makfile——基础知识

Posted rainingday

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Makfile——基础知识相关的知识,希望对你有一定的参考价值。

学习Makfile需要掌握的基础知识

一、基础规则

目标(target)…:依赖(prerequiries)…
<tab>命令(command)     #以TAB开头

make命令的使用:
执行 make 命令时,它会去当前目录下查找名为“Makefile”的文件,并根据它的指示去执行操作,生成第一个目标。
我们可以使用“-f”选项指定文件,不再使用名为“Makefile”的文件,比如:make -f Makefile.build。
我们可以使用“-C”选项指定目录,切换到其他目录里去,比如:make -C a/ -f Makefile.build
我们可以指定目标,不再默认生成第一个目标。make -C a/ -f Makefile.build other_target

二、Makefile 变量
1、定义变量

Makfile的定义变量要用到赋值符,“=”、“:=”、“?=”。还有追加“+=”

make 中对变量的赋值有两种方式:延时变量、立即变量。
A = xxx // 延时变量  变量的真实值取决于它所引用的变量的最后一次有效值。
B ?= xxx // 延时变量,如果这是第一次定义,则赋值成功;如果曾定义过,此赋值无效
C := xxx // 立即变量  变量的真实值取决于:=赋予的值。
D += yyy // 如果 D 在前面是延时变量,那么现在它还是延时变量;如果 D 在前面是立即变量,那么现在它还是立即变量

2、变量的导出(export):
在编译程序时,我们会不断地使用“make -C dir”切换到其他目录,执行其他目录里的 Makefile。如果想让某个变量的值在所有目录中都可见,要把它 export 出来
比如“CC = $(CROSS_COMPILE)gcc”,这个 CC 变量表示编译器,在整个过程中都是一样的。定义它之后,要使用“export CC”把它导出来。

 

三、Makfile的模式规则
  
使用模式规则,至少要包含“%”,否则就是一般规则。目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件。
  当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方法如下

%.o : %.c
    命令

四、Makefile的自动化变量
作用:通过一行命令来从不同的依赖文件中生成对应的目标。
自动化变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完。
自动化变量只应该出现在规则的命令中。

自动化变量  描述
$@

规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模
式中定义的目标集合。

$%

当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,
那么其值为空

$<

依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么
“$<”就是符合模式的一系列的文件集合。

$? 所有比目标新的依赖目标集合,以空格分开。
$^

所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,
“$^”会去除重复的依赖文件,只保留一份。

$+ 和“$^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。
$*

这个变量表示目标模式中"%"及其之前的部分,如果目标是 test/a.test.c,目标模
式为 a.%.c,那么“$*”就是 test/a.test。

五、Makfile中使用shell命令:
比如:TOPDIR := $(shell pwd)。这是个立即变量,TOPDIR 等于 shell 命令 pwd 的结果。

六、在 Makefile 中怎么放置第 1 个目标
执行 make 命令时如果不指定目标,那么它默认是去生成第 1 个目标。所以“第 1 个目标”,位置很重要。有时候不太方便把第 1 个目标完整地放在文件前面,这时可以在文件的前面直接放置目标,在后面再完善它的依赖与命令。比如:

 

1 First_target: // 这句话放在前面
2 .... // 其他代码,比如 include 其他文件得到后面的 xxx 变量
3 First_target : $(xxx) $(yyy) // 在文件的后面再来完善
4 command

 

七、假想目标(伪目标)

 

一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。
使用伪目标的主要是为了避免 Makefile 中定义的执行命令的目标工作目录下的实际文件出现名字冲突。

clean:
rm -f $(shell find -name "*.o")
rm -f $(TARGET)

如果当前目录下恰好有名为“clean”的文件,规则因为没有依赖,所以目标被认为是最新的,那么执行“make clean”时它就不会执行那些删除命令。为了避免这个问题,我们可以将 clean 声明为伪目标,声明方式如下:

.PHONY : clean

八、Makfile的条件判断

两对关键字:ifeq、ifneq、ifdef 和 ifndef

ifeq用法:

ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’,‘ <参数 2>’
ifeq “<参数 1>”, “<参数 2>”
ifeq “<参数 1>”, ‘<参数 2>’
ifeq ‘<参数 1>’, “<参数 2>”

上述用法中都是用来比较“参数 1”和“参数 2”是否相同,相等则为真。ifneq用法类似,不过,不相等为真。

ifdef用法:

ifdef <变量名>
如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。

九、Makefile常用函数

①函数$(foreach var,list,text)——for each var in list, change it to text。对 list 中的每一个元素,取出来赋给 var,然后把 var 改为 text 所描述的形式。

exp:
objs := a.o b.o
dep_files := $(foreach f, $(objs), .$(f).d) // 最终 dep_files := .a.o.d .b.o.d

②$(wildcard pattern)——pattern 所列出的文件是否存在,把存在的文件都列出来。

exp:
src_files := $( wildcard *.c) // 最终 src_files 中列出了当前目录下的所有.c 文件

 

以上是关于Makfile——基础知识的主要内容,如果未能解决你的问题,请参考以下文章

Makfile学习1-规则与示例

Makfile学习1-规则与示例

makfile

Makfile 和 SDL 遇到问题

Gdb调试工具/ Makfile项目管理

Android中makfile的随记