10分钟教你学会Makefile

https://wenku.baidu.com/view/205e5e12eff9aef8941e0678.html

https://cloud.tencent.com/developer/article/1406069

一般的格式是:
target:components
TAB rule

字符串替换函数——subst     $(subst <from>,<to>,<text>)    $(subst ee,EE,feet on the street)
$(subst <from>,<to>,<text>)    功能:把字串<text>;中的<from>;字符串替换成<to>;     

patsubst     $(patsubst  <pattern>,<replacement>,<text>)        $(patsubst %.c,%.o,x.c.c bar.c)
功能:查找<text>中以空白符(空格、Tab)分隔的单词是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符%,表示任意长度的字串。如果<replacement>中也包含%,那么,<replacement>中的这个%将是<pattern>中的那个%所代表的字串。可以用反斜杠\来转义,即\%来表示真实含义的%字符。返回函数返回被替换过后的字符串

$(strip <string>)    $(strip a b c )
功能:去掉string字符串中开头和结尾的空白字符(空格、Tab)。

$(findstring <FIND>,<IN>)  $(findstring a,a b c) 
功能:从字符串<IN>中查找指定的字符串<FIND>,找到返回<FIND>,找不到返回空。

$(filter <pattern...>,<text>)   sources := foo.c bar.c baz.s ugh.h   result := $(filter %.c %.s,${sources})
功能:以<pattern> 模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以有多个模式。

$(filter-out <pattern...>,<text>) objects=main1.o foo.o main2.o bar.o mains=main1.o main2.o  result := $(filter-out $(mains),$(objects)) 
功能:以<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式。

$(sort <list> )    $(sort foo bar lose)
功能:给字符串<list>中的单词排序(升序)。注意:sort函数会去掉<list>中相同的单词

$(word <n>,<text>)        $(word 2, foo bar baz)
功能:取字符串<text>中第<n>个单词。下标从1开始,如果比中的单词数要大,那么返回空字符串。

函数“ foreach”不同于其它函数。它是一个循环函数。类似于 Linux 的 shell 中的 for 语句 
$(foreach VAR,LIST,TEXT)   
这个函数的工作过程是这样的 
如果需要(存在变量或者函数的引用),首先展开变量“ VAR”和“ LIST”的引用;而表达式“ TEXT”中的变量引用不展开  
执行时把“ LIST”中用空格分割的单词依次取出赋给变量“ VAR”,然后执行“ TEXT”表达式。直到LIST的最后一个单词为空时结束
“ TEXT”中的变量或者函数引用在执行时才被展开,因此如果在“ TEXT”中存在对“ VAR”的引用,那么“ VAR”的值在每一次展开式将会到的不同的值  
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))  
此函数所实现的功能就和一下语句等价 
files := $(wildcard a/* b/* c/* d/*)

wildcard函数 
它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表 
notdir函数的作用是将参数中的路径去掉  
假设arch/arm/configs/路径下有三个文件,分别是a_defconfig、b_defconfig、c_defconfig
boards := $(wildcard arch/arm/configs/*_defconfig)  boards的值就是字符串“arch/arm/configs/a_defconfig  arch/arm/configs/b_defconfig  arch/arm/configs/c_defconfig”
boards := $(notdir $(boards)),那么boards的值就变成了“a_defconfig b_defconfig c_defconfig”

 

$(filter-out $(PHONY) $(wildcard $^),$^)
常用用法为$(wildcard *.c)
表示列举当前目录下的所有.c文件
这里$^因为会包含依赖的文件名,如果包含的该文件存在,那么将返回其含路径的文件名
所以$(wildcard $^)就是用来过滤$^包含的所有文件并且该文件确实在本地存在.

自动化变量$?代表依赖文件列表中被改变过的所有文件。
自动化变量$^代表所有通过目录搜索得到的依赖文件的完整路径名(目录 + 一般文件名)列表。
自动化变量$@代表规则的目标。
自动化变量$<代表规则中通过目录搜索得到的依赖文件列表的第一个依赖文件

自动化变量$(@D) 
The directory part of the file name of the target, with the trailing slash removed. If the value of ‘$@’ is dir/foo.o 
then ‘$(@D)’ is dir. This value is . if ‘$@’ does not contain a slash.
自动化变量$(@F)
The file-within-directory part of the file name of the target. If the value of ‘$@’ is dir/foo.o then ‘$(@F)’ is foo.o. 
‘$(@F)’ is equivalent to ‘$(notdir $@)’. 

 

有一个 make 的环境变量叫“MAKECMDGOALS”,这个变量中会存放你所指定的终极目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。这个变量可以让你使
用在一些比较特殊的情形下。比如下面的例子:

  1. sources = foo.c bar.c    
  2. ifneq ( $(MAKECMDGOALS),clean)    
  3. include $(sources:.c=.d)    
  4. endif    

基于上面的这个例子,只要我们输入的命令不是“make clean”,那么 makefile 会自动包含“foo.d”和“bar.d”这两个 makefile。  

 

静态模式规则是这样一个规则:
规则存在多个目标,并且不同的目标可以根据目标文件的名字来自动构造出依赖文件。静态模式规则比多目标规则更通用,
它不需要多个目标具有相同的依赖。但是静态模式规则中的依赖文件必须是相类似的而不是完全相同的。
的基本语法:
TARGETS ...: TARGET-PATTERN: PREREQ-PATTERNS ...
COMMANDS
...

“TAGET-PATTERN”和“PREREQ-PATTERNS”说明了如何为每一个目标文件生成依赖文件。从目标模式(TAGET-PATTERN)的目标名字中抽取一部分字符串(称为“茎”。使用“茎”替代依赖模式(PREREQ-PATTERNS)中的相应部分来产生对应目标的依赖文件。
首先 在目标模式和依赖模式中 ,一般需要包含模式字符“% ”。

在使用静态模式规则时,指定的目标必须和目标模式相匹配,否则执行make时将会得到一个错误提示。
如果存在一个文件列表,其中一部分符合某一种模式而另外一部分符合另外一种模式,这种情况下我们可以使用“filter”函数来对这个文件列表进行分类,在分类之后对确定的某一类使用模式规则。
例如:
files = foo.elc bar.o lose.o
$(filter %.o,$(files)): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
$(filter %.elc,$(files)): %.elc: %.el
emacs -f batch-byte-compile $<
其中;$(filter %.o,$(files))的结果为“bar.o lose.o”“filter”函数过滤不符合“%.o”。

 

找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。

Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。

    VPATH = src:../headers

上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(当然,当前目录永远是最高优先搜索的地方)

另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的), 这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很类似,但是它更为灵活。它可以指定不同的文件在不同的搜索目录中。这是一个很 灵活的功能。它的使用方法有三种:

 1、vpath <pattern> <directories>
    为符合模式<pattern>的文件指定搜索目录<directories>。

    2、vpath <pattern>
    清除符合模式<pattern>的文件的搜索目录。

    3、vpath
    清除所有已被设置好了的文件搜索目录。

vapth使用方法中的<pattern>需要包含“%”字符。“%”的意思是匹 配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。<pattern>指定了要搜索的文件集, 而<directories>则指定了<pattern>的文件集的搜索的目录。例如:
    vpath %.h ../headers
该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话)

 -I,添加包含路径
-I 在编译时用,告诉编译器去哪个路径下找文件
如:-I /home/hello/include

-l,添加引用链接库
-l 在链接时用到,它的作用是告诉链接器,要用到哪个库。
如:-l pthread

-L,添加链接库路径
-L 后跟路径,告诉链接器从哪找库(.so文件),只有在链接时会用到。
如:-L /home/hello/lib

-Wl:rpath,添加运行时库路径
-Wl:rpath 后面也是路径,运行的时候用。这条编译指令会在编译时记录到target文件中,所以编译之后的target文件在执行时会按这里给出的路径去找库文件。
如:-Wl:rpath=/home/hello/lib
-rpath和-rpath-link都可以在链接时指定库的路径;但是运行可执行文件时,-rpath-link指定的路径就不再有效(链接器没有将库的路径包含进可执行文件中),而-rpath指定的路径还有效,程序回到指定的路径中去找库(因为链接器已经将库的路径包含在可执行文件中了。)最后,不管使用了-rpath还是-rpath-link,LD_LIBRARY_PATH还是有效的
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值